13.java栈实现计算器
更新了代码,能跑通了,昨天果然是太晚了脑子混了,今天一看其实就差一句,在最后while循环的时候忘记把拿到的oper从栈里pop出去了,导致oper栈一直不空就要一直从数据栈中取数据进行计算所以一直在越界。
老师提供的计算器的特点:计算数据要为一位数,先减后加会导致出错。我在修改了将判断oper的函数改为循环后,即一直对比直到栈空或优先级高于栈顶符号才入栈,而非老师的版本只判断一次。保证了其可以先做减法也没有问题。但多位数的bug还未 改,有思路但就要大改了。以后有机会再说吧qwq
——————————————————————————————————————————————————————————————————
今天是大困难的一天,学习了中缀表达式、后缀表达式、前缀表达式的定义以及计算方式,不得不说发明这种方法的人脑子真的太好使。
老师讲了两种计算器,一种是通过数组栈写中缀表达式的计算器,没写出来- -,小分支真的太多太多了,想改善老师的代码的bug最后改到头昏脑胀也没改出来,参考了视频弹幕中的方法,但还是不太可行,明天接着改吧(或者不改了。中缀表达式真的好复杂- -
说起来大二的数据结构课就是从中缀表达式这里开始彻底脱节的,这次倒是确实地明白了几种表达式的计算方式及定义了。
凑合看吧,明天起来继续调试看看能不能调通。
package linkedlist; public class jisuanqi { public static void main(String[] args){ String expression="3-2-2"; ArrayStack1 numstack=new ArrayStack1(10); ArrayStack1 operstack=new ArrayStack1(10); int index=0; int num1=0; int num2=0; int oper=0; int res=0; char ch=' '; while (true){ ch=expression.charAt(index); if(operstack.isoper(ch)){ if(operstack.isEmpty()){ operstack.push(ch); }else { while (true){ if (operstack.isEmpty()){ operstack.push(ch); break; } if(operstack.priority(ch)<=operstack.priority(operstack.peek())){ num2=numstack.pop(); num1=numstack.pop(); oper=operstack.pop(); //就是这句话。。 res=numstack.cal(num1,num2,oper); numstack.push(res); }else { operstack.push(ch); break; } } } }else { numstack.push(ch-48); } index++; if (index>=expression.length()) break; } while(true){ if (operstack.isEmpty()) break; num2=numstack.pop(); num1=numstack.pop(); oper=operstack.pop(); res=numstack.cal(num1,num2,oper); numstack.push(res); } int res2=numstack.pop(); System.out.println(res2); } } class ArrayStack1{ public int top=-1; public int[] stack; public int maxSize; public ArrayStack1(int maxSize) { this.maxSize = maxSize; stack=new int[maxSize]; } public int peek(){ return stack[top]; } public int priority(int oper){ if(oper=='*'||oper=='/'){ return 1; }else if (oper=='+'||oper=='-'){ return 0; }else { return -1; } } public boolean isoper(int oper){ return oper=='+'||oper=='-'||oper=='*'||oper=='/'; } public int cal(int num1,int num2,int oper){ int res=0; switch (oper){ case '+': res=num1+num2; break; case '-': res=num1-num2; break; case '*': res=num1*num2; break; case '/': res=num1/num2; break; } return res; } public boolean isFull(){ if(top==maxSize-1) return true; return false; } public boolean isEmpty(){ if(top==-1) return true; return false; } public void push(int value){ if(isFull()){ System.out.println("栈满,无法加入"); return; } top++;//先加栈顶再赋值 stack[top]=value; } public int pop(){ if(isEmpty()){ throw new RuntimeException("栈空,没有数据"); } int value=stack[top]; top--; return value; } public void list(){ if(isEmpty()){ System.out.println("栈空,没有数据"); } for(int i=top;i>=0;i--){ System.out.printf("stack[%d]=%d",i,stack[i]); } } }
第二种计算器明显人性化太多了,是后缀表达式的计算器,虽然人类很难看懂是真的,但算起来真的太方便了,很容易就可以复现;
package linkedlist; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class caculator { public static void main(String[] args){ //String suffixExpression="30 4 + 5 * 6 -"; String suffixExpression="4 5 * 8 - 60 + 8 2 / +"; List<String> list=getListString(suffixExpression); int res=cal(list); System.out.print(res); } public static List<String> getListString(String s){ String[] sp=s.split(" "); List<String> list=new ArrayList<String>(); for (String c:sp){ list.add(c); } return list; } public static int cal(List<String> list){ Stack<String> stack=new Stack<String>(); for (String item:list){ if(item.matches("\\d+")){ stack.push(item); }else { int num2=Integer.parseInt(stack.pop()); int num1=Integer.parseInt(stack.pop()); int res=0; if (item.equals("+")){ res=num1+num2; }else if (item.equals("-")){ res=num1-num2; }else if(item.equals("/")){ res=num1/num2; }else if (item.equals("*")){ res=num1*num2; }else { throw new RuntimeException("运算符有误"); } stack.push(""+res); } } return Integer.parseInt(stack.pop()); } }