简单计算器
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 18228 Accepted Submission(s): 6416
Problem Description
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
Input
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
Output
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
Sample Input
1 + 2 4 + 2 * 5 - 7 / 11 0
Sample Output
3.00 13.36题目描述:表达式求值问题。谈谈解题过程吧:由于本人是菜菜,所以很弱,看到这个题是表达式求值,马上就用教科书上表达式求值的模板,我们学校用的是<<数据结构教程>>(第4版)李春葆的书,敲了半天,交上去wa了这题意其实不怎么明显,他没说运算数的精度,如果是2个超过60个字符的数字他们之间的运算double可能会精度受损,所以我就想用java大精度来写,我又用java写了半天,真真切切花了不少时间把c++代码给转换成了java,不过结果是wa,没办法了,于是借鉴了大神的解题思路,结果半小时不到就a了,当然之前我的想法是错了,她不会给你大数的运算,真是膜拜啊!根据大神的思路,代码如下:这种暴力简洁的代码,一目了然,也通熟易懂,耗时也少。//c++解法,没有括号的 #include <cstdio> #include <iostream> #include <cstring> #include <iomanip> using namespace std; const int maxn=10001; double num[maxn]; int main() { double d; char c; // freopen("data.in","r",stdin); while(true) { memset(num,0,sizeof(num)); int p = 0; cin >> d; num[0]=d; c=getchar(); if(d==0&&c=='\n') break; while(true) { cin>>c>>d; if(c == '/') num[p]/=d; else if(c == '*') num[p]*=d; else if(c == '-') num[++p]-=d; else num[++p]+=d; if(getchar()=='\n') break; } double res=0; for(int i = 0;i <= p;++ i) res += num[i]; cout << fixed << setprecision(2) << res << endl; } return 0; }
在用这种思想做完后,既然没有大数的处理,于是反过头去做之前的自己代码,我无意间改了下我的输入,结果交上去就a了,居然是这种低级错误,原来是我判断结束时没有判断其长度为1,ac代码如下//一般解法,没有大数 #include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn = 2000; const int MaxOp=5; struct op //设定运算符优先级 { char ch; //运算符 int pri; //优先级 }lpri[MaxOp]={{'=',0},{'+',2},{'-',2},{'*',4},{'/',4}}, rpri[MaxOp]={{'=',0},{'+',1},{'-',1},{'*',3},{'/',3}}; int leftpri(char op) //求左运算符op的优先级 { for(int i = 0;i < MaxOp;++ i) if(lpri[i].ch==op) return lpri[i].pri; } int rightpri(char op) //求有运算符op的优先级 { for(int i = 0;i < MaxOp;++ i) if(rpri[i].ch==op) return rpri[i].pri; } bool INOp(char ch) //判断ch是否为运算符 { if(ch=='+'||ch=='-'||ch=='*'||ch=='/') return true; return false; } int Precede(char op1,char op2) //op1和op2运算符优先级的比较结果 { if(leftpri(op1)<rightpri(op2)) return -1; else return 1; } void trans(char *exp,char *postexp) //将exp表达式转换成后缀表达式 { struct p { char data[maxn]; //存放运算符 int top; }op; int i = 0; //i作为postexp的下标 op.top = -1; op.top++; op.data[op.top] = '='; //将'='进栈 while(*exp!='\0') //exp表达式未扫描时循环 { if(!INOp(*exp)) //为数字字符的情况 { while(*exp >= '0'&&*exp<='9') //判断为数字 { postexp[i++]=*exp; exp++; } postexp[i++]='#'; //用'#'标志一个数值串结束 } else //为运算符的情况 { switch(Precede(op.data[op.top],*exp)) { case -1: //栈顶运算符的优先级低 op.top++;op.data[op.top]=*exp; exp++; //继续扫描其他字符 break; case 1: //退栈并输出到postexp中 postexp[i++]=op.data[op.top]; op.top--; break; } } } while(op.data[op.top]!='=') //此时exp扫描完毕,退栈到'='为止 { postexp[i++] = op.data[op.top]; op.top--; } postexp[i]='\0'; //给postexp表达式添加结束标识 } double compvalue(char *postexp) //计算后缀表达式的postexp的值 { struct { double data[maxn]; //存放数值 int top; //栈指针 }st; //定义一个运算数栈 double a,b,c,d; st.top=-1; while(*postexp!='\0') //postexp字符串未扫描时完成循环 { switch(*postexp) { case '+': //判定'+' a = st.data[st.top]; st.top--; //退栈并取值a b = st.data[st.top]; st.top--; //退栈并取值b c = a + b; //计算c st.data[++st.top]=c; //将计算结果进栈 break; case '-': //判定'-' a = st.data[st.top]; st.top--; //退栈并取值a b = st.data[st.top]; st.top--; //退栈并取值b c = b - a; //计算c st.data[++st.top]=c; //将计算结果进栈 break; case '*': //判定'*' a = st.data[st.top]; st.top--; //退栈并取值a b = st.data[st.top]; st.top--; //退栈并取值b c = a * b; //计算c st.data[++st.top]=c; //将计算结果进栈 break; case '/': //判定'/' a = st.data[st.top]; st.top--; //退栈并取值a b = st.data[st.top]; st.top--; //退栈并取值b if(a!=0) //判断被除数不能为0 { c = b/a; //计算c st.data[++st.top]=c; //将计算结果进栈 } break; default: //处理数字字符 d = 0; //将连续的数字字符转换成对应的数值存放到d中 while(*postexp >= '0'&&*postexp <= '9')//判定为数字字符 { d=10*d+*postexp-'0'; postexp++; } st.data[++st.top]=d; } postexp++; //继续处理其他字符 } return st.data[st.top]; } int main() { char exp[maxn]; char c[maxn]; int cnt=0; freopen("data.in","r",stdin); while(true) { gets(c); bool flag=true; int len = strlen(c); if(c[0]=='0'&&len==1) break; cnt=0; for(int i = 0;c[i];++ i) if(c[i]!=' ') exp[cnt++]=c[i]; exp[cnt]='\0'; char postexp[maxn]; trans(exp,postexp); printf("%.2lf\n",compvalue(postexp)); } return 0; }