如何清除C中的input缓冲区?

我有以下程序:

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键时,它将在input缓冲区中留下2个字符: Enter key (ASCII code 13)\n (ASCII code 10) 。 因此,在第2行,它将读取\n并且不会等待用户input字符。

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

其次,笔者提出了两种解决这些问题的方法:

  1. 使用fflush()

  2. 写一个这样的函数:

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

这个代码实际上工作。 但我无法解释自己是如何工作的? 因为在while语句中,我们使用getchar() != '\n' ,这意味着读取除'\n'之外'\n'任何单个字符? 如果是这样,在input缓冲区仍然是'\n'字符?

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

你在第2行看到的行为是正确的,但这不是正确的解释。 对于文本模式stream,无论您的平台使用什么行结束符(无论是回车(0x0D)+换行符(0x0A),裸CR还是裸LF)都无关紧要。 C运行时库将为您处理:您的程序将只看到换行符'\n'

如果你input一个字符并按回车,那么这个input字符将被第1行读取,然后'\n'将被第2行读取。请参阅我使用scanf %c来读取Y / N响应,但是稍后的input会被跳过。 从comp.lang.c FAQ。

至于提出的解决scheme,请参阅(同样来自comp.lang.c FAQ):

  • 如何刷新未决input,以便在下次提示时不读取用户的键入命令? fflush(stdin)工作吗?
  • 如果fflush不起作用,我可以使用什么来刷新input?

基本上说,唯一的便携方法是做:

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

你的getchar() != '\n'循环可以工作,因为一旦你调用了getchar() ,返回的字符已经被从inputstream中删除了。

另外,我觉得有义务阻止你完全使用scanf : 为什么大家都说不要使用scanf ? 我应该用什么来代替?

你也可以(也)这样做:

 fseek(stdin,0,SEEK_END); 

清除已经尝试部分读取的行的便捷方式是:

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

这读取和放弃字符,直到它获得\n这标志着文件的结尾。 如果inputstream在行结束之前被closures,它也检查EOFc的types必须是int (或更大)才能保存值EOF

没有可移植的方法来查看当前行之后是否有更多行(如果没有,则getchar将阻止input)。

线路:

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

不会只读取换行之前的字符( '\n' )。 它读取stream中的所有字符(并放弃它们) 直到包括下一个换行符(或遇到EOF)。 为了testing是真的,它必须先阅读换行。 所以当循环停止时,换行是最后读取的字符,但是它已经被读取。

至于为什么它读取换行而不是回车,这是因为系统已将换行转换为换行符。 当input被按下时,这表示行结束,但是stream包含行换行,因为这是系统的正常行尾标记。 这可能是平台依赖。

此外,在inputstream上使用fflush()不适用于所有平台; 例如,它通常不在Linux上工作。

但我无法解释自己是如何工作的? 因为在while语句中,我们使用getchar() != '\n' ,这意味着读取除'\n'之外'\n'任何单个字符? 如果是这样,在input缓冲区仍然是'\n'字符? 我误解了什么?

你可能没有意识到的是,比较发生 getchar()从input缓冲区中移除字符之后 。 所以当你到达'\n' ,它被消耗, 然后你跳出循环。

你可以试试

 scanf("%c%*c", &ch1); 

其中%* c接受并忽略换行符

一个方法,而不是fflush(标准input)调用未定义的行为,你可以写

 while((getchar())!='\n'); 

while循环之后不要忘记分号

 unsigned char a=0; if(kbhit()){ a=getch(); while(kbhit()) getch(); } cout<<hex<<(static_cast<unsigned int:->(a) & 0xFF)<<endl; 

-要么-

使用也许使用_getch_nolock() ..?

我遇到了尝试实施解决scheme的问题

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

对于任何可能有同样问题的人,我都会稍微调整一下“代码B”。

问题是,程序让我捕捉到'\ n'字符,独立于input字符,这里是代码给我的问题。

代码A

 int y; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ continue; } printf("\n%c\n", toupper(y)); 

并且调整就是在评估while循环的条件之前“捕捉”(n-1)字符,这里是代码:

代码B

 int y, x; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ x = y; } printf("\n%c\n", toupper(x)); 

可能的解释是,while循环中断时,必须将值'\ n'赋值给variablesy,所以它将成为最后一个赋值。

如果我错过了解释,代码A或代码B请告诉我,我几乎没有新的C。

希望它可以帮助别人

简短,可移植并在stdio.h中声明

 stdin = freopen(NULL,"r",stdin); 

在标准input中没有任何东西需要刷新时,不会在无限循环中挂起:

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

有点贵,所以不要在需要重复清除缓冲区的程序中使用它。

偷来自同事:)