包含 + - * / ( )优先级的表达式
用到了堆栈 、中缀表达式转后缀表达式的方法、类和对象的知识
主类:
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; }