1 importjava.util.HashMap;2 importjava.util.Map;3 importjava.util.Stack;4
5 public classFunctionStack {6
7 private MapoptLevel;8 private boolean nextIsOpt = false;9 private boolean debug = false;10 private int debug_len = 3;11
12 public FunctionStack setDebugLen(intlen) {13 this.debug_len =len;14 return this;15 }16
17 public FunctionStack setDebug(booleandebug) {18 this.debug =debug;19 return this;20 }21
22 private voidprintln(Object obj) {23 if(debug) {24 System.out.println(obj);25 }26 }27
28 publicFunctionStack() {29 optLevel = new HashMap();30 optLevel.put("(", 1);31 optLevel.put("+", 2);32 optLevel.put("-", 2);33 optLevel.put("*", 3);34 optLevel.put("/", 3);35 optLevel.put(")", 4);36 }37
38 public static voidmain(String[] args) {39
40
41 FunctionStack fs = newFunctionStack();42 fs.setDebug(true).setDebugLen(5);43 String fun = " 1 + 2 * 3 / 4 ";44 try{45 float res =fs.execute(fun);46 System.out.println("结果为:" +res);47 } catch(FunctionStackException e) {48 System.out.println(e.getMessage());49 }50 System.out.println("结束.");51 }52
53 /**
54 *55 *@paramfun56 *@return
57 *@throwsFunctionStackException58 */
59 public float execute(String fun) throwsFunctionStackException {60 this.clear();61 //TODO Auto-generated method stub
62 if (fun == null || fun.trim().length() == 0) {63 throw new FunctionStackException("表达式不能为空;");64 }65 //创建操作符堆栈和操作数堆栈
66 Stack opt = new Stack();67 Stack num = new Stack();68 //扫描整个表达式69 //point记录上一个扫描点
70 int point = 0;71 for (int i = 0; i < fun.length(); i++) {72 String scanOpt = fun.charAt(i) + "";73 if (scanOpt.equals("(")) {74 //发现左括号,压入栈75 //检查是否为空的括号
76 int right = fun.indexOf(')', i);77 if (right < 0) {78 //如果没有找到右括号
79 throw newFunctionStackException(fun80 + "\n语法错误:"
81 + "缺少右括号与之对应:"
82 + fun.substring(Math.max(point - debug_len, 0),83 Math.min(i +debug_len, fun.length())));84 } else{85 //找到右括号,检查是否为空括号
86 if (fun.substring(i + 1, right).trim().length() == 0) {87 throw newFunctionStackException(fun88 + "\n语法错误:"
89 + "括号中内容不可为空:"
90 + fun.substring(Math.max(point - debug_len, 0),91 Math.min(i +debug_len, fun.length())));92 }93 }94 //检查语法
95 String num_before_opt =fun.substring(point, i).trim();96 if (num_before_opt.length() != 0) {97 throw newFunctionStackException(fun98 + "\n语法错误:"
99 + "括号前缺少操作符:"
100 + fun.substring(Math.max(point - debug_len, 0),101 Math.min(i +debug_len, fun.length())));102 }103 //将左括号压入栈
104 println("↓压栈:" + fun.substring(i, i + 1));105 opt.push(fun.substring(i, i + 1));106 //记录扫描点
107 point = i + 1;108 } else if (scanOpt.equals(")")) {109 //发现右括号,取出栈,直到取出左括号
110 println("---计算括号开始:");111 //将括号前的数值取出
112 pushFloatStack(fun, num, point, i);113 //记录下一个是操作符
114 nextIsOpt = true;115 //检查前一个操作符是否为空
116 if(opt.empty()) {117 throw newFunctionStackException(fun118 + "\n语法错误:"
119 + "缺少左括号与之对应:"
120 + fun.substring(Math.max(point - debug_len, 0),121 Math.min(i +debug_len, fun.length())));122 }123 //取出前一个操作符
124 String optpop =opt.pop();125 println("↑↑出栈:" +optpop);126 //取出栈,直到取出左括号
127 while (!optpop.equals("(")) {128 //若取出的操作符不是左括号,执行运算;
129 calculator(optpop, num);130 if(opt.empty()) {131 throw newFunctionStackException(fun132 + "\n语法错误:"
133 + "缺少左括号与之对应:"
134 + fun.substring(Math.max(point - debug_len, 0),135 Math.min(i +debug_len, fun.length())));136 }137 optpop =opt.pop();138 println("↑↑出栈:" +optpop);139 }140
141 //记录扫描点
142 point = i + 1;143 println("---计算括号结束:");144 } else if (optLevel.get(scanOpt) != null) {145 if (scanOpt.equals("-") || scanOpt.equals("+")) {146 //如果是减号,可能是一个负号
147 if (fun.substring(point, i).trim().replaceAll("-", "")148 .replaceAll("\\+", "").trim().length() == 0) {149 //如果减号前没有操作数,视此减号为负号,point不移动,-也不压入堆栈
150 continue;151 }152 }153 //发现非括号的操作符,查看栈顶操作符优先级,选择计算or压栈154 //获取操作数,并检查语法
155 pushFloatStack(fun, num, point, i);156 //比较优先级,将栈顶优先级高的先计算
157 if (!opt.empty()) {158 //获取栈顶操作符,不取出
159 String optpop =opt.peek();160 //取栈计算,直到栈顶操作符优先级小于scanOpt
161 while (optLevel.get(optpop) >=optLevel.get(scanOpt)) {162 calculator(optpop, num);163 optpop =opt.pop();164 println("↑↑出栈:" +optpop);165 if(opt.empty()) {166 //如果操作符取空了则退出
167 break;168 }169 optpop =opt.peek();170 }171 }172 //压入操作符
173 println("↓压栈:" +scanOpt);174 opt.push(scanOpt);175 //记录扫描点
176 point = i + 1;177 } else if (scanOpt.equals("=")) {178 //发现=号,取栈计算总结果,并提前结束循环179 //获取操作数,并检查语法
180 pushFloatStack(fun, num, point, i);181 //取栈计算直到结束
182 while (!opt.empty()) {183 String optpop =opt.pop();184 println("↑↑出栈:" +optpop);185 calculator(optpop, num);186 }187 returngetResult(num);188 }189
190 }191
192 //表达式结束193 //获取操作数,并检查语法
194 pushFloatStack(fun, num, point, fun.length());195 //取栈计算直到结束
196 while (!opt.empty()) {197 String optpop =opt.pop();198 println("↑↑出栈:" +optpop);199 calculator(optpop, num);200 }201 returngetResult(num);202 }203
204 private voidclear() {205 //TODO Auto-generated method stub
206 nextIsOpt = false;207 }208
209 private float getResult(Stacknum) {210 //TODO Auto-generated method stub
211 Float res =num.pop();212 if(num.empty()) {213 returnres;214 } else{215 throw new FunctionStackException("计算错误,堆栈中还有数据;");216 }217 }218
219 /**
220 * 将操作符i前的操作数解析,并压入堆栈221 *222 *@paramfun223 *@paramnum224 *@parampoint225 * 操作数起点226 *@parami227 * 操作符位置,即操作数终点228 */
229 private void pushFloatStack(String fun, Stack num, int point, inti) {230 String num_before_opt =fun.substring(point, i).trim();231 if (num_before_opt.length() == 0) {232 //没有操作数
233 if(nextIsOpt) {234
235 //应该没有操作数,(即此处本应只有操作符,没有操作数)
236 nextIsOpt = false;237 return;238 } else{239 //应该有操作数
240 throw newFunctionStackException(fun241 + "\n语法错误:"
242 + "缺少操作数:"
243 + fun.substring(Math.max(point - debug_len, 0),244 Math.min(i +debug_len, fun.length())));245 }246 } else{247 //有操作数
248 if(nextIsOpt) {249 //应该没有操作数
250 throw newFunctionStackException(fun251 + "\n语法错误:"
252 + "缺少操作符:"
253 + fun.substring(Math.max(point - debug_len, 0),254 Math.min(i +debug_len, fun.length())));255 } else{256 //应该有操作数
257 try{258 //去除操作数中间的空格、回车、制表符
259 num_before_opt = num_before_opt.replaceAll(" ", "");260 num_before_opt = num_before_opt.replaceAll("\t", "");261 num_before_opt = num_before_opt.replaceAll("\n", "");262 Float scannum =Float.parseFloat(num_before_opt);263 println("↓压栈:" +scannum);264 num.push(scannum);265 } catch(NumberFormatException e) {266 throw new FunctionStackException(fun + "\n语法错误:"
267 + "无法识别的数值:" +num_before_opt);268 }269 }270 }271 }272
273 /**
274 *275 *@paramoptpop276 * 运算符277 */
278 private void calculator(String optpop, Stacknum) {279 //TODO Auto-generated method stub
280 Float pop2 =num.pop();281 println("↑↑出栈:" +pop2);282 Float pop1 =num.pop();283 println("↑↑出栈:" +pop1);284 println("--------计算 " + pop1 + optpop +pop2);285 if (optpop.equals("+")) {286 println("↓压栈:" + (pop1 +pop2));287 num.push(pop1 +pop2);288 } else if (optpop.equals("-")) {289 println("↓压栈:" + (pop1 -pop2));290 num.push(pop1 -pop2);291 } else if (optpop.equals("*")) {292 println("↓压栈:" + (pop1 *pop2));293 num.push(pop1 *pop2);294 } else if (optpop.equals("/")) {295 if (pop2 == 0) {296 throw new FunctionStackException("语法错误:" + "除数不可以为零:" +pop2);297 }298 println("↓压栈:" + (pop1 /pop2));299 num.push(pop1 /pop2);300 } else if (optpop.equals("(")) {301 throw new FunctionStackException("语法错误:" + "缺少右括号与之对应:" +optpop);302 } else{303 throw new FunctionStackException("语法错误:" + "错误的操作符:" +optpop);304 }305
306 }307
308 }