题目
问题描述
输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。
输入格式
输入一行,包含一个表达式。
输出格式
输出这个表达式的值。
样例输入
1-2+3*(4-5)
样例输出
-4
数据规模和约定
表达式长度不超过100,表达式运算合法且运算过程都在int内进行。
想法
使用后缀表达式计算即可。在这里有几个需要注意的地方。第一个是注意从数据栈中弹出两个操作数时,先弹出的是后操作数,这一点在进行减法和除法运算时需要注意。第二个是对后缀表达式的理解,先弹出的符号表示实际运算的优先级高,所以当读取到一个符号时,应当弹出优先级高于或者等于当前运算符的符号进行运算,因为平级运算也有有先后的。第三个是在读入表达式的时候,读到数字不能只读一位,而是而是应当考虑数字位数更多的情况。第四个是在使用C++的stack时,在进行条件判断时应当把OP.empty()放在前面,不然如果stack为空,尝试访问栈顶元素会出错。
附:后缀表达式计算
规则:从左至右遍历中缀表达式中每个数字和符号:
1.若是数字直接输出,即成为后缀表达式的一部分;
2.若是符号:
(1)若是),则将栈中元素弹出并输出,直到遇到“(”, “(”弹出但不输出;
(2)若是(,+,*等符号,则从栈中弹出并输出优先级高于或等于当前的符号,直到遇到一个优先级低的符号或者左括号;然后将当前符号压入栈中。
(优先级+,-最低,*,/次之,“(”最高)
3.遍历结束,将栈中所有元素依次弹出,直到栈为空。
实现
#include<iostream>
#include<cctype>
#include<stack>
using namespace std;
int compute(int a,int b,char op);
int main(void)
{
char ch;
stack<int>NUM;
stack<char>OP;
while((ch=getchar())!=EOF){
if(isdigit(ch)){
int num=ch-'0';
while((ch=getchar())!=EOF){
if(isdigit(ch)) num=num*10+ch-'0';
else{
ungetc(ch,stdin);
break;
}
}
NUM.push(num);
}
else{
if(ch=='(') OP.push(ch);
else if(ch=='*'||ch=='/'){
while(!OP.empty()&&(OP.top()=='*'||OP.top()=='/')){
int b=NUM.top();
NUM.pop();
int a=NUM.top();
NUM.pop();
int op=OP.top();
OP.pop();
NUM.push(compute(a,b,op));
}
OP.push(ch);
}
else if(ch=='+'||ch=='-'){
while(!OP.empty()&&(OP.top()=='*'||OP.top()=='/'||OP.top()=='+'||OP.top()=='-')){
int b=NUM.top();
NUM.pop();
int a=NUM.top();
NUM.pop();
int op=OP.top();
OP.pop();
NUM.push(compute(a,b,op));
}
OP.push(ch);
}
else if(ch==')'){
while(!OP.empty()&&OP.top()!='('){
int b=NUM.top();
NUM.pop();
int a=NUM.top();
NUM.pop();
int op=OP.top();
OP.pop();
NUM.push(compute(a,b,op));
}
OP.pop();
}
}
}
while(!OP.empty()){
int b=NUM.top();
NUM.pop();
int a=NUM.top();
NUM.pop();
int op=OP.top();
OP.pop();
NUM.push(compute(a,b,op));
}
cout<<NUM.top();
}
int compute(int a,int b,char op)
{
int ans=0;
switch(op){
case '+':
ans=a+b;
break;
case '-':
ans=a-b;
break;
case '*':
ans=a*b;
break;
case '/':
ans=a/b;
break;
}
return ans;
}