题目描述
给定一个字符串str,str表示一个公式,公式里可以有整数,加减乘除和左右括号,返回公式的计算结果(注意:题目中所有运算都是整型运算,向下取整,且保证数据合法,不会出现除0等情况)。
输入描述:
输出一行字符串,代表str(1≤lengthstr≤1000)(保证str计算的结果不会出现除零,int溢出等情况)。
输出描述:
输出一个整数,代表表达式的计算结果。
示例1
输入
48*((70-65)-43)+8*1
输出
-1816
示例2
输入
3+1*4
输出
7
算法思路:字符串给定值是中缀表达式,计算机无法直接计算,需要转换成后缀表达式(逆波兰表达式),中缀转后缀形式不唯一,但是计算结果是一致的,因为对于同一级运算,先计算前面在计算后面和先计算后面在计算前面一样。不过,后缀表达式转换成中缀表达式则是唯一的。
一般转换方法:使用两个栈,一个数字栈,一个运算符栈,在转换过程中不断计算
遍历字符串中每一个字符
1、如果是数字字符,则不断通过字符到数字的转换,然后将数字压入数字栈;
2、如果是运算符,此时运算符栈为空,直接压入该运算符,否则,不断弹出运算符栈中优先级不低于该运算符的字符
弹出的时候顺便调用计算函数calculate计算,直到遇到'(',直接弹出;
3、如果是左右括号:如果是左括号'(',直接入运算符栈,否则是右括号')',不断弹出运算符栈,并计算,直到遇到左括号'(',弹 出左括号'('结束;
4、遍历完每一个字符后,如果运算符栈还不空,不断取里面的运算符并计算,最后数字栈中就剩一个元素,即为最终的结果。
注意:这里没有考虑数字前面有负号运算符的情况,比如-4+3=-1,这里不能简单的认为'-'是减号运算符,在代码中有一个if语句用来处理这种情况。(一般情况,我们认为没有这种情况,并假定输入都是合法和规矩的,但是这边OJ有这种测试案例,不加大概通过90%,加上ac)
#include<bits/stdc++.h>
using namespace std;
int getPriority(char& ch){
if(ch=='(') return 1;
if(ch=='+' || ch=='-') return 2;
if(ch=='*' || ch=='/') return 3;
return 4;
}
void calculate(stack<int>& numStk,char& opr){
int num2=numStk.top();
numStk.pop();
int num1=numStk.top();
numStk.pop();
int res=0;
if(opr=='+'){
res=num1+num2;
}else if(opr=='-'){
res=num1-num2;
}else if(opr=='*'){
res=num1*num2;
}else{ //opr=='/'
res=num1/num2;
}
numStk.push(res);
return;
}
int main(){
string s;
cin>>s;
stack<int> numStk;
stack<char> oprStk;
int i=0;
int n=s.size();
char tmp_opr;
int flag=0;
if(s[0]=='-'){
i=1;
flag=1;
}
while(i<n){
if( s[i]=='-' && s[i-1]!=')' && (s[i-1]<'0' || s[i-1]>'9') ){
flag=1;
i++;
continue;
}
if(s[i]>='0' && s[i]<='9'){
int tmp_num=0;
while(i<n && s[i]>='0' && s[i]<='9'){
tmp_num=10*tmp_num+s[i]-'0';
i++;
}
if(flag){
tmp_num*=-1;
flag=0;
}
numStk.push(tmp_num);
}else if(s[i]=='+' || s[i]=='-' || s[i]=='*' || s[i]=='/'){
if(oprStk.empty()){
oprStk.push(s[i]);
}else{
while(!oprStk.empty()){
tmp_opr=oprStk.top();
if(getPriority(tmp_opr)>=getPriority(s[i])){
//calculate
calculate(numStk,tmp_opr);
oprStk.pop();
}else{
break;
}
}
oprStk.push(s[i]);
}
i++;
}else{ //s[i]=='(' || s[i]==')'
if(s[i]=='('){
oprStk.push(s[i]);
}else{
while(oprStk.top()!='('){
tmp_opr=oprStk.top();
calculate(numStk,tmp_opr);
oprStk.pop();
}
oprStk.pop();
}
i++;
}
}
while(!oprStk.empty()){
tmp_opr=oprStk.top();
calculate(numStk,tmp_opr);
oprStk.pop();
}
cout<<numStk.top()<<endl;
return 0;
}