表达式求值

来源:互联网 发布:java数据连接池原理 编辑:程序博客网 时间:2024/04/30 14:13

Description

 给出的表达式全为合法的四则运算表达式,含括号。

Input

 每行一个表达式,数字全为int型整数,长度不超过100字符

Output

 输出表达式的值,一律保留小数点后4位。

Sample Input

11+2-1+2-1+(-2)

Sample Output

1.00003.00001.0000-3.0000

 

 

 解法一:

//即使程序写的再差,也要坚持把它写完!/*不同的思路,所以写出的程序也有所不同,所以并不存在好坏,没有最好的程序,只有更好的,不是别人的都比自己的好,借鉴别人的一些技巧,没必要全部模仿!*/#include <cstdio>#include <cstring>int _cp[1<<7][1<<7];void Init(){memset(_cp,-1,sizeof(_cp));_cp['+']['+']=_cp['-']['-']=_cp['+']['-']=_cp['-']['+']=0;_cp['*']['*']=_cp['/']['/']=_cp['*']['/']=_cp['/']['*']=0;_cp['*']['+']=_cp['*']['-']=_cp['/']['+']=_cp['/']['-']=1;//后面优先级比前面低_cp['(']['+']=_cp['(']['-']=_cp['(']['*']=_cp['(']['/']=1;//小技巧:对使用到的情况进行初始化}bool IsDigit(char c){if(c>='0' && c<='9')return 1;return 0;}double operation(double f1,char c,double f2){switch(c){case '+':return f1+f2;break;case '-':return f1-f2;break;case '*':return f1*f2;break;case '/':return f1/f2;break;default:break;}}int main(){freopen("data.in","r",stdin);const int nMax=105;char line[nMax];while(gets(line)){int len=strlen(line);line[len]=')';line[len+1]='\0';double data_stack[nMax];char ope_stack[nMax];int data_top=-1;int ope_top=0;ope_stack[0]='(';Init();bool first=true;for(int i=0;i<=len;){if(line[i]==')')//括号中内容历编完成的情况{double f1,f2;f2=data_stack[data_top--];while(ope_top>=0 && ope_stack[ope_top--]!='(')f2=operation(data_stack[data_top--],ope_stack[ope_top+1],f2);data_stack[++data_top]=f2;i++;}else if(IsDigit(line[i]))//扫描到数字{first=false;int num=0;while(IsDigit(line[i]))//当表达式中可为浮点数时只需要追加小数点判断就行。{num+=num*10+line[i]-'0';i++;}data_stack[++data_top]=num;}else if(first && (line[i]=='+' || line[i]=='-'))//+,- 表示数的符号{int sign=1;if(line[i]=='-') sign=-1;i++;int num=0;while(IsDigit(line[i])){num+=num*10+line[i]-'0';i++;}data_stack[++data_top]=sign*num;first=false;}else if(_cp[ope_stack[ope_top]][line[i]]>=0)//后面操作符优先级低于前面的情况{if(ope_stack[ope_top]!='('){char c=ope_stack[ope_top--];double result=operation(data_stack[data_top-1],c,data_stack[data_top]);data_top-=2;data_stack[++data_top]=result;}ope_stack[++ope_top]=line[i];i++;}else{if(line[i]=='(')first=true;ope_stack[++ope_top]=line[i++];}}printf("%.4lf\n",data_stack[0]);}return 0;}

另一种思路(推荐):

/*用栈转换成逆波兰式求解,这个解法较上一解法更清楚一些!推荐主要步骤:1)去空字符2)初始化优先级3)转换:其中需要注意有:① +,- 被用作数字符号的判断② 括号匹配中注意点③ 运算操作*/#include <cstdio>#include <cstring>const int nMax=105;char line[nMax];double data_stack[nMax];char opt_stack[nMax];int data_top,opt_top;int insp[1<<7],outsp[1<<7];void init(){insp['#']=outsp['#']=0;insp['(']=1;outsp[')']=1;outsp['(']=6;insp['+']=insp['-']=2;outsp['+']=outsp['-']=3;insp['*']=insp['/']=4;outsp['*']=outsp['/']=5;}void delete_blank(){int i,j;for(i=0,j=0;line[i];i++){if(line[i]!=' ' && line[i]!='\t')line[j++]=line[i];}line[j]='\0';}bool is_digit(char c){if(c>='0' && c<='9')return 1;return 0;}double calculate(char c)//③{double f2=data_stack[data_top--];double f1=data_stack[data_top--];switch(c){case '+':return data_stack[++data_top]=f1+f2;break;case '-':return data_stack[++data_top]=f1-f2;break;case '*':return data_stack[++data_top]=f1*f2;break;case '/':return data_stack[++data_top]=f1/f2;break;default:break;}}double exchange(){int len=strlen(line);for(int i=0;i<len;i++){if((line[i]=='+' || line[i]=='-') && (i==0 || line[i-1]=='('))data_stack[++data_top]=0;//①if(is_digit(line[i])){double num=0;while(is_digit(line[i++]))num+=num*10+line[i]-'0';data_stack[++data_top]=num;i--;}else if(insp[opt_stack[opt_top]]<outsp[line[i]])opt_stack[++opt_top]=line[i];else {do{calculate(opt_stack[opt_top--]);}while(insp[opt_stack[opt_top]]>outsp[line[i]]);if(opt_stack[opt_top]!='(')opt_stack[++opt_top]=line[i];elseopt_top--;//②}}while(opt_stack[opt_top]!='#')calculate(opt_stack[opt_top--]);return data_stack[0];}int main(){freopen("data.in","r",stdin);init();while(gets(line)){delete_blank();data_top=opt_top=-1;opt_stack[++opt_top]='#';printf("%.4f\n",exchange());}return 0;}


 

 

/*解法二:使用递归实现,很不错的解法。推荐!*/#include <cstdio>#include <cstring>const int nMax=105;char line[nMax];void init(){int i,j;for(i=j=0;line[i];i++)if(line[i]!=' ' && line[i]!='\t')line[j++]=line[i];line[j]='\0';}bool is_num(int l,int r){for(int i=l;i<=r;i++)if(line[i]<'0' || line[i]>'9')return false;return true;}double calculate(int l,int r){int i;if(l>r) return 0;if(is_num(l,r)){/*double num=0;for(i=l;i<=r;i++)num=num*10+line[i]-'0';return num;*///方法二:double num;sscanf(line+l,"%lf",&num);return num;}int p;//只需要保证先加减后乘除即可for(p=0,i=l;i<=r;i++){if(line[i]=='(') p++;else if(line[i]==')') p--;if(!p && line[i]=='+')return calculate(l,i-1)+calculate(i+1,r);}//for(p=0,i=r;i>=l;i--)//无需逆向搜索for(p=0,i=l;i<=r;i++){if(line[i]=='(') p++;else if(line[i]==')') p--;if(!p && line[i]=='-')return calculate(l,i-1)-calculate(i+1,r);}for(p=0,i=1;i<=r;i++){if(line[i]=='(') p++;else if(line[i]==')') p--;if(!p && line[i]=='*')return calculate(l,i-1)*calculate(i+1,r);}//for(p=0,i=r;i>=0;i--)for(p=0,i=l;i<=r;i++){if(line[i]=='(') p++;else if(line[i]==')') p--;if(!p && line[i]=='/')return calculate(l,i-1)/calculate(i+1,r);}return calculate(l+1,r-1);}int main(){freopen("e:\data.in","r",stdin);while(gets(line)){init();printf("%.4lf\n",calculate(0,strlen(line)-1));}return 0;}


 

原创粉丝点击