This seems like a question that should be easy to search for, but any answers out there seem to be drowned out by a sea of questions asking the more common problem of converting a string to an integer.
My question is: what's an easy way to extract integers from std::strings
that might look like "abcd451efg"
or "hel.lo42-world!"
or "hide num134rs here?"
I see that I can use isDigit
to manually parse the strings myself, but I'm wondering if there is a more standard way in the vein of atoi
or stoi
, etc.
The outputs above would be 451, 42, and 134. We can also assume there is only one integer in a string (although a general solution wouldn't hurt). So we don't have to worry about strings like "abc123def456"
.
Java has an easy solution in the form of
Integer.parseInt(str.replaceAll("[\\D]", ""));
does C++ have something as straightforward?
You can use
string::find_first_of("0123456789")
to get the position of the first digit, then string::find_last_of("0123456789")
to get the position of the last digit, and finally use an atoi
on the substring defined by the two positions. I cannot think of anything simpler (without regex).
BTW, this works only when you have a single number inside the string.
Here is an example:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
string s = "testing;lasfkj358kdfj-?gt";
size_t begin = s.find_first_of("0123456789");
size_t end = s.find_last_of("0123456789");
string num = s.substr(begin, end - begin + 1);
int result = atoi(num.c_str());
cout << result << endl;
}
If you have more than 1 number, you can combine string::find_first_of
with string::find_first_not_of
to get the beginning and the end of each number inside the string.
This code is the general solution:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
string s = "testing;lasfkj358kd46fj-?gt"; // 2 numbers, 358 and 46
size_t begin = 0, end = 0;
while(end != std::string::npos)
{
begin = s.find_first_of("0123456789", end);
if(begin != std::string::npos) // we found one
{
end = s.find_first_not_of("0123456789", begin);
string num = s.substr(begin, end - begin);
int number = atoi(num.c_str());
cout << number << endl;
}
}
}