string to int


A

arnuld

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 $
 
Ad

Advertisements

B

Barry Schwarz

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.
 
A

arnuld

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.


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 :(
 
B

Barry Schwarz

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.
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.
 
P

Phil Carmody

Kenneth Brody said:
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);
Pics or it didn't happen.
-- Tom (/. uid 822)
 
Ad

Advertisements

T

Tim Rentsch

arnuld said:
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.
 
Ad

Advertisements


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

Similar Threads


Top