strtod strange behaviour

A

Alessio

Hi,

please see following code:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int i = 0 ;
char szValue[] = "-a";
char *p = NULL;

double a = 0.0;

for ( i = 'a'; i <= 'z'; i++ )
{
a = strtod(szValue, &p);

/* check for error */
if ( *p && p )
{
printf("unable to convert %s\n", szValue);
}
else
{
printf("%s converted is %g\n", szValue, a);
}

++szValue[1];
}

return 0;
}

with lcc-win32 returns

unable to convert -a
unable to convert -b
unable to convert -c
unable to convert -d
-e converted is 0
unable to convert -f
unable to convert -g
unable to convert -h
unable to convert -i
unable to convert -j
unable to convert -k
unable to convert -l
unable to convert -m
unable to convert -n
unable to convert -o
-p converted is 0
unable to convert -q
unable to convert -r
unable to convert -s
unable to convert -t
unable to convert -u
unable to convert -v
unable to convert -w
unable to convert -x
unable to convert -y
unable to convert -z

Why -e and -p is converted to 0 ?
Should be considered a bug ? On PellesC which is based on lcc too, -i
and -n are converted to 0.
Is my "check for error" stuff good ?

Thank you.
 
N

Nick Keighley

Alessio said:

[using strtod() on string of the form "- said:
unable to convert -d
-e converted is 0
unable to convert -f
unable to convert -o
-p converted is 0
Why -e and -p is converted to 0 ?

Perhaps the following quote from the C99 Standard will give you a
clue:

"The components of the exponent part are an e, E, p, or P followed
by an exponent consisting of an optionally signed digit sequence."

ah, but microsoft failed to convert any of them. Does microsoft's
compiler have a bug?
 
J

jacob navia

Alessio said:
Hi,

please see following code:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int i = 0 ;
char szValue[] = "-a";
char *p = NULL;

double a = 0.0;

for ( i = 'a'; i <= 'z'; i++ )
{
a = strtod(szValue, &p);

/* check for error */
if ( *p && p )
{
printf("unable to convert %s\n", szValue);
}
else
{
printf("%s converted is %g\n", szValue, a);
}

++szValue[1];
}

return 0;
}

with lcc-win32 returns

unable to convert -a
unable to convert -b
unable to convert -c
unable to convert -d
-e converted is 0
unable to convert -f
unable to convert -g
unable to convert -h
unable to convert -i
unable to convert -j
unable to convert -k
unable to convert -l
unable to convert -m
unable to convert -n
unable to convert -o
-p converted is 0
unable to convert -q
unable to convert -r
unable to convert -s
unable to convert -t
unable to convert -u
unable to convert -v
unable to convert -w
unable to convert -x
unable to convert -y
unable to convert -z

Why -e and -p is converted to 0 ?
Should be considered a bug ? On PellesC which is based on lcc too, -i
and -n are converted to 0.
Is my "check for error" stuff good ?

Thank you.

Thanks for your bug report. The algorithm of strtod has been modified
as follows:
(0) skip leading spaces and tabs
(1) test for string "nan"
(2) Test for leading "+" or "-". If present, read as many "+"
as there are: (++++++++1 is valid), but only one "-". Skip them.
(3) Test for "inf"
(4) At this point WE MUST HAVE A DECIMAL DIGIT (0-9) If not, there is an
error. This test was missing
(5) test for "0x", if found it is an hexadecimal number. Change base

etc.

This will be in the next release
 
J

Jean-Marc Bourguet

jacob navia said:
Thanks for your bug report. The algorithm of strtod has been modified
as follows:
(0) skip leading spaces and tabs
(1) test for string "nan"
(2) Test for leading "+" or "-". If present, read as many "+"
as there are: (++++++++1 is valid), but only one "-". Skip them.
(3) Test for "inf"
(4) At this point WE MUST HAVE A DECIMAL DIGIT (0-9) If not, there is an
error. This test was missing

+.5 seems valid to me.
(5) test for "0x", if found it is an hexadecimal number. Change base

Yours,
 
F

Fred

Hi,

please see following code:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
        int i = 0 ;
        char szValue[] = "-a";
        char *p = NULL;

        double a = 0.0;

        for ( i = 'a'; i <= 'z'; i++ )
        {
                a = strtod(szValue, &p);

                /* check for error */
                if ( *p && p )

This check is backwards. You should ensure that p is not NULL
*before* you dereference it, not after.

(Others have answered your question about the conversions)
 
K

Keith Thompson

jacob navia said:
(2) Test for leading "+" or "-". If present, read as many "+"
as there are: (++++++++1 is valid), but only one "-". Skip them.
[...]

As Richard H points out, ++++++++1 is not valid.
 
P

Paul N

Alessio wrote:
(snip)
Thanks for your bug report. The algorithm of strtod has been modified
as follows:
(0) skip leading spaces and tabs
(1) test for string "nan"
(2) Test for leading "+" or "-". If present, read as many "+"
    as there are: (++++++++1 is valid), but only one "-". Skip them.
(3) Test for "inf"
(4) At this point WE MUST HAVE A DECIMAL DIGIT (0-9) If not, there is an
    error. This test was missing
(5) test for "0x", if found it is an hexadecimal number. Change base

etc.

This will be in the next release

I may well be missing something here, but - if adding the test at (4)
is the only change, won't there still be a bug? If it converts -e to 0
before the change, adding the test will stop -e or -e5 being
converted, but (on the face of it) would still allow -5e to be
converted. Which looks wrong to me.
 
J

jacob navia

Paul said:
I may well be missing something here, but - if adding the test at (4)
is the only change, won't there still be a bug? If it converts -e to 0
before the change, adding the test will stop -e or -e5 being
converted, but (on the face of it) would still allow -5e to be
converted. Which looks wrong to me.

The exponent can't be zero. Parsing the exponent will be done later.
I fixed that too.

:)

Thanks
 
E

Eric Sosman

More generally, skip leading white space as defined by
isspace(). Note that isspace() is locale-sensitive, so the
suite of white characters may also be locale-dependent.

Possibly followed by additional characters inside parens
(see 7.20.1.3p3). The implementation gets to define the legal
forms of the n-char-sequence inside the parens, and I guess
the implementation can define them to be "none," but as far
as I can see the parens enclosing nothing are still valid
input for strtod().

As others have pointed out, only one leading plus is valid.

Or for "infinity".

A decimal point is also valid here.

YMMV, but I'd have thought putting this test prior to #4
would be simpler. Note that a hexadecimal number cannot have
an E exponent, but may have a P exponent. Also, the 0x may
be immediately followed by a (hexa)decimal point.
The exponent can't be zero. Parsing the exponent will be done later.
I fixed that too.

I guess you mean the exponent can't be empty. It certainly
*can* be zero, as in "1.2e0" or "3.4e+00" or "5.6e-000" (which
looks silly, but seems to be legal).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,061
Latest member
KetonaraKeto

Latest Threads

Top