为什么fscanf使用2次:while(!feof(File))

时间:2012-06-20 12:49:07

标签: c scanf feof

为什么当使用fscanf从文件中获取数据时,使用了2次,一次在“!feof(fin)”之前和之后,如下面的代码所示:

fscanf(fin, "%s", letta);
while(!feof(fin)){

    fscanf(fin, "%s", letta);
}

读取的单词不一样?

4 个答案:

答案 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");
}