string to int

Discussion in 'C Programming' started by arnuld, Apr 11, 2012.

  1. arnuld

    arnuld Guest

    I know we strtol() converts to long but I want to convert to an int. atoi
    () does not detect errors so I don't think its advised to use it. I am
    using strtol() anyway but putting check for INT_MAX and INT_MIN values. I
    can not check for overflow/underflow because INT_MIN,MAX and LONG_MIN,MAX
    have same values on my system. Can someone check of this behaves
    correctly ?


    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <limits.h>


    enum { VAL_SUCC = 0,
    VAL_ERR = -1
    };

    int str_to_int(const char* , int* );

    int main(void)
    {
    const char* x = "-2147483648";
    int i = 0;

    printf(" i = %d, x = %s\n", i, x);
    if( 0 > str_to_int(x, &i))
    {
    printf("IN: %s @%d: ERROR in Conversion :%s\n", __func__, __LINE__,
    __FILE__);
    }
    printf(" i = %d, x = %s\n", i, x);
    printf("INT_MAX = %d\n", INT_MAX);
    printf("LONG_MAX = %ld\n", LONG_MAX);
    printf("LONG_MIN = %ld\n", LONG_MIN);

    return 0;
    }


    int str_to_int(const char* str, int* ip)
    {
    char *endptr;
    long val;
    int ret;

    errno = 0; /* To distinguish success/failure after call */
    val = strtol(str, &endptr, 10);

    /* Check for various possible errors */
    if ((ERANGE == errno && (LONG_MAX == val || LONG_MIN == val)) ||
    ((0 != errno) && (0 == val)))
    {
    perror("strtol");
    ret = -1;
    }
    else if(endptr == str)
    {
    fprintf(stderr, "No digits were found\n");
    ret = -1;
    }
    else /* If we got here, strtol() successfully parsed a number */
    {
    printf("strtol() returned %ld\n", val);
    if ('\0' != *endptr) /* Not necessarily an error... */
    {
    printf("Further characters after number: %s\n", endptr);
    }

    if(INT_MAX < val || INT_MIN > val)
    {
    printf("IN: Value is greater/lower than what int can handle.
    Can not represent it in an integer\n");
    ret = -1;
    }
    else
    {
    *ip = val;
    ret = 0;
    }
    }

    return ret;
    }

    =========================== OUTPUT ===========================
    ~/programs/C $ ./a.out
    i = 0, x = -2147483648
    strtol() returned -2147483648
    i = -2147483648, x = -2147483648
    INT_MAX = 2147483647
    LONG_MAX = 2147483647
    LONG_MIN = -2147483648
    ~/programs/C $





    --
    arnuld
    http://LispMachine.Wordpress.com
     
    arnuld, Apr 11, 2012
    #1
    1. Advertising

  2. On 11 Apr 2012 11:22:40 GMT, arnuld <> wrote:

    >I know we strtol() converts to long but I want to convert to an int. atoi
    >() does not detect errors so I don't think its advised to use it. I am
    >using strtol() anyway but putting check for INT_MAX and INT_MIN values. I
    >can not check for overflow/underflow because INT_MIN,MAX and LONG_MIN,MAX
    >have same values on my system. Can someone check of this behaves
    >correctly ?
    >
    >
    >#include <stdio.h>
    >#include <stdlib.h>
    >#include <string.h>
    >#include <errno.h>
    >#include <limits.h>
    >
    >
    >enum { VAL_SUCC = 0,
    > VAL_ERR = -1
    >};
    >
    >int str_to_int(const char* , int* );
    >
    >int main(void)
    >{
    > const char* x = "-2147483648";
    > int i = 0;
    >
    > printf(" i = %d, x = %s\n", i, x);
    > if( 0 > str_to_int(x, &i))
    > {
    > printf("IN: %s @%d: ERROR in Conversion :%s\n", __func__, __LINE__,
    >__FILE__);
    > }
    > printf(" i = %d, x = %s\n", i, x);
    > printf("INT_MAX = %d\n", INT_MAX);
    > printf("LONG_MAX = %ld\n", LONG_MAX);
    > printf("LONG_MIN = %ld\n", LONG_MIN);
    >
    > return 0;
    >}
    >
    >
    >int str_to_int(const char* str, int* ip)
    >{
    > char *endptr;
    > long val;
    > int ret;
    >
    > errno = 0; /* To distinguish success/failure after call */
    > val = strtol(str, &endptr, 10);
    >
    > /* Check for various possible errors */
    > if ((ERANGE == errno && (LONG_MAX == val || LONG_MIN == val)) ||


    If errno == ERANGE, then there is no need to test val. It is
    guaranteed to be one of the extreme values.

    > ((0 != errno) && (0 == val)))


    If val = 0, strtol need not set errno so it may still be zero. You
    need to test endptr, not errno.

    > {
    > perror("strtol");
    > ret = -1;
    > }
    > else if(endptr == str)
    > {
    > fprintf(stderr, "No digits were found\n");
    > ret = -1;
    > }
    > else /* If we got here, strtol() successfully parsed a number */
    > {
    > printf("strtol() returned %ld\n", val);
    > if ('\0' != *endptr) /* Not necessarily an error... */
    > {
    > printf("Further characters after number: %s\n", endptr);
    > }
    >
    > if(INT_MAX < val || INT_MIN > val)
    > {
    > printf("IN: Value is greater/lower than what int can handle.
    >Can not represent it in an integer\n");
    > ret = -1;
    > }
    > else
    > {
    > *ip = val;
    > ret = 0;
    > }
    > }
    >
    > return ret;
    >}
    >
    >=========================== OUTPUT ===========================
    >~/programs/C $ ./a.out
    > i = 0, x = -2147483648
    >strtol() returned -2147483648
    > i = -2147483648, x = -2147483648
    >INT_MAX = 2147483647
    >LONG_MAX = 2147483647
    >LONG_MIN = -2147483648
    >~/programs/C $


    --
    Remove del for email
     
    Barry Schwarz, Apr 11, 2012
    #2
    1. Advertising

  3. arnuld

    arnuld Guest

    > On Wed, 11 Apr 2012 10:49:17 -0700, Barry Schwarz wrote:

    >> On 11 Apr 2012 11:22:40 GMT, arnuld <> wrote:


    >> ...SNIP....
    >> errno = 0; /* To distinguish success/failure after call */ val =
    >> strtol(str, &endptr, 10);
    >>
    >> /* Check for various possible errors */ if ((ERANGE == errno &&
    >> (LONG_MAX == val || LONG_MIN == val)) ||


    > If errno == ERANGE, then there is no need to test val. It is guaranteed
    > to be one of the extreme values.



    In some post I read (don't remember which newsgroup) that errno can be
    set by some library function even if there is no error. for that case I
    tested the rest. This code actually is taken from man page of strtol.



    >> ((0 != errno) && (0 == val)))

    >
    > If val = 0, strtol need not set errno so it may still be zero. You need
    > to test endptr, not errno.


    I trusted man page. Now I guess I am wrong :(







    --
    arnuld
    http://LispMachine.Wordpress.com
     
    arnuld, Apr 12, 2012
    #3
  4. On 12 Apr 2012 05:25:35 GMT, arnuld <> wrote:

    >> On Wed, 11 Apr 2012 10:49:17 -0700, Barry Schwarz wrote:

    >
    >>> On 11 Apr 2012 11:22:40 GMT, arnuld <> wrote:

    >
    >>> ...SNIP....
    >>> errno = 0; /* To distinguish success/failure after call */ val =
    >>> strtol(str, &endptr, 10);
    >>>
    >>> /* Check for various possible errors */ if ((ERANGE == errno &&
    >>> (LONG_MAX == val || LONG_MIN == val)) ||

    >
    >> If errno == ERANGE, then there is no need to test val. It is guaranteed
    >> to be one of the extreme values.

    >
    >
    >In some post I read (don't remember which newsgroup) that errno can be
    >set by some library function even if there is no error. for that case I
    >tested the rest. This code actually is taken from man page of strtol.


    Beware of half remembered statements or ones taken out of context.

    7.5-3 states "The value of errno is zero at program startup, but is
    never set to zero by any library function. The value of errno may be
    set to nonzero by a library function call whether or not there is an
    error, provided the use of errno is not documented in the description
    of the function in this International Standard."

    Since the use of errno is documented for strtol, you are guaranteed
    that if errno == ERANGE, then the value has been set to one of the two
    extremes as described in 7.20.1.4-8.

    >
    >
    >
    >>> ((0 != errno) && (0 == val)))

    >>
    >> If val = 0, strtol need not set errno so it may still be zero. You need
    >> to test endptr, not errno.

    >
    >I trusted man page. Now I guess I am wrong :(


    Even if a man page is correct, it only describes your particular
    system. What happens if you upgrade your system or switch to a
    different compiler?

    If you want to know what the language requires, n1256 (C99) and n1570
    (C11) are available for free downloading.

    --
    Remove del for email
     
    Barry Schwarz, Apr 12, 2012
    #4
  5. arnuld

    Phil Carmody Guest

    Kenneth Brody <> writes:
    > On 4/11/2012 7:22 AM, arnuld wrote:
    > > I know we strtol() converts to long but I want to convert to an int. atoi
    > > () does not detect errors so I don't think its advised to use it. I am
    > > using strtol() anyway but putting check for INT_MAX and INT_MIN values. I
    > > can not check for overflow/underflow because INT_MIN,MAX and LONG_MIN,MAX
    > > have same values on my system. Can someone check of this behaves
    > > correctly ?

    > [...]
    >
    > If INT_MIN/LONG_MIN, and INT_MAX/LONG_MAX are the same on your system,
    > then int and long have the same range, meaning that there is no reason
    > to check the return of strtol() to see if it's outside the range of
    > int.
    >
    > However, to be portable, your code could do something like this:
    >
    > long val;
    >
    > ... call to strtol() ...
    >
    > #if INT_MAX != LONG_MAX && INT_MIN != LONG_MIN


    ||

    > if ( val < INT_MIN || val > INT_MAX )


    If the #if is removed, then this might be optimised to a no-op
    in the cases where the #if would be false. Depending on QoI.

    > {
    > ... handle error condition here ...
    > }
    > #endif
    > return((int)val);
    >
    >
    > --
    > Kenneth Brody


    --
    > I'd argue that there is much evidence for the existence of a God.

    Pics or it didn't happen.
    -- Tom (/. uid 822)
     
    Phil Carmody, Apr 14, 2012
    #5
  6. arnuld

    Tim Rentsch Guest

    arnuld <> writes:

    > I know we strtol() converts to long but I want to convert to an int. atoi
    > () does not detect errors so I don't think its advised to use it. I am
    > using strtol() anyway but putting check for INT_MAX and INT_MIN values. I
    > can not check for overflow/underflow because INT_MIN,MAX and LONG_MIN,MAX
    > have same values on my system. Can someone check of this behaves
    > correctly ?
    >


    > [snip]
    >
    > int str_to_int(const char* str, int* ip)
    > {
    > char *endptr;
    > long val;
    > int ret;
    >
    > errno = 0; /* To distinguish success/failure after call */
    > val = strtol(str, &endptr, 10);
    >
    > /* Check for various possible errors */
    > if ((ERANGE == errno && (LONG_MAX == val || LONG_MIN == val)) ||
    > ((0 != errno) && (0 == val)))
    > {
    > perror("strtol");
    > ret = -1;
    > }
    > else if(endptr == str)
    > {
    > fprintf(stderr, "No digits were found\n");
    > ret = -1;
    > }
    > else /* If we got here, strtol() successfully parsed a number */
    > {
    > printf("strtol() returned %ld\n", val);
    > if ('\0' != *endptr) /* Not necessarily an error... */
    > {
    > printf("Further characters after number: %s\n", endptr);
    > }
    >
    > if(INT_MAX < val || INT_MIN > val)
    > {
    > printf("IN: Value is greater/lower than what int can handle.
    > Can not represent it in an integer\n");
    > ret = -1;
    > }
    > else
    > {
    > *ip = val;
    > ret = 0;
    > }
    > }
    >
    > return ret;
    > }
    >
    > [snip]


    The amazing thing about this code is that a whole integer
    conversion routine, including the range checks, can be
    written more succinctly than this. Try doing that as your
    exercise, it will help your learning a lot.
     
    Tim Rentsch, May 7, 2012
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Schnoffos
    Replies:
    2
    Views:
    1,252
    Martien Verbruggen
    Jun 27, 2003
  2. Hal Styli
    Replies:
    14
    Views:
    1,713
    Old Wolf
    Jan 20, 2004
  3. arun
    Replies:
    8
    Views:
    484
    Dave Thompson
    Jul 31, 2006
  4. aling
    Replies:
    8
    Views:
    1,038
    Jim Langston
    Oct 20, 2005
  5. Replies:
    9
    Views:
    467
    James Kanze
    Apr 17, 2007
Loading...

Share This Page