我想知道是否有办法在不破坏 C 标准的情况下知道输入缓冲区stdin
是否为空。目标是正确清理所述缓冲区,因为通过使用以下两个选项之一:
char c;
while ((c = getchar()) != '\n' && c != EOF);
任何一个
scanf("%*[^\n]%*c");
如果输入缓冲区为空,它将保持等待接收来自键盘的数据,这会适得其反,因为清理输入缓冲区时的目标只是清空它(避免以后读取先前输入的数据的剩余部分)透明的方式,而不是请求数据。简而言之,如果缓冲区有内容,则清理缓冲区,如果缓冲区为空,则什么也不做。
清理过程:一旦知道输入缓冲区何时为空,输入的每个字符都会被读取,直到验证它是干净的,此时它将停止读取,以免等待从请求数据键盘。
更新:这样做时scanf("%d", &n)
,知道缓冲区中是否还有数据是没有问题的,因为如果%d
说明符后没有空格,缓冲区中总会有数据。如果有空格,scanf("%d ", &n)
表示一旦用键盘输入数字,stdin
后面的换行符就会从缓冲区中清除,留空。stdin
因此,在这种情况下,一旦,缓冲区的状态将不知道scanf
,因为它是否为空取决于用户是否输入了一个或多个以空格分隔的数字。
如果标识符后面没有空格,则表示输入数据时按下的换行符保留在缓冲区中,即使仅正确输入了数字,缓冲区中也始终有内容。因此,缓冲区可以在之后安全地刷新。
gets
在用or读取字符串的情况下getchar
,由于在输入字符串时会读取换行符,那么接下来的处理方式就是@eferion 的解决方案中公开的一种,即stdin
在输入数据后手动知道缓冲区中是否有内容。
在我到目前为止找到的可能的解决方案中,它们都超出了 C 标准:
fpurge
或者__fpurge
在 glibc 中:它可以完美运行,但是在 Linux with 的情况下__fpurge
,它属于 GNU 标准库。tcflush
determios.h
:这个 POSIX 定义的解决方案类似于fpurge
但不是刷新高级流缓冲区FILE *
,而是刷新与文件描述符 (fd) 关联的低级缓冲区。由于最终目标是使用 , , 等函数清除缓冲区scanf
,fwrite
因此getchar
此解决方案不起作用。它仅对使用诸如read
处理文件描述符之类的函数有效。select
deunistd.h
:这个 POSIX 定义的函数可用于判断与文件描述符关联的缓冲区是否为空。它可以完美地工作,但与 的情况一样tcflush
,仅适用于与文件描述符关联的低级缓冲区。我实现了一个函数,select
用于清除与数据输入的文件描述符关联的低级缓冲区,它工作得很好(它做同样的事情tcflush
),但它不影响与输入流关联的高级缓冲区FILE *
。您遗漏的一个细节,我不知道是有意还是无意,通常是在脏读后删除缓冲区......也就是说,当您知道缓冲区有数据被认为是垃圾时。
如果您将该假设添加到您的等式中,您添加的第一个代码可以完美地解决您的问题:
我想我记得你介绍的第二个系统有一个缺点,如果输入缓冲区的第一个字符只是一个换行符,它就会卡住......但现在我没有可以测试它的环境并且确认它。
取自评论如果用户超过允许的最大值,如何采取行动?
C 是一种低级语言,有它的优点和问题……但这不应该是其中之一:
如果我们之前使用 fgets 读取数据,我们可以确定 STDIN 输入缓冲区中是否还有任何内容。如下,我们看下面的代码:
如果我们已经对 fgets 有一点经验,我们就会知道如果它仍然没有达到字符限制,在这种情况下设置为 10。然后在读取的字符串中它将保存返回值为 0xA 的行。让我们看看一些输出:
我们看到,如果我们的变量在其位置 Strlen - 1 值 0xA 意味着缓冲区中没有可读取的内容。
否则,缓冲区中仍有一些数据,纯换行和/或附加文本 + 换行