ciobufferstdinflush

How can I clear an input buffer in C?


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 has explained: The program will not work properly because at Line 1 when the user presses Enter, it will leave in the input buffer 2 characters: the Enter key (ASCII code 13) and \n (ASCII code 10). Therefore, in Line 2, it will read the \n and will not wait for the user to enter a character.

OK, I got this. But my first question is: Why doesn't the second getchar() (ch2 = getchar();) read the Enter key (13), rather than the \n character?

Next, the author proposed two ways to solve such problems:

  1. use fflush()

  2. write a function like this:

void
clear (void)
{
    while ( getchar() != '\n' );
}

This code worked actually. But I cannot explain how it works. Because in the while statement, we use getchar() != '\n', that means read any single character except '\n'? If so, does the '\n' character still remain in the input buffer?


Solution

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

    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.

    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 %c to read a Y/N response, but later input gets skipped. from the comp.lang.c FAQ.

    As for the proposed solutions, see (again from the comp.lang.c FAQ):

    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.

    Also, I feel obligated to discourage you from using scanf entirely: Why does everyone say not to use scanf? What should I use instead?