Q: I figured I could use scanf more safely if I checked its return value to make sure that the user typed the numeric values I expect:
int n; while(1) { printf("enter a number: "); if(scanf("%d", &n) == 1) break; printf("try again: "); } printf("you typed %d\n", n);but sometimes it seems to go into an infinite loop. [footnote] Why?
A: When scanf is attempting to convert numbers, any non-numeric characters it encounters terminate the conversion and are left on the input stream. Therefore, unless some other steps are taken, unexpected non-numeric input ``jams'' scanf again and again: scanf never gets past the bad character(s) to encounter later, valid data. If the user types a character like `x' in response to the code above, the code will loop printing ``try again'' forever, but it won't give the user a chance to try.
You may be wondering why scanf leaves unmatchable characters on the input stream. Suppose you had a compact data file containing lines consisting of a number and an alphabetic code string, without intervening whitespace, like
123CODEYou might want to parse this data file with scanf, using the format string "%d%s". But if the %d conversion did not leave the unmatched character on the input stream, %s would incorrectly read "ODE" instead of "CODE". (The problem is a standard one in lexical analysis: when scanning an arbitrary-length numeric constant or alphanumeric identifier, you never know where it ends until you've read ``too far.'' This is one reason that ungetc exists.)
See also question 12.20.
References:
ISO Sec. 7.9.6.2
H&S Sec. 15.8 pp. 357-64