[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

strtod usage for "just the number"?

David Mathog

4/28/2011 7:06:00 PM

The C string to double conversion functions all seem to operate on the
front of the input string, turning as much of it is as possible into a
number. In a situation where the string should be entirely the
number, and nothing should follow it, the best I have come up with to
handle this case is:

char *atoken;
char *to;
double dtmp;
/* lots of other stuff, generating atoken */
errno=0;
dtmp=strtod(atoken,&to);
if(errno || !to || *to != '\0'){
fprintf(stderr,"fatal error: incorrect number syntax
%s",atoken);
}

It works but isn't very pretty, what with 3 tests for the various
failure modes. Is there another way to go about this, more along the
lines of:

if(cvtS2D(atoken,&dtmp)){
}

?
Where the hypothetical conversion function returns 0 if the input
string is just a number, and something
else for all the other cases?

Thanks,

David Mathog
11 Answers

Fred

4/28/2011 7:38:00 PM

0

On Apr 28, 12:05 pm, David Mathog <dmat...@gmail.com> wrote:
> The C string to double conversion functions all seem to operate on the
> front of the input string, turning as much of it is as possible into a
> number.  In a situation where the string should be entirely the
> number, and nothing should follow it, the best I have come up with to
> handle this case is:
>
> char *atoken;
> char *to;
> double dtmp;
>        /* lots of other stuff, generating atoken */
>         errno=0;
>         dtmp=strtod(atoken,&to);
>         if(errno || !to || *to != '\0'){
>           fprintf(stderr,"fatal error: incorrect number syntax
> %s",atoken);
>         }
>
> It works but isn't very pretty, what with 3 tests for the various
> failure modes.  Is there another way to go about this, more along the
> lines of:
>
>   if(cvtS2D(atoken,&dtmp)){
>   }
>
> ?
> Where the hypothetical conversion function returns 0 if the input
> string is just a number, and something
> else for all the other cases?
>

strtod only sets errno if a range error occurred, so you do not need
that check to determine whether the field had bad characters in it.

You do not need the check (*to != '\0') since if 'to' is not NULL, it
points to the first unused character, which is guaranteed to be
something other than the NUL character.

That leaves you with:
if ( to ) { ... }
--
Fred K

China Blue Veins

4/28/2011 7:43:00 PM

0

In article <80cfb36d-0f07-4c7f-844b-3385e074af28@18g2000prd.googlegroups.com>,
David Mathog <dmathog@gmail.com> wrote:

> The C string to double conversion functions all seem to operate on the
> front of the input string, turning as much of it is as possible into a
> number. In a situation where the string should be entirely the
> number, and nothing should follow it, the best I have come up with to
> handle this case is:
>
> char *atoken;
> char *to;
> double dtmp;
> /* lots of other stuff, generating atoken */
> errno=0;
> dtmp=strtod(atoken,&to);
> if(errno || !to || *to != '\0'){
> fprintf(stderr,"fatal error: incorrect number syntax
> %s",atoken);
> }
>
> It works but isn't very pretty, what with 3 tests for the various
> failure modes. Is there another way to go about this, more along the
> lines of:
>
> if(cvtS2D(atoken,&dtmp)){
> }
>
> ?
> Where the hypothetical conversion function returns 0 if the input
> string is just a number, and something
> else for all the other cases?

Sure. Add the following code:

int cvtS2D(char *string, double *value) {
errno=0;
*value=strtod(atoken,&to);
if(errno || !to || *to != '\0'){
fprintf(stderr,"fatal error: incorrect number syntax %s",atoken);
return 0;
}else
return 1;
}
...
if(cvtS2D(atoken,&dtmp)){
...
}

Hint: you can always add your own layer in front stdlib.

--
Damn the living - It's a lovely life. I'm whoever you want me to be.
Silver silverware - Where is the love? At least I can stay in character.
Oval swimming pool - Where is the love? Annoying Usenet one post at a time.
Damn the living - It's a lovely life. Why does Harmony have blue veins?

David Resnick

4/28/2011 8:20:00 PM

0

On Apr 28, 3:05 pm, David Mathog <dmat...@gmail.com> wrote:
> The C string to double conversion functions all seem to operate on the
> front of the input string, turning as much of it is as possible into a
> number.  In a situation where the string should be entirely the
> number, and nothing should follow it, the best I have come up with to
> handle this case is:
>
> char *atoken;
> char *to;
> double dtmp;
>        /* lots of other stuff, generating atoken */
>         errno=0;
>         dtmp=strtod(atoken,&to);
>         if(errno || !to || *to != '\0'){
>           fprintf(stderr,"fatal error: incorrect number syntax
> %s",atoken);
>         }
>
> It works but isn't very pretty, what with 3 tests for the various
> failure modes.  Is there another way to go about this, more along the
> lines of:
>
>   if(cvtS2D(atoken,&dtmp)){
>   }
>
> ?
> Where the hypothetical conversion function returns 0 if the input
> string is just a number, and something
> else for all the other cases?
>

Why not just write your own function that does what the one above
does?
Lets you also control whether things that strtod will accept like
NAN or INFINITY or hex forms should count as "numbers".

-David

Ben Bacarisse

4/28/2011 8:30:00 PM

0

Fred <fred.l.kleinschmidt@boeing.com> writes:

> On Apr 28, 12:05 pm, David Mathog <dmat...@gmail.com> wrote:
>> The C string to double conversion functions all seem to operate on the
>> front of the input string, turning as much of it is as possible into a
>> number.  In a situation where the string should be entirely the
>> number, and nothing should follow it, the best I have come up with to
>> handle this case is:
>>
>> char *atoken;
>> char *to;
>> double dtmp;
>>        /* lots of other stuff, generating atoken */
>>         errno=0;
>>         dtmp=strtod(atoken,&to);
>>         if(errno || !to || *to != '\0'){
>>           fprintf(stderr,"fatal error: incorrect number syntax
>> %s",atoken);
>>         }
>>
>> It works but isn't very pretty, what with 3 tests for the various
>> failure modes.  Is there another way to go about this, more along the
>> lines of:
>>
>>   if(cvtS2D(atoken,&dtmp)){
>>   }
>>
>> ?
>> Where the hypothetical conversion function returns 0 if the input
>> string is just a number, and something
>> else for all the other cases?
>>
>
> strtod only sets errno if a range error occurred, so you do not need
> that check to determine whether the field had bad characters in it.
>
> You do not need the check (*to != '\0') since if 'to' is not NULL, it
> points to the first unused character, which is guaranteed to be
> something other than the NUL character.
>
> That leaves you with:
> if ( to ) { ... }

I don't think that's right. If the programmer passes a valid pointer
as the second argument, it will get set to something -- either the value
of the first argument if no conversion could be done or to point just
past the converted data (even if that is a null byte).

As a result 'to == atoken || *to' is a sufficient test for failure in
this case.

--
Ben.

Fred

4/28/2011 8:47:00 PM

0

On Apr 28, 1:30 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> Fred <fred.l.kleinschm...@boeing.com> writes:
> > On Apr 28, 12:05 pm, David Mathog <dmat...@gmail.com> wrote:
> >> The C string to double conversion functions all seem to operate on the
> >> front of the input string, turning as much of it is as possible into a
> >> number.  In a situation where the string should be entirely the
> >> number, and nothing should follow it, the best I have come up with to
> >> handle this case is:
>
> >> char *atoken;
> >> char *to;
> >> double dtmp;
> >>        /* lots of other stuff, generating atoken */
> >>         errno=0;
> >>         dtmp=strtod(atoken,&to);
> >>         if(errno || !to || *to != '\0'){
> >>           fprintf(stderr,"fatal error: incorrect number syntax
> >> %s",atoken);
> >>         }
>
> >> It works but isn't very pretty, what with 3 tests for the various
> >> failure modes.  Is there another way to go about this, more along the
> >> lines of:
>
> >>   if(cvtS2D(atoken,&dtmp)){
> >>   }
>
> >> ?
> >> Where the hypothetical conversion function returns 0 if the input
> >> string is just a number, and something
> >> else for all the other cases?
>
> > strtod only sets errno if a range error occurred, so you do not need
> > that check to determine whether the field had bad characters in it.
>
> > You do not need the check  (*to != '\0') since if 'to' is not NULL, it
> > points to the first unused character, which is guaranteed to be
> > something other than the NUL character.
>
> > That leaves you with:
> >    if ( to ) { ... }
>
> I don't think that's right.  If the programmer passes a valid pointer
> as the second argument, it will get set to something -- either the value
> of the first argument if no conversion could be done or to point just
> past the converted data (even if that is a null byte).
>
> As a result 'to == atoken || *to' is a sufficient test for failure in
> this case.
>

You're right. The first test (to==token) is needed in case 'token'
is empty, in which case *to is '\0', so just checking *to is
not sufficient to test for failure.

--
Fred K

lawrence.jones

4/28/2011 9:01:00 PM

0

David Mathog <dmathog@gmail.com> wrote:
> The C string to double conversion functions all seem to operate on the
> front of the input string, turning as much of it is as possible into a
> number. In a situation where the string should be entirely the
> number, and nothing should follow it, the best I have come up with to
> handle this case is:
>
> char *atoken;
> char *to;
> double dtmp;
> /* lots of other stuff, generating atoken */
> errno=0;
> dtmp=strtod(atoken,&to);
> if(errno || !to || *to != '\0'){
> fprintf(stderr,"fatal error: incorrect number syntax %s",atoken);
> }

That isn't quite correct. strtod() will never set "to" to a null
pointer, but it will set it equal to atoken if no conversion could be
performed.

> It works but isn't very pretty, what with 3 tests for the various
> failure modes. Is there another way to go about this, more along the
> lines of:
>
> if(cvtS2D(atoken,&dtmp)){
> }

int cvtS2D(const char * restrict p, double * restrict d)
{
char *q;
errno = 0;
*d = strtod(p, &q);
return (errno != 0 || q == p || *q != '\0');
}
--
Larry Jones

It's going to be a long year. -- Calvin

katmac

4/30/2011 4:29:00 AM

0

On Apr 28, 3:05 pm, David Mathog <dmat...@gmail.com> wrote:
> The C string to double conversion functions all seem to operate on the
> front of the input string, turning as much of it is as possible into a
> number.  In a situation where the string should be entirely the
> number, and nothing should follow it, the best I have come up with to
> handle this case is:
>
> char *atoken;
> char *to;
> double dtmp;
>        /* lots of other stuff, generating atoken */
>         errno=0;
>         dtmp=strtod(atoken,&to);
>         if(errno || !to || *to != '\0'){
>           fprintf(stderr,"fatal error: incorrect number syntax
> %s",atoken);
>         }
>
> It works but isn't very pretty, what with 3 tests for the various
> failure modes.  Is there another way to go about this, more along the
> lines of:
>
>   if(cvtS2D(atoken,&dtmp)){
>   }
>
> ?
> Where the hypothetical conversion function returns 0 if the input
> string is just a number, and something
> else for all the other cases?
>
> Thanks,
>
> David Mathog

char junk;
return !(sscanf( atoken, "%lf%c", dtmp, &junk ) == 1);

The same pattern can be used for anything sscanf can decode (which is
quite a lot)

Jorgen Grahn

4/30/2011 2:02:00 PM

0

On Thu, 2011-04-28, David Mathog wrote:
> The C string to double conversion functions all seem to operate on the
> front of the input string, turning as much of it is as possible into a
> number. In a situation where the string should be entirely the
> number, and nothing should follow it, the best I have come up with to
> handle this case is:
....
> It works but isn't very pretty, what with 3 tests for the various
> failure modes. Is there another way to go about this, more along the
> lines of:
>
> if(cvtS2D(atoken,&dtmp)){
> }

With these functions I tend to prefer returning the value and
passing a pointer to an errno-like error:

double cvtS2D(const char* buf, int* error);

int err = 0;
const double foo = cvsS2D(buf, &err);
const double bar = cvsS2D(buf2, &err);
if(err) // at least one input was broken

Although tastes (and usage patterns) vary.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Keith Thompson

4/30/2011 3:55:00 PM

0

katmac <bkattwinkel@gmail.com> writes:
> On Apr 28, 3:05 pm, David Mathog <dmat...@gmail.com> wrote:
>> The C string to double conversion functions all seem to operate on the
>> front of the input string, turning as much of it is as possible into a
>> number.  In a situation where the string should be entirely the
>> number, and nothing should follow it, the best I have come up with to
>> handle this case is:
>>
>> char *atoken;
>> char *to;
>> double dtmp;
>>        /* lots of other stuff, generating atoken */
>>         errno=0;
>>         dtmp=strtod(atoken,&to);
>>         if(errno || !to || *to != '\0'){
>>           fprintf(stderr,"fatal error: incorrect number syntax
>> %s",atoken);
>>         }
>>
>> It works but isn't very pretty, what with 3 tests for the various
>> failure modes.  Is there another way to go about this, more along the
>> lines of:
>>
>>   if(cvtS2D(atoken,&dtmp)){
>>   }
>>
>> ?
>> Where the hypothetical conversion function returns 0 if the input
>> string is just a number, and something
>> else for all the other cases?
>
> char junk;
> return !(sscanf( atoken, "%lf%c", dtmp, &junk ) == 1);
>
> The same pattern can be used for anything sscanf can decode (which is
> quite a lot)

Unfortunately, if the string being scanned represents a number
outside the range of the target type, the behavior of sscanf is
undefined. See C99 7.19.6.2p10 (it's split across pages in n1256).

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

David Mathog

5/2/2011 3:47:00 PM

0

On Apr 30, 7:01 am, Jorgen Grahn <grahn+n...@snipabacken.se> wrote:
> On Thu, 2011-04-28, David Mathog wrote:
>
> >   if(cvtS2D(atoken,&dtmp)){
> >   }
>
> With these functions I tend to prefer returning the value and
> passing a pointer to an errno-like error:
>
>    double cvtS2D(const char* buf, int* error);
>
>    int err = 0;
>    const double foo = cvsS2D(buf, &err);
>    const double bar = cvsS2D(buf2, &err);
>    if(err) // at least one input was broken
>
> Although tastes (and usage patterns) vary.

Right, styles vary. I would have done that like:

if(!cvtS2D(buf1,&dtmp1)){ boom("message1"); }
if(!cvtS2D(buf2,&dtmp2)){ boom("message2"); }

Either way, the important part is that the function returns ONE
unambiguous status value, which I think is better than having to check
multiple values to see if there was a problem or not. There are a lot
of C functions that follow the second path, including and especially
all those that depend on errno,
where one must look at one value for "the operation did not work (or
maybe it did but this might be a special case)" and another value for
"the problem was (or wasn't) ...". For instance, fscanf returning
EOF.

Regards,

David Mathog