C语言 文件操作中一些问题的解决方法(空文件处理&重复读取)

(ahhh第二篇来了!!打卡!)

问题总结

最近在文件操作这一块遇到了一些问题,总的来说有以下:
① 文件为空时,依旧执行读取语句
② 读取文件内容时,最后一个内容会被重复读取

代码问题&解决方案

问题发现
对于①,很多时候会因为文件为空而导致程序错误,代码写的好好的理论上没问题怎么就错了呢?
下面是一段常犯的错误代码:

//(VS2019)
FILE* fp;
fopen_s(&fp, name, "r");  // 名字为 name 的文件
if(fp != NULL)
{
     
	while (!feof(fp))
	{
      /* ... */ }
}

乍一看好像没什么问题,但一旦运行,就会发现即使文件为空,while语句也依然被执行

原因分析
feof的作用为检测文件尾标记是否被读取过,是则返回值1。
从功能上就可以发现,必须读取到标记才会返回1,但一开始标志根本就没被读到,即使文件为空,所以结果便是读取到了尾标记,然后while循坏便被意外地执行了1次。

解决方案
知道了原因,问题就好解决了,个人有以下两种方法:

法一:

该方法是每次循环读取一下需要的内容
然后判断是否读取到了文件尾标记
如果是则退出,不是则执行目标步骤
while (!feof(fp))
{
     
	fscanf_s( ... );
	if (feof(fp)) break;  // 到达尾部便退出
	/* ... */
}

法二:

该方法是读取文件的第一个字符,看是否为文件尾标记
如果不是则执行目标步骤(注意要用rewind将位置指针指向开头)
(该方法针对空文件检测,check!=EOF也可以拉到while外边省点资源)
char check;  //对文件尾部进行检测
check = getc(fp);  //读取一个字符看是不是文件尾部标记
rewind(fp);  //如果不是空文件,记得把标记还原到开头(因为上面移动了一下)
while (!feof(fp) && check!=EOF)
{
      /* ... */ }
注意区分:EOF的值为-1,是文件文件尾标记的定义值
而feof读取到文件尾标记时返回值为1
(注意不要写成 feof(fp)!=-1 噢)

通过这两个方法,空文件问题就已经解决啦!!!
下面看一下第二个问题,有了①的基础,其实②差不多道理

简单分析一下②:
为什么最后一个会被重复读取呢?究其原因还是feof的工作原理在搞事情!
在读取到最后一个内容时,feof并没有读取到文件尾标记,所以会继续向下读取导致while多执行1次。

解决方案
用上面①的法一可以很好解决这个问题,事实上法一应该是最保险的了,法二只能针对空文件的检测,可以拿来单独使用。


一点小疑惑(待解)
但为什么最后输出的内容而不是尾标记而是重复的内容呢?
2333老实说我也不清楚,不过通过测试,我刻意把最后一次的读取操作去掉了,也就是不去读取那个文件尾标记。
!!然后,再次输出竟然还是重复的内容,所以我怀疑可能缓冲区的内容并没有被清除,导致了下一次输出依旧是该重复内容

⬇⬇⬇⬇⬇⬇⬇
最后:
aaaa结尾只是本人猜测不知道对不对,线上没能找到该答案
路过的大神们可以帮忙看看噢!!

hu~ 第二篇完成了!!
一定要坚持下去哦2333 (寒冰小澈)

你可能感兴趣的:(实战经验,c语言)