使用正则提取算术表达式元素入栈时出现空字符串的问题求助
解决C++正则拆分表达式时出现空字符串的问题及后缀表达式实现思路
问题原因分析
你的代码出现空字符串主要有两个核心原因:
- 正则表达式的分支匹配逻辑:你用了
[0-9]*(匹配0个或多个数字),这个分支允许匹配空字符串。当正则引擎遇到非数字字符(比如*、()时,会优先匹配这个分支的空结果,从而产生空token。 std::smatch的遍历方式:你的正则包含一个捕获组(...),所以smatch中会包含整个匹配结果(索引0)和捕获组内容(索引1)。遍历smatch时会输出这两个元素,比如匹配运算符时,捕获组可能是空,就会输出空串;同时你只调用了一次regex_search,无法获取所有token。
另外,你的正则还遗漏了幂运算符^,也没有处理原字符串中的空格,这些都会影响后续的token提取。
修正方案
1. 修正正则表达式
把[0-9]*改为[0-9]+(匹配1个或多个数字,避免空匹配),加入幂运算符^,同时可以匹配空格以便后续过滤:
std::regex tokenRegex(R"(\d+|[+*\-/%^()]|\s+)");
这里用了原始字符串字面量R"(...)",避免了转义字符的繁琐。
2. 正确遍历所有匹配结果
使用循环调用regex_search,每次更新搜索的起始位置,确保提取出所有token。
3. 过滤无效token并区分栈存储
提取token后,先过滤空格,然后判断是操作数还是运算符/括号,分别存入对应的栈。
完整修正代码
#include <iostream> #include <string> #include <regex> #include <stack> #include <cctype> #include <algorithm> void Stack::findIT() { std::string expr = "56*((6+2)/(8-7)* 2^3)"; // 修正后的正则:匹配数字、运算符、括号、空格 std::regex tokenRegex(R"(\d+|[+*\-/%^()]|\s+)"); std::smatch matchResult; auto searchStart = expr.cbegin(); std::stack<int> operandStack; std::stack<char> operatorStack; while (std::regex_search(searchStart, expr.cend(), matchResult, tokenRegex)) { std::string token = matchResult[0]; // 过滤空格类型的token if (std::all_of(token.begin(), token.end(), ::isspace)) { searchStart = matchResult.suffix().first; continue; } // 判断是操作数还是运算符/括号,分别入栈 if (std::isdigit(token[0])) { // 转换为整数存入操作数栈(如果需要支持浮点数可以用stod) operandStack.push(std::stoi(token)); std::cout << "操作数入栈:" << token << "\n"; } else { // 运算符或括号存入运算符栈 operatorStack.push(token[0]); std::cout << "运算符/括号入栈:" << token << "\n"; } // 更新下一次搜索的起始位置 searchStart = matchResult.suffix().first; } // 后续可以在这里实现后缀表达式的转换逻辑(比如Shunting-yard算法) }
额外说明
如果需要支持浮点数(比如3.14),可以把正则中的\d+改为\d+(\.\d+)?,并将std::stoi改为std::stod。另外,实现后缀表达式转换建议参考调度场算法(Shunting-yard Algorithm),它能很好地处理运算符优先级和括号。
内容的提问来源于stack exchange,提问作者Benjamin Sx
相关产品推荐
相关产品推荐

