问题:以字符形式输入一个计算式求值,如1+2-(3-2)/2+3/(4*8)
思路:
栈实现计算表达式值;双栈:数字栈和运算符栈;每次对当前字符判断,数字则压入数字栈,运算符则判断运算符栈与当前运算符优先级;优先级相等,则字符串栈出栈一个元素(运算符),优先级低则将当前运算符压入运算符栈中;优先级高则优先级高则区出栈数字栈两个数字与出栈运算符栈栈顶运算符做运算,结果压入数字栈中,当前运算符不变;判断程序结束边界为当前字符为‘#’或运算符栈栈顶字符为‘#’;
Code:
public class caculate {
/*
* 用数组之间关系存储优先级关系下标0、1、2、3、4、5、6分别对应+、-、*、/、(、)、#运算符,#表示运算表达式的开始与结束
*/
static char[][] c= {{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='}};
/*
* 比较运算符x与y之间的优先级,返回
*/
static char compare(String x,String y) {
int i = 0,j = 0;
char x1=x.charAt(0);
char y1=y.charAt(0);
switch(x1) {
case '+':i=0;break;
case '-':i=1;break;
case '*':i=2;break;
case '/':i=3;break;
case '(':i=4;break;
case ')':i=5;break;
case '#':i=6;break;
}
switch(y1) {
case '+':j=0;break;
case '-':j=1;break;
case '*':j=2;break;
case '/':j=3;break;
case '(':j=4;break;
case ')':j=5;break;
case '#':j=6;break;
}
// System.out.println(x+":"+y+","+c[i][j]);
return c[i][j];
}
//获取下一个输入(操作符or操作数);0-9(48~57)对应ASCII十进制判断是数字还是运算符,数字则判断是几位数
static String getnext(String s) {
int i,t,q;
String s1=""+s.charAt(0);
t=(int)s.charAt(0);
if(t>=48&&t<=57) {
q=0;
}else {
q=1;
}
for(i=1;i<s.length();i++) {
t=(int)s.charAt(i);
if(t>=48&&t<=57) {
if(q==0) {
s1=s1+s.charAt(i);
}else {
break;
}
}else {
break;
}
}
// System.out.println("getnext:"+s1);
return s1;
}
/*
* 计算y与x之间s操作的值
*/
static double solve(double x,double y,String s) {
char c=s.charAt(0);
double r = 0;
switch(c) {
case '+':r=x+y;break;
case '-':r=y-x;break;
case '*':r=x*y;break;
case '/':r=y/x;break;
}
// System.out.println(x+s+y+"="+r);
return r;
}
public static void main(String[] args) {
Scanner as=new Scanner(System.in);
String s=as.nextLine();
System.out.println(s);
s=s+'#';
Stack num=new Stack();
Stack cha=new Stack();
cha.push("#");
String k;
double x,y,t=0;
boolean state=false;
//获取当前字符组合,以字符型形式返回
k=getnext(s);
//判断当前字符组合(下一个是字符还是数)是数字还是运算符,数字state值为true,运算符state值为false
if((int)k.charAt(0)>=48&&(int)k.charAt(0)<=57) {
state=true;
}else {
state=false;
}
while(!k.equals("#")||!cha.peek().equals("#")) {
t=0;//状态标记
// System.out.println("k:"+k+",s:"+s);
if(state) {
num.push(Double.valueOf(k));//判断当前字符组合是数字则存入数字栈
}else {
/*
* 当前字符组合是运算符则将运算符栈顶运算符与当前运算符比较优先级(调用封装好的静态方法compare)
* 运算符栈顶运算符优先级低则将当前运算符入栈;优先级高则数字栈出栈两个数x,y,运算符栈出栈c,调用封装好的solve函数岁x,y做
* 运算符c操作(注意x,y之间运算顺序);优先级相等则运算符栈出栈一个元素
*
*/
switch(compare((String)cha.peek(), k)) {//当前字符组合是运算符则将运算符栈顶运算符与当前
case '<':cha.push(k);break;
case '>':x=(double) num.pop();y=(double) num.pop();num.push(solve(x,y,(String)(cha.pop())));t=1;break;
case '=':cha.pop();break;
}
}
if(t==0) {//对当前字符组是数、运算符时优先级小于和等于运算符栈栈顶运算符优先级的情况截取掉执行完的字符组;
s=s.substring(k.length(), s.length());
}
k=getnext(s);
if((int)k.charAt(0)>=48&&(int)k.charAt(0)<=57) {//判断当前字符是数字还是运算符,数字state值为true,运算符state值为false
state=true;
}else {
state=false;
}
}
System.out.println(num.peek());//输出数字栈中的结果(运结束时,表达式结果存储在数字栈中(栈顶元素))
}
}