This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Re: scanf conflict with ANSI/ISO C99 fscanf Example 3 -- glibc scanf accepting invalid integer and floating point strings
- From: mjn3 at codepoet dot org (Manuel Novoa III)
- To: Andreas Jaeger <aj at suse dot de>
- Cc: libc-alpha at sources dot redhat dot com
- Date: Sat, 13 Sep 2003 08:59:10 -0600
- Subject: Re: scanf conflict with ANSI/ISO C99 fscanf Example 3 -- glibc scanf accepting invalid integer and floating point strings
- References: <20030912185236.GA6346@codepoet.org> <u8llssn8kr.fsf@gromit.moeb>
Hello,
On Sat, Sep 13, 2003 at 03:04:20PM +0200, Andreas Jaeger wrote:
> mjn3@codepoet.org (Manuel Novoa III) writes:
> >
> > #include <stdio.h>
> > #include <stdlib.h>
> >
> > int main(void)
> > {
> > int count;
> > float quant;
> > char units[21], item[21];
> >
> > count = sscanf("100ergs of energy", "%f%20s of %20s", &quant, units, item);
>
> 100 ergs of energy...
>
> 100e is the initial suffix for a floating point number which cannot be
> parsed correctly, so your input is wrong,
Sigh... I know that "100e" the initial prefix for a floating point
number which can't be parsed correctly by scanf. That's the point.
I suppose I assumed incorrectly that people would have a copy of
the ANSI/ISO C99 standard on hand. So, here's the original
example copied from the standard.
************************************************************************
19) EXAMPLE 3 To accept repeatedly from stdin a quantity, a unit of
measure, and an item name:
#include <stdio.h>
/* ... */
int count; float quant; char units[21], item[21];
do {
count = fscanf(stdin, "%f%20s of %20s", &quant, units, item);
fscanf(stdin,"%*[^\n]");
} while (!feof(stdin) && !ferror(stdin));
20) If the stdin stream contains the following lines:
2 quarts of oil
12.8degrees Celsius
lots of luck
10.0LBS of dirt
100ergs of energy
the execution of the above example will be analogous to the following
assignments:
quant = 2; strcpy(units, "quarts"); strcpy(item, "oil");
count = 3;
quant = 12.8; strcpy(units, "degrees");
count = 2; // "C" fails to match "o"
count = 0; // "l" fails to match "%f"
quant = 10.0; strcpy(units, "LBS"); strcpy(item, "dirt");
count = 3;
count = 0; // "100e" fails to match "%f"
count = EOF;
************************************************************************
I simply isolated the "100ergs of energy" test string in my posted
test. Here's the output illustrating how glibc handled this case.
> > count = 3
> > Error! count should be 0, as per Example 3 for fscanf in the ANSI/ISO C99 spec.
> > quant = 100.000000
> > units = "rgs"
> > item = "energy"
So, instead of glibc's scanf failing with a matching failure for "%f" as
it should have, it accepted "100E" as a valid floating point string,
assigned 100 to quant, and then continued processing. It went on to
set units to "rgs" (notice the missing 'e') and items to "energy".
The remaining tests illustrated the fact that glibc's scanf is
accepting floating point and integer strings as valid when they
are missing digits in required places.
Is that clearer?
Manuel