"Army1987" <pl********@for.itwrites:
Is this a good way to discard unread data after scanf()?
while (getchar() != '\n')
;
No.
According to the FAQ scanf always leaves the trailing newline on the input
stream, so there's no risk of discarding any more than needed. (In the best
case, when scanf() correctly works and the user hasn't input spurious data
beside those required in the control string, the loop will only iterate
once.)
What scanf leaves on the input stream depends on the format string.
With the right format string, it can consume the trailing newline.
In a later followup, you said you're using a "%d" format. In that
case, *if* you're going to use scanf() for input, then the above loop
with the addition of a check for EOF (see below) is reasonable,
assuming you want to accept just one integer value per input line.
But scanf() is usually not the best way to handle interactive input.
A better approach is to use fgets() to read an entire line at a time,
then use sscanf() to parse the line.
But even that has problems. If either scanf() or sscanf() with a "%d"
format attempts to read a number that won't fit in type int, the
behavior is undefined; there's no way to detect the error once it's
happened. If that's a concern, you might consider using strtol(),
which does detect and report overflow and underflow.
fgets() can also have problems with very long lines. I *think* this
is covered in the FAQ.
(The only problem is if for some reason stdin is a file and it ends. But I
could well use drastic solutions such as
assert(!feof(stdin) && !ferror(stdin));
as the loop body, since if a program designed to be interactive reads from a
file which ends we can't do anything better than abort execution.)
By "stdin is a file", I assume you mean that the program is reading
from a disk file rather than from, say, a keyboard. But you can
easily reach an end-of-file condition when reading from a keyboard.
<OT>On Unix-like systems, this is usually caused by the user typing
control-D; on DOS or Windows systems, it's usually control-Z.</OT You
should handle that case cleanly.
You can do much better than just aborting execution with a message
like:
assertion "!feof(stdin) && !ferror(stdin)" failed: file "c.c", line 6
You can test for end-of-file (preferably by comparing the result of
getchar() to EOF, not by calling feof() or ferror()), and you can
*gracefully* terminate the program. Quite often, reaching end-of-file
is the normal way for a program to terminate, simply because it has no
more work to do. In an interactive program that's expecting more
input, you can at least terminate with an error message that's going
to be meaningful to the user.
--
Keith Thompson (The_Other_Keith)
ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"