包含 + - * / ( )優先級的表達式
用到了堆棧 、中綴表達式轉后綴表達式的方法、類和對象的知識
主類:
1 import java.util.Arrays; 2 import java.util.Scanner; 3 4 public class Compute{ 5 public static void main(String[] args){ 6 Scanner input = new Scanner(System.in); 7 String str = input.nextLine(); 8 9 String[] inOrderArrays = strToArrays(str); 10 System.out.println(Arrays.toString(inOrderArrays)); 11 String[] postOrderArrays = toPostOrder(inOrderArrays); 12 System.out.println(Arrays.toString(inOrderArrays)); 13 Double result = toCompute(postOrderArrays); 14 System.out.printf("%.3f",result); 15 } 16 /* 17 將字符串分割成操作數和操作符的字符串數組 18 */ 19 public static String[] strToArrays(String str){ 20 int strLength = str.length(); 21 int beginIndex = 0; int endIndex = 0; 22 String[] Arrays = new String[strLength]; 23 int arraysIndex = 0; 24 25 for(int i = 0; i < strLength; i++){ 26 if(str.charAt(i)=='*'||str.charAt(i)=='/'||str.charAt(i)=='+'||str.charAt(i)=='-'||str.charAt(i)=='('||str.charAt(i)==')'){ 27 endIndex = i -1 ; 28 if(beginIndex <= endIndex ){ 29 Arrays[arraysIndex] = str.substring(beginIndex, endIndex+1); 30 Arrays[arraysIndex + 1] = String.valueOf(str.charAt(i)); 31 arraysIndex += 2; 32 beginIndex = i + 1; 33 } 34 else{ 35 Arrays[arraysIndex] = String.valueOf(str.charAt(i)); 36 arraysIndex += 1; 37 beginIndex = i + 1; 38 } 39 } 40 } 41 Arrays[arraysIndex] = str.substring(beginIndex, str.length()); 42 String[] Arrays2 = new String[arraysIndex+1]; 43 for(int i = 0; i < arraysIndex+1; i++) { 44 Arrays2[i] = Arrays[i]; 45 } 46 return Arrays2; 47 } 48 /* 49 將中綴表達式轉為后綴表達式,返回的是字符串數組 50 */ 51 public static String[] toPostOrder(String[] arrays){ 52 /*規則: 53 *1,運算數直接輸出 54 *2,左括號壓入堆棧 55 *3,右括號 將棧頂的運算符彈出並輸出,括號出棧不輸出 56 *4,運算符: 57 * 若優先級大於棧頂運算符,壓入棧 58 * 若優先級小於或等於棧頂運算符,棧頂運算符彈出並輸出, 59 * 繼續和新棧頂比較,直到比棧頂運算符優先級大,將它壓入棧 60 *5,對象處理完畢后,將棧中運算符彈出並輸出 61 */ 62 Stack operStack = new Stack();//創建了一個操作符的棧 63 int arraysLength = arrays.length; 64 String[] arrays2 = new String[arraysLength];//輸出后的字符數組 65 int tempIndex = 0; 66 67 //將字符串數組遍歷 68 for(int i = 0; i < arraysLength; i++){ 69 //操作符入棧 70 if(isOper(arrays[i])){ 71 //棧為空時直接入棧 72 if(operStack.isEmpty()){ 73 operStack.push(arrays[i]); 74 } 75 else{ 76 //操作符為"("時直接入棧 77 if( arrays[i].equals("(") ){ 78 operStack.push(arrays[i]); 79 } 80 //操作符為")"時棧頂出棧並輸出,直到遇到"(", "("出棧,")"不入棧 81 else if( arrays[i].equals(")") ){ 82 while(operStack.peek().equals("(") == false ){ 83 arrays2[tempIndex] = operStack.pop(); 84 tempIndex += 1; 85 } 86 operStack.pop();//"("出棧 87 } 88 //其他操作符需要比較與棧頂的優先級 89 else{ 90 //棧頂是"(", 直接入棧 91 if(operStack.peek().equals("(") ){ 92 operStack.push(arrays[i]); 93 } 94 else{ 95 //優先級高,直接入棧 96 if(getPriority(arrays[i].charAt(0)) > getPriority(operStack.peek().charAt(0)) 97 && operStack.isEmpty() == false ){ 98 operStack.push(arrays[i]); 99 } 100 //優先級低或者相等,棧頂出棧並輸出,直到優先級比棧頂高 101 else{ 102 while(getPriority(arrays[i].charAt(0)) <= getPriority(operStack.peek().charAt(0)) 103 && operStack.isEmpty() == false){ 104 arrays2[tempIndex] = operStack.pop(); 105 tempIndex += 1; 106 //若棧頂全部彈出,則直接入棧 107 if(operStack.isEmpty()) { 108 operStack.push(arrays[i]); 109 break; 110 } 111 } 112 if(getPriority(arrays[i].charAt(0)) > getPriority(operStack.peek().charAt(0))){ 113 operStack.push(arrays[i]); 114 } 115 } 116 } 117 } 118 } 119 } 120 //操作數直接添加到 字符串數組2 121 else if(isNum(arrays[i])){ 122 arrays2[tempIndex] = arrays[i]; 123 tempIndex += 1; 124 } 125 else{ 126 } 127 } 128 while(!operStack.isEmpty()){ 129 arrays2[tempIndex] = operStack.pop(); 130 tempIndex += 1; 131 } 132 String[] arrays3 = new String[tempIndex]; 133 for(int i = 0; i < tempIndex ;i++){ 134 arrays3[i] = arrays2[i]; 135 } 136 return arrays3; 137 } 138 /* 139 得到操作符的優先級 140 */ 141 public static int getPriority(char c){ 142 if(c == '*' || c == '/'){ 143 return 2; 144 } 145 else if (c == '+' || c == '-'){ 146 return 1; 147 } 148 else{ 149 return 999; 150 } 151 } 152 /* 153 由后綴表達式計算得值 154 */ 155 public static double toCompute(String[] arrays){ 156 /*規則: 157 *中綴表達式不用比較優先級 158 *將運算數入棧,每讀到一個運算符 159 *就彈出棧頂的兩個運算數,運算完畢后將結果壓入棧 160 */ 161 Stack numStack = new Stack();//創建了一個操作數的棧 162 int arraysLength = arrays.length; 163 //遍歷后綴表達式的字符串數組 164 for(int i = 0; i < arraysLength; i++){ 165 if(isNum(arrays[i])){ 166 numStack.push(arrays[i]); 167 } 168 else if(isOper(arrays[i])){ 169 Double num2 = Double.parseDouble(numStack.pop()); 170 Double num1 = Double.parseDouble(numStack.pop()); 171 if(arrays[i].equals("+")){ 172 Double result = num1 + num2; 173 numStack.push(result.toString()); 174 } 175 else if(arrays[i].equals("-")){ 176 Double result = num1 - num2; 177 numStack.push(result.toString()); 178 } 179 else if(arrays[i].equals("*")){ 180 Double result = num1 * num2; 181 numStack.push(result.toString()); 182 } 183 else if(arrays[i].equals("/")){ 184 Double result = num1 / num2; 185 numStack.push(result.toString()); 186 } 187 else{ 188 } 189 } 190 else{ 191 } 192 } 193 Double result = Double.parseDouble(numStack.pop()); 194 return result; 195 } 196 /* 197 判斷該字符串是否為操作符 198 */ 199 public static boolean isOper(String str){ 200 if(str.equals("*")||str.equals("/")|| 201 str.equals("+")||str.equals("-")|| 202 str.equals("(")||str.equals(")")){ 203 return true; 204 } 205 else{ 206 return false; 207 } 208 } 209 /* 210 判斷該字符串是否為操作數 211 */ 212 public static boolean isNum(String str){ 213 if(str.equals("*")||str.equals("/")|| 214 str.equals("+")||str.equals("-")|| 215 str.equals("(")||str.equals(")")){ 216 return false; 217 } 218 else{ 219 return true; 220 } 221 } 222 }
設計一個存放字符串對象的棧類:
1 import java.util.ArrayList; 2 3 public class Stack{ 4 private ArrayList<String> stack = new ArrayList<>(); 5 6 public boolean isEmpty(){ 7 return stack.size() == 0; 8 } 9 public int getSize(){ 10 return stack.size(); 11 } 12 public String peek(){ 13 if(!isEmpty()) { 14 return stack.get(stack.size() -1 ); 15 } 16 else { 17 return "false"; 18 } 19 } 20 public String pop(){ 21 if(!isEmpty()){ 22 String top = stack.get(stack.size() - 1); 23 stack.remove(stack.size() - 1); 24 return top; 25 } 26 else{ 27 return "false"; 28 } 29 } 30 public void push(String o){ 31 stack.add(o); 32 } 33 @Override 34 public String toString(){ 35 return "Stack:" + stack.toString(); 36 } 37 }
測試結果:
下一步,我在思考利用javaFX的界面編程知識實現這個簡易計算器的界面化
修改:
在表達式的字符串轉換為字符串數組的函數中,沒有考慮到末尾可能是操作符結尾的情況,會導致字符串數組多了一個null元素
/* 將字符串分割成操作數和操作符的字符串數組 */ public static String[] strToArrays(String str){ int strLength = str.length(); int beginIndex = 0; int endIndex = 0; String[] Arrays = new String[strLength]; int arraysIndex = 0; for(int i = 0; i < strLength; i++){ if(str.charAt(i)=='*'||str.charAt(i)=='/'||str.charAt(i)=='+'||str.charAt(i)=='-'||str.charAt(i)=='('||str.charAt(i)==')'){ endIndex = i -1 ; if(beginIndex <= endIndex ){ Arrays[arraysIndex] = str.substring(beginIndex, endIndex+1); Arrays[arraysIndex + 1] = String.valueOf(str.charAt(i)); arraysIndex += 2; beginIndex = i + 1; } else{ Arrays[arraysIndex] = String.valueOf(str.charAt(i)); arraysIndex += 1; beginIndex = i + 1; } } }
//簡單的判斷一下表達式是否是以操作符結尾還是操作數結尾
if(!isOper(String.valueOf(str.charAt(strLength - 1)))){ Arrays[arraysIndex] = str.substring(beginIndex,strLength); arraysIndex += 1; } String[] Arrays2 = new String[arraysIndex]; for(int i = 0; i < arraysIndex; i++) { Arrays2[i] = Arrays[i]; } System.out.println(arraysIndex); return Arrays2; }