题目描述
小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算式,其中只有“(”,“)”,“0-9”,“+”,“-”,“*”,“/”,“^”求出的值就是密码。小明数学学得不好,还需你帮他的忙。(“/”用整数除法,取商)
输入
输入共1行,为一个算式。
输出
输出共1行,就是密码。
样例输入
1+(3+2)*(7^2+6*9)/(2)
样例输出
258
提示
100%的数据满足:算式长度<=30 其中所有数据在231-1的范围内。
解题思路:
此题的关键是将运算符与数分开存入两个栈中。每次将符号压入栈前判断该运算符的优先级是否大于前一个运算符。若前一个运算符大则前一个运算符与刚存入的两个数进行运算然后再压入栈中。最终完成运算。
以下代码借鉴过大神的思路,我加入了详细的备注。
借鉴于这位大神
https://blog.csdn.net/u011123263/article/details/14457865
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
int rate(char a)//该函数给每个运算符定优先级
{
if(a=='+'||a=='-')return 1;
if(a=='*'||a=='/')return 2;
if(a=='^')return 3;
if(a=='(')return 0;
}
void cal(stack<int>&a,stack<char>&b)//该函数进行计算,每次出栈两个数和一个运算符进行计算,结果再压入存数栈中
{ int num1=0,num2=0;
char s;
num1=a.top();
a.pop();
num2=a.top();
a.pop();
s=b.top();
b.pop();
if(s=='+')a.push(num2+num1);
else if(s=='-')a.push(num2-num1);
else if(s=='*')a.push(num2*num1);
else if(s=='/')a.push(num2/num1);
else if(s=='^')
{ int res=1;
for(int i=1;i<=num1;i++)
res=res*num2;
a.push(res);
}
}
int main()
{
char s[1000];
cin>>s;
int flag=0,sum=0;
stack<int>calnum;
stack<char>calsign;
for(int i=0;i<strlen(s);i++)
{
if(isdigit(s[i]))
{
sum=sum*10+s[i]-'0';//sum用于存储数字
flag=1;
}
else
{
if(flag){ calnum.push(sum);flag=0;sum=0;}//flag用于标记字符串的数是否读完,以遇到符号结束 后清零
if(s[i]=='(')
{
calsign.push(s[i]);//遇到左括号直接压入符号栈后结束
continue;
}
if(s[i]==')')
{
while(calsign.top()!='(')
{
cal(calnum,calsign); //配对的括号内优先进行计算,直到遇到左括号为止,然后将左括号出栈
}
calsign.pop();
continue;
}
if(calsign.empty())calsign.push(s[i]);//若符号栈为空,直接压入符号
else
{
while(!calsign.empty()&&rate(calsign.top())>=rate(s[i]))//若要压入符号优先级比栈顶的优先级要小,则计算
cal(calnum,calsign);
calsign.push(s[i]);
}
}
}
if(flag){
calnum.push(sum);//因为最后不以符号结尾所以最后一个数需再做处理
}
while(!calsign.empty())cal(calnum,calsign);
cout<<calnum.top()<<endl;
return 0;
}