I'm quite novice to C , but here's my question. While building a regex to store names and corresponding numbers, I got an error while trying to convert the captured values in my std::smatch object to other types, like a std::string, size_t or float. The values below, given by res [1/2/3/4] do give me what I want when simply outputted through cout. Doing anything more with them doesn't work though. For example, passing them to a function which expects a string or a float.
I tried to figure out the type with e.g. typeid() and see if I could convert it, but no success. The attempt with typeid() gave the following type, which I don't recognize:
NSt7__cxx119sub_matchIN9__gnu_cxx17__normal_iteratorIPKcNS_12basic_stringIcSt11char_traitsIcESaIcEEEEEEE
Here is the relevant code:
#include <regex>
#include <fstream>
#include <string>
#include <typeinfo>
using namespace std;
void regexExampleFunction(string filename)
{
ifstream file(fileName);
regex rex("^([A-z.] \\s?[a-z] )\\s([A-z] )\\s(\\d{5})\\s(\\d.\\d)");
smatch res;
string line;
while (getline(file, line))
{
regex_search(line, res, rex);
cout << res[1] << " " << res[2] << " " << res[3] << " " << res[4] << '\n';
cout << typeid(res[1]).name() << '\n'; // outputs the type above^
}
}
int main(int argc, char **argv)
{
regexExampleFunction(argv[1]);
}
There must be some error I'm making, or just something I'm missing. It'd be great to hear your feedback.
CodePudding user response:
Mistake you are making:
It looks like you are trying to use the elements of the std::smatch object as if they were of a certain type, but they are actually of type std::sub_match, which is a helper class that represents a sequence of characters within a string.
To use the captured values as a different type, you will need to convert them first. You can use the std::sub_match::str method to get the string representation of the matched sub-expression, and then use one of the standard C type conversion functions such as std::stoi, std::stoul, and std::stof to convert the string to the desired type.
Here's my approach:
To convert the elements of an std::smatch object to different types, you can use standard C type conversion functions such as std::stoi, std::stoul, and std::stof.
For example, to convert the first element of an std::smatch object to a std::string, you can use the std::string constructor that takes an std::string_view object as an argument:
std::string str = std::string(m[1]);
To convert the second element of an std::smatch object to a size_t, you can use the std::stoul function:
size_t num = std::stoul(m[2]);
And to convert the third element of an std::smatch object to a float, you can use the std::stof function:
float f = std::stof(m[3]);
You can also use the std::smatch::str method to get the string representation of an element, and then use one of the above methods to convert it to the desired type.
std::string str = m[1].str();
size_t num = std::stoul(m[2].str());
float f = std::stof(m[3].str());
Hope it clarifies your confusion.