C如何处理EOF?

#include  int main() { FILE* f=fopen("book2.txt","r"); char a[200]; while(!feof(f)) { fscanf(f,"%s",a); printf("%s ",a); printf("%d\n",ftell(f)); } fclose(f); return 0; } 

我有上面的代码。 book2.txt包含“abcdef abcdef”,光标移动到换行符(即:abcdef abcdef \ n)。 我得到以下结果。

 abcdef 6 abcdef 13 abcdef 19 

我希望得到

 abcdef 6 abcdef 13 15 

我究竟做错了什么?

自己测试I / O操作; 不要使用feof()除非你正在编写Pascal(并且C不是Pascal!)

 #include  int main(void) { FILE *f = fopen("book2.txt", "r"); char a[200]; if (f != 0) { while (fscanf(f, "%199s", a) == 1) { printf("%s ", a); printf("%ld\n", ftell(f)); } putchar('\n'); fclose(f); } return 0; } 

请注意,修订后的代码在使用之前测试f ,并通过指定字符串在转换规范中的长度来防止缓冲区溢出。 请注意, %s会读取空格字符; 除非每行没有空格,否则它不会读取行。

fscanf()类的操作报告故障后,使用feof()来区分转换失败,I / O错误和EOF。 例如:

 #include  int main(void) { FILE *f = fopen("book2.txt", "r"); char a[200]; if (f != 0) { while (fscanf(f, "%199s", a) == 1) { printf("%s ",a); printf("%ld\n", ftell(f)); } putchar('\n'); if (feof(f)) printf("EOF\n"); else if (ferror(f)) printf("I/O error\n"); else printf("Conversion failed\n"); fclose(f); } return 0; } 

使用%s ,您将无法转换失败,并且I / O错误也非常不可能。 但是,如果转换说明符为%d ,则数据中的标点符号可能会导致“转换失败”。

在超过25年的C编码中,我的代码中有2个地方使用了数千个文件中的feof() (几个月前我做过检查 ),在这两种情况下,代码都区分了EOF和错误(大致如图所示)。

feof不会告诉你,在你到达文件末尾之后,你已经到了文件的末尾。 检查fscanf的结果(返回值)。 它会告诉你什么时候它不能再读了。 如果fscanf命中文件的末尾, 它将返回EOF(并且feof将在发生这种情况后返回true)。

现在只是为了好玩,看看这种做法。 实际上不要这样做。

 while(1) { switch(fscanf(f,"%s",a)){ case 1: printf("%s ",a); printf("%d\n",ftell(f)); continue; case EOF: break; } break; } 

这种方式是错误的,因为它很聪明 。 在一些案例中,整个循环的行为将变得非常难以辨别(例如, 该程序 )。 使用fscanf您实际上只需要知道是否获得了所需的所有数据。 让下一个输入读取函数在找到它时处理EOF。 这个fscanf调用需要填充x个值,所以,

 if (fscanf(f,"%d %d %d", &i, &j, &k) != 3) /* cannot continue. need ijk values for next computation */ 

然后做你的错误响应,或退出循环,或者你的程序下一步需要做什么。 但是如果fscanf返回3以外的任何值,它就不会读取3个值。