2014-07-24 28 views
3

我想通過解析UVA985中的輸入來嘗試C++ 11 regex庫,但是,我不明白如何在容器中存儲所有匹配,以便可以遍歷並與它一起工作。如何在C++中正確存儲正則表達式匹配

#include <regex> 
#include <string> 
#include <iostream> 
#include <vector> 
#include <cstdio> 

using namespace std; 

vector<string> get_names(const string &sentence) { 
    vector<string> vname; 
    regex author_regex("(.+\\.\\,\\s)|(.+\\.:)", regex_constants::ECMAScript); 
    smatch names; // This is always empty 
    regex_match(sentence, names, author_regex); // Is this correct? 
    for (auto name: names) { 
     vname.push_back(name.str() + "."); 
    } 
    return vname; 
} 

int main(void) { 
    const string papers[] = { 
     "Smith, M.N., Martin, G., Erdos, P.: Newtonian forms of prime \ 
      factor matrices", 
     "Erdos, P., Reisig, W.: Stuttering in petri nets", 
     "Smith, M.N., Chen, X.: First oder derivates in structured programming", 
     "Jablonski, T., Hsueh, Z.: Selfstabilizing data structures" }; 
    vector<vector<string>> input_data; 
    for (auto paper : papers) { 
     input_data.push_back(get_names(paper)); 
    } 

    int counter = 1; 
    for (auto scenario : input_data) { 
     cout << "Paper " << counter << ":\n"; 
     for (auto author: scenario) { 
      cout << author << endl; 
      counter += 1; 
     } 
    } 
    return 0; 
} 

我試圖改變正則表達式模式爲爲.簡單的事,但容器smatch總是空的,我失去了什麼?

+0

'regex_match'只有在表達式匹配完整的輸入字符串時纔會成功。你的不是。您可能正在尋找'regex_search' –

+0

@IgorTandetnik謝謝,如果您將它寫爲答案,我會高興地接受。 –

回答

3

在容器中存儲可以通過兩種方式完成,範圍構造和默認構造,然後插入。 <regex>庫包含std::sregex_token_iterator這將返回符合您的模式的字符串。我們可以使用它來範圍構造並返回一個std::vector<>

std::vector<std::string> names(std::sregex_token_iterator(sentence.begin(), sentence.end(), author_regex), 
           std::sregex_token_iterator()); 
return names; 

現在你的正則表達式需要一些工作。引文中的每個作者字段由姓氏("\\w+,")和代表第一個/中間名稱("(\\w.)+")的首字母定義。現在,只要我們沒有遇到冒號,我們就想這樣做,所以我們可以用"(?!:)"作爲我們的表達前綴。將這三者結合起來,我們現在就可以從每個引用中獲得所有作者的名字。不幸的是,超越第一名的每個名字現在都有一個領先的空間。這可以通過忽略任何前導空格來刪除("[^ ]+")。現在我們將所有這些結合起來,並得到"(?!:)[^ ]+\\w+, (\\w.)+"。你get_names()現在看起來

std::vector<std::string> get_names(const std::string& sentence) { 
    std::regex author_regex("(?!:)[^ ]+\\w+, (\\w.)+", std::regex_constants::ECMAScript); 

    std::vector<std::string> names(std::sregex_token_iterator(sentence.begin(), sentence.end(), author_regex), 
            std::sregex_token_iterator()); 
    return names; 
} 

回到main(),如果你想與std::copy()名稱與std::back_inserter()或與std::inserter()一個std::set<>轉儲到std::vector<>

int main() { 
    const std::string citations[] = {"Smith, M.N., Martin, G., Erdos, P.: Newtonian forms of prime factor matrices", 
            "Erdos, P., Reisig, W.: Stuttering in petri nets", 
            "Smith, M.N., Chen, X.: First oder derivates in structured programming", 
            "Jablonski, T., Hsueh, Z.: Selfstabilizing data structures"}; 
    std::set<std::string> all_authors; 

    for (const auto& citation : citations) { 
     auto citation_authors = get_names(citation); 
     std::copy(citation_authors.begin(), citation_authors.end(), std::back_inserter(all_authors)); 
    } 
}