5

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
vvvsg
  • 401
  • 1
  • 7
  • 15
  • possible duplicate of ["while( !feof( file ) )" is always wrong](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong) – Sourav Ghosh Mar 19 '15 at 11:26
  • 1
    I read that but I think my case is different. – vvvsg Mar 19 '15 at 11:29
  • Before you finish the `main` function, you should put in a `return 0;`, or some number. – Gophyr Mar 19 '15 at 11:38
  • show your input(data and EOF). also use `%u` for `unsigned int` – BLUEPIXY Mar 19 '15 at 11:40
  • Can you show the code you are having trouble with (show the code, not an english description of the code). It seems you have posted the working code, not the broken code. – M.M Mar 19 '15 at 12:18
  • Also can you clarify that you're aware that the best solution is just to not do `while ( !feof( stdin ) ) ` at all? (the code you have posted is weakly designed, hopefully it's in the book as an example of what not to do!) – M.M Mar 19 '15 at 12:20

3 Answers3

4

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.

Sigi
  • 4,826
  • 1
  • 19
  • 23
1

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
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
0

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 );
     }
}
Eric Aya
  • 69,473
  • 35
  • 181
  • 253