【发布时间】:2014-03-12 04:36:05
【问题描述】:
我正在尝试测试(使用boost::regex)文件中的一行是否仅包含由空格分隔的数字条目。我遇到了一个我不明白的异常(见下文)。如果有人能解释为什么会抛出它,那就太好了。也许我在这里以定义模式的方式做了一些愚蠢的事情?这是代码:
// regex_test.cpp
#include <string>
#include <iostream>
#include <boost/regex.hpp>
using namespace std;
using namespace boost;
int main(){
// My basic pattern to test for a single numeric expression
const string numeric_value_pattern = "(?:-|\\+)?[[:d:]]+\\.?[[:d:]]*";
// pattern for the full line
const string numeric_sequence_pattern = "([[:s:]]*"+numeric_value_pattern+"[[:s:]]*)+";
regex r(numeric_sequence_pattern);
string line= "1 2 3 4.444444444444";
bool match = regex_match(line, r);
cout<<match<<endl;
//...
}
我编译成功了
g++ -std=c++11 -L/usr/lib64/ -lboost_regex regex_test.cpp
到目前为止,生成的程序运行良好,match == true 如我所愿。但后来我测试了一个输入行,比如
string line= "1 2 3 4.44444444e-16";
当然,我的模式不是为识别4.44444444e-16 格式而构建的,我希望match == false。但是,相反,我收到以下运行时错误:
terminate called after throwing an instance of
'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::runtime_error> >'
what(): The complexity of matching the regular expression exceeded predefined bounds.
Try refactoring the regular expression to make each choice made by the state machine unambiguous.
This exception is thrown to prevent "eternal" matches that take an indefinite period time to locate.
为什么会这样?
注意:我给出的例子是极端的,因为在点之后少放一位就可以了。这意味着
string line= "1 2 3 4.4444444e-16";
正如预期的那样导致match == false。所以,我很困惑。这里发生了什么?
已经谢谢了!
更新:
问题似乎解决了。鉴于alejrb 的提示,我将模式重构为
const string numeric_value_pattern = "(?:-|\\+)?[[:d:]]+(?:\\.[[:d:]]*)?";
这似乎可以正常工作。不知何故,原始模式 [[:d:]]+\\.?[[:d:]]* 中的孤立可选 \\. 留下了以不同方式匹配长数字序列的许多可能性。
我希望这个模式现在是安全的。但是,如果有人找到一种方法来使用它以新形式进行爆炸,请告诉我!对我来说这是否仍然可能不是那么明显......
【问题讨论】:
标签: c++ regex boost-regex