代码解释
while(j<str.size()&&isdigit(str[j])){
x=x*10+str[j++]-'0';
}
把字符串中里面连续的数字转化为int类型变量,比如输入996/332+8,正常的挨个字符扫描只能扫到’9’,‘9’,‘6’,但是按照上面代码的算法是重新开了一个循环,直接把’9’,‘9’,'6’转化为了int类型的996
else if(c=='('){
op.push(c);
遇到左括号直接入栈就完事儿了
else if(c==')'){
while(op.top()!='(')
eval();
op.pop();
}
遇到了右括号就要不断的从之前的操作符栈和num栈里面取出来计算,然后直到操作符栈顶为左括号。最后把'('
删除就完事儿了
else{
while(op.size()&&pr[op.top()]>=pr[c])
eval();
op.push(c);
}
这是扫描到的字符为'+'
,'-'
,'\*'
,'/'
的情况,这个时候需要比较操作符栈里面和当前扫描到的操作符的优先级进行比较,记住:操作符栈里面的是以前扫描过的操作符是'+'
,'-'
,'\*'
,'/'
里面的一种,也就是说,当前扫描到操作符
和以前的操作符
比较,看看谁的优先级高,如果是以前的操作符优先级高,那么直接计算以前的,如果是现在的优先级高,那么把当前的操作符入操作符栈,等待下一个数字就完事儿了!
while(op.size())
eval();
cout<<num.top()<<endl;
如果扫描完字符依然没有计算完,那么直接继续取出操作符栈里面的计算,最后拿出来num.top()作为结果输出即可!
#include<iostream>
#include<string>
#include<algorithm>
#define N 100086
#include<unordered_map>
#include<stack>
using namespace std;
stack<char> op;
stack<int> num;
unordered_map<char,int> pr{{'+',1},{'-',1},{'*',2},{'/',2}};
void eval(){
int x=0;
int b=num.top();num.pop();
int a=num.top();num.pop();
char c=op.top();op.pop();
if(c=='+')
x=a+b;
else if(c=='-')
x=a-b;
else if(c=='*')
x=a*b;
else if(c=='/')
x=a/b;
num.push(x);
}
int main(){
string str;
cin>>str;
for(int i=0;i<str.size();++i){
char c=str[i];
if(isdigit(c)){
int x=0,j=i;
while(j<str.size()&&isdigit(str[j])){
x=x*10+str[j++]-'0';
}
i=j-1;
num.push(x);
}else if(c=='('){
op.push(c);
}else if(c==')'){
while(op.top()!='(')
eval();
op.pop();
}else{
while(op.size()&&pr[op.top()]>=pr[c])
eval();
op.push(c);
}
}
while(op.size()) eval();
cout<<num.top()<<endl;
return 0;
}
输入用例,使用ide单步调试尝试理解代码或者直接手算也行,但是我还是推荐用ide单步调试比较好,这里用到的变量多,比较复杂,用ide不会算错数!观察这两个用例的计算过程即可完整理解本算法!
- ((7*8)+(9-7))/((12-6)-(6-3))
- 7*8/4+5*7-3/2