As @MFisherKDX says, check the return value of scanf
. From the scanf man page:
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in
the event of an early matching failure.
The value EOF is returned if the end of input is reached before either
the first successful conversion or a matching failure occurs. EOF is
also returned if a read error occurs, in which case the error
indicator for the stream (see ferror(3)) is set, and errno is set
indicate the error.
So capturing the return value of scanf
in an int
variable and then comparing that variable to 1
(in your case, because you are only attempting to read 1 item) should tell you if scanf
successfully read an integer value.
However, there is a nasty pitfall when using scanf
that you should be aware of. If you do type n
at the prompt, scanf
will fail and return 0
, but it will also not consume the input you typed. Which means that the next time you call scanf
, it will read the same input (the n
character you typed), and fail again. And it will keep doing so no matter how many times you call scanf
. It always amazes me that computer science educators continue to teach scanf
to students, given not only this potential pitfall, but several other pitfalls as well. I wish I had a nickel for every hour that some CS student somewhere has spent struggling to get scanf
to behave the way their intuition tells them it should. I'd be retired on my own private island by now. But I digress.
One way around this particular pitfall is to check if scanf
failed, and if so, to purposely consume and discard all input from stdin
up to and including the next newline character or EOF
, whichever comes first.
First let's look at some unfixed code that causes an infinite loop if you enter a non-integer as input:
// Typing the letter 'n' and hitting <Enter> here causes an infinite loop:
int num, status;
while (1) {
printf("Enter a number: ");
status = scanf("%d", &num);
if (status == 1)
printf("OK\n");
else
printf("Invalid number\n");
}
The above code will (after you type n
and hit <Enter>
), will enter an infinite loop, and just start spewing "Invalid number" over and over. Again, this is because the n
you entered never gets cleared out of the input buffer.
There are a few possible ways to get around this problem, but the consensus seems to be that the most portable and reliable way to do so is as follows:
// Fixed. No more infinite loop.
int num, status;
while (1) {
printf("Enter a number: ");
status = scanf("%d", &num);
if (status == 1)
printf("OK\n");
else {
printf("Invalid number\n");
// Consume the bad input, so it doesn't keep getting re-read by scanf
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) ;
if (ch == EOF) break;
}
}