给出的表达式全为合法的四则运算表达式,含括号。
给出的表达式全为合法的四则运算表达式,含括号。
每行一个表达式,数字全为int型整数,长度不超过100字符
输出表达式的值,一律保留小数点后4位。
1 1+2 -1+2 -1+(-2)
1.0000 3.0000 1.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]; else opt_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; }