清空stdin缓冲区?

4
我在编写代码时使用了fgets获取用户输入。然后,我编写了一个循环来持续询问用户输入,直到用户打印出quit。但第二次它询问时,“Please enter your input”写了2次而不是1次,并且第一次没有等待我的输入。 所以,我谷歌了一下,发现stdin缓冲区被填满了,需要清除。 我找到了这个解决方案:
void dump_line(FILE * fp) {
    int ch;
    while ((ch = fgetc(fp)) != EOF && ch != '\n') {
        /* null body */;
    }
}

然后从主函数调用:

dump_line(stdin);

我很难理解这个问题。据我理解,它只是将“ch”赋值为fgetc(stdin)的值。我无法理解将fgetc(stdin)赋值给“ch”如何清除缓冲区。

非常感谢您的帮助!

缓冲区并没有被填充。它只包含一个换行符,你还没有读取,而你发布的循环读取了它。 - user207421
7个回答

6

以下是我在纯C语言中使用的旧代码片段,用于用户输入:

int get_line(char *buffer, int bsize)
{
    int ch, len;

    fgets(buffer, bsize, stdin);

    /* remove unwanted characters from the buffer */
    buffer[strcspn(buffer, "\r\n")] = '\0';

    len = strlen(buffer);

    /* clean input buffer if needed */
    if(len == bsize - 1)
        while ((ch = getchar()) != '\n' && ch != EOF);

    return len;
}

该函数从标准输入中检索指定数量的字符并将它们存储到给定的缓冲区中。自动清除stdin输入缓冲区中剩余的内容。此外,它会删除输入数据中的换行符(\r和\n)。

该函数返回成功读取的字符数。


3
fgetc(stdin)分配给ch并不会清除缓冲区,真正起到清空缓冲区作用的是调用fgetc(stdin)函数本身。每次调用(因此每次循环迭代)都会从stdin中吃掉一个字符。
工作原理如下:
  1. 调用fgetc(stdin)函数,并将结果分配给ch
  2. 如果ch不等于EOF'\n',则返回1。
当循环停止时,以下两种情况之一将为真:要么你刚刚吃掉了标记当前行结尾的字符(也就是说,你现在位于下一行),要么stdin为空,你将不会获得任何更多的输入。(对于交互式应用程序来说,后者是半异常的,但当人们从其他地方向您的应用程序管道传输数据时,这种情况很常见。请做好准备。)

2

它仅仅将“ch”的值赋为fgetc(stdin)的返回值

调用fgetc会产生副作用,即从文件流中读取并移除一个字符。


哦,好的,我想知道为什么教程完全忘记提到它。 谢谢 :d - stensootla

0

清空缓冲区的另一个示例:

char ch[1];
while(1){
    ch[0] = fgetc(stdin);
    if(ch[0] == '\n' || ch[0] == EOF) break;
}

0

这是同样的循环,但写法不同,也许这样会更好理解:

void dump_line(FILE * fp) { /* dump a line from fp */
    int ch; /* temporary storage for character */

    while (1) {
        ch = fgetc(fp); /* read char from fp, this removes it from the stream */

        if (ch == EOF)  /* break if we reached END-OF-FILE */
            break;

        if (ch == '\n') /* break if we reached a newline, because */
            break;      /* we have succesfully read a line */
    }
}

0

fgetc() 从缓冲区获取一个字符。此代码从缓冲区读取字符,直到文件结束或达到新行。


-1

这是我想出来的一个两行代码的解决方案,希望能对某些人有所帮助。

char ch;
while ((ch = fgetc(stdin)) == EOF || ch == '\n');

fgetc同时从STDIN缓冲区中读取并删除。它会一直这样做,直到遇到EOF或换行符,表示STDIN现在为空。


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