c - 如何清除 C 中的输入缓冲区?

标签 c io buffer stdin flush

我有以下程序:

int main(int argc, char *argv[])
{
    char ch1, ch2;
    printf("Input the first character:"); // Line 1
    scanf("%c", &ch1);
    printf("Input the second character:"); // Line 2
    ch2 = getchar();

    printf("ch1=%c, ASCII code = %d\n", ch1, ch1);
    printf("ch2=%c, ASCII code = %d\n", ch2, ch2);

    system("PAUSE");
    return 0;
}

正如上述代码的作者所解释的: 该程序将无法正常工作,因为在第 1 行,当用户按 Enter 时,它将在输入缓冲区中留下 2 个字符:Enter 键(ASCII 代码 13 )和\n(ASCII 代码10)。因此,在第 2 行中,它将读取 \n 并且不会等待用户输入字符。

好的,我明白了。但我的第一个问题是:为什么第二个 getchar() (ch2 = getchar();) 不读取 Enter 键 (13),而不是 \n 字符?

接下来,作者提出了两种方法来解决此类问题:

  1. 使用fflush()

  2. 编写这样的函数:

void
clear (void)
{
    while ( getchar() != '\n' );
}

这段代码确实有效。但我无法解释它是如何工作的。因为在while语句中,我们使用了getchar() != '\n',那就意味着读取除了'\n'之外的任何单个字符?如果是这样,'\n' 字符是否仍保留在输入缓冲区中?

最佳答案

The program will not work properly because at Line 1, when the user presses Enter, it will leave in the input buffer 2 character: Enter key (ASCII code 13) and \n (ASCII code 10). Therefore, at Line 2, it will read the \n and will not wait for the user to enter a character.

您在第 2 行看到的行为是正确的,但这并不是完全正确的解释。对于文本模式流,平台使用什么换行符(无论是回车符 (0x0D) + 换行符 (0x0A)、裸 CR 还是裸 LF)并不重要。 C 运行时库将为您处理这个问题:您的程序将仅看到 '\n' 换行符。

如果您键入一个字符并按 Enter 键,则该输入字符将在第 1 行读取,然后 '\n' 将在第 2 行读取。请参阅 I'm using scanf %c to read a Y/N response, but later input gets skipped.来自 comp.lang.c 常见问题解答。

至于建议的解决方案,请参阅(再次来自 comp.lang.c FAQ):

这基本上表明唯一可移植的方法是:

int c;
while ((c = getchar()) != '\n' && c != EOF) { }

您的 getchar() != '\n' 循环有效,因为一旦您调用 getchar(),返回的字符就已从输入流中删除。

此外,我觉得有义务阻止您完全使用 scanf:Why does everyone say not to use scanf? What should I use instead?

关于c - 如何清除 C 中的输入缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54764590/

相关文章:

java - 如何减少 System.out.println() 所花费的时间;

java - 从同一个 FileInputStream 中读取字符串和二进制文件

ios - 将自定义文本添加到 UITextField 缓冲区

c++ - stream::seekoff 是否更新输入序列?

c - 如何在C中使用特殊字符?

c - 我想以 DD/MM/YYYY 格式向用户询问日期,并且我想在 DD 或 MM 或 YYYY 之后自动插入 '/'

c - 更新多个进程使用的共享库中的全局变量

c - 如何以 C 标准方式进行位表示?

haskell - unsafeDupablePerformIO 和 accursedUnutterablePerformIO 有什么区别?

c - 使用 C 中的缓冲区和多线程从文本文件读取