Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

fflush vs gets

3 views
Skip to first unread message

Dwight Hugget

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to
I'm a newbie to C and find it confusing when working with scanf().
Books say use fflush(stdin) everytime after scanf() to clear the
buffer
before subsequent calls. Other books say do a gets(buffer) to clear.
What are the pros and cons here ?

all help appreciated
-dwight
--
comp.lang.c.moderated - moderation address: cl...@plethora.net

Nick Maclaren

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to

In article <clcm-2000...@plethora.net>, "Dwight Hugget" <jama...@concentric.net> writes:
|> I'm a newbie to C and find it confusing when working with scanf().
|> Books say use fflush(stdin) everytime after scanf() to clear the
|> buffer
|> before subsequent calls. Other books say do a gets(buffer) to clear.
|> What are the pros and cons here ?

fflush(stdin) is simply wrong, in a standard and portable context.
It is undefined behaviour. fflush is defined only for output files.
It won't do what I think you want on any system that I know of, anyway.

There is no standard-provided facility to do what I think you want
to do, but using gets will read the rest of the line. Actually,
DON'T use gets, because a very long line will cause your buffer
to overflow - use fgets, and go round in a loop if the length is
non-zero and the last character is not a newline.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QG, England.
Email: nm...@cam.ac.uk
Tel.: +44 1223 334761 Fax: +44 1223 334679

Chris Torek

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
In article <clcm-2000...@plethora.net>

Dwight Hugget <jama...@concentric.net> writes:
>I'm a newbie to C and find it confusing when working with scanf().
>Books say use fflush(stdin) everytime after scanf() to clear the
>buffer
>before subsequent calls. Other books say do a gets(buffer) to clear.
>What are the pros and cons here ?

fflush(stdin):
PRO: none.
CON: does not work. (POSIX *requires* fflush(input_stream)
not to flush input. Borland C fails to implement
POSIX. Of course, Borland C does not even attempt
to implement POSIX, but other C systems do.)

gets(buf):
PRO: works.
CON: enables viruses, Internet worms, etc.

Consider a third alternative, the "comp.lang.c approved method":

int c;

while ((c = getchar()) != EOF)
if (c == '\n')
break;

PRO: works.
CON: none.

Also consider the advice of the c.l.c FAQ, i.e., do not use scanf
directly.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.

Erik Max Francis

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
Dwight Hugget wrote:

> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?

fflush(stdin) invokes undefined behavior. fflush only works on output
streams.

--
Erik Max Francis | email m...@alcyone.com | icq 16063900
Alcyone Systems | web http://www.alcyone.com/max/
San Jose, CA | languages en, eo | icbm 37 20 07 N 121 53 38 W
USA | 961.953 Ms pL | 353 days left | &tSftDotIotE
__
/ \ It's better to be quotable than to be honest.
\__/ Tom Stoppard

Malcolm

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
In article <clcm-2000...@plethora.net>,

"Dwight Hugget" <jama...@concentric.net> wrote:
> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?
>

cons for both methods. fflush, like a water closet, flushes only output, not
input. gets() is a wonderful function which (unlike fgets() ) will often
process input correctly even when its buffer overflows, but isn't suitable
for clearing input as the buffer is highly likely to overflow, which may
cause your program to crash.

do this instead

void clearstdin(void)
{
int ch; /* note integer */

do
{
ch = fgetc(stdin);
} while(ch != '\n' && ch != EOF);
}

This will clear the input up to the next newline or end-of-file
> all help appreciated
> -dwight

wtmit...@my-deja.com

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
In article <clcm-2000...@plethora.net>,
"Dwight Hugget" <jama...@concentric.net> wrote:
> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer

Throw away any books which say that. The fflush() function is
defined only for output streams. It is not to be used with an
input stream as its argument. See section 12.26 of the
comp.lang.c FAQ.

> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?
>

Throw away any books which say that. The gets() function is always
dangerous, and should never be used. Use the fflush() function
instead. See section 12.23 of the comp.lang.c FAQ.

Hans-Bernhard Broeker

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
In comp.lang.c.moderated Dwight Hugget <jama...@concentric.net> wrote:
> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?

Only cons. Both families of books are wrong, but for different
reasons.

fflush(stdin) is an old DOSism, and will not work anywhere else (with
'luck', and the right compiler, not even on DOS). The C language
itself only defines the effect of fflush() for output streams, not for
input.

gets(buffer) is bad because gets() is bad, by design. If at all, you
should be using fgets(stdin,buffer,buffersize). Make it a habit
*never* to use gets().

--
Hans-Bernhard Broeker (bro...@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Mette et Francois Christiansen-Lauze

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
Dwight Hugget wrote:
>
> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?
>
> all help appreciated
> -dwight

> --
> comp.lang.c.moderated - moderation address: cl...@plethora.net

fflush() works for output streams!
You can't use is for an input stream. I think that
the norm says that the behaviour of flush() for an input
stream is undefined.
Probably you should think of buying a new book.

Francois

mike burrell

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
In comp.lang.c Dwight Hugget <jama...@concentric.net> wrote:
> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?

dann's post is highly recommended, but unfortunately he forgot to give you
solution to your problem :)

instead of using scanf, use a combination of fgets() and sscanf()

--
/"\ m i k e b u r r e l l
\ / ASCII RIBBON CAMPAIGN mik...@home.com
X AGAINST HTML MAIL http://mikpos.dyndns.org
/ \

Martin Ambuhl

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to

Dwight Hugget wrote:
>
> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer

Books that say this should be donated to your nearest paper recycling
center. fflush() is not defined on input streams (except for updated
streams on which the last operation was output).

> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?

Books that say this should be burnt. gets() is so dangerous that the
paper cannot be recycled. Use fgets() and check for '\n'.


--
Martin Ambuhl mam...@earthlink.net

What one knows is, in youth, of little moment; they know enough who
know how to learn. - Henry Adams

