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

C程序打印最后一行两次(文件I/O),c,C,最近我在读Deitel出版的《C如何编程》第七版的文件处理部分。对于写入文件,它使用以下示例: // 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; //

最近我在读Deitel出版的《C如何编程》第七版的文件处理部分。对于写入文件,它使用以下示例:

// 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
输出:

1 test 25.6
2 some 95
2 some 95
改为:

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

关键是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”(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()

更正的代码为:

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

可能与我读到的内容重复,但我认为我的情况不同。在您完成
main
函数之前,您应该输入
返回0,或一些数字。显示您的输入(数据和EOF)。对于
unsigned int
也使用
%u
可以显示您遇到问题的代码(显示代码,而不是代码的英文描述)。看起来你已经发布了工作代码,而不是坏代码。阅读文档(习惯于查找内容-这很有帮助)。
while ( !feof( stdin ) ) { 
    if( !feof( stdin ) )
    {
        fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
        printf( "%s", "? " );
        scanf( "%d%29s%lf", &account, name, &balance );
     }
}