Как сопоставить несколько результатов с помощью std:: regex

например. Если у меня есть строка, подобная "первая секунда четвертая четвертая", и я хочу сопоставить каждое отдельное слово в одной операции для вывода "один за другим".

Я просто подумал, что "(\ b\S *\b) {0,}" будет работать. Но на самом деле это не так.

Что мне делать?

Здесь мой код:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    regex exp("(\\b\\S*\\b)");
    smatch res;
    string str = "first second third forth";
    regex_search(str, res, exp);
    cout << res[0] <<" "<<res[1]<<" "<<res[2]<<" "<<res[3]<< endl;
}   

Я с нетерпением жду вашей любезной помощи.:)

Ответ 1

Это можно сделать в regex C++11.

Два метода:

  • Вы можете использовать () в regex для определения ваших захватов.

    Вот так:

    string var = "first second third forth";
    
    const regex r("(.*) (.*) (.*) (.*)");  
    smatch sm;
    
    if (regex_search(var, sm, r))
    {
        for (int i=1; i<sm.size(); i++)
        {
            cout << sm[i] << endl;
        }
    }
    

    Смотрите в прямом эфире: http://coliru.stacked-crooked.com/a/e1447c4cff9ea3e7

  • Вы можете использовать sregex_token_iterator():

    string var = "first second third forth";
    
    regex wsaq_re("\\s+"); 
    copy( sregex_token_iterator(var.begin(), var.end(), wsaq_re, -1),
        sregex_token_iterator(),
        ostream_iterator<string>(cout, "\n"));
    

    Смотрите это в прямом эфире: http://coliru.stacked-crooked.com/a/677aa6f0bb0612f0

Ответ 2

Вы можете использовать функцию suffix() и искать снова, пока не найдете совпадения:

int main()
{
    regex exp("(\\b\\S*\\b)");
    smatch res;
    string str = "first second third forth";

    while (regex_search(str, res, exp)) {
        cout << res[0] << endl;
        str = res.suffix();
    }
}   

Ответ 3

Просто перебирайте строку во время regex_searching, например:

{
    regex exp("(\\b\\S*\\b)");
    smatch res;
    string str = "first second third forth";

    string::const_iterator searchStart( str.cbegin() );
    while ( regex_search( searchStart, str.cend(), res, exp ) )
    {
        cout << ( searchStart == str.cbegin() ? "" : " " ) << res[0];
        searchStart += res.position() + res.length();
    }
    cout << endl;
}

Ответ 4

не стесняйтесь использовать мой код. Он будет захватывать все группы во всех матчах:

vector<vector<string>> U::String::findEx(const string& s, const string& reg_ex, bool case_sensitive)
{
    regex rx(reg_ex, case_sensitive ? regex_constants::icase : 0);
    vector<vector<string>> captured_groups;
    vector<string> captured_subgroups;
    const std::sregex_token_iterator end_i;
    for (std::sregex_token_iterator i(s.cbegin(), s.cend(), rx);
        i != end_i;
        ++i)
    {
        captured_subgroups.clear();
        string group = *i;
        smatch res;
        if(regex_search(group, res, rx))
        {
            for(unsigned i=0; i<res.size() ; i++)
                captured_subgroups.push_back(res[i]);

            if(captured_subgroups.size() > 0)
                captured_groups.push_back(captured_subgroups);
        }

    }
    captured_groups.push_back(captured_subgroups);
    return captured_groups;
}

Ответ 5

Мое чтение документации заключается в том, что regex_search выполняет поиск первого совпадения и что ни одна из функций из std::regex не выполняет "сканировать", как вы ищите. Тем не менее, библиотека Boost, похоже, поддерживает это, как описано в С++, чтобы токенизировать строку, используя регулярное выражение