问题
Here is a basic character counting program in C:
#include <stdio.h>
#include <stdlib.h>
int main(){
long nc = 0;
while(getchar() != EOF)
nc++;
printf("%ld\n" , nc);
}
When I am entering "abcde" as an input, it displays a value of 6(after triggering the EOF test), +1 for the newline character. But my doubt is that getchar()
, as its name itself suggests, takes only 1 character into account. But when I am entering "abcde" at one go itself, it still works. Why is this so? What problem am I doing here?
回答1:
Standard input, by default, is line-buffered with an interactive device. This means that your program won't see any input at all until a complete line is ready, in your case when you hit Enter. One good reason for this is that if the user types her 8 character password, then hits backspace 8 times, and then types her username and hits Enter, then your program only gets her username, and never sees the correction, which is usually what you want when your shell gives the opportunity to edit your input before you send it anywhere.
So what happens is essentially this:
You call
getchar()
. No input is available, so it waits.You press a. It's not the end of a line, so no input is sent to your program,
getchar()
has nothing to read, so it still waits.You press b. It's not the end of a line, so no input is sent to your program,
getchar()
has nothing to read, so it still waits.You press c. It's not the end of a line, so no input is sent to your program,
getchar()
has nothing to read, so it still waits.You press d. It's not the end of a line, so no input is sent to your program,
getchar()
has nothing to read, so it still waits.You press e. It's not the end of a line, so no input is sent to your program,
getchar()
has nothing to read, so it still waits.You press Enter. Now it is the end of a line, so the input
"abcde\n"
is sent to your program.getchar()
now has input to read, so it returns'a'
, incrementsnc
, and loops back to wait for input.Immediately,
getchar()
has more input to read from the rest of the characters in that line, so it returns'b'
, incrementsnc
, and loops back to wait for input.Immediately,
getchar()
has more input to read from the rest of the characters in that line, so it returns'c'
, incrementsnc
, and loops back to wait for input.Immediately,
getchar()
has more input to read from the rest of the characters in that line, so it returns'd'
, incrementsnc
, and loops back to wait for input.Immediately,
getchar()
has more input to read from the rest of the characters in that line, so it returns'e'
, incrementsnc
, and loops back to wait for input.Immediately,
getchar()
has more input to read from the rest of the characters in that line, so it returns'\n'
, incrementsnc
, and loops back to wait for input.If you signified end-of-input, perhaps by pressing Control-D, then
getchar()
has nothing to read and knows there will never be anything to read, so it returnsEOF
and your loop ends. If it were not end-of-input, thengetchar()
would just again wait here for you to enter a new line of input.
So what actually happened here is that getchar()
did nothing until you hit Enter. Then, probably before you even took your finger off the Enter key, it ran six times and consumed the six characters of input that you typed. But despite getchar()
running six times, you were only prompted to enter something once (twice, if you include having to type Control-D), because getchar()
will only wait for your input when it doesn't already have input available and waiting.
Back in the days where standalone terminals were common, the actual terminal device might not even transmit any characters to the computer until the end of a line, and could have a small amount of on-board memory to allow for this kind of local line-based editing, so the computer itself might literally never see it until end-of-line. On the kind of modern PC many people use, the operating system, down at the terminal driver level, will more probably be buffering these characters itself, and just presenting them and making them available to your program one line at a time (unless you specifically tell it that you want characters immediately, of course).
回答2:
When you type in abcde\n
(\n
generated from Enter), it gets flushed into the standard input stream (stdin
).
getchar()
, as its name itself suggests, takes only 1 character into account
Yes, that's right. But notice that getchar
is used in a loop which loops until getchar
returns EOF
. Also, recall that getchar
reads input from the stdin
.
So, in the first iteration, after you type in the data, getchar
reads the first character a
. In the second iteration, it doesn't wait for input since the stdin
still contains bcde\n
and hence, reads the next character b
and so on.
Finally, the loop breaks when you trigger EOF
. Then, the printf
gets executed (printing 6
since six characters were read) and the program ends.
回答3:
getchar
reads next characters from standard input's buffer, and returns it, since you feed six characters - "abcde\n" - into the standard input, and you are calling getchar
in a while loop, that means the loop body was run for six times, it read the chars one by one. You can test this by:
int c;
while ((c = getchar()) != EOF) {
printf("got %c\n", c);
nc++;
}
来源:https://stackoverflow.com/questions/37100201/how-is-the-getchar-function-able-to-take-multiple-characters-as-input