为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C++ C
慕田峪4524236 2019-06-05 15:54:44
我有以下节目: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 key (ASCII code 13)和\n (ASCII code 10)..因此,在第2行,它将读取\n并且不会等待用户输入字符。好的,我来处理。但我的第一个问题是:为什么第二个getchar() (ch2 = getchar();)不读取Enter key (13),而不是\n角色?接下来,作者提出了解决这类问题的两种方法:使用fflush()编写如下函数:voidclear (void){       while ( getchar() != '\n' );}这个代码实际上起作用了。但我无法解释它是如何工作的?因为在while语句中,我们使用getchar() != '\n',这意味着读取除'\n'?如果是,则在输入缓冲区中仍然保留'\n'角色?
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

程序将无法正常工作,因为在第1行,当用户按Enter时,它将留在输入缓冲区2字符中:Enter键(ASCII代码13)和\n(ASCII代码10)。因此,在第2行,它将读取\n,而不会等待用户输入字符。

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

如果键入一个字符并按Enter键,则该输入字符将按第1行读取,然后'\n'将由第2行读取。看见我在用scanf %c读取Y/N响应,但稍后将跳过输入。

至于拟议的解决办法,见(同样来自于comp.lang.c FAQ):

  • 如何才能刷新挂起的输入,这样用户的打字机就不会在下一个提示符中读取?将要fflush(stdin)工作?

  • 如果fflush不会工作,我能用什么来冲洗输入?

从根本上说,唯一的可移植方法是:

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

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

另外,我觉得有义务劝阻你不要使用scanf完全:为什么每个人都说不要用scanf?我应该用什么代替?


查看完整回答
反对 回复 2019-06-05
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

你也可以这样做:

fseek(stdin,0,SEEK_END);


查看完整回答
反对 回复 2019-06-05
?
心有法竹

TA贡献1866条经验 获得超5个赞

台词:

int ch;while ((ch = getchar()) != '\n' && ch != EOF)
    ;

不会只读取行提要之前的字符('\n')。它读取流中的所有字符(并丢弃它们)。直至并包括下一个行提要(或者遇到EOF)。要使测试为真,它必须先读取行提要;因此,当循环停止时,linefeed是最后读取的字符,但它已被读取。

至于为什么它读取行提要而不是回车,这是因为系统已经将返回转换为linefeed。当按下Enter键时,这意味着线路的结束.但是流包含一个行提要,因为这是系统的正常行尾标记。这可能与平台有关。

此外,使用fflush()在输入流上,并不是所有的平台都能工作;例如,它通常不能在Linux上工作。


查看完整回答
反对 回复 2019-06-05
  • 3 回答
  • 0 关注
  • 659 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信