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()); } }

浙公網安備 33010602011771號