2014-02-10 40 views
11

來匹配多個結果。例如,如果我有一個字符串,如「第一個第二個第三個」,並且我想在一個操作中匹配每個單詞以逐個輸出em。如何使用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; 
} 

我期待着您的慈祥的幫助。 :)

+0

這是一個解決方案:regex exp(「(。*)\\ b \\ S * \\ b」); \t smatch res; \t string str =「第一第二第三第四」; \t而(regex_search(STR,RES,EXP,regex_constants :: MATCH_ANY)) \t { \t \t COUT << RES [0] << ENDL; \t \t str = res.suffix()。STR(); \t} – AntiMoron

回答

15

中所述,這可以在的regex中完成。

兩個methos:

  1. 您可以使用()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

  2. 您可以使用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

+0

哪個更好?爲什麼? – Yola

+0

我試過使用'smatch.size()',並在大小超出範圍後使用類似代碼觸發'regex.mark_count()+ 1'。 –

4

我對the documentation的看法是,regex_search搜索第一個匹配項,並且std::regex中沒有任何功能按照您的要求執行「掃描」。但是,Boost庫似乎支持這一點,如C++ tokenize a string using a regular expression

+0

基本上,如果你想從'std :: regex'獲得這個功能,你必須以某種方式處理最後一次匹配結束時的字符串拆分,然後重新檢查剩下的內容,直到或者沒有更多匹配正在發生。我沒有一個工作的例子,但是現在在現代C++中,你可能會使用'std :: regex_token_iterator'來實現這個技巧。 http://en.cppreference.com/w/cpp/regex/regex_token_iterator –

5

隨時可以使用我的代碼。這將捕獲所有組中的所有比賽:

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; 
} 
+0

您正在泄漏「rx」異常。你有沒有任何理由不把它分配到堆棧上? auto rx {regex(reg_ex,case_sensitive?regex_constants :: icase:0)}; –

+0

@AxelRietschin沒有合理的理由!那次我不知道正則表達式標誌的默認值! –

+0

答案已根據@AxelRietschin評論更新。 –

8

在你的字符串簡單地重複,而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; 
} 
+0

如果res.position()是相對於原始字符串,肯定應該是'searchStart = str.cbegin()+ match.position()+ match.length();'。 –

+0

這幾乎是正確的。你可能監督了「+ =」;)這導致了這樣一個事實,即res.position()與搜索有關,而不是原始字符串。所以你的話是正確的,以防止第一輪循環。 – St0fF

+1

這是迄今唯一對我有意義的解釋。謝謝! – awwsmm

9

你可以使用後綴()函數,直到你不再次搜索」 t找到一個匹配:

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(); 
    } 
} 
+0

這樣你就可以在每個循環上重新分配str。在我看來,這是浪費時間和堆碎片。 – St0fF