A thick skin is a gift from God. - Konrad Adenauer
__________________________________________________________
Fight spam now!
Get your free anti-spam service: http://www.brightmail.com

Jerry Coffin

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
In article <clcm-2000...@plethora.net>, jama...@concentric.net
says...

> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?

The pros are that books are usually made from paper, so even though
they're awful books on C, the ones you've been looking at can be
burned to keep you warm if some delayed reaction to Y2K kills your
furnace...

The cons are that using fflush on an input file produces undefined
results, and gets is a function that's dangerous no matter HOW it's
used.

If you want to clear a buffer, you'll want to figure out exactly what
you want to clear from the buffer, and do so. You might, for example,
want to ignore characters up to the next new-line. In that case, you
can use scanf itself a bit differently to handle the situation:

scanf("%*[^\n]");

to read and discard characters until it encounters a new-line.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Keith Thompson

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
"Dwight Hugget" <jama...@concentric.net> writes:
> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?

Your books are wrong. The fflush() function is used for output
files; fflush(stdin) produces undefined behavior. The gets()
function should never be used under any circumstances. The scanf()
function is potentially dangerous; for example, scanf with a simple
"%s" format is as bad as gets().

(Some would argue that gets() can be used safely in limited
circumstances. This may be true, but *only* if the program calling it
is part of a system where the author has complete control over what
can appear in the program's stdin -- and it's generally easier just to
use fgets() anyway.)

See the C FAQ at <http://www.eskimo.com/~scs/C-faq/top.html>.
Section 12 discusses stdio; section 18 includes links to information
about some decent books on C.

Also, you cross-posted your article to comp.lang.c,
comp.lang.c.moderated, and comp.std.c. It's not appropriate for
comp.std.c, which is for discussion of the C standard, not for
programming questions. It should probably have been posted to either
comp.lang.c or comp.lang.c.moderated, but not both. I've redirected
followups to comp.lang.c only.

--
Keith Thompson (The_Other_Keith) k...@cts.com <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Welcome to the last year of the 20th century.

GaryHC

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
>I'm a newbie to C and find it confusing when working with scanf().
>Books say use fflush(stdin) everytime after scanf() to clear the
>buffer
>before subsequent calls. Other books say do a gets(buffer) to clear.
>What are the pros and cons here ?
>

I think you need different books. Both these approaches have
serious problems. See items 12.23 and 12.26 in the FAQ.
Take a look at 12.20 while you're at it.

The usual advice is to use fgets() instead of gets(), but neither
of them will do what you want. They both stop after reading a
newline. So if the user has typed ahead "1\n2", the "2"
will still be in the buffer after the gets() or fgets().

Are you sure you want to clear the buffer between reads?
Why not let the user type ahead of the prompts?

-- Gary Culp
-- Keil Software

Mette et Francois Christiansen-Lauze

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
Hans-Bernhard Broeker wrote:
>
> In comp.lang.c.moderated Dwight Hugget <jama...@concentric.net> wrote:
> > I'm a newbie to C and find it confusing when working with scanf().
> > Books say use fflush(stdin) everytime after scanf() to clear the
> > buffer
> > before subsequent calls. Other books say do a gets(buffer) to clear.
> > What are the pros and cons here ?
>
> Only cons. Both families of books are wrong, but for different
> reasons.
>
> fflush(stdin) is an old DOSism, and will not work anywhere else (with
> 'luck', and the right compiler, not even on DOS). The C language
> itself only defines the effect of fflush() for output streams, not for
> input.
>
> gets(buffer) is bad because gets() is bad, by design. If at all, you
> should be using fgets(stdin,buffer,buffersize). Make it a habit
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fgets(buffer, buffersize, stdin) instead
You might have been working a bit to late last night ;-)


> *never* to use gets().
>
> --
> Hans-Bernhard Broeker (bro...@physik.rwth-aachen.de)
> Even if all the snow were burnt, ashes would remain.

> --
> comp.lang.c.moderated - moderation address: cl...@plethora.net

Francois

wtmit...@my-deja.com

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
In article <clcm-2000...@plethora.net>, I blathered;

> [...] The gets() function is always
> dangerous, and should never be used. Use the fflush() function [...]

I meant to say fgets(), of course, not fflush(). Oops.

Peter S. Shenkin

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
Hi,

I know I'm being dense here, but could someone explain to me
what problem this person is trying to solve? I've read this
and the FAQ section posted by Dann Corbitt, and I still don't
get it.

Why would you possibly want to discard the user's input, and
how in the world would you know what part to discard?

-P.

Dwight Hugget <jama...@concentric.net> wrote in message
news:clcm-2000...@plethora.net...


> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?
>

> all help appreciated
> -dwight

Dwight Hugget

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
So what is the proper way for me to do this:
printf(" Please enter an option to perform a conversion: ");
scanf("%c",&selection);
......

