问题
I have this code
while(1){
printf("hello world !\n");
fgetc(stdin);
}
when this runs and I enter a letter like this:
hello world !
a
it ignores the fgetc(stdin) in the next loop and prints hello world twice without waiting for input.
hello world !
a
hello world !
hello world !
a
hello world !
hello world !
a
hello world !
hello world !
a
hello world !
hello world !
I have tried putting fflush(stdin) before or after the fgetc(stdin) but it still produces the same behaviour, what am I doing wrong ?
回答1:
Terminals tend to be line-buffered, meaning that stream contents are accessible on a line-by-line basis.
So, when fgetc
starts reading from STDIN, it's reading a full line, which includes the newline character that ended that line. That's the second character you're reading.
As for fflush
, that's for flushing output buffers, not input buffers.
So, what you want to do here is to purge the input buffer by reading from it until its empty, or just explicitly ignore newline characters.
回答2:
That's because you actually enter two characters: 'a' and a newline. Also, since terminal is normally line-buffered your program will only see your input once you hit the newline. It'll be informative to enter a longer line of text, too.
If you want to change this behavior you have two options: reading entire lines (i.e. all characters up to a newline or end-of-file) or switching terminal to non-canonical mode. The latter makes sense if you're working on an interactive terminal application like a text editor. See termios manpage for details. In short, you'll want to set MIN and TIME options to zero to make reads from terminal return immediately as data becomes available. If you do go down this path, make sure you switch the terminal back when you exit, including due to reception of a signal.
fflush()
affects the output, not the input.
回答3:
There are two characters: a
and \n
(newline). Your loop reads reads the a
, then loops and prints "hello world !". It then sees \n
and loops and prints "hello world !". When you type a
+\n
in the terminal, it's storing the two characters in the stdin buffer. fgetc(stdin);
will read from the stdin buffer if there is a char available, otherwise it waits until a char is added to the buffer.
Since terminals are line-buffered (ie, do not send the content to the program until a newline is reached) you have a few options:
- read the entire line into a buffer, but take only the first character
- ignore newlines
- turn off line-buffering
To turn off line buffering, look at http://c-faq.com/osdep/cbreak.html and http://www.flipcode.com/archives/_kbhit_for_Linux.shtml and http://ubuntuforums.org/showthread.php?t=225713 (although I have not tested any of the code here).
回答4:
You have two characters there, 'a'
and '\n'
. That is the problem, because fgetc will only read ONE character. This is the documentation.
If you enter only a '\n'
- hit enter only - you will have the expected behaviour.
Hope it helps!
来源:https://stackoverflow.com/questions/12063879/fgetcstdin-in-a-loop-is-producing-strange-behaviour