将临时std :: string传递给boost :: regex_match

时间:2013-03-04 23:23:43

标签: c++ regex boost

我想将一串整数对解析为数字。我使用这段代码:

#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编译的boost 1.52得到了什么:

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

提升1.52铿锵3.2:

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

我的代码出了什么问题?

3 个答案:

答案 0 :(得分: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-&gt; str()调用boost :: sub_match方法的事实:

basic_string<value_type> str()const;

并按值返回std :: string。因此传递给regex_match和boost :: smatch对象的临时std :: string实际上会记住原始字符串中的位置,这实际上是在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似乎有相同的签名,那里存在这个问题吗?

答案 1 :(得分:3)

我不知道Boost现在有什么细节,但我不认为这会影响到这一点。我也不知道为什么你在调用regex_match之后得到了时髦的结果,但这不是必需的; token_iterator已经完成了那场比赛,所以你需要的只是

std::cout << (*i)[1].str() << ':' << (*i)[2].str() << std::endl;

或者,如果您愿意:

std::cout << i->str(1) << ':' << i->str(2) << std::endl;

请注意,这是C ++ 11。它也适用于Boost,但我还没有尝试过。

答案 2 :(得分:3)

我不确定Boost.Regex的实现细节,但似乎将sregex_token_iterator循环内的解除引用的for复制到临时std::string可以解决问题:< / p>

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知识的人可以给出更好的答案。