Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Facebook Sign In with Google Sign In with OpenID

Categories

We have migrated to a new platform! Please note that you will need to reset your password to log in (your credentials are still in-tact though). Please contact lee@programmersheaven.com if you have questions.
Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

checking for errors using strtod in C

digitalranadigitalrana Posts: 19Member
Hi,
Im writing a C program that accepts some values as command line arguments and performs some calculations on them.

I need the strings read form the command line to be converted to float or double (whichever). That's not a problem. Using either atof() or strtof() (or atod() and strtod()) works fine.

My main problem is trying to handle the error if the user does not enter a floating poin value. I read the specification for strtod() to capture errors but i can't make head or tail of it. Could someone please explain how the error checking part of these functions works?

(e.g.: if the user enters "hello" instead of "5.54353" i need to be able to respond and print and error message saying "floating point value not entered".)

Thanks in advance.
«1

Comments

  • IDKIDK Posts: 1,784Member
    : Hi,
    : Im writing a C program that accepts some values as command line arguments and performs some calculations on them.
    :
    : I need the strings read form the command line to be converted to float or double (whichever). That's not a problem. Using either atof() or strtof() (or atod() and strtod()) works fine.
    :
    : My main problem is trying to handle the error if the user does not enter a floating poin value. I read the specification for strtod() to capture errors but i can't make head or tail of it. Could someone please explain how the error checking part of these functions works?
    :
    : (e.g.: if the user enters "hello" instead of "5.54353" i need to be able to respond and print and error message saying "floating point value not entered".)
    :
    : Thanks in advance.
    :

    This is what I could make out of the man page:

    char a[100];
    char *sp = a, **ep = a+100
    double b;
    scanf("%s");
    b=strtod(a,sp,ep);
    if(b==0&&sp==*ep)
    printf("error");

  • LundinLundin Posts: 3,711Member
    : : Hi,
    : : Im writing a C program that accepts some values as command line arguments and performs some calculations on them.
    : :
    : : I need the strings read form the command line to be converted to float or double (whichever). That's not a problem. Using either atof() or strtof() (or atod() and strtod()) works fine.
    : :
    : : My main problem is trying to handle the error if the user does not enter a floating poin value. I read the specification for strtod() to capture errors but i can't make head or tail of it. Could someone please explain how the error checking part of these functions works?
    : :
    : : (e.g.: if the user enters "hello" instead of "5.54353" i need to be able to respond and print and error message saying "floating point value not entered".)
    : :
    : : Thanks in advance.
    : :
    :
    : This is what I could make out of the man page:
    :
    : char a[100];
    : char *sp = a, **ep = a+100
    : double b;
    : scanf("%s");
    : b=strtod(a,sp,ep);
    : if(b==0&&sp==*ep)
    : printf("error");
    :
    :


    There seems to be a lot of error handling surrounding those strto.. functions. This is what ANSI C says to explain the code posted by IDK:

    [code]
    double strtod(const char * restrict nptr, char ** restrict endptr);

    /--/

    If the subject sequence is empty or does not have the expected form,
    no conversion is performed; the value of nptr is stored in the object
    pointed to by endptr, provided that endptr is not a null pointer.
    [/code]
  • IDKIDK Posts: 1,784Member
    :
    : There seems to be a lot of error handling surrounding those strto.. functions. This is what ANSI C says to explain the code posted by IDK:
    :
    : [code]
    : double strtod(const char * restrict nptr, char ** restrict endptr);
    :
    : /--/
    :
    : If the subject sequence is empty or does not have the expected form,
    : no conversion is performed; the value of nptr is stored in the object
    : pointed to by endptr, provided that endptr is not a null pointer.
    : [/code]
    :

    Ops, made an err...

    Here's the corrected version:
    [code]
    char a[100];
    char **ep = a+100
    double b;
    scanf("%s");
    b=strtod(a,ep);
    if(b==0&&a==*ep)
    printf("error");
    [/code]


    This is what the man page says:
    [code]
    double strtod(const char *nptr, char **endptr);

    ...

    RETURN VALUE
    These functions return the converted value, if any.

    If endptr is not NULL, a pointer to the character after the last char-
    acter used in the conversion is stored in the location referenced by
    endptr.

    If no conversion is performed, zero is returned and the value of nptr
    is stored in the location referenced by endptr.

    If the correct value would cause overflow, plus or minus HUGE_VAL
    (HUGE_VALF, HUGE_VALL) is returned (according to the sign of the
    value), and ERANGE is stored in errno. If the correct value would
    cause underflow, zero is returned and ERANGE is stored in errno.
    [/code]

    A little more complex, and without the restrict qualifier (never seen it before).

    Also, this was listed a little below:
    [code]
    CONFORMING TO
    ANSI C describes strtod, C99 describes the other two functions.
    [/code]

    Where the other two funcs are strof and strtold.
  • LundinLundin Posts: 3,711Member
    : :
    : : There seems to be a lot of error handling surrounding those strto.. functions. This is what ANSI C says to explain the code posted by IDK:
    : :
    : : [code]
    : : double strtod(const char * restrict nptr, char ** restrict endptr);
    : :
    : : /--/
    : :
    : : If the subject sequence is empty or does not have the expected form,
    : : no conversion is performed; the value of nptr is stored in the object
    : : pointed to by endptr, provided that endptr is not a null pointer.
    : : [/code]
    : :
    :
    : Ops, made an err...
    :
    : Here's the corrected version:
    : [code]
    : char a[100];
    : char **ep = a+100
    : double b;
    : scanf("%s");
    : b=strtod(a,ep);
    : if(b==0&&a==*ep)
    : printf("error");
    : [/code]
    :
    :
    : This is what the man page says:
    : [code]
    : double strtod(const char *nptr, char **endptr);
    :
    : ...
    :
    : RETURN VALUE
    : These functions return the converted value, if any.
    :
    : If endptr is not NULL, a pointer to the character after the last char-
    : acter used in the conversion is stored in the location referenced by
    : endptr.
    :
    : If no conversion is performed, zero is returned and the value of nptr
    : is stored in the location referenced by endptr.
    :
    : If the correct value would cause overflow, plus or minus HUGE_VAL
    : (HUGE_VALF, HUGE_VALL) is returned (according to the sign of the
    : value), and ERANGE is stored in errno. If the correct value would
    : cause underflow, zero is returned and ERANGE is stored in errno.
    : [/code]
    :
    : A little more complex, and without the restrict qualifier (never seen it before).
    :
    : Also, this was listed a little below:
    : [code]
    : CONFORMING TO
    : ANSI C describes strtod, C99 describes the other two functions.
    : [/code]
    :
    : Where the other two funcs are strof and strtold.
    :


    I posted only the relevant part of the description, the whole text is 2 pages. restrict is a C99 invention, if I remember correctly it is there to prevent several pointers to mess around with the same memory location. When implementing memcpy() for example:

    void *memcpy(void * restrict s1, const void * restrict s2, size_t n);

    The compiler manufacturer can be sure that s1 and s2 aren't pointing at the same memory location, and therefore make the function more efficient.
  • IDKIDK Posts: 1,784Member
    :
    : I posted only the relevant part of the description.

    Me to, the whole text is about 4 pages.
    I think the overflow checking is very relevant.


    And the main reason I posted it was that I found this strange:
    Ansi C: double strtod(const char * restrict nptr, char ** restrict ndptr);
    Man (C99): double strtod(const char *nptr, char **endptr);

    This means that this could happen (becouse memcpy is defined void *memcpy(void *dest, const void *src, size_t n)):
    memcpy(a,a);
    And that would be bad...
  • LundinLundin Posts: 3,711Member
    Note that C99 is just a draft standard and not many compilers support it. Correct me if I'm wrong, but I doubt that 'man' would refer to C99?

    : memcpy(a,a);

    Yep, that is undefined behaviour in "classic" C. In C99 I believe you would get a compiler error. But imo, the programmer that writes memcpy() to copy "source" to the same location as "destination" will have to suit themselves, because then they have likely got a bug in the code.
  • IDKIDK Posts: 1,784Member
    [b][red]This message was edited by IDK at 2006-8-28 2:43:22[/red][/b][hr]
    : Note that C99 is just a draft standard and not many compilers support it. Correct me if I'm wrong, but I doubt that 'man' would refer to C99?
    :

    man refers to, as listed before:

    [code]
    man strtod:
    CONFORMING TO
    ANSI C describes strtod, C99 describes the other two functions.

    man memcpy:
    CONFORMING TO
    SVID 3, BSD 4.3, ISO 9899
    [/code]

    : : memcpy(a,a);
    :
    : Yep, that is undefined behaviour in "classic" C. In C99 I believe you would get a compiler error. But imo, the programmer that writes memcpy() to copy "source" to the same location as "destination" will have to suit themselves, because then they have likely got a bug in the code.
    :

    memcpy(a,a+1); should also give compile error, but it could be usefull.


  • Gregry2Gregry2 Posts: 607Member
    : [b][red]This message was edited by IDK at 2006-8-28 2:43:22[/red][/b][hr]
    : : Note that C99 is just a draft standard and not many compilers support it. Correct me if I'm wrong, but I doubt that 'man' would refer to C99?
    : :
    :
    : man refers to, as listed before:
    :
    : [code]
    : man strtod:
    : CONFORMING TO
    : ANSI C describes strtod, C99 describes the other two functions.
    :
    : man memcpy:
    : CONFORMING TO
    : SVID 3, BSD 4.3, ISO 9899
    : [/code]
    :
    : : : memcpy(a,a);
    : :
    : : Yep, that is undefined behaviour in "classic" C. In C99 I believe you would get a compiler error. But imo, the programmer that writes memcpy() to copy "source" to the same location as "destination" will have to suit themselves, because then they have likely got a bug in the code.
    : :
    :
    : memcpy(a,a+1); should also give compile error, but it could be usefull.
    :
    :
    :

    What about memmove()?
    {2}rIng
  • LundinLundin Posts: 3,711Member
    [b][red]This message was edited by Lundin at 2006-8-28 23:35:12[/red][/b][hr]
    : : [b][red]This message was edited by IDK at 2006-8-28 2:43:22[/red][/b][hr]
    : : : Note that C99 is just a draft standard and not many compilers support it. Correct me if I'm wrong, but I doubt that 'man' would refer to C99?
    : : :
    : :
    : : man refers to, as listed before:
    : :
    : : [code]
    : : man strtod:
    : : CONFORMING TO
    : : ANSI C describes strtod, C99 describes the other two functions.
    : :
    : : man memcpy:
    : : CONFORMING TO
    : : SVID 3, BSD 4.3, ISO 9899
    : : [/code]
    : :
    : : : : memcpy(a,a);
    : : :
    : : : Yep, that is undefined behaviour in "classic" C. In C99 I believe you would get a compiler error. But imo, the programmer that writes memcpy() to copy "source" to the same location as "destination" will have to suit themselves, because then they have likely got a bug in the code.
    : : :
    : :
    : : memcpy(a,a+1); should also give compile error, but it could be usefull.
    : :
    : :
    : :
    :
    : What about memmove()?
    : {2}rIng
    :

    memmove() is almost the same thing as memcpy() : it is safer, but not as fast. Should be identical in C90 and C99:

    7.21.2.2 The memmove function

    Synopsis
    #include
    void *memmove(void *s1, const void *s2, size_t n);

    Description
    The memmove function copies n characters from the object pointed to by
    s2 into the object pointed to by s1. Copying takes place as if the n
    characters from the object pointed to by s2 are first copied into a
    temporary array of n characters that does not overlap the objects
    pointed to by s1 and s2, and then the n characters from the temporary array are copied into the object pointed to by s1.


  • BitByBit_ThorBitByBit_Thor Posts: 2,444Member
    : Here's the corrected version:
    : [code]
    : char a[100];
    : char **ep = a+100
    : double b;
    : scanf("%s");
    : b=strtod(a,ep);
    : if(b==0&&a==*ep)
    : printf("error");
    : [/code]
    :
    :
    : This is what the man page says:
    : [code]
    : double strtod(const char *nptr, char **endptr);
    :
    : ...
    :
    : RETURN VALUE
    : These functions return the converted value, if any.
    :
    : If endptr is not NULL, a pointer to the character after the last char-
    : acter used in the conversion is stored in the location referenced by
    : endptr.
    :
    : If no conversion is performed, zero is returned and the value of nptr
    : is stored in the location referenced by endptr.
    :
    : If the correct value would cause overflow, plus or minus HUGE_VAL
    : (HUGE_VALF, HUGE_VALL) is returned (according to the sign of the
    : value), and ERANGE is stored in errno. If the correct value would
    : cause underflow, zero is returned and ERANGE is stored in errno.
    : [/code]
    :

    Sorry if this seems like a stupid question, but I always get confused with pointers (as a lot of people do).
    Why is endptr a **, and not just a *?

    Best Regards,
    Richard

«1
Sign In or Register to comment.