如何清除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
字符?
其次,笔者提出了两种解决这些问题的方法:
-
使用
fflush()
-
写一个这样的函数:
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,它也检查EOF
。 c
的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) { }
有点贵,所以不要在需要重复清除缓冲区的程序中使用它。
偷来自同事:)