使用fscanf()和feof()函数

3

这是我的代码。

#include<stdio.h>
void main(){
    FILE *fp;
    int a,b;
    fp=fopen("hello.txt","r");
    while(!feof(fp)){
      fscanf(fp,"%d %d",&a,&b);
      printf("%d %d\n",a,b);
    }
}

我的 hello.txt 文件是

1   2
3   4

我的输出是

1   2
3   4
4   4

为什么我的最后一行会被打印两次。难道fp已经到达了EOF?

此外,stackoverflow上的标签说“通常情况下,当它被使用时,使用它的代码是错误的。”这是什么意思?

谢谢。


在C和C++中,main函数应该返回int类型(尽管编译器可能允许其他类型的返回值,但不要这样做)。 - Jacob Parker
2
这是一个很棒的标签描述。eof 确实几乎永远不是你想要的。 - Kerrek SB
你滥用了 feof: https://dev59.com/jG035IYBdhLWcg3wbPU5 - William Pursell
4个回答

6

您绝不能在未立即检查其结果的情况下执行输入操作!

以下内容应该可行:

while (fscanf(fp,"%d %d",&a,&b) == 2)
{
    printf("%d %d\n",a,b);
}

这将在第一次转换失败或文件结束时停止。或者,您可以区分转换失败(跳过错误行)和文件结尾;请参阅 fscanf 的文档。


3
此外,stackoverflow中的标签说“通常情况下,使用它的代码是错误的。”这是什么意思?
这意味着feof()函数(以及与EOF相关的其他功能)的使用经常被误解和错误。您的代码也是如此。
首先,fscanf()并不总是做你想要的事情,更好的方法是使用fgets()从文件中获取行。然而,如果您真的想使用fscanf(),那么请检查它是否能够读取任何内容,否则当它无法读取时,您将打印比所需多一次的变量。因此,您应该这样做:
fp = fopen("hello.txt", "r");

while(fscanf(fp, "%d %d", &a, &b) == 2) {
    printf("%d %d\n", a, b);
}

fclose(fp);

此外,请务必使用空格,因为您的代码很难阅读。

2
你出现额外的一行是因为EOF直到fscanf尝试第三次读取后才被设置,所以它失败了,而你仍然打印了结果。以下代码将实现你预期的效果:
while(1){
  fscanf(fp,"%d %d",&a,&b);
  if (feof(fp))
     break;
  printf("%d %d\n",a,b);
}

(请注意,此示例仅检查EOF而不检查错误)

这将在格式不正确的输入上出错例如此处 - Kerrek SB
@KerrekSB 这只是一个feof如何工作的示例,使用原始代码 - 这回答了问题。 - teppic

0
你可以做以下事情:
#include <stdio.h>

void main(){
    FILE *fp;
    int a,b;
    fp=fopen("file.txt","r");
    while(fscanf(fp,"%d %d",&a,&b)==2)
    {
      printf("%d %d\n",a,b);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接