完成算数表达式的计算如(2+13)(10-8/(1+1*3))
代码
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
string s="(2+1*3)*(10-8/(1+1*3))";
char opx[10]={'+','-','*','/','(',')','\0'};//哪些运算符
int opn[265];//运算符对应的数字
char priority[10][10]={//上一个运算符和现在运算符的优先顺序。'='是要消除配对的括号。
{'>', '>', '<', '<', '<', '>','>'},
{'>', '>', '<', '<', '<', '>','>'},
{'>', '>', '>', '>', '<', '>','>'},
{'>', '>', '>', '>', '<', '>','>'},
{'<', '<', '<', '<', '<', '=',' '},
{'<', '<', '<', '<', '=', ' ',' '},
{'<', '<', '<', '<', '<', '<','='}
};
void optonum(){//实现符号和数字的对应
for(int i=0;i<7;i++)opn[opx[i]]=i;
for(int i=0;i<7;i++)cout<<opx[i]<<"\t";cout<<endl;
for(int i=0;i<7;i++)cout<<opn[opx[i]]<<"\t";cout<<endl;
}
vector<int> d;//"运算数"栈。先进后出
vector<int> op;//运算符队列,优先级底的先放进栈。
int cal(int d1,int opx,int d2){//二元运算
switch(opx){
case 0:return d1+d2;break;
case 1:return d1-d2;break;
case 2:return d1*d2;break;
case 3:return d1/d2;break;
}
}
void view(int x,char c){//观察"运算数"和运算符栈
cout<<"算式:"<<s<<"\t数:"<<x<<"\t字符:"<<c<<endl;
cout<<"运算符:";for(vector<int>::iterator i=op.begin();i!=op.end();i++)cout<<"\t"<<opx[*i];cout<<"|"<<endl;
cout<<"运算数:";for(vector<int>::iterator i=d.begin();i!=d.end();i++)cout<<"\t"<<*i;cout<<"|"<<endl;
//system("pause");
}
int main(){
optonum();//完成运算符号和数字的转换
int num=0,//输入的数字
opx1,opx2,//当前运算符和上一个运算符
num1,num2;//前后两个运算数
op.push_back(opn['\0']);//率先放进一个"字符串结束标记",以判断完成运算
for(int i=0;i<=s.length();i++){//遍历算式每个字符
view(num,s[i]);//观察到了哪个字符,运算数栈和运算符栈
if(isdigit(s[i]))num=num*10+s[i]-'0';//该位置是数字,有可能是多为数字
else{//运算符
if(isdigit(s[i-1])){
d.push_back(num);num=0;
}//该字符不是数字,而且前一个是数字,就可以把数字放进运算数队列
opx2=opn[s[i]];//把字符转换成"运算数字"
while(!op.empty()){//有运算符就循环
opx1=op.back();//前一个运算符
cout<<"运算符:\t"<<opx[opx1]<<"和"<<opx[opx2]<<"\t";
if(priority[opx1][opx2]=='>'){//进行上一个优先的运算
op.pop_back();//消除运算的符号
num2=d.back();d.pop_back();//前后两个运算数
num1=d.back();d.pop_back();//第二取出的是第一个运算符
int ans=cal(num1,opx1,num2);
cout<<"算式___________:"<<num1<<" "<<opx[opx1]<<" "<<num2<<endl;
d.push_back(ans);//运算结果放进栈
cout<<num1<<" "<<opx[opx1]<<" "<<num2<<"=结果:"<<ans<<endl;
}else if(priority[opx1][opx2]=='<'){//优先级低,放进队列
op.push_back(opx2);
cout<<"推迟计算!"<<endl;
break;
}else if(priority[opx1][opx2]=='='){//括号配对,消除括号
op.pop_back();
cout<<"消括号!"<<endl;
break;
}
}
}
}
cout<<"结果:"<<d.back();
return 0;
}
程序推进数据
+ - * / ( )
0 1 2 3 4 5 6
算式:(2+13)(10-8/(1+13)) 数:0 字符:(
运算符: |
运算数:|
运算符: 和( 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:2
运算符: (|
运算数:|
算式:(2+13)(10-8/(1+13)) 数:2 字符:+
运算符: (|
运算数:|
运算符: (和+ 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:1
运算符: ( +|
运算数: 2|
算式:(2+13)(10-8/(1+13)) 数:1 字符:
运算符: ( +|
运算数: 2|
运算符: +和 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:3
运算符: ( + |
运算数: 2 1|
算式:(2+13)(10-8/(1+13)) 数:3 字符:)
运算符: ( + |
运算数: 2 1|
运算符: 和) 算式___________:1 * 3
1 * 3=结果:3
运算符: +和) 算式___________:2 + 3
2 + 3=结果:5
运算符: (和) 消括号!
算式:(2+13)(10-8/(1+13)) 数:0 字符:
运算符: |
运算数: 5|
运算符: 和* 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:(
运算符: |
运算数: 5|
运算符: 和( 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:1
运算符: * (|
运算数: 5|
算式:(2+13)(10-8/(1+13)) 数:1 字符:0
运算符: * (|
运算数: 5|
算式:(2+13)(10-8/(1+13)) 数:10 字符:-
运算符: * (|
运算数: 5|
运算符: (和- 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:8
运算符: * ( -|
运算数: 5 10|
算式:(2+13)(10-8/(1+13)) 数:8 字符:/
运算符: * ( -|
运算数: 5 10|
运算符: -和/ 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:(
运算符: * ( - /|
运算数: 5 10 8|
运算符: /和( 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:1
运算符: * ( - / (|
运算数: 5 10 8|
算式:(2+13)(10-8/(1+13)) 数:1 字符:+
运算符: * ( - / (|
运算数: 5 10 8|
运算符: (和+ 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:1
运算符: * ( - / ( +|
运算数: 5 10 8 1|
算式:(2+13)(10-8/(1+13)) 数:1 字符:
运算符: * ( - / ( +|
运算数: 5 10 8 1|
运算符: +和* 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:3
运算符: * ( - / ( + |
运算数: 5 10 8 1 1|
算式:(2+13)(10-8/(1+13)) 数:3 字符:)
运算符: * ( - / ( + |
运算数: 5 10 8 1 1|
运算符: 和) 算式___________:1 * 3
1 * 3=结果:3
运算符: +和) 算式___________:1 + 3
1 + 3=结果:4
运算符: (和) 消括号!
算式:(2+13)(10-8/(1+13)) 数:0 字符:)
运算符: * ( - /|
运算数: 5 10 8 4|
运算符: /和) 算式___________:8 / 4
8 / 4=结果:2
运算符: -和) 算式___________:10 - 2
10 - 2=结果:8
运算符: (和) 消括号!
算式:(2+13)(10-8/(1+1*3)) 数:0 字符:
运算符: *|
运算数: 5 8|
运算符: *和 算式___________:5 * 8
5 * 8=结果:40
运算符: 和 消括号!
结果:40
几个点
- 遇到非数字字符,如果前一个是数字字符,就把num放进队列
- 右括号前所有算式都要算完