为什么使用 fscanf 从文件中获取数据时,使用了 2 次,一次在 "!feof(fin)" 之前和之后,如下面的代码所示:
fscanf(fin, "%s", letta);
while(!feof(fin)){
fscanf(fin, "%s", letta);
}
读的字不一样?
不,读取的单词不会相同,因为您从文件中读取了两次,每次都会得到不同的数据。
测试中的条件while
以查看您是否在文件末尾,为此必须进行读取尝试,这需要循环fscanf()
之前。
进入循环后,您希望继续从文件中读取。大概循环内会有更多代码来处理您正在读取的数据。
在您发布的代码中,如果您在第一次读取尝试时遇到文件结尾,您将不会进入 ( while
) 循环。
do-while
将此与测试位于循环底部的构造进行对比(即读取仅发生一次,在循环的“底部”)。在那里,您将始终至少进入循环一次。
在这里使用这样的东西可能没有意义feof()
,但是(我想,如果我弄错了,请道歉)学习 C 的许多人似乎“想要”。
事实是它fscanf()
本身有一个返回值;如果文件结束,它将无法执行请求的扫描,它会告诉您。EOF
如果文件结束,它甚至会返回特殊常量。所以只需循环返回值 fscanf()
:
while( fscanf(fin, "%s", letta) == 1 )
{
/* Process, parse, store or do whatever with letta. */
}
因为只有在调用fscanf
. 尚未调用时,条件while(!feof(fin))
没有意义。fscanf
feof
直到您尝试读取文件末尾之后才返回 true。想象一个像下面这样的文件:
这是一个测试$ ^
where^
表示文件中的当前位置,$
表示 EOF。在第一次调用 之后fscanf(fin, "%s", letta);
,流如下所示:
这是一个测试$ ^
在循环的三次迭代(读取“is”、“a”和“test”)之后,您将得到:
这是一个测试$ ^
此时,feof(fin)
仍然返回false
,因为此时您只知道您已经到达字符串“test”的末尾。因此,您的循环将再执行一次。由于你在文件的末尾,没有什么要读的,所以内容letta
不会改变,所以看起来你已经读了两次“test”。 现在 feof(fin)
将返回 true。
这个故事的寓意是你不应该使用feof
你的循环条件;相反,您应该使用读取操作本身的结果,如下所示:
errno = 0;
while (fscanf(fin, "%s", letta) == 1)
{
// process letta
}
if (feof(fin))
{
printf("Reached end of file\n");
}
else
{
perror("Error on read");
}