Given a string that should represent a number, I'd like to put it into a conversion function which would provide notification if the whole string did not convert.
For input: "12":
istringstream::operator>> outputs 12atoi outputs 12stoi outputs 12For input "1X" I'd like a failure response but I get:
istringstream::operator>> outputs 1atoi outputs 1stoi outputs 1For input "X2":
istringstream::operator>> outputs 0 and sets an error flagatoi outputs 0stoi throws an error[Live Example]
Is there a way to provoke the error behavior on input "1X"?
The atoi() function converts a character string to an integer value. The input string is a sequence of characters that can be interpreted as a numeric value of the specified return type.
Using the stoi() function The stoi() function converts a string data to an integer type by passing the string as a parameter to return an integer value. The stoi() function contains an str argument. The str string is passed inside the stoi() function to convert string data into an integer value.
In C++, the stoi() function converts a string to an integer value. The function is shorthand for “string to integer,” and C++ programmers use it to parse integers out of strings. The stoi() function is relatively new, as it was only added to the language as of its latest revision (C++11) in 2011.
stoistolstoll Interprets a signed integer value in the string str . Function discards any whitespace characters (as identified by calling isspace() ) until first non-whitespace character is found.
Edit: In c++17 or later from_chars is preferred. See here for more: https://topanswers.xyz/cplusplus?q=724#a839
For a given string str there are several ways to accomplish this each with advantages and disadvantages. I've written a live example here: https://ideone.com/LO2Qnq and discuss each below:
strtolAs suggested here strtol's out-parameter can be used to get the number of characters read. strtol actually returns a long not an int so a cast is happening on the return.
char* size;
const int num = strtol(str.c_str(), &size, 10);
if(distance(str.c_str(), const_cast<const char*>(size)) == str.size()) {
cout << "strtol: " << num << endl;
} else {
cout << "strtol: error\n";
}
Note that this uses str.c_str() to refer to the same string. c_str Returns pointer to the underlying array serving as character storage not a temporary if you have C++11:
c_str()anddata()perform the same function
Also note that the pointer returned by c_str will be valid between the strtol and distance calls unless:
- Passing a non-
constreference to thestringto any standard library function
- Calling non-
constmember functions on thestring, excludingoperator[],at(),front(),back(),begin(),rbegin(),end()andrend()
If you violate either of these cases you'll need to make a temporary copy of i's underlying const char* and perform the test on that.
sscanfsscanf can use %zn to return the number of characters read which may be more intuitive than doing a pointer comparison. If base is important, sscanf may not be a good choice. Unlike strtol and stoi which support bases 2 - 36, sscanf provides specifiers for only octal (%o), decimal (%d), and hexadecimal (%x).
size_t size;
int num;
if(sscanf(str.c_str(), "%d%zn", &num, &size) == 1 && size == str.size()) {
cout << "sscanf: " << num << endl;
} else {
cout << "sscanf: error\n";
}
stoiAs suggested here stoi's output parameter works like sscanf's %n returning the number of characters read. In keeping with C++ this takes a string and unlike the C implementations above stoi throws an invalid_argument if the first non-whitespace character is not considered a digit for the current base, and this unfortunately means that unlike the C implementations this must check for an error in both the try and catch blocks.
try {
size_t size;
const auto num = stoi(str, &size);
if(size == str.size()) {
cout << "stoi: " << num << endl;
} else {
throw invalid_argument("invalid stoi argument");
}
} catch(const invalid_argument& /*e*/) {
cout << "stoi: error\n";
}
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