给出一个表达式,其中运算符仅包含+,-,*,/,^
(加 减 乘 整除 乘方)要求求出表达式的最终值。
数据可能会出现括号情况,还有可能出现多余括号情况。
数据保证不会出现大于或等于2^31的答案。
数据可能会出现负数情况。
输入格式
输入仅一行,即为表达式。
输出格式
输出仅一行,既为表达式算出的结果。
输入样例:
(2+2)^(1+1)
输出样例:
16
思路:
(1):双栈,1个栈存储数字,一个栈存储运算符
(2):运算符优先级,栈顶运算符和即将入栈的运算符的优先级比较:
如果栈顶的运算符优先级低,新运算符直接入栈
如果栈顶的运算符优先级高,先出栈计算,新运算符再入栈
出栈计算:取出数字栈前两个数字,运算符栈顶进行一次运算,并将结果存入数字栈
如果遇到'(',直接入栈,如果遇到')',除非运算符栈顶是'(',
否则不断进行运算,直到遇见左括号,将左括号弹出
特别的:对于负数要进行判断:如果运算符是'-'并且运算符前一个字符不是数字或者')',
则表示这是一个负数,如果'-'下一个字符是'(',直接在数字栈存入-1,在运算符栈存入'*',
题目中说可能会有多余括号,为此只需要保证'('数量>')'数量
#include<iostream>
#include<stack>
#include<unordered_map>
#include<cmath>
using namespace std;
stack<char> ops;//数字栈
stack<int> num;//运算符栈
unordered_map<char,int>ump={{'+',1},{'-',1},{'*',2},{'/',2},{'^',3}};
//key表示运算符,value表示优先级
int qmi(int x,int k){
int res=1;
while(k){
if(k&1) res*=x;
x*=x;
k>>=1;
}
return res;
}
void cal(){//运算函数
int a=num.top();num.pop();
int b=num.top();num.pop();
char c=ops.top();ops.pop();
int ans=0;
if(c=='+') ans=b+a;
if(c=='-') ans=b-a;
if(c=='*') ans=b*a;
if(c=='/') ans=b/a;
if(c=='^') ans=qmi(b,a);
num.push(ans);
}
int main()
{
string s,str;
cin>>s;
for(int i=0;i<s.size();++i) str+='(';
s=str+s+')';//应对多余括号
for(int i=0;i<s.size();++i){
if(s[i]>='0'&&s[i]<='9'){//判断数字
int j=i,t=0;
while(s[j]>='0'&&s[j]<='9'){
t=t*10+s[j]-'0';
j++;
}
num.push(t);
i=j-1;
}
else if(s[i]=='-'&&!(s[i-1]>='0'&&s[i-1]<='9'||s[i-1]==')')){//判断负数
if (s[i + 1] == '('){//负数且下一个是'('
num.push(-1);
ops.push('*');
}
else{
int j=i+1,t=0;
while(s[j]>='0'&&s[j]<='9'){
t=t*10+s[j]-'0';
j++;
}
num.push(-t);
i=j-1;
}
}
else if(s[i]=='(') ops.push(s[i]);//左括号直接入栈
else if(s[i]==')'){//右括号不断计算直到遇到左括号
while(ops.top()!='(')cal();
ops.pop();
}
else{//运算符优先级比较
while(ops.size()&&ump[ops.top()]>=ump[s[i]])
cal();
ops.push(s[i]);
}
}
cout<<num.top();
}