vvvsg
vvvsg

Reputation: 401

C program prints the last line twice (File I/O)

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

Answers (3)

SHUBHAM KHANNA
SHUBHAM KHANNA

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

Sigi
Sigi

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

Paul Ogilvie
Paul Ogilvie

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

Related Questions