When using the function atoi
(or strtol
or similar functions for that matter), how can you tell if the integer conversion failed or if the C-string that was being converted was a 0
?
For what I'm doing, 0
is an acceptable value and the C-string being converted may contain any number of 0
s. It may also have leading whitespace.
Return Value 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.
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 .
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.
Returns. The atoi function returns the integer representation of a string. The atoi function skips all white-space characters at the beginning of the string, converts the subsequent characters as part of the number, and then stops when it encounters the first character that isn't a number.
The proper function (as long as you are insisting on using C-style functions) is strtol
and the conversion code might look as follows
const char *number = "10"; /* for example */ char *end; long value = strtol(number, &end, 10); if (end == number || *end != '\0' || errno == ERANGE) /* ERROR, abort */; /* Success */ /* Add whatever range checks you want to have on the value of `value` */
Some remarks:
strtol
allows (meaning: quietly skips) whitespace in front of the actual number. If you what to treat such leading whitespace as an error, you have to check for it yourself.
The check for *end != '\0'
makes sure that there's nothing after the digits. If you want to permit other characters after the actual number (whitespace?), this check has to be modified accordingly.
P.S. I added the end == number
check later to catch empty input sequences. "All whitespace" and "no number at all" inputs would have been caught by *end != '\0'
check alone. It might make sense to catch empty input in advance though. In that case end == number
check will/might become unnecessary.
Since this is tagged c++:
template< typename T > inline T convert(const std::string& str) { std::istringstream iss(str); T obj; iss >> std::ws >> obj >> std::ws; if(!iss.eof()) throw "dammit!"; return obj; }
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