输入描述:
输入一个算术表达式
输出描述:
得到计算结果
示例1
输入
3+2*{1+2*[-4/(8-6)+7]}
输出
25
1.运算符的优先级:
在运算过程中,任意两个前后相继出现的运算符 的优先关系如下表所示:
+ | - | * | / | ( | ) | [ | ] | { | } | @ | |
---|---|---|---|---|---|---|---|---|---|---|---|
+ | > | > | < | < | < | > | < | > | < | > | > |
- | > | > | < | < | < | > | < | > | < | > | > |
* | > | > | > | > | < | > | < | > | < | > | > |
/ | > | > | > | > | < | > | < | > | < | > | > |
( | < | < | < | < | < | = | > | > | |||
) | > | > | > | > | > | > | > | > | > | ||
[ | < | < | < | < | < | < | < | = | > | ||
] | > | > | > | > | > | > | > | ||||
{ | < | < | < | < | < | < | < | < | < | = | |
} | > | > | > | > | > | > | |||||
@ | < | < | < | < | < | < | < | = |
2.算法基本过程如下:
首先初始化操作数栈Operand和运算符栈Operator,并将表达式起始符"@"压入运算符栈。加入"@"是为了方便计算,例如:
@(7+15)*(23-28/4)@。
再依次读入表达式中的每个字符,若是操作数,则直接进入操作数栈Operand;若是运算符,则与运算符栈Operator的栈顶运算符进行优先权比较,并作如下处理:
(1).若栈顶运算符的优先级低于刚读入的运算符,则让刚读入的运算符进Operator栈。
(2).若栈顶运算符的优先级高于刚读入的运算符,则让栈顶运算符退栈,送入op,同时将操作数栈Operand连退两次,得到两个操作数a,b,对a,b进行op运算后,将运算结果作为中间结果压入Operand栈。
(3).若栈顶运算符的优先级与刚读入的运算符的运算符的优先级相同,说明左右括号相遇,只需要将栈顶运算符(左括号)退栈即可。
3.本题注意负号的处理,负号又能是负数的前缀标志,也有可能是减法运算符。
#include <stdio.h>
#include <string.h>
char table[11][11] = {
{'>', '>', '<', '<', '<', '>', '<', '>', '<', '>', '>'},
{'>', '>', '<', '<', '<', '>', '<', '>', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '<', '>', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '<', '>', '<', '>', '>'},
{'<', '<', '<', '<', '<', '=', '#', '>', '#', '>', '#'},
{'>', '>', '>', '>', '#', '>', '>', '>', '#', '>', '>'},
{'<', '<', '<', '<', '<', '<', '<', '=', '#', '>', '#'},
{'>', '>', '>', '>', '#', '#', '#', '>', '#', '>', '>'},
{'<', '<', '<', '<', '<', '<', '<', '<', '<', '=', '#'},
{'>', '>', '>', '>', '#', '#', '#', '#', '#', '>', '>'},
{'<', '<', '<', '<', '<', '#', '<', '#', '<', '#', '='}
};
char opp[11] = {'+','-','*','/','(',')','[', ']', '{' , '}','@'};
int Execute(int a, char op, int b) {
switch(op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
}
}
char Cmp(char a, char b) {
int row, col;
for(int i = 0; i < 11; i++) {
if(a == opp[i])
row = i;
if(b == opp[i])
col = i;
}
return table[row][col];
}
int ExpEvaluation(char str[]) {
char Operator[105]; //操作符栈
int Operand[105]; //操作数栈
int operandPointer = 0; //操作数栈顶指针
int operatorPointer = 0; //操作符栈顶指针
int i = 0;
int n = strlen(str);
int a, b, val;
char op;
int sign = 1;
Operator[operatorPointer++] = '@';
while(str[i] != '@' || Operator[operatorPointer - 1] != '@') {
if((str[i] == '-') && (str[i-1] == '{' || str[i-1] == '[' || str[i-1] == '(' || str[i-1] == '@')) {//负号是负数的标记
sign = -1;
i++;
continue;
}
if(!(str[i] >= '0' && str[i] <= '9')) { //操作符
sign = 1;
switch(Cmp(Operator[operatorPointer-1], str[i])) {
case '<': Operator[operatorPointer++] = str[i];
i++;
break;
case '=': operatorPointer--;
i++;
break;
case '>': a = Operand[--operandPointer];
b = Operand[--operandPointer];
op = Operator[--operatorPointer];
val = Execute(b, op, a);
Operand[operandPointer++] = val;
break;
}
}
else { //操作数
int temp = 0;
while(str[i] >= '0' && str[i] <= '9') {
temp = temp * 10 + str[i] - '0';
i++;
}
Operand[operandPointer++] = temp*sign;
}
}
return Operand[operandPointer-1];
}
int main() {
char s[105];
while(gets(s)) {
s[strlen(s)] = '@';
int ans = ExpEvaluation(s);
printf("%d\n", ans);
}
return 0;
}