c - 从 stdin 读取文本文件在最后一行停止

标签 c stdin eof feof

我写了一个小程序来测试从 stdin 读取文本文件:

int main(){
    char c;

    while(!feof(stdin)){

        c = getchar();       //on last iteration, this returns '\n'

        if(!isspace(c))      //so this is false
            putchar(c);

        //remove spaces
        while (!feof(stdin) && isspace(c)){    //and this is true
                c = getchar();  //      <-- stops here after last \n
                if(!isspace(c)){
                    ungetc(c, stdin);
                    putchar('\n');
                }
        }
    }
    return 0;
}

然后我将一个小文本文件传递给它:

jimmy   8
phil    6
joey    7

最后一行 (joey 7) 以 \n 字符结尾。

我的问题是,在它读取并打印最后一行之后,然后循环返回以检查更多输入,没有更多的字符要读取,它就停在代码块中注明的行处。

问题:feof() 返回 true 的唯一方法是在读取失败之后,如此处所述:Detecting EOF in C .为什么对 getchar 的最终调用没有触发 EOF,我该如何更好地处理这个事件?

最佳答案

您的代码中存在多个问题:

  • 您不包括 <stdio.h> , 也不 <ctype.h> ,或者至少您没有发布整个源代码。
  • 您使用 feof()检查文件结尾。正如 Why is “while ( !feof (file) )” always wrong? 中强调的那样,这几乎从来都不是正确的方法。
  • 您从 char 中的流中读取字节多变的。这会阻止对 EOF 的正确测试并且还会导致 isspace(c) 的未定义行为.将类型更改为 int .

这是一个改进的版本:

#include <stdio.h>

int main(void) {
    int c;

    while ((c = getchar()) != EOF) {
        if (!isspace(c)) {
            putchar(c);
        } else {
            //remove spaces
            while ((c = getchar()) != EOF && isspace(c)) {
                continue;  // just ignore extra spaces
            }
            putchar('\n');
            if (c == EOF)
                break;
            ungetc(c, stdin);
        }
    }
    return 0;
}

虽然您的方法带有 ungetc()在功能上是正确的,最好以这种方式使用辅助变量:

#include <stdio.h>
#include <ctype.h>

int main(void) {
    int c, last;

    for (last = '\n'; ((c = getchar()) != EOF; last = c) {
        if (!isspace(c)) {
            putchar(c);
        } else
        if (!isspace(last))
            putchar('\n');
        }
    }
    return 0;
}

关于c - 从 stdin 读取文本文件在最后一行停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39320237/

相关文章:

c - 保存指针的内存地址

c - fgets() 如何从 stdin 读取数据?

python - 如何找出文件是否位于 `eof` ?

c++ - 对 C++ Primer 示例中的控制流执行感到困惑

C 初学者 : Does scanf "receive" the EOF marker from standard input?

c++ - 如何在valgrind中启动时修复 fatal error (与libc6-dbg和libc6-dbg:i386连接)

c - 在 win32 应用程序中使用 GetDlgItemText()

c - 如何用 C 语言编写求解器程序的替代品?

c# - 将图像写入 Process.StandardInput.BaseStream 的更快方法

c - 在 Windows 上将 select() 与 STDIN 一起使用?