最近写了一个计算器,便将其中的核心模块——表达式求值这一块稍微封装了一下,以便以后能更好的代码复用,在此我想说一下我的感悟,写程序的时候尽量将那些能单独成为模块的尽量用函数或者类封装起来,并提供通用接口,这样写出来的代码既可以给别人用,以后自己遇到相似的问题时工作量也会小很多。代码写的不是很好,难免会有BUG,忘发现BUG的亲们能提醒我下,好让我改进。
函数原型:public String suffix_expression(String expression);
说明:次函数传入参数只有一个就是expression——你要计算的表达式,返回类型为String,有两种情况,一是返回正确结果,二是返回错误信息。此函数只能处理普通的四则运算表达式,含有平方,开方或者其他运算符本函数处理不了。
例如:10+2*5,2.5*4+(3+2)等等都可以处理
全部代码如下:(没有封装成类了,要用的可以直接将此段代码拷贝至自己的代码中,然后调用suffix_expression函数即可)
view plain
private String suffix_expression(String expression)//中缀表达式转换后缀表达式(逆波兰式)
{
//Stack
Stack
Stack
int len=expression.length();//
char c1;
double number;
int m,n=-1;
for(int i=0;i { c1=expression.charAt(i); if(isOprator(c1)||(i==len-1))//如果是运算符,将前面的数数字入s3栈,操作符入s4栈 { if(i==len-1&&(!isOprator(c1)))//当最后一位且不是操作符时,将前面的数压栈 m=i+1; else m=i; //操作数入栈,向前遍历到下一个运算符,将中间的字符串转化为double for(int j=i-1;j>=0;j--) { if(isOprator(expression.charAt(j))) { n=j; break; } n=j-1; } if(m!=n+1)//只有当这两个值不等时中间才会有操作数 { number=Double.parseDouble(expression.substring(n+1,m)); s3.push(number); } //运算符入栈 if(i==0&&(c1!='('))//当表达式第一个字符就为运算符且不是左括号时,返回表达式错误 { return "表达式错误!"; } else if(isOprator(c1))//且是操作符时 { while(true) { if(s4.isEmpty()||s4.peek()=='('||c1=='(')//如果栈为空或者栈顶元素为(或者c1为(时,则直接将运算符压入栈内 { s4.push(c1); break; } else if(c1==')')//当c1为)时,依次弹出s4中的运算符并压入s3,直到(,舍弃这一对括号 { while(s4.peek()!='(') { s3.push(s4.pop()); if(s4.isEmpty())//弹出所有不为左括号之后堆栈为空,则表达式不合法 { return "缺少左括号"; } } s4.pop();//弹出( break; } else { if(priorityCompare(c1,s4.peek())==1)//判断优先级,优先级高入栈,优先级低将栈顶运算符压入s3 { s4.push(c1); break; } else { s3.push(s4.pop()); } } } } } else continue; } while(!s4.isEmpty())//表达式结束后,依次将s4剩下的运算符压入s3 { if((char)s4.peek()=='(') re