C ++正则表达式匹配多行

时间:2015-03-05 07:35:46

标签: c++ regex

我正在尝试在以下输入字符串上模拟一个简单汇编程序(作为我的CS课程的一部分)的工作:“MOV R \ nADD R \ nSUB 30 \ nSTORE 1000 \ nHALT”

我想将单个指令与该字符串分开。所以我使用了以下正则表达式“^。+ $”,这意味着它应匹配以新行开头和结尾的1个或多个字符。

但是,C ++ regex_match函数不会获得该模式的任何匹配项。但在线测试人员向我展示了这种模式正是我所需要的。

这是我的代码片段,试图提取说明:

regex regInst("^.+$", regex::flag_type::icase | regex::flag_type::ECMAScript);
string input = "MOV R\nADD R\nSUB 30\nSTORE 1000\nHALT";
smatch instructions, opcode, operand;
regex_match(input, instructions, regInst); // *instructions* is empty after this

我正在使用Visual Studio 2013.我也尝试过使用以下模式:

  • ^(。+)$
  • (^。+ $)+

1 个答案:

答案 0 :(得分:0)

您在单行模式下使用主播^$,因此^仅匹配字符串的开头,$匹配字符串的结尾,而不是锚定到行尾。

C ++ regex库没有.NET Regex所具有的多行/单行选项,因此您希望使用regex_search代替regex_match,但正如我在评论中所说 - 回复你原来的帖子:你不应该使用正则表达式来解析汇编代码,并且使用正则表达式作为粗略的标记化工具就是在你需要的只是一个锤子时使用打桩机:strtok是你的朋友。

char* input = "MOV R\nADD R\nSUB 30\nSTORE 1000\nHALT";
const char* delimiters = " \n"

char* token = strtok( input, delimiters  );
while( token != nullptr ) {

    cout << token << endl;
    token = strtok( nullptr, delimiters );
}

请注意,strtok是有状态的,这解释了以strtok作为第一个参数的后续nullptr调用的非确定性。这在此处记录:http://www.cplusplus.com/reference/cstring/strtok/

另请注意,strtok实际修改了输入字符串,因此inputchar*而不是const char* conststring(因为string::c_str()返回const char*)。

不幸的是,

strtok是C函数之一,它没有C ++ - 惯用的替代品。您可以使用Boost的string::split方法,但这会引入新的内存分配,而strtok就地修改字符串缓冲区以将分隔符转换为\0,这样您就可以使用char*带有以null结尾的字符串函数的值 - 所以它有它的好处(即不需要分配额外的内存或额外的字符串复制)。


更完整的解决方案:

strtok的一个问题是你不知道哪个分隔符被覆盖了,所以当你有一个语法赋予不同的分隔符不同的语义时(如你所说:&#39; {{ 1}}&#39;(空格)是操作数分隔符,&#39;`\ n&#39;是操作码分隔符。

解决方案是获取未修改的字符串副本,并使用相对指针获取字符索引以确定遇到的分隔符。这确实有点失败了使用来最小化内存使用量的观点,但它确实消除了测试每个返回值作为执行语法规则的方法的需要:

strtok