17

I am new to c++ regex. I have a string "{1,2,3}" and I want to extract the numbers 1 2 3. I thought I should use regex_search but it failed.

#include<iostream>
#include<regex>
#include<string>
using namespace std;
int main()
{
        string s1("{1,2,3}");
        string s2("{}");
        smatch sm;
        regex e(R"(\d+)");
        cout << s1 << endl;
        if (regex_search(s1,sm,e)){
                cout << "size: " << sm.size() << endl;
                for (int i = 0 ; i < sm.size(); ++i){
                        cout << "the " << i+1 << "th match" <<": "<< sm[i] <<  endl;
                }
        }
}

The result:

{1,2,3}
size: 1
the 1th match: 1
1
  • You probably want to use regex_match() with an appropriate expression describing this format. Commented Sep 13, 2015 at 19:29

1 Answer 1

24

std::regex_search returns after only the first match found.

What std::smatch gives you is all the matched groups in the regular expression. Your regular expression only contains one group so std::smatch only has one item in it.

If you want to find all matches you need to use std::sregex_iterator.

int main()
{
    std::string s1("{1,2,3}");
    std::regex e(R"(\d+)");

    std::cout << s1 << std::endl;

    std::sregex_iterator iter(s1.begin(), s1.end(), e);
    std::sregex_iterator end;

    while(iter != end)
    {
        std::cout << "size: " << iter->size() << std::endl;

        for(unsigned i = 0; i < iter->size(); ++i)
        {
            std::cout << "the " << i + 1 << "th match" << ": " << (*iter)[i] << std::endl;
        }
        ++iter;
    }
}

Output:

{1,2,3}
size: 1
the 1th match: 1
size: 1
the 1th match: 2
size: 1
the 1th match: 3

The end iterator is default constructed by design so that it is equal to iter when iter has run out of matches. Notice at the bottom of the loop I do ++iter. That moves iter on to the next match. When there are no more matches, iter has the same value as the default constructed end.

Another example to show the submatching (capture groups):

int main()
{
    std::string s1("{1,2,3}{4,5,6}{7,8,9}");
    std::regex e(R"~((\d+),(\d+),(\d+))~");

    std::cout << s1 << std::endl;

    std::sregex_iterator iter(s1.begin(), s1.end(), e);
    std::sregex_iterator end;

    while(iter != end)
    {
        std::cout << "size: " << iter->size() << std::endl;

        std::cout << "expression match #" << 0 << ": " << (*iter)[0] << std::endl;
        for(unsigned i = 1; i < iter->size(); ++i)
        {
            std::cout << "capture submatch #" << i << ": " << (*iter)[i] << std::endl;
        }
        ++iter;
    }
}

Output:

{1,2,3}{4,5,6}{7,8,9}
size: 4
expression match #0: 1,2,3
capture submatch #1: 1
capture submatch #2: 2
capture submatch #3: 3
size: 4
expression match #0: 4,5,6
capture submatch #1: 4
capture submatch #2: 5
capture submatch #3: 6
size: 4
expression match #0: 7,8,9
capture submatch #1: 7
capture submatch #2: 8
capture submatch #3: 9
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. Can I ask what "end" is for? Looks like you didn't initialize it. std::sregex_iterator end;
@daydayup The end iterator is default constructed by design so that it is equal to iter when iter has run out of matches. Notice at the bottom of the loop I do ++iter. That moves iter on to the next match. When there are no more matches, iter has the same value as the default constructed end. I added another example to show the submatching.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.