Page 300 in
says "100e" shouldn't match "%f". But I got
[hjl@gnu-6 tmp]$ cat s.c
count = fscanf(stdin, "%f%s", &quant, buf);
printf ("quant = %lf\n",quant );
printf ("count = %d\n", count);
printf ("string = %s\n", buf);
[hjl@gnu-6 tmp]$ gcc s.c
[hjl@gnu-6 tmp]$ cat x.input
100ergs of energy
[hjl@gnu-6 tmp]$ ./a.out < x.input
quant = 100.000000
count = 2
string = rgs
I was told that Windows and MacOS behave the same as glibc.
The implementation is correct. The implementation must behave as if at most one character can be pushed back. Since only after the 'r' is read the mistake is found the result is rgs for the string.
This bug is valid. Nobody is claiming scanf should pushback two characters, but it needs to report a matching failure rather than accepting "100e" as if it were a valid floating point representation. The C standard could not be more explicit on this matter.
Why shouldn't the scanf() function read "100" from "100e" ?
If it shouldn't read even "100" from "100e" (according to the standard), what it should leave in the input stream after that matching failure ? What is the next character during the next call of a reading function ?
> Why shouldn't the scanf() function read "100" from "100e" ?
Formally, because it's specified not to. See 220.127.116.11:
"An input item is read from the stream, unless the specification includes an n specifier. An input item is defined as the longest sequence of input characters which does not exceed any specified field width and which is, or is a prefix of, a matching input sequence.251) The first character, if any, after the input item remains unread.
... If the input item is not a matching sequence, the execution of the directive fails: this condition is a matching failure. ...
251) fscanf pushes back at most one input character onto the input stream. Therefore, some sequences that are acceptable to strtod, strtol, etc., are unacceptable to fscanf."
Conceptually, because scanf only has one character of "lookahead". "100e" is all read because it's a valid initial sequence of a floating point string. The next character (or EOF) is then inspected and seen not to match, and thus left unread. And the directive is required to fail. glibc basically does this except it wrongly makes the directive succeed and assigns a value to the invalid partial float string.
Duplicate of bug 12701.
*** This bug has been marked as a duplicate of bug 12701 ***