【问题标题】:peek at input buffer, and flush extra characters in C查看输入缓冲区,并刷新 C 中的额外字符
【发布时间】:2026-01-25 00:05:02
【问题描述】:

如果我想在 C 中接收一个字符输入,我将如何检查是否发送了额外的字符,如果是,我将如何清除?

有没有类似 getc(stdin) 的函数,但它不提示用户输入字符,所以我可以输入while(getc(stdin)!=EOF);?或者一个函数来查看缓冲区中的下一个字符,如果它不返回 NULL(或任何会存在的),我可以调用一个(另一个)函数来刷新标准输入?

编辑

所以现在,scanf 似乎在起作用,但是有没有办法让它读取 whole 字符串,直到换行符?而不是到最近的空白?我知道我可以将 "%s %s %s" 或其他任何内容放入格式字符串中,但我可以处理任意数量的空格吗?

【问题讨论】:

    标签: c input stdin flush peek


    【解决方案1】:

    您无法刷新输入流。如果这样做,您将调用未定义的行为。最好的办法是:

    int main() {
      int c = getchar();
      while (getchar() != EOF);
      return 0;
    }
    

    使用scanf魔法:

    #include <stdio.h>
    #include <stdlib.h> 
    
    #define str(s) #s
    #define xstr(s) str(s)
    #define BUFSZ 256
    
    int main() {
      char buf[ BUFSZ + 1 ];
      int rc = scanf("%" xstr(BUFSZ) "[^\n]%*[^\n]", buf);
      if (!feof(stdin)) {
        getchar();
      }
      while (rc == 1) {
        printf("Your string is: %s\n", array);
        fflush(stdout);
        rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", array);
        if (!feof(stdin)) {
            getchar();
        }
       }
       return 0;
    }
    

    【讨论】:

    • 我试过了,但是每次while循环调用getchar()时,都会提示输入另一个字符……不是吗?好像。
    • while 循环等待另一个字符。根据您的系统,将有一个按键组合来表示输入结束。这应该可以解决问题。
    • 所以 getchar() 只会询问用户输入,如果输入缓冲区为空?而且,在询问用户时,如果用户输入了多个字符,是否会填满输入缓冲区?
    • 您用于读取字符的任何方法都容易受到这些问题的影响。你想达到什么目的?
    • 我并没有真正指出问题,我只是不清楚每个函数的行为...... getc() 和 getchar() 之间有什么区别,除了文件流的参数?我会使用 getch(或调查它),但这不是标准的......现在我正在玩 scanf,但 scanf 是否让缓冲区为空?
    【解决方案2】:

    您可以使用getline 读取整行输入。

    或者(针对您的原始问题),您可以在 stdin 上调用 selectpoll 以查看是否还有其他字符要读取。

    【讨论】:

    • 选择或投票? getline甚至在C中吗?我以为它只是C++中cin的成员...
    • getline 在 glibc 中,但它不是标准的 C。我想如果你在 Windows 上你不能使用它。至少,选择应该在任何地方都可用。
    【解决方案3】:

    我今天遇到了类似的问题,我找到了一种似乎可行的方法。我不知道你的具体情况,所以我不知道它是否适合你。

    我正在编写一个需要从键盘获取单个字符的例程,并且它需要是三个特定击键之一(“1”、“2”或“3”)。如果不是其中之一,则程序需要发送错误消息并循环返回以再次尝试。

    问题在于,除了 getchar() 返回的我输入的字符之外,“Enter”键击(将击键发送到程序)保存在输入缓冲区中。该(非打印)换行符然后由纠错循环中的 getchar() 工具返回,进一步导致第二条错误消息(因为换行符不是“1”,也不是“2” ,也不是“3”。)

    这个问题更加复杂,因为我有时会超前于自己,而不是输入单个字符,而是输入这些选项之一将要求的文件名。然后我在缓冲区中有一整串不需要的字符,导致一长串错误消息向下滚动屏幕。

    不酷。

    不过,似乎已经解决了以下问题:

    c = getchar();  // get first char in line
    while(getchar() != '\n') ; // discard rest of buffer
    

    第一行是实际使用我输入的字符的那一行。第二行处理输入缓冲区中剩余的任何残留物。它只是创建一个循环,一次从输入缓冲区中提取一个字符。语句循环时没有指定要执行的操作。它只是读取一个字符,如果它不是换行符,则返回下一个。当它找到换行符时,循环结束并继续程序中的下一个业务顺序。

    【讨论】:

      【解决方案4】:

      我们可以创建一个函数来清除键盘缓冲区,如下所示:

      #include <stdio.h>
      
      void clear_buffer(){
         char b;
         //this loop take character by character in the keyboard buffer using 
         //getchar() function, it stop when the variable "b" was
         //enter key or EOF.
         while (((b = getchar()) != '\n') && (b != EOF));
      }
      
      int main()
      {
          char input;
          //get the input. supposed to be one char!
          scanf("%c", &input); 
          //call the clearing function that clear the buffer of the keyboard 
          clear_buffer(); 
          printf("%c\n",input); //print out the first character input
          // to make sure that our function work fine, we have to get the
          // input into the "input" char variable one more time
          scanf("%c", &input); 
          clear_buffer();  
          printf("%c\n",input);
          return 0;
      }
      

      【讨论】:

        【解决方案5】:

        使用需要大量字符(超过 1 个,可能是 256 个)的读取,并查看实际返回的字符数。如果你得到不止一个,你知道;如果你只有一个,那就是所有可用的。

        你没有提到平台,这很快就变得相当棘手。例如,在 Unix (Linux) 上,正常机制将返回一行数据 - 可能是您所追求的一个字符和一个换行符。或者,也许您说服您的用户输入 ^D(默认)来发送前面的字符。或者,也许您使用控制功能将终端置于原始模式(如viemacs 之类的程序)。

        在 Windows 上,我不太确定 -- 我认为有一个 getch() 函数可以满足您的需要。

        【讨论】:

          【解决方案6】:

          你为什么不用scanf而不是getc,通过使用scanf你可以得到整个字符串。

          【讨论】:

          • scanf 好吗?我的意思是,我读过(我忘了在哪里)它很容易遇到问题
          • 您可能会遇到缓冲区溢出问题,但是 Windows 中的 scanf 变体 scanf_s(_s 代表安全)可以保护您免受此问题的影响。