How is the “getchar()” function able to take multiple characters as input?

▼魔方 西西 提交于 2019-12-04 08:46:10

问题


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:

  1. You call getchar(). No input is available, so it waits.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. You press Enter. Now it is the end of a line, so the input "abcde\n" is sent to your program.

  8. getchar() now has input to read, so it returns 'a', increments nc, and loops back to wait for input.

  9. Immediately, getchar() has more input to read from the rest of the characters in that line, so it returns 'b', increments nc, and loops back to wait for input.

  10. Immediately, getchar() has more input to read from the rest of the characters in that line, so it returns 'c', increments nc, and loops back to wait for input.

  11. Immediately, getchar() has more input to read from the rest of the characters in that line, so it returns 'd', increments nc, and loops back to wait for input.

  12. Immediately, getchar() has more input to read from the rest of the characters in that line, so it returns 'e', increments nc, and loops back to wait for input.

  13. Immediately, getchar() has more input to read from the rest of the characters in that line, so it returns '\n', increments nc, and loops back to wait for input.

  14. 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 returns EOF and your loop ends. If it were not end-of-input, then getchar() 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!