1

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

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

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

读的字不一样?

4

4 回答 4

1

不,读取的单词不会相同,因为您从文件中读取了两次,每次都会得到不同的数据。

测试中的条件while以查看您是否在文件末尾,为此必须进行读取尝试,这需要循环fscanf() 之前。

进入循环后,您希望继续从文件中读取。大概循环内会有更多代码来处理您正在读取的数据。

在您发布的代码中,如果您在第一次读取尝试时遇到文件结尾,您将不会进入 ( while) 循环。

do-while将此与测试位于循环底部的构造进行对比(即读取仅发生一次,在循环的“底部”)。在那里,您将始终至少进入循环一次。

于 2012-06-20T12:51:02.830 回答
1

在这里使用这样的东西可能没有意义feof(),但是(我想,如果我弄错了,请道歉)学习 C 的许多人似乎“想要”。

事实是它fscanf()本身有一个返回值;如果文件结束,它将无法执行请求的扫描,它会告诉您。EOF如果文件结束,它甚至会返回特殊常量。所以只需循环返回值 fscanf()

while( fscanf(fin, "%s", letta) == 1 )
{
   /* Process, parse, store or do whatever with letta. */
}
于 2012-06-20T12:57:53.247 回答
1

因为只有在调用fscanf. 尚未调用时,条件while(!feof(fin))没有意义。fscanf

于 2012-06-20T12:59:28.453 回答
0

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");
} 
于 2012-06-20T13:57:27.943 回答