scanf() leaves the newline character in the buffer

I have the following program:

int main(int argc, char *argv[])
{
  int a, b;
  char c1, c2;
  printf("Enter something: ");
  scanf("%d",&a); // line 1
  printf("Enter other something: ");
  scanf("%d", &b); // line 2

  printf("Enter a char: ");
  scanf("%c",&c1); // line 3
  printf("Enter another char: ");
  scanf("%c", &c2); // line 4

  printf("Done"); // line 5

  system("PAUSE");

  return 0;
}

As I read in the C book, the author says that scanf() left a newline character in the buffer, therefore, the program does not stop at line 4 for user to enter the data, rather it stores the new line character in c2 and moves to line 5.

Is that right?

However, does this only happen with char data types? Because I did not see this problem with int data types as in line 1, 2, 3. Is it right?


Solution 1:

The scanf() function skips leading whitespace automatically before trying to parse conversions other than characters. The character formats (primarily %c; also scan sets %[…] — and %n) are the exception; they don't skip whitespace.

Use " %c" with a leading blank to skip optional white space. Do not use a trailing blank in a scanf() format string.

Note that this still doesn't consume any trailing whitespace left in the input stream, not even to the end of a line, so beware of that if also using getchar() or fgets() on the same input stream. We're just getting scanf to skip over whitespace before conversions, like it does for %d and other non-character conversions.


Note that non-whitespace "directives" (to use POSIX scanf terminology) other than conversions, like the literal text in scanf("order = %d", &order); doesn't skip whitespace either. The literal order has to match the next character to be read.

So you probably want " order = %d" there if you want to skip a newline from the previous line but still require a literal match on a fixed string, like this question.

Solution 2:

Use scanf(" %c", &c2);. This will solve your problem.