Reputation: 3415
I have the following c code
if (sscanf(input, "s %d\n", &value) == 1){}
Where it is suppose to parse the following
s -inf
....
s 0
s 1
s 2
....
s inf
but not such things as
s 5junkjunkjunk
Because it shouldn't match as there is something in between %d
and the \n
. Yet it does work even though it doesn't fit the format string.
Upvotes: 0
Views: 1942
Reputation: 153338
After accept answer
inf
is nicely read as a floating point.
Agree scanf()
is cumbersome, but sscanf()
is versatile.
Note: "%n"
reports the number of char
scanned and does not contribute to sscanf()
result.
char buf[100];
if (fgets(buf, sizeof buf, input) == NULL) EOForIOerror();
int n;
double x;
if (sscanf("s %lf %n", &x, &n) != 1 || buf[n]) ScanFailure();
// if needed
if (!isinf(x) && round(x) != x) NumberIsNotInfinityNorWholeNumber();
// x is good to go
Details:
If no legit number is found, sscanf()
does not return 1 and ScanFailure()
is called.
Else is a legit number is found, " %n"
scans any number 0 or more trailing white-spaces such as '\n'
. Then it sets the offset of the scan in n
. This location will be the first non-white-space after the number. If it is not '\0'
then ScanFailure()
is called.
Upvotes: 1
Reputation: 140455
This is (one of the) reasons why one should never use *scanf
: it's ridiculously difficult to get it to handle malformed input robustly.
The correct way to parse something like this is: use fgets
(or getline
if you have it) to read an entire line, manually check for and skip over the leading "s "
, then use strtod
to parse the number, then check whether strtod
set *endp
to point to a newline.
If the syntax is even a little more complicated than what you have it may be time to reach for lex
and yacc
.
Upvotes: 1
Reputation: 51226
If you read the docs for scanf()
, you'll find that every appearance of a whitespace character in the format string matches any number of whitespace characters (including zero) in the input. sscanf()
can't be forced to match an entire string -- it "succeeds" if it matches everything in the format string, even if this leaves other characters (junkjunkjunk
) unconsumed.
Upvotes: 1