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

Reading text file from stdin stops at last line

提问人:corporateWhore 提问时间:9/5/2016 最后编辑:CommunitycorporateWhore 更新时间:9/5/2016 访问量:972

问:

我编写了一个简短的程序来测试从以下位置读取文本文件: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

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

问:返回 true 的唯一方法是在读取失败后,如下所述:在 C 中检测 EOF。为什么不是触发EOF的最终调用,我该如何更好地处理此事件?feof()getchar

C 标准 eof feof

评论

4赞 r3mainer 9/5/2016
为什么“while ( !feof (file) )”总是错的?
0赞 corporateWhore 9/5/2016
我不确定。它没有检测到任何失败的读取?
4赞 r3mainer 9/5/2016
点击链接并阅读。您应该检查返回值 from (它返回一个 ,而不是一个 ),并测试该值是否为 EOF。测试作为语句的条件几乎总是错误的。getchar()intcharfeof()while()
0赞 corporateWhore 9/5/2016
好的,但是当没有可得到时,最后的调用仍然失败。它只是挂在那里。getcharchar
2赞 Weather Vane 9/5/2016
无论使用愚蠢的书,都应该被烧毁。数以百万计的学生被它误导了。while(!feof(fp))

答:

2赞 chqrlie 9/5/2016 #1

代码中存在多个问题:

  • 你没有包括 ,也没有 ,或者至少你没有发布整个源代码。<stdio.h><ctype.h>
  • 用于检查文件末尾。这几乎从来都不是正确的方法,正如为什么“while ( !feof (file) )”总是错的?feof()
  • 从变量中的流中读取字节。这会妨碍对 进行适当的测试,并导致 的未定义行为。将类型更改为 。charEOFisspace(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;
}

评论

0赞 corporateWhore 9/5/2016
我阅读了链接,并认为我更好地理解了这个话题。所以谢谢你。但是,即使合并了建议的更改,执行仍然会在最后一次调用时停止。在第 11 行。getchar()
0赞 chqrlie 9/5/2016
你说的停止是什么意思?它至少应该输出'\n'
0赞 corporateWhore 9/5/2016
好的,我认为这是一个eclipse调试器问题。在 eclipse 中,当调试行到达时,它只是停止并且不会再继续。我唯一的选择是按下停止按钮。当我编译它并在终端中运行它时,它工作得很好。对不起。while((c = getchar()) != EOF && isspace(c)
0赞 corporateWhore 9/5/2016
这绝对是一个日食问题。我刚刚在 cLion 中尝试了相同的代码,它也运行良好。我必须单独调查eclipse问题。谢谢你的帮助。