Search code examples
cinputinputstreamgetchar

getchar() function in C: why it won't print a character right after I use getchar?


I am just a beginner in programming. And I am learning the K&R's book, the C Programming Language. While I am reading, I become more and more curious about this question -- when there is a loop to get characters one by one from the input and I put an outputing function in the loop, whose result I thought would be like print each character right after it had been entered. However, the result seems like the computer will only print out a whole package of characters after I tap a key.

Such as the answer of exercise 1-22 from K&R's book:

/* K&R Exercise 1-22 p.34 
 *
 * Write a program to "fold" long input lines into two or more
 * shorter lines after the last non-blank character that occurs before the n-th
 * column of input.  Make sure your program does something intelligent with very
 * long lines, and if there are no blanks or tabs before the specified column.
 */

#include <stdio.h>

#define LINE_LENGTH 80
#define TAB '\t'
#define SPACE ' '
#define NEWLINE '\n'

void entab(int);

int main()
{
    int i, j, c;
    int n = -1;     /* The last column with a space. */
    char buff[LINE_LENGTH + 1];

    for ( i=0; (c = getchar()) != EOF; ++i )
    {
        /* Save the SPACE to the buffer. */
        if ( c == SPACE )
        {
            buff[i] = c;
        }
        /* Save the character to the buffer and note its position. */ 
        else
        {
            n = i;
            buff[i] = c;
        }

        /* Print the line and reset counts if a NEWLINE is encountered. */
        if ( c == NEWLINE )
        {
            buff[i+1] = '\0';
            printf("%s", buff);

            n = -1;
            i = -1;
        }
        /* If the LINE_LENGTH was reached instead, then print up to the last
         * non-space character. */
        else if ( i == LINE_LENGTH - 1 )
        {
            buff[n+1] = '\0';
            printf("%s\n", buff);

            n = -1;
            i = -1;
        }
    }
}

I supposed the program would turn out to be like, it would print out only one line of characters, whose length is 80, right after I entered just 80 characters (and I haven't tapped an ENTER key yet). However, it doesn't show up that way! I can totally enter the whole string no matter how many characters there are. When I finally decide to finish the line, I just tap ENTER key, and it will give me the right outputs: the long string is cut into several short pieces/lines, which have 80 characters (and of course the last one may contain less than 80 characters).

I wonder WHY does that happened?


Solution

  • Usually (and in your case), stdin is line-buffered, so your programme doesn't receive the characters as they are typed, but in chunks, when the user enters a newline (Return), or, possibly, when the system buffer is full.

    So when the user input is finally sent to your programme, it is copied into the programme's input buffer. That's where getchar() reads the characters from to fill buff.

    If the input is long enough, buff will be filled with LINE_LENGTH characters from the input buffer and then printed several times (until the entire contents of the input buffer have been consumed).

    On Linux (methinks generally on Unix-ish systems, but I'm not sure), you can also send the input to the programme without entering a newline by typing Ctrl+D on a non-empty line (as the first input on a line, that closes stdin; at a later point in an input line, you can close stdin by typing it twice), so if you type Ctrl+D after entering LINE_LENGTH [or more] characters without a newline, [at least the initial part of] the input is printed immediately then.