C程序打印最后一行两次(文件I / O)

时间:2015-03-19 11:25:27

标签: c

最近我正在阅读Deitel的第7版C How to Program的文件处理部分。对于写入文件,它使用以下示例:

// 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

如您所见,它首先在else块中扫描并打印数据,然后在while循环中扫描和打印数据。因为我认为两次做它是没有意义的,它只是删除了if-else部分并编译了它。好吧它工作正常但后来我意识到它复制了输出文件中的最后一行输入。在Deitel版本中它没有。

我的版本出了什么问题?为什么它重复最后一行?我认为这可能是循环条件的问题,但我不确定..

编辑:这个代码是由迪特尔使用的,我不相信这是错的,因为他正在使用if-else来解决由!feof引起的问题。但是我想知道如何在没有if-else的情况下修复它。

在没有if-else的编辑版本中,只有循环输入和输出是:

输入:

1 test 25.6
2 some 95

输出:

1 test 25.6
2 some 95
2 some 95

3 个答案:

答案 0 :(得分:4)

重点是EOF测试必须始终遵循scanf(),并且在打印读取信息之前。

if-else条件仅用于处理最终的打开错误条件,因此您修改代码的方式并不完全清楚。然而,人们经常尝试这样做:

  while ( !feof( stdin ) ) { 
     scanf( "%d%29s%lf", &account, name, &balance );
     fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
     printf( "%s", "? " );
  }

这是错误的,因为在阅读最后一个数据时,它不会读取EOF&#34; (EOF是你在读完数据后>遇到的条件):只有后续的scanf()会这样做,而输出函数会输出错误的数据(以前的数据,不会被覆盖,因为输入错误,这就是重复最后一行的原因。)

例如,这是正确的:

  for ( ;; ) { 
     scanf( "%d%29s%lf", &account, name, &balance );
     if (feof( stdin )) break;
     fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
     printf( "%s", "? " );
  }

实际上,我更喜欢它,而不是像Deitel所建议的那样两次重复相同的scanf()行。

答案 1 :(得分:1)

更改为:

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

答案 2 :(得分:0)

更正的代码是:

while ( !feof( stdin ) ) { 
    if( !feof( stdin ) )
    {
        fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
        printf( "%s", "? " );
        scanf( "%d%29s%lf", &account, name, &balance );
     }
}