安全求值逆波兰表达式需用std::stack分词计算:先用std::istringstream自动跳过空白符切分token,严格区分运算符与带符号数字;遇运算符前检查栈大小≥2,弹栈顺序为先b后a,除法前判零;建语法树须分离分词与建树逻辑,推荐用std::stack或std::vector实现。

用std::stack安全求值逆波兰表达式
要把一串空格分隔的字符串(如"4 13 5 + /")正确算出整数结果,必须先完整切分token、严格区分运算符与带符号数字、每次弹栈前确认栈里至少有两个数。
第一步:声明std::stack,别用int——中间结果可能溢出,比如"1000000000 1000000000 +"就超了。
第二步:用std::istringstream iss(expr)读取整个字符串,再循环iss >> token。这一步自动跳过所有空格、制表符、换行,不用手动trim,也不会把"-123"错切成"-"和"123"。
第三步:对每个token,先判断是否为"+"、"-"、"*"或"/"——只有完全匹配才当运算符;其余一律走std::stoll(token)转数字并压栈。这能防止std::stoi("-")抛异常。
第四步:遇到运算符时,必须立刻检查st.size() ,不满足就抛std::runtime_error("not enough operands")。别信“题目保证合法”,本地随便输{"5","0","/"}就能触发崩溃。
第五步:弹栈顺序不能错——先取b = st.top(); st.pop();,再取a = st.top(); st.pop();。加减乘除都按a op b算,除法还要在计算前加if (b == 0) throw ...,C++整除默认向零截断,不用额外处理。
构建语法树必须另起函数,不能塞进求值逻辑里
如果需求明确要求返回语法树根节点,那就得彻底拆开:一个函数只负责分词,另一个函数专用于建树。混在一起会导致栈操作和指针管理互相污染,轻则空指针解引用,重则内存泄漏。
方法一:用std::stack<:unique_ptr>>建树
定义struct TreeNode { std::string val; std::unique_ptr,数字token创建叶节点后压栈;运算符token弹出两个节点,先弹的是右子节点,后弹的是左子节点,新建运算符节点并连接后压栈。
方法二:用std::vector<:unique_ptr>>替代栈
好处是能随时打印中间状态调试。取右子节点用nodes.back(),取左子节点用nodes[nodes.size()-2],删掉末尾两个元素后push_back新节点。遍历完若nodes.size() != 1,说明表达式非法。
分词鲁棒性决定整个流程成败
90%的崩溃和结果错误,根源都在分词环节。逐字符扫描或简单split(" ")会栽在" 4\t-13 5 + / "这种输入上——连续空白、制表符、尾部空格全会搞乱索引。
唯一可靠做法是std::istringstream iss(expr); std::string token; while(iss >> token) { /* 处理 */ }。它内部自动跳过任意空白符,且operator>>返回false时循环自然终止,不会多读。
千万别在分词后还做token.erase(0, token.find_first_not_of(" \t\n"))这类手动清理——iss >> token已经干完了,重复操作反而可能把合法负号开头的数字(如"-0")误判为运算符。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











