如何在C语言程序中清除stdin?

时间:2018-10-03 04:45:33

标签: c stdin

这是一个看似简单的问题,但我回答太久了:

我正在尝试使用fgets()从C程序中的用户读取输入。但是,我遇到一个问题,如果用户输入的字符多于设置为读取的fgets()的字符,则下一次从用户读取字符串的调用会自动读取stdin缓冲区中的其余字符,这不是我的行为想。

我尝试了多种方法清除stdin流,虽然我知道类似的东西

while(getchar()!='\n'); 将起作用,这需要用户点击输入一个额外的时间,这不是我想要的时间。

代码的结构看起来像这样:

    void read_string(char *s, int width){
        fgets(s,width,stdin);
        clear_stdin();
        .
        .   
    }

    while (1){
        read_string()
        .
        .
    }

但是我无法获得需要正常工作的clear_stdin()函数。我到底该如何清除标准输入,而无需用户不必要两次按Enter键?

3 个答案:

答案 0 :(得分:4)

无法以可移植的方式清除stdin (因为未指定来自<stdio.h>的功能)。顺便说一句,stdin通常不仅可以是终端,还可以是redirectionpipe(甚至可能是某些socket)。细节当然很重要(例如您的操作系统和/或运行环境)。

您可以避免stdio并使用operating system特定的方式来处理标准输入(例如,在POSIX系统上以file descriptor级别工作)。

在Linux上(具体而言),您可能会了解有关the Tty demystified的更多信息,并根据这些知识编写低级代码。参见termios(3)。考虑使用readline(3)

您可以use(至少在Linux上)getline(3)读取堆分配的行缓冲区。

答案 1 :(得分:4)

要实现所需的功能-如果提供的缓冲区被过度填充,则读取并忽略换行符,直到换行符为止-您需要有条件地读取换行符,只有在其中没有换行符时才这样做读取的输入缓冲区。

void read_string(char *s, int width)
{
    if (fgets(s, width, stdin) != 0)
    {
        size_t length = strlen(s);
        if (length > 0 && s[length-1] != '\n')
        {
            int c;
            while ((c = getchar()) != '\n' && c != EOF)
                ;
        }
        /* Use the input data */
    }
    else
        /* Handle EOF or error */
}

该技术的另一部分是确保使用足够大的缓冲区,以防止任何人溢出该缓冲区。将char buffer[4096];视为开标价;您可以根据需要增加它。这样一来,任何人都不可能(能够)在一行上键入足够的数据来溢出您提供的缓冲区,从而避免了该问题。

另一种选择是使用POSIX getline()。它将一行读入已分配的空间,分配更多的空间,直到数据适合(或内存不足)。与fgets()相比,它还有至少另一个主要优点-它报告读取的行中的字符数,这意味着它不会与空字节('\0'混淆,通常键入 Control -@ )。相比之下,您无法用fgets()判断在第一个空字节之后是否输入了任何数据;您必须假设输入在第一个空字节处停止。

请注意,如果问题(while (getchar() != '\n');中显示的简单循环在读取换行符之前遇到EOF,则该循环将变为无限循环。

答案 2 :(得分:2)

while ((getchar()) != '\n');

这并不总是可行的...(但是,好的一面是,它不如它可移植的情况)。但是,如果尚未重定向stdin,则除非手动EOF,否则用户输入的终端字符通常会换行。提取期望内容后,假设您不期望\n,则可以耗尽其中的内容,直到(包括)“ \ n”,然后重新进行迭代。正如其他人所建议的那样,大多数情况下,与手动条纹案例处理相比,存在更高级别的界面来更可靠地处理此细节。

More Details on Challenge and Solutions 此链接的标题中包含“ C \ C ++”的基本原理,它不作为实体存在。请放心,我们给出了单独的 C示例,这些示例与其他C ++示例是离散的。