C / CONSOLE INPUT AND OUTPUT
scanf and why it leaves input behind
Predict which characters scanf leaves in stdin, fix the stray-newline %c bug, and escape the retry loop a failed conversion causes.
What you will learn
- Predict exactly which byte scanf leaves in stdin after each conversion
- Use a leading space, as in " %c", to skip the newline a previous %d left behind
- Spot the infinite scanf loop caused by a byte that is never consumed
- Drain a bad line with a getchar loop to '\n' or EOF instead of fflush(stdin)
Understanding scanf and why it leaves input behind
stdin is a queue of bytes, not a sequence of answers. When you type 42 and press Enter, your program eventually sees three bytes: '4', '2', '\n'. scanf("%d", &n) moves forward only while the bytes can still belong to an integer, stops the moment one cannot, and advances the stream no further. The '\n' is not part of an integer, so it stays exactly where it was, first in line for whatever read comes next.
Which leftovers you notice depends on the conversion. %d, %u, %x, %f and %s all begin by skipping any run of whitespace, so a stray newline is invisible to them, which is why two consecutive %d reads work even though each one leaves a newline behind. %c, %[ and %n skip nothing: %c means give me the next byte, whatever it is, and that byte is the newline. A literal space in the format string is itself a directive meaning consume zero or more whitespace bytes here, which is the only difference between "%c" and " %c".
The second way scanf leaves input behind is matching failure. If the next byte cannot begin the requested conversion, scanf stops, returns the number of assignments it completed (0 if the very first one failed), and deliberately leaves the offending byte unread. Calling scanf again does not change the stream, so an identical call fails identically forever; you have to remove those bytes yourself, normally everything up to and including the next newline. Running out of input is a different case: then scanf returns EOF, and draining will not rescue you.
<stdio.h>
/* run it with the input piped so nothing is echoed back:
printf '42\nA\n' | ./demo */
int main(void)
{
int n;
char c;
int r1, r2;
r1 = scanf("%d", &n); /* reads '4' and '2', stops at the '\n' */
r2 = scanf("%c", &c); /* %c skips nothing, so it takes that '\n' */
printf("r1 = %d, n = %d\n", r1, n);
printf("r2 = %d, c = %d %s\n", r2, c,
c == '\n' ? "(newline)" : "(some other byte)");
return 0;
}
scanf consumes only the bytes that fit its conversions and stops at the first byte that does not, leaving that byte, usually the Enter newline, waiting for the next read.
Worked examples
The leading space fix
One space in front of %c consumes the newline that %d refused to take.
<stdio.h>
int main(void)
{
int n;
char c;
/* printf '42\nA\n' | ./demo */
scanf("%d", &n);
scanf(" %c", &c);
printf("n = %d, c = '%c'\n", n, c);
return 0;
}
Example explained
Line 1scanf("%d", &n) stores 42 and stops in front of the '\n', leaving it unread.
Line 2The space in " %c" is a directive that reads and discards a run of whitespace, so the '\n' disappears here.
Line 3%c then takes the first non-whitespace byte, 'A', and stores it as a single character with no terminator added.
Line 4Because a space matches blanks, tabs and newlines alike, the same code also works for input typed as 42 A on one line.
%s stops at whitespace and never eats it
Two %s reads pull two words out of one line, and the newline is still sitting there afterwards.
<stdio.h>
int main(void)
{
char a[16], b[16];
char tail;
/* printf 'Ada Lovelace\n' | ./demo */
scanf("%15s", a);
scanf("%15s", b);
scanf("%c", &tail);
printf("a = %s\n", a);
printf("b = %s\n", b);
printf("tail = %d\n", tail);
return 0;
}
Example explained
Line 1The first %15s stops at the space after Ada and does not store or consume it, so " Lovelace\n" is still queued.
Line 2The second %15s skips that leftover space by itself, because %s begins with whitespace skipping.
Line 3Nothing consumed the final newline, so %c reports 10, the code for '\n'.
Line 4The width 15 leaves room for the '\0' in a 16-byte array; a bare %s has no limit and would write past the end.
A failed conversion is not consumed
Three identical scanf calls on the text abc all fail on the same byte.
<stdio.h>
int main(void)
{
int n, r, i;
/* printf 'abc\n' | ./demo */
for (i = 1; i <= 3; i++) {
r = scanf("%d", &n);
printf("call %d returned %d\n", i, r);
}
return 0;
}
Example explained
Line 1Call 1 skips leading whitespace, finds 'a', which cannot start an integer, and stops before it: a matching failure with 0 assignments.
Line 2The 'a' is left in the stream, so the stream position is identical when call 2 starts.
Line 3Calls 2 and 3 therefore behave the same way; replacing the for loop with while (scanf("%d", &n) != 1) would print forever.
Line 4n is never assigned in any of the three calls, so only the return value carries usable information.
Drain the line, then retry
Discarding bytes up to the newline moves the stream forward so the next scanf can succeed.
<stdio.h>
static void skip_rest_of_line(void)
{
int ch;
while ((ch = getchar()) != '\n' && ch != EOF)
;
}
int main(void)
{
int n, r;
/* printf 'abc\n7\n' | ./demo */
while ((r = scanf("%d", &n)) != 1) {
if (r == EOF)
return 1;
printf("not an integer, dropping that line\n");
skip_rest_of_line();
}
printf("n = %d\n", n);
return 0;
}
Example explained
Line 1scanf returns 0 on the first pass, and at that moment 'a' is still the next unread byte.
Line 2skip_rest_of_line removes 'a', 'b', 'c' and the '\n', leaving the stream at the start of the next line.
Line 3ch is an int, not a char, so the EOF value cannot collide with a real character code.
Line 4The retry now reads '7', returns 1, and the loop ends; the EOF check stops the loop when the input simply ran out.
Important notes
Trailing whitespace in a format, as in scanf("%d\n", &n), tells scanf to keep skipping whitespace until it sees a non-whitespace byte, which at a terminal looks like the program hung after you pressed Enter.
while (getchar() != '\n') ; without an EOF test never ends when the input runs out without a final newline, because getchar keeps returning EOF.
Common mistakes
Writing scanf("%c", &reply) straight after scanf("%d", &count): reply becomes '\n' (10), so a y/n question is answered before the user types anything and the wrong branch runs.
Calling fflush(stdin) to clear leftovers: the C standard leaves flushing an input stream undefined, so depending on the library it discards data, does nothing, or fails, and the stray newline usually survives.
Retrying scanf after a return of 0 without draining: the unmatched byte is still first in the queue, so the prompt and the failure repeat forever at full CPU speed.
Try it yourself
Change, predict, then run
Write a program that reads an int with scanf("%d") and then a char with scanf("%c"), printing the char with %d; run it with the input 5 then Enter then k, then add a space before %c and run it again to watch the printed code change from 10 to 107.
Open the C workspaceCheck your understanding
A program calls scanf("%d", &n) in a loop, prints an error message whenever the return value is not 1, and retries. The input line is abc. Why does the loop never end?
- scanf returns EOF after the first failure, and EOF never compares equal to 1, so the test can never be satisfied
- The 'a' that caused the matching failure is left unread, so every retry starts at the same byte and fails the same way
- The newline from Enter satisfies %d and stores 0 into n each time, so the loop keeps getting a fresh but useless value
- scanf remembers the failed text internally and replays it until it is called with a different format string
Show answer
A matching failure stops the scan without consuming the offending byte, so the stream position is unchanged and the identical call produces the identical result until you drain the line yourself. The newline option is tempting because the newline is the usual leftover, but %d skips whitespace rather than converting it, so scanf never even reaches the newline here: it stops at 'a' and returns 0, not EOF.