delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/07/12/01:07:18

From: j DOT aldrich6 AT genie DOT com
Message-Id: <199607120458.AA205067505@relay1.geis.com>
Date: Fri, 12 Jul 96 04:17:00 UTC 0000
To: lehmann AT mathematik DOT th-darmstadt DOT de
Cc: djgpp AT delorie DOT com, norbertj AT panix DOT com
Mime-Version: 1.0
Subject: Re: Beating fflush to death

Reply to message 8794437    from LEHMANN AT MATHE on 07/11/96  9:56AM


>: My how to write C books says that SOMETIMES scanf leaves a newline
>: character behind in the buffer.  The book suggests fflush(stdin) which as
>: we all know does not work.  I use gets(dum) (char dum[1]) to clear the
>: buffer after each scanf fpr this particular program.

Your C book ought to explain exactly why this is so.  The reason is related
to the way in which scanf() reads input.  For each format specifier, scanf()
reads the input stream until it finds an invalid character or a whitespace
character (space, tab, newline), at which point it stops reading, *leaving
that character still in the buffer*.  For example, suppose you had a statement
like:

scanf( "%d%d", &n1, &n2 );

and the user typed this:

55 102[Enter]

What your program would get is the string "55 102\n".  scanf() reads the first
number, stopping at the first whitespace character (the space).  Then it starts
reading the second number.  The first thing it sees is whitespace (the space
where it stopped the first time), so it keeps going until it sees a
non-whitespace
character (the '1').  Then it reads in the second number, stopping at the
newline.
Thus, the newline is still in the buffer!

Now, if you were to immediately issue another call to scanf() right after this
one,
you'd be ok, because scanf() discards all leading whitespace.  But if you
called
getchar(), you would get back the '\n' that is still in the buffer.  And if you
called
gets() or fgets(), it would see the newline as the end of the string it was
told to
read and return without waiting for the user to input anything.  This is why it
is
important to "flush" stdin after a call to scanf().

>: 1. Will this work on ALL versions of DOS?  If so, why is something like
>: it built into the lib?

fflush(stdin) is a hackish bit of nonsense introduced by Borland to make
things easier for lazy users.  According to the ANSI spec, fflush's behavior
is only defined for _output_ streams.

>gets doesn't check for buffer overruns, so you may overwrite some
>other part of your data with this call, if there is more than a single
>newline character available. (Remember the Internet worm, that
>exploited a similar bug in fingerd to propagate), if you want to use
>gets, don't , use fgets instead, it has a buffer size parameter and is
>safer.

But fgets(), because it stops before overflowing its buffer, may sometimes
leave data in the input buffer.  You need to check the strings it returns for
'\n' before using them.  Also, remember that while gets() replaces the '\n'
with a null, fgets() leaves it in.  It's a significant, though often
overlooked,
difference.

>: 4. Is the inconsistency between systems like DOS - UNIX or is it internal
>: to each system

Most _systems_ handle i/o streams in the same general fashion.  What
differs is the _compilers_ you use.  As I mentioned above, Borland has
introduced a lot of "helpful enhancements" that do not adhere to the ANSI
spec.  I particularly dislike flushall(), and closeall().  Real programmers
should be able to keep track of these things themselves, and besides,
there's always sync().  :)

>Well, scanf isn't really a function that should be used at all IMHO, I
>prefer fgets and fscanf, at least you get a chance to examine the
>string in case of an error.

Good point.  I have stopped using scanf() entirely in my programs
because it is too easy for users to make it fail.  Simply reading and
parsing data myself works far better (and more elegantly, too).  At
most I may resort to an sscanf() to read data from a string, but that
only in limited circumstances.  I haven't gotten as far yet as switching
to fgets(), but I will as soon as I find an elegant way of handling too-
long lines.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019