C语言 如何清除C中的输入缓冲区?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7898215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to clear input buffer in C?
提问by ipkiss
I have the following program:
我有以下程序:
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;
}
As the author of the above code have explained:
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 \nand will not wait for the user to enter a character.
正如上面代码的作者所解释的:程序将无法正常运行,因为在第 1 行,当用户按下 Enter 键时,它会在输入缓冲区中留下 2 个字符:Enter key (ASCII code 13)和\n (ASCII code 10)。因此,在第 2 行,它将读取\n并且不会等待用户输入字符。
OK, I got this. But my first question is: Why the second getchar()(ch2 = getchar();) does not read the Enter key (13), rather than \ncharacter?
好的,我明白了。但我的第一个问题是:为什么第二个getchar()( ch2 = getchar();) 不读取Enter key (13), 而不是\n字符?
Next, the author proposed 2 ways to solve such probrems:
接下来,作者提出了2种方法来解决此类问题:
use
fflush()write a function like this:
void clear (void) { while ( getchar() != '\n' ); }
用
fflush()写一个这样的函数:
void clear (void) { while ( getchar() != '\n' ); }
This code worked actually. But I cannot explain myself how it works? Because in the while statement, we use getchar() != '\n', that means read any single character except '\n'? if so, in the input buffer still remains the '\n'character?
这段代码实际上有效。但我无法解释它是如何工作的?因为在 while 语句中,我们使用getchar() != '\n',这意味着读取任何单个字符,除了'\n'? 如果是这样,在输入缓冲区中仍然保留'\n'字符吗?
回答by jamesdlin
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.
程序将无法正常运行,因为在第 1 行,当用户按下 Enter 键时,它会在输入缓冲区中留下 2 个字符:Enter 键(ASCII 代码 13)和 \n(ASCII 代码 10)。因此,在第 2 行,它将读取 \n 并且不会等待用户输入字符。
The behavior you see at line 2 is correct, but that's not quite the correct explanation. With text-mode streams, it doesn't matter what line-endings your platform uses (whether carriage return (0x0D) + linefeed (0x0A), a bare CR, or a bare LF). The C runtime library will take care of that for you: your program will see just '\n'for newlines.
您在第 2 行看到的行为是正确的,但这并不是正确的解释。对于文本模式流,您的平台使用什么行尾(无论是回车 (0x0D) + 换行符 (0x0A)、裸 CR 还是裸 LF)都无关紧要。C 运行时库将为您处理这些:您的程序将只看到'\n'换行符。
If you typed a character and pressed enter, then that input character would be read by line 1, and then '\n'would be read by line 2. See I'm using scanf %cto read a Y/N response, but later input gets skipped.from the comp.lang.c FAQ.
如果您键入一个字符并按 Enter,那么该输入字符将被第 1 行读取,然后'\n'将被第 2 行读取。请参阅我正在使用scanf %c读取 Y/N 响应,但稍后的输入被跳过。来自 comp.lang.c 常见问题解答。
As for the proposed solutions, see (again from the comp.lang.c FAQ):
至于建议的解决方案,请参见(再次来自 comp.lang.c FAQ):
- How can I flush pending input so that a user's typeahead isn't read at the next prompt? Will
fflush(stdin)work? - If
fflushwon't work, what can I use to flush input?
which basically state that the only portable approach is to do:
它基本上说明唯一可移植的方法是:
int c;
while ((c = getchar()) != '\n' && c != EOF) { }
Your getchar() != '\n'loop works because once you call getchar(), the returned character already has been removed from the input stream.
您的getchar() != '\n'循环有效,因为一旦您调用getchar(),返回的字符已从输入流中删除。
Also, I feel obligated to discourage you from using scanfentirely: Why does everyone say not to use scanf? What should I use instead?
另外,我觉得有义务劝阻你scanf完全不要使用:为什么每个人都说不要使用scanf?我应该用什么代替?
回答by Ramy Al Zuhouri
You can do it (also) this way:
你可以(也)这样做:
fseek(stdin,0,SEEK_END);
回答by M.M
A portable way to clear up to the end of a line that you've already tried to read partially is:
一种清除您已经尝试部分阅读的行尾的便携式方法是:
int c;
while ( (c = getchar()) != '\n' && c != EOF ) { }
This reads and discards characters until it gets \nwhich signals the end of the file. It also checks against EOFin case the input stream gets closed before the end of the line. The type of cmust be int(or larger) in order to be able to hold the value EOF.
这会读取并丢弃字符,直到它得到\n表示文件结束的信号。它还检查EOF输入流在行尾之前关闭的情况。的类型c必须是int(或更大的)才能保存值EOF。
There is no portable way to find out if there are any more lines after the current line (if there aren't, then getcharwill block for input).
没有可移植的方法来确定当前行之后是否还有其他行(如果没有,getchar则将阻止输入)。
回答by Dmitri
The lines:
线路:
int ch;
while ((ch = getchar()) != '\n' && ch != EOF)
;
doesn't read only the characters before the linefeed ('\n'). It reads all the characters in the stream (and discards them) up to and includingthe next linefeed (or EOF is encountered). For the test to be true, it has to read the linefeed first; so when the loop stops, the linefeed was the last character read, but it has been read.
不只读取换行符 ( '\n')之前的字符。它读取流中的所有字符(并丢弃它们)直到并包括下一个换行符(或遇到 EOF)。要使测试为真,它必须先读取换行符;所以当循环停止时,换行是最后一个读取的字符,但它已经被读取了。
As for why it reads a linefeed instead of a carriage return, that's because the system has translated the return to a linefeed. When enter is pressed, that signals the end of the line... but the stream contains a line feed instead since that's the normal end-of-line marker for the system. That might be platform dependent.
至于为什么它读取的是换行而不是回车,那是因为系统已经将回车翻译成了换行。当按下 enter 时,这表示行的结束......但流包含换行符,因为这是系统的正常行尾标记。这可能取决于平台。
Also, using fflush()on an input stream doesn't work on all platforms; for example it doesn't generally work on Linux.
此外,fflush()在输入流上使用并不适用于所有平台;例如,它通常不适用于 Linux。
回答by zwol
But I cannot explain myself how it works? Because in the while statement, we use
getchar() != '\n', that means read any single character except'\n'?? if so, in the input buffer still remains the'\n'character??? Am I misunderstanding something??
但我无法解释它是如何工作的?因为在 while 语句中,我们使用
getchar() != '\n',这意味着读取除'\n'??之外的任何单个字符。如果是这样,在输入缓冲区中仍然保留'\n'字符???我是不是误会了什么??
The thing you may not realize is that the comparison happens aftergetchar()removes the character from the input buffer. So when you reach the '\n', it is consumed and thenyou break out of the loop.
您可能没有意识到比较发生在getchar()从输入缓冲区中删除字符之后。因此,当您到达 时'\n',它会被消耗,然后您会跳出循环。
回答by kapil
you can try
你可以试试
scanf("%c%*c", &ch1);
where %*c accepts and ignores the newline
其中 %*c 接受并忽略换行符
one more method instead of fflush(stdin) which invokes undefined behaviour you can write
另一种方法而不是 fflush(stdin) 调用您可以编写的未定义行为
while((getchar())!='\n');
don't forget the semicolon after while loop
不要忘记while循环后的分号
回答by antadlp
I encounter a problem trying to implement the solution
我在尝试实施解决方案时遇到问题
while ((c = getchar()) != '\n' && c != EOF) { }
I post a little adjustment 'Code B' for anyone who maybe have the same problem.
我为可能有同样问题的任何人发布了一些调整“代码 B”。
The problem was that the program kept me catching the '\n' character, independently from the enter character, here is the code that gave me the problem.
问题是程序让我抓住了 '\n' 字符,独立于输入字符,这是给我带来问题的代码。
Code A
代码 A
int y;
printf("\nGive any alphabetic character in lowercase: ");
while( (y = getchar()) != '\n' && y != EOF){
continue;
}
printf("\n%c\n", toupper(y));
and the adjustment was to 'catch' the (n-1) character just before the conditional in the while loop be evaluated, here is the code:
并且调整是在评估while循环中的条件之前“捕获”(n-1)字符,这是代码:
Code B
代码 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));
The possible explanation is that for the while loop to break, it has to assign the value '\n' to the variable y, so it will be the last assigned value.
可能的解释是,要中断 while 循环,它必须将值 '\n' 分配给变量 y,因此它将是最后分配的值。
If I missed something with the explanation, code A or code B please tell me, I'm barely new in c.
如果我在解释、代码 A 或代码 B 中遗漏了某些内容,请告诉我,我对 c 几乎不陌生。
hope it helps someone
希望它可以帮助某人
回答by Michael Grieswald
unsigned char a=0;
if(kbhit()){
a=getch();
while(kbhit())
getch();
}
cout<<hex<<(static_cast<unsigned int:->(a) & 0xFF)<<endl;
-or-
-或者-
use maybe use _getch_nolock()..???
使用也许使用_getch_nolock()..???
回答by James Blue
Another solution not mentioned yet is to use: rewind(stdin);
另一个尚未提及的解决方案是使用:rewind(stdin);
回答by Jason Enochs
Short, portable and declared in stdio.h
简短、可移植并在 stdio.h 中声明
stdin = freopen(NULL,"r",stdin);
Doesn't get hung in an infinite loop when there is nothing on stdin to flush like the following well know line:
当 stdin 上没有任何东西要刷新时,不会陷入无限循环,如下面众所周知的行:
while ((c = getchar()) != '\n' && c != EOF) { }
A little expensive so don't use it in a program that needs to repeatedly clear the buffer.
有点贵所以不要在需要重复清除缓冲区的程序中使用它。
Stole from a coworker :)
从同事那里偷的:)

