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个值。