118.算术表达式求值
C时间限制:3000 毫秒 | C内存限制:3000 Kb
题目内容:
输入一个由数字、+,-,*,/ 组成的算术表达式,求其值。
输入描述
一个表达式,其中每个运算数为正整数
输出描述
计算结果,保留2位小数
输入样例
1+12*3-4/2
输出样例
35.00
解题思路:
1转换为后缀表达式
2利用后缀表达式求值
这里栈就派上用场了,从左到右一个个遍历表达式,遇到操作数就入栈,
遇到操作符就依次取出栈顶的两个操作数进行计算,并把计算结果入栈,
供后面计算,直到栈为空,说明表达式计算完毕,否则说明表达式有问题。
求后缀表达式样例
2+3*(7-4)
2 3 7 4 - * +
12+23*(37-14)
12 23 37 14 - * +
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
const int len=10000;
char ifx[len+1];//中缀
char sfx[2*len+1];//后缀
bool IsDig(char a){//判断是否为数字
if('0'<=a&&a<='9')return true;
else return false;
}
bool IsOperator(char a){//判断是否为运算符
if(a=='+'||a=='-'||a=='*'||a=='/')return true;
else return false;
}
bool Yxj(char a,char b){//判断优先级
int x,y;
switch(a){
case '*':
case '/':x=2;break;
case '+':
case '-':x=1;break;
}
switch(b){
case '*':
case '/':y=2;break;
case '+':
case '-':y=1;break;
}
if(x>=y)return true;
else return false;
}
//中缀转后缀
void infixToSuffix(){
stack<char> optr;//运算符符
while(optr.empty()==false) optr.pop();
int k=0;
sfx[k]='\0';
for(int i=0;ifx[i];i++){
if(IsDig(ifx[i])){//遇到数字直接输出到sfx
sfx[k++]=ifx[i];
if(!IsDig(ifx[i+1]))
sfx[k++]=' ';//当后面一个不是数字时才输入空格
}else if(ifx[i]=='('){//遇到前括号直接入栈
optr.push(ifx[i]);
}else if(ifx[i]==')'){//遇到后括号 ,出栈,直到遇到前括号
while(optr.top()!='('){
sfx[k++]=optr.top();
sfx[k++]=' ';
optr.pop();
}optr.pop();
}else if(IsOperator(ifx[i])){//遇到运算符
if(optr.empty())//栈为空时直接入栈
optr.push(ifx[i]);
else{
while(Yxj(optr.top(),ifx[i])){ //当栈为空时,访问top()会出错
sfx[k++]=optr.top();
sfx[k++]=' ';
optr.pop();
if(optr.empty())//加了这一行,问题解决了
break;
}
optr.push(ifx[i]);
}
}
}
while(!optr.empty()){
sfx[k++]=optr.top();
sfx[k++]=' ';
optr.pop();
}
sfx[k-1]='\0';
}
//计算一次
double calOnce(double a,char optr,double b){
switch(optr){
case '+':return a+b;
case '-':return a-b;
case '*':return a*b;
case '/':return a/b;
}
}
//用后缀表达式计算结果
//12 23 37 14 - * +
double getAnswer(){
infixToSuffix();
//puts(sfx);
stack<double> dig;//操作数栈
while(dig.empty()==false)dig.pop();
double x=0;
double a,b,ans=0;
for(int i=0;sfx[i];i++){
if(sfx[i]==' ') continue;
else if(IsDig(sfx[i])){
if(IsDig(sfx[i+1]))
x=x*10+sfx[i]-'0';
else{
x=x*10+sfx[i]-'0';
dig.push(x);
x=0;
}
}else{//遇到操作符
b=dig.top();dig.pop();
a=dig.top();dig.pop();//先入栈的计算时应该在前面
ans=calOnce(a,sfx[i],b);
//printf("%.2lf%c%.2lf=%.2lf\n",a,sfx[i],b);
dig.push(ans);
}
}
return ans;
}
int main(){
while(~scanf("%s",ifx)){
printf("%.2lf\n",getAnswer());
}
return 0;
}