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/53884555/

相关文章:

Java缓冲区和流: Releasing underlying resources

c - 在这种情况下,fflush 有什么用?

c - 复位 vector 在现代处理器中的意义

c - JNI 库中 OS/X 上的指针截断为 'realloc()'

c - 为什么 "*(&arr+4)"与 "&arr[4]"不同?

c++ - 打印存储在 C 字符串中的字符的 ASCII 代码 - 需要解释

c - 以字节为单位读取文件中的可打印 ASCII 字符

c - 在 C 程序中使用 arg[v] 命令行参数

c++ - `ios_base::app` 是否保证 `ios_base::out` 被隐式指定?

linux - 间歇性二进制数据的实时监控