在使用C语言来对文件操作的时候,我们经常使用一些feof、fgetc函数,但是在使用的过程中也会遇到一些小问题。
在今天编写C语言时候,我写了如下一段代码:
#include <stdio.h> int main(){ FILE *fp = fopen("code.txt","r"); if (fp != NULL) { while (!feof(fp)) { printf("%c",fgetc(fp)); } } else printf("fail to open!"); fclose(fp); return 0; }code.txt:
if else then a1 abc 22看上去貌似没什么问题,这是一段输出code.txt文件内所有字符的一个小程序。 我来用图片指出一下实际出现的问题:
可以看到,程序输出的结果比txt文件的字符多出了一个?符号。
经过查阅相关资料发现,fgetc函数在,传入参数fp到达文件末尾的时候,会返回一个EOF,这个EOF的实值是-1。 那么会不会是fgetc函数多输出了一遍呢?循环到达文件末尾没有停止,而是把最后的EOF也输出了? 我添加了两行代码,实验了一下:
#include <stdio.h> int main(){ FILE *fp = fopen("code.txt","r"); putchar(-1); printf("\n"); if (fp != NULL) { while (!feof(fp)) { printf("%c",fgetc(fp)); } } else printf("fail to open!"); fclose(fp); return 0; }结果果然: -1 的输出结果果然就是这个?符号,也就是说,循环多走了一遍,才结束,导致EOF被当作字符输出了。 在查阅相关资料后得到如下的经验:
feof函数的判断方法不是判断当前指针是否指向文件末尾,而是根据上一次读取的返回值进行判断,如果上一次读取的返回值为EOF,那么feof(fp)为真,否则为假。
而fgetc函数的方法刚好是:先读取当前指针指向的内容,再让指针向后移。
这样一来,刚好,如果两者放在一起操作,就会发生多读一个EOF的现象: getc在读到txt文档最后一个字符的时候,fp指向最后一个字符,读出字符后,fp向后移,fp指向EOF,进行下一次循环,feof判断是否到达文档末尾:由于上一次fgetc读出的是文档最后一个字符,所以即使fp当前已经指向了EOF,feof函数还是会返回假,这样循环就又继续了,下一次循环中,就会将fp指向的EOF输出,fp后移(已经到达文档尾,无法后移);
所以,我将代码改为了这种:
#include <stdio.h> int main(){ FILE *fp = fopen("code.txt","r"); if (fp != NULL) { char ch = fgetc(fp); while (!feof(fp)) { putchar(ch); ch = fgetc(fp); } } else printf("fail to open!"); fclose(fp); return 0; }输出结果就是正常的: