2025/11/25

栈实现表达式求值

使用键盘输入数学表达式(含数字,四种运算符+、-、、/和小括号,其中运算数都是一位数(0~9)),将数学表达式转化成后缀表达式输出,利用后缀表达式求表达式的值并输出。

输入格式:
输入正确的表达式(可以有空格)后回车,得到后缀表达式和结果。输入括号缺失的表达式,输出"ERROR:缺少括号"。输入两个除括号外运算符连续的表达式,输出"ERROR:表达式缺操作数"。

输出格式:
请在这里描述输出格式。例如:对每一组输入,在一行中输出A+B的值。

输入样例:
在这里给出一组输入。例如:

5(8-(3+2))
输出样例:
在这里给出相应的输出。例如:
5832+-

15

为了防止空格影响,先去除输入字符串中的空白字符
// 预处理:去除空格
int idx = 0;
for (int i = 0; input[i] != '\0'; i++) {
if (!isspace(input[i])) {
expr[idx++] = input[i];
}
}
expr[idx] = '\0';

然后检查输入是否合法,不合法的情况有两种:
1.括号不匹配
int left = 0, right = 0;
for (int i = 0; i < len; i++) {
if (expr[i] == '(') left++;
if (expr[i] == ')') right++;
// ... 其他校验
}
if (left != right) return -1; // 括号不匹配
2.连续输入了运算符
if (i > 0) {
char prev = expr[i-1];
char curr = expr[i];
// 排除括号的情况,判断是否是连续运算符
if (!((prev == '(' || prev == ')') || (curr == '(' || curr == ')'))) {
if (priority(prev) >= 1 && priority(curr) >= 1) {
return 0; // 运算符连续(缺操作数)
}
}
}

第三步:中缀转后缀(核心转换逻辑,合法性通过后想)
计算机不擅长直接计算中缀表达式(因为要考虑优先级和括号),但后缀表达式(逆波兰表达式) 无需考虑优先级,只需用栈就能计算,因此必须先完成转换。
转换规则(核心思考)
用一个栈存储运算符,遍历中缀表达式的每个字符,规则如下:
遇到的字符 处理逻辑
数字 直接加入后缀表达式(操作数无需优先级处理)
左括号( 压入栈(括号是优先级的边界,先存起来)
右括号) 弹出栈顶运算符到后缀表达式,直到遇到左括号(左括号弹出但不加入后缀)
运算符+/-/*/ 比较当前运算符与栈顶运算符的优先级:

  1. 栈顶优先级 ≥ 当前优先级 → 弹出栈顶到后缀;
  2. 重复 1 直到栈顶优先级 < 当前优先级,再将当前运算符压栈
    遍历结束后 弹出栈中剩余的所有运算符到后缀表达式

第四步:计算后缀表达式(最后一步,转换完成后想)
后缀表达式的计算逻辑非常简单:用栈存储操作数,遍历后缀表达式:
遇到数字 → 压入栈;
遇到运算符 → 弹出栈顶两个操作数(注意顺序:后弹出的是左操作数,先弹出的是右操作数),用运算符计算后,将结果压回栈;
遍历结束后,栈中剩余的唯一数字就是结果。

posted on 2025-11-27 08:47  才一斤  阅读(5)  评论(0)    收藏  举报

导航