Reputation: 401
Recently I was reading file processing section of C How to Program, 7th ed by Deitel. For writing to a file, it uses this example:
// Fig. 11.2: fig11_02.c
// Creating a sequential file
#include <stdio.h>
int main( void )
{
unsigned int account; // account number
char name[ 30 ]; // account name
double balance; // account balance
FILE *cfPtr; // cfPtr = clients.dat file pointer
// fopen opens file. Exit program if unable to create file
if ( ( cfPtr = fopen( "clients.dat", "w" ) ) == NULL ) {
puts( "File could not be opened" );
} // end if
else {
puts( "Enter the account, name, and balance." );
puts( "Enter EOF to end input." );
printf( "%s", "? " );
scanf( "%d%29s%lf", &account, name, &balance );
// write account, name and balance into file with fprintf
while ( !feof( stdin ) ) {
fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
printf( "%s", "? " );
scanf( "%d%29s%lf", &account, name, &balance );
} // end while
fclose( cfPtr ); // fclose closes file
} // end else
} // end main
as you can see, it scans and prints data first in else block, then in a while loop. since I thought it's pointless to do it twice, it just removed the if-else part and compiled it. well it worked fine but then I realized it duplicates the last line of input in the output file. in the Deitel version it does not.
what's wrong with my version?? why does it duplicates the last line? I think this might be an issue with loop condition but I'm not sure..
edit: this code is used by Dietel and I don't believe it's wrong because he is using if-else to fix the problem caused by !feof. but i wanted to know how do i fix it without that if-else.
in edited version without if-else and only with loop the input and output are:
input:
1 test 25.6
2 some 95
output:
1 test 25.6
2 some 95
2 some 95
Upvotes: 5
Views: 8011
Reputation: 1
The corrected code is:
while ( !feof( stdin ) ) {
if( !feof( stdin ) )
{
fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
printf( "%s", "? " );
scanf( "%d%29s%lf", &account, name, &balance );
}
}
Upvotes: 0
Reputation: 4926
the point is that the EOF test must always follow the scanf(), and be before printing the read information.
The if-else condition is just for handling the eventual open error condition, so how you have modified the code is not totally clear. However people often try to do:
while ( !feof( stdin ) ) {
scanf( "%d%29s%lf", &account, name, &balance );
fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
printf( "%s", "? " );
}
and this is wrong because when reading the last data it will not "read the EOF" (EOF is the condition you met after you have finished reading data): only the subsequent scanf()
will do, and the output functions will print wrong data (the previous ones, not overwritten because of the input error, that's why the last line is repeated).
For example this is correct:
for ( ;; ) {
scanf( "%d%29s%lf", &account, name, &balance );
if (feof( stdin )) break;
fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
printf( "%s", "? " );
}
And actually I prefer it over repeating the same scanf()
line twice as suggested by Deitel.
Upvotes: 4
Reputation: 25286
Change to:
else {
puts( "Enter the account, name, and balance." );
puts( "Enter to end input." );
// write account, name and balance into file with fprintf
while (scanf( "%d%29s%lf", &account, name, &balance)==3)
{
fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
printf( "%s", "? " );
}
fclose( cfPtr ); // fclose closes file
} // end else
Upvotes: 1