How to properly flush stdin in fgets loop

There is unfortunately a lot of confusion about “flushing input” in C. The confusion arises almost entirely from one of the strange facts about the popular-but-flawed scanf function: it generally does not read full lines of input, and it generally leaves the newline character \n on the input stream after it converts its input. For example, if you write a program that says

printf("Type a number:\n");
scanf("%d", &n);

and if the user types “123” and hits the Return key, the number 123 will get stored into the variable n, but the \n character corresponding to the Return key will be left on the input stream. If the next thing your program does is to call fgets, or getchar, imagining that you’ll begin reading the next line of input the user typed, your program will instead immediately read that leftover newline. It will seem as if the user typed an extra blank line, or something.

This problem is ridiculously widespread. Vast numbers of beginning C programmers have gotten stuck on it. In a nutshell, there are three recommended ways of fixing it:

  1. After calling a function like scanf that leaves the newline in the input buffer, and before calling a function like getchar or fgets that expects to start on a new line, use the little loop while((c = getchar()) != '\n' && c != EOF) to read and discard the newline that scanf left on the input buffer.

  2. Don’t use scanf at all, or if you do, don’t try to mix it with calls to getchar or fgets.

  3. (popular but badly problematic) Call fflush(stdin) to flush the unwanted input.

The problems with #3 have been widely discussed, so I won’t say any more about those problems or that solution. The recommended “portable” alternative is #1, but it obviously works only if there is at least one unwanted newline in the input waiting to be flushed. If not, solution #1 will wrongly read and discard a line of wanted input, instead.

So you can’t use #1 everywhere. You can’t sprinkle it randomly in your program; you can’t use it everywhere you might have used fflush(stdin). In general, as mentioned already, you’ll need it only after calling scanf and before calling getchar or fgets.

In the code fragment in the question, there may not have been a need to use solution #1 at all. The fgets function is perfectly capable of cleanly reading individual lines of input all by itself. No additional flushing of input or discarding of newlines is necessarily required. (If there was a call to scanf down underneath do_something(), however, additional newline handling might have been necessary.)

Leave a Comment