I have heard that I should use strtol
instead of atoi
due to its better error handling. I wanted to test out strtol
by seeing if I could use this code to check if a string is an integer:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
string testString = "ANYTHING";
cout << "testString = " << testString << endl;
int testInt = strtol(testString.c_str(),NULL,0);
cout << "errno = " << errno << endl;
if (errno > 0)
{
cout << "There was an error." << endl;
cout << "testInt = " << testInt << endl;
}
else
{
cout << "Success." << endl;
cout << "testInt = " << testInt << endl;
}
return 0;
}
I replaced ANYTHING
with 5
and it worked perfectly:
testString = 5
errno = 0
Success.
testInt = 5
And when I do it with 2147483648
, the largest possible int
+ 1 (2147483648), it returns this:
testString = 2147483648
errno = 34
There was an error.
testInt = 2147483647
Fair enough. But, when i try it with Hello world!
, it incorrectly thinks it's a valid int
and returns 0
:
testString = Hello world!
errno = 0
Success.
testInt = 0
Notes:
According with the man page of strtol
. You must define your function such as:
bool isNumeric(const std::string& str) {
char *end;
long val = std::strtol(str.c_str(), &end, 10);
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) {
// if the converted value would fall out of the range of the result type.
return false;
}
if (end == str) {
// No digits were found.
return false;
}
// check if the string was fully processed.
return *end == '\0';
}
In C++11, I prefer to use std::stol
instead of std::strtol
, such as:
bool isNumeric(const std::string& str) {
try {
size_t sz;
std::stol(str, &sz);
return sz == str.size();
} catch (const std::invalid_argument&) {
// if no conversion could be performed.
return false;
} catch (const std::out_of_range&) {
// if the converted value would fall out of the range of the result type.
return false;
}
}
std::stol
calls std::strtol
, but you works directly with std::string
and the code is simplified.