What's the C++ way of parsing a string (given as char *) into an int? Robust and clear error handling is a plus (instead of returning zero).
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Correctly parse PDF paragraphs with Python
- Why does const allow implicit conversion of refere
- thread_local variables initialization
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- How do I get from a type to the TryParse method?
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
What not to do
Here is my first piece of advice: do not use stringstream for this. While at first it may seem simple to use, you'll find that you have to do a lot of extra work if you want robustness and good error handling.
Here is an approach that intuitively seems like it should work:
This has a major problem:
str2int(i, "1337h4x0r")
will happily returntrue
andi
will get the value1337
. We can work around this problem by ensuring there are no more characters in thestringstream
after the conversion:We fixed one problem, but there are still a couple of other problems.
What if the number in the string is not base 10? We can try to accommodate other bases by setting the stream to the correct mode (e.g.
ss << std::hex
) before trying the conversion. But this means the caller must know a priori what base the number is -- and how can the caller possibly know that? The caller doesn't know what the number is yet. They don't even know that it is a number! How can they be expected to know what base it is? We could just mandate that all numbers input to our programs must be base 10 and reject hexadecimal or octal input as invalid. But that is not very flexible or robust. There is no simple solution to this problem. You can't simply try the conversion once for each base, because the decimal conversion will always succeed for octal numbers (with a leading zero) and the octal conversion may succeed for some decimal numbers. So now you have to check for a leading zero. But wait! Hexadecimal numbers can start with a leading zero too (0x...). Sigh.Even if you succeed in dealing with the above problems, there is still another bigger problem: what if the caller needs to distinguish between bad input (e.g. "123foo") and a number that is out of the range of
int
(e.g. "4000000000" for 32-bitint
)? Withstringstream
, there is no way to make this distinction. We only know whether the conversion succeeded or failed. If it fails, we have no way of knowing why it failed. As you can see,stringstream
leaves much to be desired if you want robustness and clear error handling.This leads me to my second piece of advice: do no use Boost's
lexical_cast
for this. Consider what thelexical_cast
documentation has to say:What?? We've already seen that
stringstream
has a poor level of control, and yet it saysstringstream
should be used instead oflexical_cast
if you need "a higher level of control". Also, becauselexical_cast
is just a wrapper aroundstringstream
, it suffers from the same problems thatstringstream
does: poor support for multiple number bases and poor error handling.The best solution
Fortunately, somebody has already solved all of the above problems. The C standard library contains
strtol
and family which have none of these problems.Pretty simple for something that handles all the error cases and also supports any number base from 2 to 36. If
base
is zero (the default) it will try to convert from any base. Or the caller can supply the third argument and specify that the conversion should only be attempted for a particular base. It is robust and handles all errors with a minimal amount of effort.Other reasons to prefer
strtol
(and family):There is absolutely no good reason to use any other method.
In C, you can use
int atoi (const char * str)
,Parses the C-string str interpreting its content as an integral number, which is returned as a value of type int.
From C++17 onwards you can use
std::from_chars
from the<charconv>
header as documented here.For example:
As a bonus, it can also handle other bases, like hexadecimal.
In the new C++11 there are functions for that: stoi, stol, stoll, stoul and so on.
It will throw an exception on conversion error.
Even these new functions still have the same issue as noted by Dan: they will happily convert the string "11x" to integer "11".
See more: http://en.cppreference.com/w/cpp/string/basic_string/stol
You can use stringstream's
I know three ways of converting String into int:
Either use stoi(String to int) function or just go with Stringstream, the third way to go individual conversion, Code is below:
1st Method
2nd Method
3rd Method - but not for an individual conversion