如何在C语言中检查stdin是否为空。

5
我正在重新学习C编程,因此下面的问题是为了更好地理解。 使用scanf(),我发现清空stdin很重要(或者自己找到这个方法也不会花费太长时间)。我通过你的帮助进一步了解到,fflush(stdin)不是标准化的,例如gcc就不支持该函数。 我开始使用以下代码段来清空stdin。感谢这里提供的代码段,如果stdin非空,则它能正常工作。但是,如果stdin为空,则它将无法工作。我的清空函数中的fgetc()只是等待并阻止程序。事实上,到目前为止我所知道的所有其他stdin读取函数(如scanf()、fgetc()、gets()、fgets()、getchar())都表现出相同的行为。因此,我的清空函数实际上是有条件的清空:只有在缓冲区非空时才进行清空。如果为空,清空操作将阻塞程序并等待从stdin接收输入。这不是我想要的。因此,我需要一种方法来检查stdin是否为空。如果为空,则继续执行。如果不为空,则运行我的清空函数。 因此,我正在寻找的是一种C标准方法来检查stdin是否为空。 非常感谢您的帮助!
void flush_line(FILE *);


/* function to flush stdin in a C standard way since*/
/* fflush(stdin) has undefined behaviour. */
/* s. http://stackoverflow.com/questions/20081062/fflushstdin-does-not-work-compiled-with-gcc-in-cygwin-but-does-compiled-with-v */
void flush_line(FILE *fin)
{
    int ch;
    do
    {
        ch = fgetc(fin);

    } while (ch != '\n' && ch != EOF);

}

很不幸,那可能不会很好地工作,因为fgetc会在没有字符可读时阻塞。 - Some programmer dude
“清空”输入流的确切含义是什么? - CB Bailey
刷新指的是清空输入流,以确保在请求用户输入并从stdin读取此输入之前没有任何不应该存在的内容。 - user3010324
@CharlesBailey 可能正在消耗其中的所有剩余数据... - A4L
哦,如果fin是一个文件(而不是stdin),那么你就无法知道实现是否继续连续缓冲,因此缓冲区可能永远不会清空。 - Some programmer dude
显示剩余6条评论
3个回答

1
不要把stdin看作数据是否可用的地方。它被称为流的原因是你总是对来自它的下一个数据感兴趣,无论何时可能都会有。
具体而言,你决定出于某个原因“刷新”(也许“排空”是更好的词)流。也许你请求用户输入整数,但他们输入了字母。那么你就知道,流不是“空的”,因为里面有字母!所以读取到下一个换行符是一个合理的想法。
或者,为了与某些其他实用程序兼容,你有一个协议,其中某一行输入是无关紧要的。然后你可以“排空”该行;不管用户是否已经输入任何内容,因为你必须等待他们输入后才能接受更多的输入。

我非常喜欢这个答案!在遇到这个问题之前,我陷入了困境,直到有了这种关于“流”的新思路。如果阅读失败,只需再次阅读即可。 - Eon

0

我用了一种“癌性”的方法解决了这个问题,但它运行良好。只有当标准输入(stdin)是脏的(非空)时才有效,因此在清除之前始终向stdin发送\n。是的,我知道,这似乎是一个非常丑陋的解决方案,但这是我能想到的唯一明智的可移植方式,因为select或poll在Windows上无法使用)。

这就是:

void flush_stdin() {
    char c;
    ungetc('\n', stdin); // ensure that stdin is always dirty
    while(((c = getchar()) != '\n') && (c != EOF));
}

1
现在while循环立即停止,因为您已获取它正在搜索的'\n'。 - Adam Bajger

0

您可以使用select或poll来检查文件描述符是否可读。但这不是ANSI C的标准。


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