题目:
后缀表达式,又称逆波兰式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行。
运用后缀表达式进行计算的具体做法:
建立一个操作数栈S。然后从左到右读表达式,如果读到操作数就将它压入栈S中,如果读到n元运算符(即需要参数个数为n的运算符)则取出由栈顶向下的n项操作数进行运算,再将运算的结果代替原栈顶的n项压入栈中。重复上面过程,如果后缀表达式读完且栈中只剩一个操作数,则该数就是运算结果;如果后缀表达式读完但是栈中操作数多于一个,则后缀表达式错误;如果栈中操作数只剩一个,但是后缀表达式还未读完且当前运算符为双元操作符,则后缀表达式同样错误。
输入格式:
在一行中输入一个以#号结束的非空后缀式,#不属于表达式的一部分,操作数和运算符都以空格分隔,运算数为绝对值不超过100的整数,运算符仅有+、-、*、/ 四种。
输出格式:
输出后缀式计算结果,所有的计算都只取结果的整数部分。题目保证计算的中间和最后结果的绝对值都不超过109。
如果执行除法时出现分母为零的非法操作,则在一行中输出:Error: X/0,X是当时的分子。
如果后缀表达式中运算符多了或者少了,则在一行中输出:Expression Error: X,X是当时栈顶元素。
输入样例1:
5 -2 + 3 * #
输出样例1:
9
输入样例2:
5 -2 2 + / #
输出样例2:
Error: 5/0
输入样例3:
5 -1 3 + / - * #
输出样例3:
Expression Error: 2
代码:
#include "stdio.h"
/**
* 后缀表达式求值 - 异常处理 + 数组模拟栈
* @return
*/
int main() {
char expression[100];
int stack[100], sum, top = 0, num1, num2; //top=0表示栈空 top指向栈顶元素
gets(expression);
for (int i = 0; expression[i] != '#'; i++) { //直到结束符 # 才退出
if (expression[i] >= '0' && expression[i] <= '9') {
sum = expression[i] - '0';
int j;
for (j = i + 1; expression[j] != '#'; j++) { //寻找并拼接连续数字
if (expression[j] >= '0' && expression[j] <= '9') {
sum = sum * 10 + (expression[j] - '0');
} else {
break; //若不为连续数字,则退出循环
}
}
if (i > 0 && expression[i - 1] == '-') {
//若该数的前一位为负数,则取反
sum = -sum;
}
i = j - 1;
stack[++top] = sum;
} else if (expression[i] == ' ') {
continue; //遇到空格就跳过
} else if (expression[i] == '-' && expression[i + 1] != ' ') {
continue; //遇到负数先走一步,不进行减法运算
} else { //遇到运算符
if (top < 2) {
printf("Expression Error: %d\n", stack[top]);
return 0; //直接退出程序
}
num1 = stack[top--]; //先将num1 num2取出
num2 = stack[top--];
switch (expression[i]) {
case '+':
stack[++top] = num2 + num1;
break;
case '-':
stack[++top] = num2 - num1; //减法为前-后
break;
case '*':
stack[++top] = num2 * num1;
break;
case '/':
if (num1 == 0) {
printf("Error: %d/0\n", num2);
return 0; //直接退出
}
stack[++top] = num2 / num1; //num1为后操作数
break;
}
}
}
if (top != 1) {
printf("Expression Error: %d\n", stack[top]);
} else {
printf("%d\n", stack[top]);
}
return 0;
}