应使用双栈法解析四则运算表达式,而非std::stringstream或std::stod;维护nums和ops栈,按优先级计算,处理括号与负号,并严格校验输入合法性。

用 std::stringstream 和 std::stod 解析表达式太危险
直接用字符串流或类型转换函数处理用户输入的四则运算表达式(比如 "3 + 4 * 2"),几乎必然出错。这些工具不理解运算符优先级,也不会递归解析括号,std::stod("3 + 4 * 2") 只会读到 3 就停,后面全被忽略。真要这么做,得自己拆分 token、建栈、模拟运算过程——相当于重写一个简易解释器。
推荐用双栈法实现中缀表达式求值(支持 + - * / 和括号)
这是教科书级解法,稳定、易懂、能覆盖常见需求。核心是维护两个栈:nums 存操作数,ops 存运算符。遇到数字就入 nums;遇到运算符时,先检查栈顶是否该立即计算(比如当前是 *,而栈顶是 +,那 + 不能等,得先算掉);遇到左括号无条件入栈,右括号则一路弹出直到左括号。
- 优先级判断用
map:比如{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2} - 注意负号处理:若
-出现在开头或左括号后(如"(-5 + 3)"),应视为一元负号,需补 0 入nums - 除零必须检查:
if (b == 0) throw std::runtime_error("division by zero");
double calc(double a, double b, char op) {
switch(op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': if (b == 0) throw std::runtime_error("division by zero"); return a / b;
}
return 0;
}
别硬啃字符串解析,先用空格分隔再处理更稳妥
如果只要求用户输入带空格的格式(如 "3 + 4 * 2" 或 "10 / ( 2 - 1 )"),可以先用 std::istringstream 按空格切分 token,再逐个识别数字、运算符、括号。这样避免手写跳过空白、识别多位数、处理小数点等边界问题。
- 读 token 时用
while (iss >> token),token是std::string - 判断
token == "("或token == ")"比判断单个字符更清晰 - 数字用
std::stod(token)安全转换,前提是已确认token不含非法字符
输入验证和错误恢复容易被忽略
真实场景下,用户可能输 "3++4"、"(5 + " 或 "abc * 2"。只靠双栈逻辑无法捕获所有异常,必须在解析前/中加校验:
立即学习“C++免费学习笔记(深入)”;
- 扫描原始字符串,确保每个字符属于
0-9、+-*/()、空格;小数点需成对出现在数字中 - 左右括号数量必须相等,且过程中右括号不能多于左括号
- 连续两个运算符(除一元负号外)非法,如
"3 * + 4" - 计算完成后,
nums应只剩 1 个数,ops应为空,否则说明表达式不完整
这些检查点分散在词法分析和语法计算阶段,漏掉任意一个,程序就可能崩溃或返回错误结果。










