在 C 中使用 fscanf() 如何区分文件结尾和错误?

tom*_*ser 1 c scanf eof feof

根据手册,int fscanf(FILE *stream, const char *format, ...)返回成功匹配和分配的输入项的数量,可以少于提供的数量,甚至在早期匹配失败的情况下为零。我该如何区分:

  • 零匹配和分配的项目
  • 文件结尾
  • 一个空文件?

Jon*_*ler 5

例如,请参阅 POSIX 规范的“返回值”部分fscanf()。

  • 通过fscanf()返回 0报告零匹配和分配的项目。

  • 通过fscanf()返回 EOF报告文件结束。

  • 第一次调用fscanf()返回 EOF会报告一个空文件。

请注意,该规定使得很难发现空文件(无字节)和其中没有有用数据的文件之间的区别。考虑这个测试程序(我称它为eof59.c,编译为创建eof59):

#include <stdio.h>

int main(void)
{
    char buffer[256];
    int rc;

    while ((rc = scanf("%255s", buffer)) != EOF)
        printf("%d: %s\n", rc, buffer);
}
Run Code Online (Sandbox Code Playgroud)

如果你把它/dev/null作为输入(最终的空文件)运行,它什么也没说。但是,如果您向它提供一个带有单个空格(并且没有换行符)的文件,或者只是一个换行符,或者实际上是任何空格序列,它也不会说什么。您还可以尝试将格式字符串替换为" x %255s". 向它提供一个只有一个x(可能周围有空格)的文件不会产生任何输出。将 a 文件y作为第一个字符(空格除外)提供给它,程序会运行很长时间,报告0:每一行输出。

请注意,这while (!feof(file))总是错误的,但是在诸如scanf()返回 EOF 之类的函数之后,您可以合法地使用feof()并ferror()消除真正的 EOF 和文件流上的错误(例如磁盘崩溃或……)之间的歧义。

if (feof(stdin))
    printf("EOF on standard input\n");
if (ferror(stdin))
    printf("Error on standard input\n");
Run Code Online (Sandbox Code Playgroud)

使用显示的代码,您通常应该看到“标准输入上的 EOF”;在标准输入上生成(甚至模拟)错误可能非常困难。您不应看到两条消息,而应始终看到其中一条消息。