2013-03-04 102 views
2

我想將一串整數對解析爲數字。我用這個代碼:將臨時std :: string傳遞給boost :: regex_match

#include <iostream> 
#include <boost/regex.hpp> 

int main() 
{ 
    boost::regex reg("(\\d+):(\\d+)"); 

    std::string test = "1:2 3:4 5:6"; 

    boost::sregex_token_iterator end; 
    for(boost::sregex_token_iterator i(test.begin(), test.end(), reg); i != end; ++i) { 
     boost::smatch what; 
     if(boost::regex_match(i->str(), what, reg)) 
      std::cout << "found: \"" << what[1].str() << "\":\"" << what[2].str() << "\"" << std::endl; 
    } 

    return 0; 
} 

預期輸出:

found: "1":"2" 
found: "3":"4" 
found: "5":"6" 

我與GCC 4.7.2編譯提升1.52得到了什麼:

found: "2":"2" 
found: "4":"4" 
found: "6":"6" 

提升1.52鐺3.2:

found: "":"2" 
found: "":"4" 
found: "":"6" 

我的代碼有什麼問題?

+0

值得一提的是,在clang ++/libC++中實現的'std :: regex'輸出期望的輸出。 – Cubbi 2013-03-05 01:59:39

+0

@Cubbi它仍然可以是UB,除非它們改變了smatch如何存儲子表達式的結果 – Slava 2013-03-05 02:03:05

回答

3

我不知道Boost現在有什麼細節,但我不認爲這會影響到這一點。我也不知道爲什麼你在撥打regex_match後得到時髦的結果,但這不是必需的;該token_iterator已經做了那場比賽,因此,所有你需要的是

的std ::法院< <(* I)[1]名爲.str()< < ':' < <(* I)[2]名爲.str ()< < std :: endl;

,或者如果你喜歡:

的std :: COUT < <異> STR(1)< < ':' < <異> STR(2)< <的std :: ENDL;

請注意,這是C++ 11。它也應該和Boost一起工作,但我沒有嘗試過。

+0

錯誤:類型'boost :: sregex_token_iterator'(又名'regex_token_iterator ')不提供下標運算符 – Slava 2013-03-05 00:16:29

+0

@Slava - 修復。 – 2013-03-05 12:35:26

3

我不知道Boost.Regex的實現細節,但似乎複製解除引用的sregex_token_iteratorfor循環內的臨時std::string修復該問題:

std::string copied(i->str()); 
boost::smatch what; 
if(boost::regex_match(copied, what, reg)) { 
    std::cout << "found: \"" << what[1].str() << "\":\"" << what[2].str() << "\"" << std::endl; 
} 

希望有人提供更好的知識Boost.Regex可以給出更好的答案。從弗雷澤提示

+0

很好,謝謝!其實複製是沒有必要的 - const引用就足夠了。 – Slava 2013-03-05 00:36:58

4

謝謝,一個可能的解決方案是:

for(boost::sregex_token_iterator i(test.begin(), test.end(), reg); i != end; ++i) { 
    boost::smatch what; 
    const std::string &str = i->str(); 
    if(boost::regex_match(str, what, reg)) 
     std::cout << "found: \"" << what[1].str() << "\":\"" << what[2].str() << "\"" << std::endl; 
} 

於是問題就來了一個事實,即I-> STR()調用的boost :: sub_match方法:

basic_string<value_type> str()const; 

和它通過值返回std :: string。所以臨時的std :: string傳遞給regex_match和boost :: smatch對象實際上會記住原始字符串中的位置,在boost :: regex_match完成後它實際上會被銷燬。 類似的問題可以被複制,因爲這:

std::string function(); 
boost::smatch what; 
if(boost::regex_match(function(), what, reg)) ... 

或我相信這樣的代碼是脆弱的,以及:

boost::smatch what; 
if(boost::regex_match(std::string("abc"), what, reg)) ... 

我不知道怎麼這種情況可以在編譯時預防和它應該是視爲一個錯誤。 std :: regex_match似乎有相同的簽名,這個問題存在嗎?

+2

這個問題也存在於'std :: regex'中,因爲'match_results'被定義爲將迭代器保存到傳遞給'regex_match'的字符串中,並且在它被破壞時它們將失效。 – interjay 2013-03-06 10:46:07

相關問題