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:
strtol
As 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-
const
reference to thestring
to any standard library function
- Calling non-
const
member 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.
sscanf
sscanf
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";
}
stoi
As 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