http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
On success, the function returns the converted integral number as an int
value. If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.
So how I differ between atoi("poop")
and atoi("0")
and atoi("0000000")
Yes I can loop and check for all zeroes in case I get 0 result, but isn't there a better way?
Notice: I use ANSI C89
atoi returns the integer value represented by the character string up to the first unrecognized character. If no initial segment of the string is a valid integer, the return value is 0. No indication of overflow or other error is returned, so you should validate the string before calling atoi .
The atoi() function returns an int value that is produced by interpreting the input characters as a number. The return value is 0 if the function cannot convert the input to a value of that type. The return value is undefined in the case of an overflow.
It is a perfectly good, sound function from the C standard. If you care about success/failure, then you clearly should not use atoi(); there is no way for it to tell you whether it succeeded and returned 0 or failed and returned 0. atoi is not deprecated it was never in the standard to begin with.
Since strtol() can legitimately return 0, LONG_MAX, or LONG_MIN (LLONG_MAX or LLONG_MIN for strtoll()) on both success and failure, the calling program should set errno to 0 before the call, and then determine if an error occurred by checking whether errno has a nonzero value after the call. According to POSIX.
That's one of the reasons atoi
is sometimes considered unsafe. Use strtol
/ strtoul
instead. And if you have it use strtonum
.
The function atoi
is more dangerous than you might think. The POSIX
standard says:
If the value cannot be represented, the behavior is undefined.
The C99 standard says this also:
7.20.1
The functions atof, atoi, atol, and atoll need not affect the value of the integer expression errno on an error. If the value of the result cannot be represented, the behavior is undefined.
As described by @cnicutar and @ouah, atoi
can't distinguish a valid 0 from an invalid string making the strtol
family better options.
But Why? and How? First understand that both atoi
and strtol
only convert the initial set of numbers in a string to numeric values. Any trailing non-numeric characters are simply ignored. strtol
can be used to check for invalid strings because in addition to a numeric value, it also returns a pointer to the end of the numeric portion of the string. Thus if this end
pointer still refers to the start of the original string, you can tell that there was an error and no characters from the string were converted.
There are a few of other subtleties, as seen in the code example:
long lnum; int num; char *end; errno = 0; lnum = strtol(in_str, &end, 10); //10 specifies base-10 if (end == in_str) //if no characters were converted these pointers are equal fprintf(stderr, "ERROR: can't convert string to number\n"); //If sizeof(int) == sizeof(long), we have to explicitly check for overflows if ((lnum == LONG_MAX || lnum == LONG_MIN) && errno == ERANGE) fprintf(stderr, "ERROR: number out of range for LONG\n"); //Because strtol produces a long, check for overflow if ( (lnum > INT_MAX) || (lnum < INT_MIN) ) fprintf(stderr, "ERROR: number out of range for INT\n"); //Finally convert the result to a plain int (if that's what you want) num = (int) lnum;
Note: If you are sure the input string will be within the valid int range, you can eliminate lnum
and simply cast strtol's return directly: num = (int) strtolen(in_str, &end, 10);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With