Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
| Path | csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail |
|---|---|
| From | Keith Thompson <kst-u@mib.org> |
| Newsgroups | comp.lang.c |
| Subject | Re: sscanf error checking |
| Date | Wed, 14 Dec 2016 09:34:25 -0800 |
| Organization | None to speak of |
| Lines | 109 |
| Message-ID | <ln8trio1ni.fsf@kst-u.example.com> (permalink) |
| References | <o2rp71$3e7$1@dont-email.me> |
| Mime-Version | 1.0 |
| Content-Type | text/plain; charset=us-ascii |
| Injection-Info | mx02.eternal-september.org; posting-host="f4d023dc7368ee832f7340f59496ea26"; logging-data="17447"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+WJWolFBKB4rsk/daWRXUH" |
| User-Agent | Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) |
| Cancel-Lock | sha1:MhPD7AqCOFes9gtmO2YHyfRHgjw= sha1:kJNrQd4FZIWlU/aGyC44bYOSzxM= |
| Xref | csiph.com comp.lang.c:99360 |
Show key headers only | View raw
BartC <bc@freeuk.com> writes:
> I got the impression, according to the 'while-loop reading from file'
> thread (where I was strongly chastised for being lax with
> error-handling), that 'sscanf' was /the/ way to detect errors in
> numerical input.
Your impression is incorrect.
> But then I come across this:
>
> double x;
> int status;
> char* str = "123..456";
>
> status = sscanf(str,"%lf",&x);
>
> printf("Status = %d\n",status);
> printf("X = %f\n",x);
>
> Output:
>
> Status = 1
> X = 123.000000
Your input starts with a valid floating-point constant, "1.23.".
sscanf successfully parses it. It uses a greedy algorithm (see
the standard for the precise specification), so it doesn't care
that there's invalid data following the valid date.
If I change the format string to "%lf%lf", I get two results,
123.0 (scanned from "123.") and 0.456 (scanned from ".456").
If you want to require spaces between the two constants, you can insert
a "%*[ ]" format specifier, or "%*[ \t\v\r\l]" to accept any white space
characters other than newline. (Please don't assume that I'm arguing
this isn't more complicated than it should be. I'm describing how it
works, not defending it.)
If you're doing this kind of thing, you might consider using a
(non-standard) regular expression library, or perhaps lex/flex.
> The same when scanning "123GARBAGE". It's just stopping when it sees
> something that can't be part of the number without reporting anything
> amiss.
Yes.
> Which is not far off why I do.
What?
> Am I doing something wrong or is sscanf not as great at verifying input
> as is made out?
Made out by whom?
I've pointed out serious problems with the *scanf() function before.
Calling fgets() (or perhaps something that can handle arbitrarily long
lines) followed by sscanf() is generally better than calling scanf().
For one thing, scanf() skips whitespace before each parsed item
*including newline* so it can be bad for line-oriented input. If you're
trying to scan 3 items per line, but one line has only 2 items, scanf()
will get out of synch. Using fgets() to read a line at a time avoids
that.
But it doesn't avoid the other problems with *scanf().
If you want to parse "123..456" to get "123." *and* an indication that
there's garbage after the valid data, you can do something like:
char rest[100];
status = sscanf(str, "%lf%[^\n]", &x, rest);
to capture the rest of the string (`rest` has to be big enough); you can
then examine the contents of rest to decide what to do.
But none of this solves what is in my opinion the very worst feature of
the *scanf() functions. On numeric input, if the input item is
syntactically correct but outside the range of the target type, the
behavior is undefined. N1570 7.21.6.2p10:
If this object does not have an appropriate type, or if the
result of the conversion cannot be represented in the object,
the behavior is undefined.
If you're reading numeric input from a data source that you don't
control, it's impossible to use *scanf() safely.
I would love to see a future C standard change this, so that numeric
overflow is treated as a matching failure or in some well defined
manner.
> Doing strtof("123..456",0) returns 123.0000.
>
> If I do float("123..456") in Python it reports an error.
Sure, if you pass 0 (a null pointer) as the second argument to
strtof(), you're discarding information. strtof() (or strtod()
if you're using type double, as you did in the original example)
will tell you exactly how much of the input it consumed. It also
has well defined behavior on numeric overflow. It's IMHO more
complicated than it should be, but it works.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
sscanf error checking BartC <bc@freeuk.com> - 2016-12-14 15:42 +0000
Re: sscanf error checking John Gordon <gordon@panix.com> - 2016-12-14 15:58 +0000
Re: sscanf error checking Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2016-12-14 11:14 -0500
Re: sscanf error checking gazelle@shell.xmission.com (Kenny McCormack) - 2016-12-14 16:11 +0000
Re: sscanf error checking BartC <bc@freeuk.com> - 2016-12-14 17:51 +0000
Re: sscanf error checking gazelle@shell.xmission.com (Kenny McCormack) - 2016-12-14 18:09 +0000
Re: sscanf error checking Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-14 19:49 +0000
Re: sscanf error checking BartC <bc@freeuk.com> - 2016-12-14 20:43 +0000
Re: sscanf error checking Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-14 16:40 +0000
Re: sscanf error checking Keith Thompson <kst-u@mib.org> - 2016-12-14 09:34 -0800
Re: sscanf error checking Robert Wessel <robertwessel2@yahoo.com> - 2016-12-14 14:52 -0600
Re: sscanf error checking supercat@casperkitty.com - 2016-12-15 07:24 -0800
Re: sscanf error checking Keith Thompson <kst-u@mib.org> - 2016-12-15 11:26 -0800
Re: sscanf error checking Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-12-15 15:35 -0800
Re: sscanf error checking Keith Thompson <kst-u@mib.org> - 2016-12-15 16:28 -0800
Re: sscanf error checking Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-12-15 16:37 -0800
Re: sscanf error checking supercat@casperkitty.com - 2016-12-15 16:38 -0800
Re: sscanf error checking raltbos@xs4all.nl (Richard Bos) - 2016-12-15 20:20 +0000
Re: sscanf error checking Keith Thompson <kst-u@mib.org> - 2016-12-15 12:33 -0800
sscanf error checking asetofsymbols@gmail.com - 2016-12-16 01:49 -0800
sscanf error checking asetofsymbols@gmail.com - 2016-12-16 01:53 -0800
csiph-web