printf(" Please enter the amount of $US to convert to
$CANADIAN: ");
scanf("%lf",&input_dollar_amount);
I assume I should use sscanf????

"Chris Torek" <to...@elf.bsdi.com> wrote in message
news:clcm-2000...@plethora.net...


> In article <clcm-2000...@plethora.net>
> Dwight Hugget <jama...@concentric.net> writes:

> >I'm a newbie to C and find it confusing when working with scanf().
> >Books say use fflush(stdin) everytime after scanf() to clear the
> >buffer
> >before subsequent calls. Other books say do a gets(buffer) to
clear.
> >What are the pros and cons here ?
>

> fflush(stdin):
> PRO: none.
> CON: does not work. (POSIX *requires* fflush(input_stream)
> not to flush input. Borland C fails to implement
> POSIX. Of course, Borland C does not even attempt
> to implement POSIX, but other C systems do.)
>
> gets(buf):
> PRO: works.
> CON: enables viruses, Internet worms, etc.
>
> Consider a third alternative, the "comp.lang.c approved method":
>
> int c;
>
> while ((c = getchar()) != EOF)
> if (c == '\n')
> break;
>
> PRO: works.
> CON: none.
>
> Also consider the advice of the c.l.c FAQ, i.e., do not use scanf
> directly.
> --
> In-Real-Life: Chris Torek, Berkeley Software Design Inc
> El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
> http://claw.bsdi.com/torek/ (not always up) I report spam to
abuse@.

L.E.F.

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
>I'm a newbie to C and find it confusing when working with scanf().
>Books say use fflush(stdin) everytime after scanf() to clear the
>buffer

Uh-oh, buy a new book don't fflush(stdin) and don't use scanf.

Paul Jarc

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
nm...@cus.cam.ac.uk (Nick Maclaren) writes:
> Actually, DON'T use gets, because a very long line will cause your
> buffer to overflow - use fgets, and go round in a loop if the length
> is non-zero and the last character is not a newline.

If the input is to be discarded, then:
scanf("%*[^\n]%*c");
will suffice.


paul

cbfal...@my-deja.com

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
In article <malcolm...@my-deja.com> wrote:

> In article "Dwight Hugget" <jama...@concentric.net> wrote:
> > I'm a newbie to C and find it confusing when working with scanf().
> > Books say use fflush(stdin) everytime after scanf() to clear the
> > buffer before subsequent calls. Other books say do a gets(buffer)

> > to clear.
> > What are the pros and cons here ?
> >
>
> cons for both methods. fflush, like a water closet, flushes only
> output, not input. gets() is a wonderful function which (unlike
> fgets() ) will often process input correctly even when its buffer
> overflows, but isn't suitable for clearing input as the buffer is
> highly likely to overflow, which may cause your program to crash.
>
> do this instead
>
> void clearstdin(void)
> {
> int ch; /* note integer */
>
> do
> {
> ch = fgetc(stdin);
> } while(ch != '\n' && ch != EOF);
> }
>
> This will clear the input up to the next newline or end-of-file

The problem with this is that it will flush the NEXT line if a \n has
already been encountered. To guard against this, in general, you need
to globally retain the LAST character input (apart from EOF). This can
be done with the library putback mechanism, but then you have to be
sure that all the routines that extract data (floats, integers,
characters, strings, whatever) do the appropriate putbacks.

This problem is neatly handled in standard Pascal i/o semantics (just
to make a point, not start a language war) by the presence of input^,
which holds the LAST character input, together with the EOF and EOLN
booleans. Unfortunately the Borland/Turbo family of Pascals don't do
this properly.

At any rate, for complete portability and to bullet proof against
user mis-entry, you should get your inputs through your own library
only, and take care of these things.

As an aside, this long discussion was started by someone reading and
quoting a poor book giving lousy advice, and this brought forth the
wrath and ire of many many readers. Interesting.

--
Chuck Falconer
(cbfal...@my-deja.com)

John Bode

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
In article <clcm-2000...@plethora.net>,

"Dwight Hugget" <jama...@concentric.net> wrote:
> I'm a newbie to C and find it confusing when working with scanf().
> Books say use fflush(stdin) everytime after scanf() to clear the
> buffer
> before subsequent calls. Other books say do a gets(buffer) to clear.
> What are the pros and cons here ?
>

Neither is an acceptable method. fflush() is only defined for output
streams -- it's effect on the input stream is undefined, and hence
unpredictable. There may be some platforms where fflush(stdin) does
remove unread characters from the input stream, but this is by accident
rather than design. It should not be used to clear the input stream.

gets() has a serious flaw in that there's no way to prevent it from
writing beyond the end of your target buffer. It should not be used,
period.

You can either use fgets() or getchar() repeatedly until you find a
newline character:

void ClearInput (FILE *stream)
{
int c;

do
{
c = fgetc (stream);
} while (c != '\n' && c != EOF);
}

There are several reasons why using scanf() for interactive input is a
bad idea. First is the problem with newlines being left in the input
stream. Another problem is that, like gets(), scanf() can potentially
write beyond the end of a target buffer, leading to unpredictable
behavior. Finally, scanf() doesn't give you many tools for dealing with
bad input -- for example, if you are expecting a double and read 1.2b4,
scanf("%f", &foo) will happily convert and assign the 1.2 to foo,
leaving the 'b' in the input stream to foul up a later read. Now you've
consumed bad data, but you don't know about it until after the fact.

Instead of using scanf(), use a combination of fgets() and either
sscanf(), strtok(), or strchr() to read input.

--
www.biggerhammer.com | Low Technology Solutions for
| High Technology Problems

Get the FAQ's at http://www.eskimo.com/~scs/C-faq/top.html

Raymond Johnson

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
On Tue, 18 Jan 2000 20:06:14 GMT, "Dwight Hugget"
<jama...@concentric.net> wrote:

>I'm a newbie to C and find it confusing when working with scanf().
>Books say use fflush(stdin) everytime after scanf() to clear the
>buffer
>before subsequent calls. Other books say do a gets(buffer) to clear.
>What are the pros and cons here ?
>

>all help appreciated

Ok, I've just read all the replies so I'm not gonna comment on the
pros and cons as everyone else has. Personally I'd use the fgets()
and sscanf() as has been suggested but if you're looking for a simple
solution to using scanf(), I have it.

The most common problem associated with scanf() is that if you are
looking for a specific input, such as an integer, most ppl don't
realize that the scanf() terminates input when the <enter> key is
pressed, yet the newline character is not part of the input character
and many people leave it out of the scanf() formatted string. However
the newline character is still sitting in the input buffer and the
next use of scanf() will consume that newline whether it's part of the
next scanf() format or not. I.E. If you are asked for an integer
like the number 10, then are asked for another integer, it will be as
if you had already typed in a newline, hence since a character was
read that was not an integer, the scanf() function would terminate,
returning 0 as no variables were successfully read.
For example:

printf( "Enter an integer: ");
scanf( "%d", &variable1);

printf( "Enter another integer: " );
scanf( "%d", &variable2 );

if for the first part you type in 10 then enter, the second scanf()
reads the \n character and procedes to the next line in the code, with
no value stored in variable2. To solve this, set your formatting in
the scanf() statement to consume all trailing whitespace:

printf( "Enter an integer: " );
scanf( "%d ", &variable1 );

Note the space following the %d. This single space will result in the
consumption of any and all trailing whitespace following the integer.
So if you type in
10 \n
variable1 contains the value 10 and the remaining whitespace is
discarded.

You could also put a space in front of the %d but since leading
whitespace is trashed when scanning in an integer, this would be
redundant.

As an addendum, you may want a little more info about the format
string. Here we are simply reading in a sole integer. Suppose you
want to read in a date that includes a slash. You could set up the
format string like this:

printf( "Please enter a date of the form month/day/year : " );
scanf( "%d/%d/%d ", &month, &day, &year );

Here it will scan in an integer (month) then look for and discard a
slash, then another integer (day), then look for and discard a slash,
then lastly another integer (year).

Please keep in mind that this is not good programming because it is
too easy to have errors associated with formatted input such as this.
fgets() and scanf() are a much better choice for formatted input as it
allows you to handle input errors with much greater ease. However I
hope it helps you to understand the use of scanf().

Good luck.

Nick Maclaren

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
In article <clcm-2000...@plethora.net>,

Peter S. Shenkin <she...@schrodinger.com> wrote:
>
>I know I'm being dense here, but could someone explain to me
>what problem this person is trying to solve? I've read this
>and the FAQ section posted by Dann Corbitt, and I still don't
>get it.
>
>Why would you possibly want to discard the user's input, and
>how in the world would you know what part to discard?

Interactive prompting - think of the passwd command.

You can do the job properly, but need primitives that Unix and
its related networking do not have. Some other systems and
some other networking protocols have done better. I.e. the
key is to have proper end-to-end handshaking, and to be able to
send some output, tagged with a flag that says 'flush all
queued input as this message goes past.'

You can do a bad job, assuming Unix, Microsoft etc. and that
either the display is local, or connected by a near-instantaneous
connexion. Most modern windowing systems rely on this, which
is why they go wrong when the machine or network gets overloaded.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QG, England.
Email: nm...@cam.ac.uk
Tel.: +44 1223 334761 Fax: +44 1223 334679

Paul Jarc

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
"Dwight Hugget" <jama...@concentric.net> writes:
> So what is the proper way for me to do this:
> printf(" Please enter an option to perform a conversion: ");

fflush(stdout);

> scanf("%c",&selection);

You could also use `selection=getchar();', but either way, you ought
to check for EOF.

> printf(" Please enter the amount of $US to convert to $CANADIAN: ");

fflush(stdout);

> scanf("%lf",&input_dollar_amount);
> I assume I should use sscanf????

fgets+sscanf is one way to go about it. You can use scanf, but you
have to account for the fact that if the user enters non-numeric data,
then that data will remain in the input stream after the above scanf
call. You'll have to skip past that input, perhaps to the next line,
to avoid an infinite loop. fgets+scanf is often conidered easier.


paul

Paul Jarc

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
"Peter S. Shenkin" <she...@schrodinger.com> writes:
> I know I'm being dense here, but could someone explain to me
> what problem this person is trying to solve? I've read this
> and the FAQ section posted by Dann Corbitt, and I still don't
> get it.

My guess is that the books recommend skipping input data (for the rest
of the line, or whatever's in the stdio buffer) following a scanf to
get past bad data, if there was any. This is just one more flaw in
these books. (Skipping bad data might be appropriate in some
circumstances, but shouldn't be generally recommended.)

Chris Torek

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
In article <clcm-2000...@plethora.net>,
Peter S. Shenkin <she...@schrodinger.com> wrote:
>I know I'm being dense here, but could someone explain to me
>what problem this person is trying to solve? I've read this
>and the FAQ section posted by Dann Corbitt, and I still don't
>get it.
>
>Why would you possibly want to discard the user's input, and
>how in the world would you know what part to discard?

The short answers are: "You don't, and you don't."

What is going on here is a kludge piled on top of an already "bad"
(in some sense) program. Instead of fixing the actual *problem*,
certain books that purport to teach C suggest fixing the *symptoms*.

This is a bit like going in to the doctor with incipient pneumonia
and being given a cough suppressant.

The root of the problem is the use of scanf(). The scanf() function
is a large and complex beast that often does something almost but
not quite entirely unlike what you desired.

The entire scanf() family works by interpreting "directives". These
directives are not well suited to interactive ("talking to a human")
input. In particular, a directive like " " or "\n" means: "skip as
much input white space as you can find, INCLUDING NEWLINES." Most
conversion directives (including %d and %f) have an implicit skip as
well. This means that if you print a prompt:

printf("please enter a number: ");
fflush(stdout);

and then ask for input using `scanf("%d", &var)', and the human enters
a blank line, the computer simply sits there, rather than re-prompting.

The next problem is that the scanf() family tend to leave unconsumed
input. Anything that does not "meet the requirements" is left in
place. If the user, who is supposed to enter a number, enters
"three" instead of "3", the "t" does not meet the requirements for
"%d". The entire line ("three\n") is left in the input stream.
If the user *does* enter a number, such as "3", only the newline
is left in the stream. If the user enters a number followed by a
blank (or tab or other whitespace), the blank and newline are both
left in the stream.

This characteristic (of leaving "extra" input behind as a trap to
the unwary) leads people to write the "discard user's input" code.
Unfortunately, they often use implementation-specific constructs like
fflush(stdin), or broken ones like an unadorned getchar() or a
scanf format like "%*[^\n]%*c". To see why this last format is broken,
read the next paragraphs.

Another substantial problem with the scanf() functions is that they
interpret directives sequentially, and stop as soon as they get a
"matching failure". This seems often to surprise people. In
particular, consider the format directive "%*[^\n]". This consists
of several parts. The "%" introduces the conversion. The asterisk
"*" suppresses assignment of the result of the conversion, so that
no additional buffer is required. The "[" specifies that the
conversion is to do a character-class match, the initial "^" inverts
the class, and the class itself consists only of a single character,
"\n". The "]" terminates the class and is the end of that directive.
This directive thus means "match things that are not newlines".

The tricky bit here is that any %[ directive MUST MATCH AT LEAST
ONE CHARACTER. If it fails to match at least one character, the
scan terminates. The call returns without looking at any further
directives. Thus, if the next input character is a newline, this
"%*[" directive fails, and the "%*c" NEVER OCCURS. The format
sequence "%*[^\n]%*c" only clears out the rest of a line if there
is at least one character before the newline.

This problem can be fixed (as others noted) by using two separate
calls. An initial scanf() with "%*[^\n]" will either eat everything
up to but not including a newline, or fail. A subsequent "%*c"
(or plain old getchar()) will consume the newline, if there was one.

That last "if" matters too: perhaps the user signalled EOF. In this
case, the getchar() or scanf("%*c") might -- this decision is left
to the people who write your compiler -- either immediately return
EOF, or go back to the user for more input. If the implementors
choose the latter, the user might have to click on "end this thing"
(^D, ^Z, mouse button, front panel switch, or whatever) one extra
time. This is annoying, if nothing else.

(Incidentally, offhand, I think %[ and %c are the only two directives
that do not immediately skip whitespace, including newlines.)

So what *is* the "right" answer? There are various ways to do
this. You can write horrendously complicated code using getchar,
ungetc, and scanf, carefully checking all the return values. You
can call fgets() to read a complete line, then -- having "sandboxed"
it, as it were, use sscanf() and not worry too much about bad input.
You can call fgets() and use strtol() and other string-parsing
functions. The simpler approaches all share one common characteristic,
though: they first read a complete line (including the terminating
newline), and only then try to pick it apart. That gives users
time to mull over their answer, type something in, erase it, type
something else, erase that, think a bit more, and then give Regis
Philbin their "final answers" by pressing ENTER or RETURN. :-) You
then get the whole thing at once, and can dissect it as needed.


--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.

Paul Jarc

unread,
Jan 20, 2000, 3:00:00 AM1/20/00
to
ray...@bit.csc.lsu.edu (Raymond Johnson) writes:
> For example:
>
> printf( "Enter an integer: ");
> scanf( "%d", &variable1);
>
> printf( "Enter another integer: " );
> scanf( "%d", &variable2 );
>
> if for the first part you type in 10 then enter, the second scanf()
> reads the \n character and procedes to the next line in the code, with
> no value stored in variable2.

False. Newline is not special to scanf in this way. The second scanf
call will skip any leading whitespace in the input stream before
applying the %d conversion, including newlines. C99 7.19.6.2p8:
# Input white-space characters (as specified by the isspace function)
# are skipped, unless the specification includes a [, c, or n
# specifier.

7.4.1.9p2 (the isspace function):
# The standard white-space characters are the following: space (' '),
# form feed ('\f'), new-line ('\n'), carriage return ('\r'),
# horizontal tab ('\t'), and vertical tab ('\v').

> To solve this, set your formatting in
> the scanf() statement to consume all trailing whitespace:
>
> printf( "Enter an integer: " );
> scanf( "%d ", &variable1 );
>
> Note the space following the %d. This single space will result in the
> consumption of any and all trailing whitespace following the integer.

This is the same consumption that happens before any conversion, other
than %[, %c, and %n.

> You could also put a space in front of the %d but since leading
> whitespace is trashed when scanning in an integer, this would be
> redundant.

Which is why the trailing space in the previous scanf format is
unnecessary.

> printf( "Please enter a date of the form month/day/year : " );
> scanf( "%d/%d/%d ", &month, &day, &year );
>
> Here it will scan in an integer (month) then look for and discard a
> slash, then another integer (day), then look for and discard a slash,
> then lastly another integer (year).

Zero or more whitespace characters before any of the integers will
also be silently ignored.

If your C implementation behave as you describe, get your money back.


paul

Douglas A. Gwyn

unread,
Jan 23, 2000, 3:00:00 AM1/23/00
to
Dwight Hugget wrote:
> So what is the proper way for me to do this:
> printf(" Please enter an option to perform a conversion: ");
> scanf("%c",&selection);
> ......

> printf(" Please enter the amount of $US to convert to
> $CANADIAN: ");
> scanf("%lf",&input_dollar_amount);
> I assume I should use sscanf????

First, you should insert fflush(stdout)s after the printfs,
to ensure that the prompt is seen before the attempt to read
input. Second, it's almost never a good idea to use scanf
for parsing interactive input; if your local programming
shop doesn't already have input+validation library functions,
you should write your own and save them for future reuse.
Third, in many environments (notably UNIX), the standard C
support does not read anything from standard input until
a newline has been entered. (This calls for yet another
set of local programming library functions, with a uniform
interface but slightly different implementations on different
platforms. In fact you really ought to have a test for the
standard input and output being attached to an interactive
device, so you don't prompt into a redirected stdout etc.)

Why doesn't standard C provide more of this stuff already?
There are lots of reasons, but basically it's a waste of
time trying to standardize new functions for the old
"terminal"-oriented I/O when so many programs these days
don't interact with humans via that mechanism.

Jerry Coffin

unread,
Jan 23, 2000, 3:00:00 AM1/23/00
to
In article <clcm-2000...@plethora.net>, p...@po.cwru.edu says...

> nm...@cus.cam.ac.uk (Nick Maclaren) writes:
> > Actually, DON'T use gets, because a very long line will cause your
> > buffer to overflow - use fgets, and go round in a loop if the length
> > is non-zero and the last character is not a newline.
>
> If the input is to be discarded, then:
> scanf("%*[^\n]%*c");
> will suffice.

Not really -- scanf will only attempt the %*c if the previous scanset
has matched at least one character. IOW, it'll sucessfully remove the
new-line from the input buffer if and only if the user enters at least
one character of garbage after the input you were trying to read to
start with.

--
Later,
Jerry.

The universe is a figment of its own imagination.

John Bode

unread,
Jan 23, 2000, 3:00:00 AM1/23/00
to
In article <clcm-2000...@plethora.net>,
"Peter S. Shenkin" <she...@schrodinger.com> wrote:
> Hi,

>
> I know I'm being dense here, but could someone explain to me
> what problem this person is trying to solve? I've read this
> and the FAQ section posted by Dann Corbitt, and I still don't
> get it.
>
> Why would you possibly want to discard the user's input, and
> how in the world would you know what part to discard?
>
> -P.
>

The problem that the OP is running into is that using scanf() in a naive
manner can leave newlines or other characters embedded in the input
stream, which may cause future calls to scanf() to barf. For example,
if you're repeatedly reading numeric data using scanf("%d", &foo), and
the user fat-fingers a non-numeric character, subsequent
scanf("%d",&foo) calls will not read past that character unless you
remove it some other way (either by getchar() or scanf ("%c", &junk)).

The OP was unfortunate enough to be reading brain-damaged books. Not
only do they promote a bad way to get input (scanf()), they compound
this error by offering two buggy "solutions" to the problems scanf()
causes (one of which doesn't work at all, and the other of which can
introduce a point of failure in the code).

The correct solution is to not use scanf() at all, and replace it with a
combination of fgets() and either sscanf(), strtok(), or strchr().

> Dwight Hugget <jama...@concentric.net> wrote in message
> news:clcm-2000...@plethora.net...


> > I'm a newbie to C and find it confusing when working with scanf().
> > Books say use fflush(stdin) everytime after scanf() to clear the
> > buffer
> > before subsequent calls. Other books say do a gets(buffer) to clear.
> > What are the pros and cons here ?
> >
> > all help appreciated

> > -dwight


> > --
> > comp.lang.c.moderated - moderation address: cl...@plethora.net
> --
> comp.lang.c.moderated - moderation address: cl...@plethora.net
>

--


www.biggerhammer.com | Low Technology Solutions for
| High Technology Problems

Peter S. Shenkin

unread,
Jan 23, 2000, 3:00:00 AM1/23/00
to
Hi,

Chris Torek <to...@elf.bsdi.com> wrote in message
news:clcm-2000...@plethora.net...


> In article <clcm-2000...@plethora.net>,
> Peter S. Shenkin <she...@schrodinger.com> wrote:
> >I know I'm being dense here, but could someone explain to me
> >what problem this person is trying to solve? I've read this
> >and the FAQ section posted by Dann Corbitt, and I still don't
> >get it.
> >
> >Why would you possibly want to discard the user's input, and
> >how in the world would you know what part to discard?

...


> So what *is* the "right" answer? There are various ways to do
> this. You can write horrendously complicated code using getchar,
> ungetc, and scanf, carefully checking all the return values. You
> can call fgets() to read a complete line, then -- having "sandboxed"
> it, as it were, use sscanf() and not worry too much about bad input.

...

Thanks, Chris. This is clear now. The fgets/sscanf method is what
I've always used when I've had to do this kind of thing. I've also
found that this is a place where checking the return value of
sscanf can be *extremely* helpful.

By the way, the original question was phrased in terms of how to
discard part of the user's input. The answers all refer to the
opposite question -- namely, how to read the user's input. Still,
it seems that the responses do address the original poster's query.

-P.

cbfal...@my-deja.com

unread,
Jan 23, 2000, 3:00:00 AM1/23/00
to
In article <clcm-2000...@plethora.net>,
"Peter S. Shenkin" <she...@schrodinger.com> wrote:
> Hi,

>
> I know I'm being dense here, but could someone explain to me
> what problem this person is trying to solve? I've read this
> and the FAQ section posted by Dann Corbitt, and I still don't
> get it.
>
> Why would you possibly want to discard the user's input, and
> how in the world would you know what part to discard?
>
> -P.
>
> Dwight Hugget <jama...@concentric.net> wrote in message
> news:clcm-2000...@plethora.net...

> > I'm a newbie to C and find it confusing when working with scanf().
> > Books say use fflush(stdin) everytime after scanf() to clear the
> > buffer before subsequent calls. Other books say do a gets(buffer)
> > to clear.
> > What are the pros and cons here ?

For example, a prompt asks for a numerical value. The user enters
"123.456 q" before hitting ENTER. Note the trailing blanks etc. If
the input parser stops (as it should) on the first character that
doesn't belong in a number, the string " q\n" remains. He wants to
remove that, and produce a prompt for the next input.

The other choice is to insist that the numeric is terminated by the
ENTER, and give error messages on the above sample. But why penalize
the poor user for things that can be easily handled. This sort of
thing is considered non-user-friendly.

--
Chuck Falconer
(cbfal...@my-deja.com)

cbfal...@my-deja.com

unread,
Jan 23, 2000, 3:00:00 AM1/23/00
to
In article <clcm-2000...@plethora.net>,
John Bode <john...@my-deja.com> wrote:
... snip ...

> gets() has a serious flaw in that there's no way to prevent it from
> writing beyond the end of your target buffer. It should not be used,
> period.
>
> You can either use fgets() or getchar() repeatedly until you find a
> newline character:
>
> void ClearInput (FILE *stream)
> {
> int c;
>
> do
> {
> c = fgetc (stream);
> } while (c != '\n' && c != EOF);
> }
>
> There are several reasons why using scanf() for interactive input
> is a bad idea. First is the problem with newlines being left in
> the input stream. Another problem is that, like gets(), scanf()

> can potentially write beyond the end of a target buffer, leading
> to unpredictable behavior. Finally, scanf() doesn't give you many
> tools for dealing with bad input -- for example, if you are
> expecting a double and read 1.2b4, scanf("%f", &foo) will happily
> convert and assign the 1.2 to foo, leaving the 'b' in the input
> stream to foul up a later read. Now you've consumed bad data, but
> you don't know about it until after the fact.
>
> Instead of using scanf(), use a combination of fgets() and either
> sscanf(), strtok(), or strchr() to read input.

Leaving off the exact implementations, what I want in a user
numerical input mechanism is:

1. Skip leading blanks and tabs. Optionally also leading '\n's.
2. Check first character(s) for a valid numeric.
Else return an error.
3. Parse the numeric up to a termination character. This may
involve gobbling trailing '0's. If overflow occurs, signal
appropriately (may mean returning an error code, don't take
the work 'signal' too seriously). Return both the value and
the terminating character.

Now, in your above example, the calling routine can check that the
terminating character is either a ' ', a '\t', or a '\n'. In these
cases it is safe to flush the input line through the '\n' (unless the
terminator was a '\n'), and emit the next prompt.

I think I have covered everything but the implementation - if not I am
sure I will hear about it.

BTW, your 'ClearInput(f)' routine above is the equivalent of Pascal's
"readln(f);" standard function. Note that I did NOT say "readln(f,
value);"

Ariel Scolnicov

unread,
Jan 23, 2000, 3:00:00 AM1/23/00
to
Paul Jarc <p...@po.cwru.edu> writes:

> "Peter S. Shenkin" <she...@schrodinger.com> writes:

> > I know I'm being dense here, but could someone explain to me
> > what problem this person is trying to solve? I've read this
> > and the FAQ section posted by Dann Corbitt, and I still don't
> > get it.
>

> My guess is that the books recommend skipping input data (for the rest
> of the line, or whatever's in the stdio buffer) following a scanf to
> get past bad data, if there was any. This is just one more flaw in
> these books. (Skipping bad data might be appropriate in some
> circumstances, but shouldn't be generally recommended.)
>

Programs have been known to be written in which comments in the input
are allowed. I fail to see how such a specification is wrong.
Generally, when you use the same input file for several purposes
(reading by 1 or more programs, as well as reading by people), it is
nearly inevitable to want to ignore portions of it.

[Is this C?]

--
Ariel Scolnicov

David R Tribble

unread,
Jan 25, 2000, 3:00:00 AM1/25/00
to
cbfal...@my-deja.com wrote:
>
> Peter S. Shenkin <she...@schrodinger.com> wrote:
>> I know I'm being dense here, but could someone explain to me
>> what problem this person is trying to solve? I've read this
>> and the FAQ section posted by Dann Corbitt, and I still don't
>> get it.
>>
>> Why would you possibly want to discard the user's input, and
>> how in the world would you know what part to discard?
>>
>> Dwight Hugget <jama...@concentric.net> wrote:
>> > I'm a newbie to C and find it confusing when working with scanf().
>> > Books say use fflush(stdin) everytime after scanf() to clear the
>> > buffer before subsequent calls. Other books say do a gets(buffer)
>> > to clear.
>> > What are the pros and cons here ?
>
> For example, a prompt asks for a numerical value. The user enters
> "123.456 q" before hitting ENTER. Note the trailing blanks etc. If
> the input parser stops (as it should) on the first character that
> doesn't belong in a number, the string " q\n" remains. He wants to
> remove that, and produce a prompt for the next input.

Which is why reading the entire response in a single call to fgets(),
and then parsing its contents with sscanf(), is a pretty good
solution. Not only does it avoid the inherent problems with
scanf(), it also allows the program to ignore any trailing fluff in
the user's input.

-- David R. Tribble, da...@tribble.com, http://david.tribble.com --

Steve Summit

unread,
Feb 12, 2000, 3:00:00 AM2/12/00
to
[posted and mailed]

In article <clcm-2000...@plethora.net>, Peter S. Shenkin


<she...@schrodinger.com> wrote:
>Dwight Hugget <jama...@concentric.net> wrote in message
>news:clcm-2000...@plethora.net...

>> I'm a newbie to C and find it confusing when working with scanf().
>> Books say use fflush(stdin) everytime after scanf() to clear the buffer
>> before subsequent calls. Other books say do a gets(buffer) to clear.
>> What are the pros and cons here ?
>

> I know I'm being dense here, but could someone explain to me
> what problem this person is trying to solve? I've read this
> and the FAQ section posted by Dann Corbitt, and I still don't
> get it.
>
> Why would you possibly want to discard the user's input, and
> how in the world would you know what part to discard?

I think this was probably answered, but just in case...

It's likely that you've never tried to call scanf and gets in the
same program. If you haven't, you're blissfully unaware of this
messy little problem.

Suppose you write this trivial program:

#include <stdio.h>
int main()
{
int i;
char string[80];
printf("enter an integer:\n");
scanf("%d", &i);
printf("enter a string:\n");
gets(string);
printf("You typed %d and \"%s\"\n", i, string);
return 0;
}

Looks perfectly straightforward, right? But if you compile and
run it (which I encourage you to do, if you're still unfamiliar
with this problem), you'll see something weird, and you will
find yourself (I guarantee it) asking question 12.18 in the
comp.lang.c FAQ list: "I'm reading a number with scanf %d and
then a string with gets(), but the compiler seems to be skipping
the call to gets()!" (We'll have more to say later about using
gets at all, but hold that thought.)

Let's look very carefully at what happens. The first printf call
prints the first prompt, and we type "123" and hit the return
key. The input stream now contains

1 2 3 \n

Now we hit the scanf call, and scanf sees the format string %d
indicating that we've asked it to read an int. It reads the
character '1' from the input stream and says to itself "okay,
that's a digit, so it can be part of an int." It reads the
characters '2' and '3', and they're digits, too. The next
character is '\n', which is not a digit. So scanf does two
things:

1. It terminates processing of the %d directive; it now
knows that the complete integer it has read is 123;
it stores this value as requested into the location
of the variable i.

2. (This is the key point.) It pushes the \n character,
which terminated the digit string but which it didn't
otherwise use, back onto the input stream.

So after the first scanf call, the input stream contains

\n

Now the second printf call prints the second prompt. Suppose we
type "test" and hit the enter key. The input stream now contains

\n t e s t \n

So now we come to the gets call. gets's job, of course, is to
read one line of input, up to the next newline. But the very
first character gets sees is a \n, so as far as it's concerned
it's just read a blank line. It returns that blank line (an
empty string, since gets always deletes the newline from the
line before returning it to you), and the input stream is left
containing

t e s t \n

The third printf call prints the (somewhat surprising) results
of the two inputs, and the program terminates, with the string
"test" and the final newline unconsumed.

If this still isn't quite making sense, try running the program
again, and typing something more than a number in response to the
first prompt. That is, try typing "123 abc" or "123abc", and
then hitting the return key, when asked to "enter an integer".

(Actually, the above description isn't quite right. No matter
what you type on the first line, the input stream after the first
scanf call still contains a \n, so the gets call reads it right
away, without pausing for you to enter anything more. So you
don't really get a chance to type "test" at all. To answer the
FAQ list's question another way, the problem is not that the
compiler somehow "skips" the gets call, the problem is that the
gets call satisfies its need for input in an unexpected way, and
skips the part about pausing the program to wait for you to type
anything more.)

With the scenario above as background, we can now answer your
question, "Why would you possibly want to discard the user's
input?" For better or worse, many beginning programmers use
scanf to read numbers and gets to read strings. This is in large
part, of course, because these functions are taught early in many
books and programming classes. And this, in turn, is because
these functions are superficially and seductively attractive;
they seem very easy and convenient to use. But they don't play
at all well together (plus they have some other problems, which
we'll get to).

When the beginning programmer writes a program like the above
and discovers that it doesn't work quite right, he is likely to
receive the handwaving explanation (from the instructor or the
textbook author) that there is some "garbage left behind on the
input stream by scanf". (We, who understand the situation more
accurately, now know that the "garbage" is, in the example we
walked through, simply the \n that resulted from our hitting the
return key after entering the requested number.) To allow
further input to proceed as expected, these instructors and
authors go on to explain, the "garbage" must be "discarded".
One all-too-popular (and, again, superficially attractive) way of
doing this is to call fflush(stdin), despite the fact that this
is a misguided application of the standard fflush function, an
application that is not guaranteed to (and in fact most certainly
does not) work everywhere. But it "works" under a large number
of popular PC C compilers, so the "idiom" is, unfortunately,
widespread.

What's the right solution? It's extremely easy to get stuck
on the fact that fflush(stdin), for some presumably stupid
and pedantic reason, is not guaranteed to work everywhere.
One then starts casting about looking for a "portable"
replacement. The problem is that, depending on precisely what
one is trying to do, there are quite a few different tacks one
might take in attempting to write some well-defined or portable
code to "discard garbage from stdin". (In the general case, as
you correctly ask, "How in the world would [one] know what part
to discard?")

If the definition of the "garbage from stdin" that we're trying
to discard is "input from the previous line which wasn't consumed
by scanf", it turns out that there are a couple of not entirely
unreasonable approaches. We could write the loop

while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;

to read and discard characters up to the next newline. (Notice
that the comment "/* discard the character */" in this fragment
does not stand in for some code I didn't write yet -- it stands
in for some code I deliberately didn't write at all. The body of
the loop is empty; we do nothing with the characters we're
reading, thus discarding them. The \n which terminates the
loop is discarded, too.)

Since that loop would clutter our code pretty badly if we had
to interpose it after every scanf call, we might encapsulate it
into a function we could call, perhaps called "flushline" or
something. Or, recognizing that "read characters up to a
newline" is precisely what the Standard functions gets and fgets
already do, we might simply interpose calls to gets or fgets,
reading into a dummy buffer which we ignore (and hence discard),
perhaps accompanied by comments explaining that these dummy calls
are to "get rid of the garbage left behind by scanf". But these
are still ugly, unclean, unsatisfying solutions. It won't be
long before one of our scanf calls, for some reason, *does*
consume a newline character after all, such that our compensating
"read and discard characters up to the next newline" code will
read and discard the next line of input, a real line of input,
which will then be lost to the input-reading code which expected
it. We could try to predict which scanf calls will and which
scanf calls won't leave "garbage behind", and sprinkle "flushline"
calls after only those scanf calls which need them, but this is a
hit-or-miss proposition, and a later reader will never be able to
understand precisely what we're up to. There's got to be a
better way.

The "better way", as indicated in the FAQ list, is either to
abandon scanf entirely, or to use it exclusively. If your
input is intended to be line-based, you can read *all* lines
of input as strings, using fgets or the like, and for those
that were supposed to be numeric, convert the strings to numbers
using functions like atoi, strtol, atof, or maybe even sscanf.
(This is the general approach I recommend.) Or, since the
problem is that it's scanf that does Not Play Well With Others,
you can switch to a scheme where you use scanf for everything,
using it to read your strings, too (with %s or the like).

Finally, I should add a couple of postscripts. It turns out
that scanf has other problems besides the fact that it tends to
leave little undigested "surprises" on the input stream, so there
are other reasons to consider abandoning it. And, of course,
as discussed at length in comp.lang.c of late, gets has a fatal
problem which counterindicates its use for much of anything.

Steve Summit
s...@eskimo.com
--
Programming Challenge #5: Love your abstractions.
See http://www.eskimo.com/~scs/challenge/.

0 new messages