Well, this is one very misinformed thread!
I'll comment on scanf since I think it's an awful function. Scanf expects data of the correct type. If you enter in the wrong data then it fails to work. Now you can catch this by catching the return code, scanf returns the number of items it read in so if it returns 0 you know that it failed on the first entry.
Thankyou! Most people completely ignore the return value, which is a very poor practise. You are one of the more enlightened people, though still not enlightened enough to use scanf correctly.
You may think this appropriate
int check = 1;
int var = 0;
while(check){
check = !scanf("%d", &var);
}
Since there's only one variable read, it will either return 0 on failure or 1 on success. The ! inverts this and check feeds it back into the while loop (so that this will loop until there is correct input).
You may think job done. Unfortunately scanf doesn't flush the input buffer on failure so if I enter 'error' it will stay on the input buffer for the next time, this program gives an infinite loop on an error.
There are several things wrong here. Firstly, scanf may return a negative integer! It's far more appropriate to check that scanf is reading the correct number of items, like: while (scanf("%d", &var) != 1 && getchar() >= 0);
Why do you mention
flushing input buffer? No such thing as an
input buffer buffer is required. To flush is to write; Writing to a file open for input just makes no sense, and is hence undefined behaviour. That'd be roughly the same as saying that you flush the toilet and the waste comes
out of the bowl! The reason for the infinite loop you mention has nothing to do with
flushing, and everything to do with ungetc. When scanf comes across a
conversion failure, it
ungetc's the character back onto the stream, ready to be read next time you call scanf.
For example, let us say we call scanf to expect integer input, and it gets "a{enter}". scanf reads 'a' from stdin, notices the invalid data and returns 0, indicating a conversion failure... but before it returns, it puts 'a' back into stdin. We loop to retry, and the same thing happens all over again...
So what can we do? We could call fflush(stdin); but this behaviour is undefined according to the C standard. ...
You can use getchar, as I did above, to read
and discard a character in a portable, well defined way.
Personally I prefer to use fgets. ...
Great! Stick to what you know how to use. It seems very wise to refrain from using angle grinders and other power-tools until you know how to use them safely. Just be aware that scanf does have neat applications. Due to the fact that scanf requires no "buff" variable, parsing could be much more efficient in applications that use stdin heavily.
@Boykie: When scanf using %d gets the following string from stdin: "1234\n", it'll parse 1234 and leave the '\n' on the stream. This is what your %c picks up: A newline.
@
Daisycrystal: Is it often that you flush the toilet to find the waste flying back up at your face? Don't use fflush(stdin) on a computer programmed toilet

That's undefined behaviour. Read this entire post for a well defined alternative, which will work on every system today and well into the future.
@
VakhoQ: You are very confused. getchar returns an int, not a char. Why is that so? The successful return value of getchar() will be an
unsigned char value. Are you sure the negative EOF is an unsigned char value? I suggest reading the manpages for getchar. What is the difference between "k" and 'k'? Which book are you reading?
@Promo2: Sure. Disect the following format string: "%*[0-9]%[0-9]%*[0-9]%*[0-9]". Google "opengroup scanf" for more information about the %[ format specifier. It requires a char input.
@Alexander: cplusplus.com is probably not the best reference for C functions. I'd suggest opengroup.
@poffpaul: C++ is not C, nor a superset of C. To clarify, there are features of C that C++ doesn't have, and that are subtly different to features that appear to be the same. Take modulo for example... -3 % 2 isn't required to be the same in C++ as it is in C. Another example is implicit void pointer conversion: char *foo = malloc(42); doesn't work in C++. Don't learn C++ as though it'll teach you C, because it won't. Learn C as though it'll teach you C, and C++ as though it'll teach you C++. Read this entire post for a solution to your problem.
Edited by object, 04 January 2013 - 08:35 AM.