为什么当使用fscanf从文件中获取数据时,使用了2次,一次在“!feof(fin)”之前和之后,如下面的代码所示:
fscanf(fin, "%s", letta);
while(!feof(fin)){
fscanf(fin, "%s", letta);
}
读取的单词不一样?
答案 0 :(得分:1)
由于您从文件中读取两次,所以读取的单词不会相同,每次都会得到不同的数据。
while
测试中的条件,看看你是否在文件末尾,为了做到这一点,必须进行读取尝试,这需要fscanf()
之前< / em>循环。
进入循环后,您想继续从文件中读取。据推测,循环中会有更多代码来处理您正在阅读的数据。
在您发布的代码中,如果您在第一次尝试读取时遇到文件结尾,则不会进入(while
)循环。
将此与do-while
构造进行对比,其中测试位于循环的底部(即,仅在循环的“底部”发生一次读取)。在那里,你总是至少进入一次循环。
答案 1 :(得分:1)
在这里使用feof()
可能没有任何意义,但是很多人(我猜,如果我弄错了,道歉)学习C似乎“想要”。
事实是fscanf()
本身具有返回值;如果文件结束,它将无法执行请求的扫描,它会告诉你。如果文件结束,它甚至会返回特殊常量EOF
。所以只需循环返回fscanf()
:
while( fscanf(fin, "%s", letta) == 1 )
{
/* Process, parse, store or do whatever with letta. */
}
答案 2 :(得分:1)
因为EOF标志仅在调用fscanf
后设置。 <{1}}尚未被调用时,条件while(!feof(fin))
没有意义。
答案 3 :(得分:0)
feof
才会返回true。想象一下如下文件:
This is a test$ ^
其中^
表示文件中的当前位置,$
表示EOF。第一次调用fscanf(fin, "%s", letta);
后,流看起来像这样:
This is a test$ ^
在循环的三次迭代(读“是”,“a”和“测试”)之后,你有这个:
This 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");
}