表达式的求值
(第一遍忘了把运算结果压入数字栈 ๑乛◡乛๑)
#include<stack>
#include<stdio.h>
using namespace std;
char str[220];//保存表达式字符串
int mat[][5]={//优先级矩阵
//若mat[i][j]==1 则表示i号运算符优先级大于j号运算符
//人为添加在表达式首尾的标记运算符为0号
//+ - * /分别为1-4号
1,0,0,0,0,
1,0,0,0,0,
1,0,0,0,0,
1,1,1,0,0,
1,1,1,0,0,
};
stack<int> op;//运算符栈,保存运算符编号
stack<double> in;//数字栈,运算结果可能存在浮点数,所以保存元素为double
void getOp(bool &reto,int &retn,int &i){
//获得表达式中下一个元素
//若函数运行结束时 引用变量reto为true 则表示该元素为一个运算符,其编号保存在引用变量retn中;
//否则,表示该元素为一个数字,其值保存在引用变量retn中。引用变量i表示遍历到的字符串下标
if(i==0&&op.empty()==true){
//若此时字符串遍历第一个字符,且运算符栈为空。我们人为添加编号为0的标记字符
reto=true;//为字符串
retn=0;//编号为0
return;//返回
}
if(str[i]==0)//若此时遍历字符为空字符,则表示字符已经被遍历完
{
reto=true;
retn=0;
return;
}
if(str[i]>='0'&&str[i]<='9')
{
reto=false;//返回为数字
}
else{
reto=true;
if(str[i]=='+'){
retn=1;
}
else if(str[i]=='-'){
retn=2;
}
else if(str[i]=='*'){
retn=3;
}
else if(str[i]=='/'){
retn=4;
}
i+=2;//i递增,跳过该运算字符和该运算字符后的空格
return;
}
retn=0;//返回结果为数字
for(;str[i]!=' '&&str[i]!=0;i++){
//若字符串未被遍历完,且下一个字符不是空格,则依次遍历其后数字,计算当前连续数字字符表示的数值
retn*=10;
retn+=str[i]-'0';
}
if(str[i]==' ')
i++;
return;
}
int main(){
while(gets(str)){
if(str[0]=='0'&&str[1]==0) break;//若输入只有一个0,则退出
bool retop; int retnum;
int idx=0;//遍历到的字符串下标
while(!op.empty()) op.pop();
while(!op.empty()) in.pop();//清空两个栈
while(true){
getOp(retop,retnum,idx);//获取表达式中下一个元素
if(retop==false){
//若该元素为数字
in.push((double)retnum);
}
else{
double tmp;
if(op.empty()==true||mat[retnum][op.top()]==1){
op.push(retnum);
//若运算符栈为空或者当前遍历到的运算符优先级大于栈顶运算符
//将该运算符压入运算符堆栈
}
else{
while(mat[retnum][op.top()]==0){
//当前运算符优先级小于栈顶运算符则重复循环
int ret=op.top();//保存栈顶运算符
op.pop();//弹出
double b=in.top();
in.pop();
double a=in.top();
in.pop();
//从数字堆栈栈顶弹出两个数字,依次保存在遍历a,b中
if(ret==1) tmp=a+b;
else if(ret==2) tmp=a-b;
else if(ret==3) tmp=a*b;
else tmp=a/b;
in.push(tmp);
}
op.push(retnum);//将当前运算符压入运算符栈
}
}
if(op.size()==2&&op.top()==0) break;
//若运算符栈只有两个元素 且栈顶元素为标记运算符,则表示表达式求值结束
}
printf("%.2f\n",in.top());
}
return 0;
}
结果示例