Lisp表达式求值器异常抛出与捕获问题求助
Lisp表达式求值器异常抛出问题
问题描述
实现LispExpressionEvaluator时,无法正确抛出并打印LispExpressionEvaluatorException和LispExpressionException。已尝试在evaluate方法中添加catch块但未生效,目前除最后3个测试用例外其余测试均正常运行,求解决方案。
相关代码
LispExpressionEvaluator类
package PJ2; import java.util.*; public class LispExpressionEvaluator extends LispExpressionEvaluatorException { // 当前输入的Lisp表达式 private String currentExpression; // 主表达式栈,参考evaluate()中的算法 private Stack<Object> inputExprStack; private Stack<Double> evaluationStack; public LispExpressionEvaluator() { currentExpression = ""; inputExprStack = new Stack<Object>(); evaluationStack = new Stack<Double>(); } public LispExpressionEvaluator(String inputExpression) { if(inputExpression == null) { throw new LispExpressionEvaluatorException(); } currentExpression = inputExpression; inputExprStack = new Stack<Object>(); evaluationStack = new Stack<Double>(); } public void reset(String inputExpression){ if(inputExpression == null) { throw new LispExpressionEvaluatorException();} currentExpression = inputExpression; inputExprStack.clear(); evaluationStack.clear(); } // 计算当前运算符和对应操作数的结果 private void solveCurrentParenthesisOperation() { boolean isNumber = true; double endResult = 0; if(inputExprStack == null) { throw new LispExpressionEvaluatorException();} String click = ""; while (isNumber) { if (!inputExprStack.empty()) { click = String.valueOf(inputExprStack.pop()); } else { isNumber = false; break; } try { Double number = Double.parseDouble(click); evaluationStack.push(number); } catch (NumberFormatException e) { isNumber = false; } } if (evaluationStack.size() == 0) return; switch (click) { case "+": endResult = evaluationStack.pop(); while (!evaluationStack.empty()){ endResult +=evaluationStack.pop(); } break; case "-": endResult = evaluationStack.pop(); if(evaluationStack.size() == 0){ endResult = -endResult; } while (!evaluationStack.empty()){ endResult -=evaluationStack.pop(); } break; case "*": endResult = evaluationStack.pop(); while (!evaluationStack.empty()){ endResult *=evaluationStack.pop(); } break; case "/": endResult = evaluationStack.pop(); if(evaluationStack.size() == 0 && endResult != 0){ endResult = 1.0/endResult; } while (!evaluationStack.empty()){ endResult /=evaluationStack.pop(); } break; default: endResult = evaluationStack.pop(); break; } inputExprStack.push(endResult); System.out.println(endResult + " line 165"); } /** * 计算currentExpression中的Lisp表达式,返回结果 */ public double evaluate() { Scanner currentExpressionScanner = new Scanner(currentExpression); currentExpressionScanner = currentExpressionScanner.useDelimiter("\\s*"); if (inputExprStack == null) { throw new LispExpressionEvaluatorException(); } while (currentExpressionScanner.hasNext()) { if (currentExpressionScanner.hasNextInt()) { String dataString = currentExpressionScanner.findInLine("\\d+"); inputExprStack.push(Double.parseDouble(dataString)); } else { String aToken = currentExpressionScanner.next(); char item = aToken.charAt(0); switch (item) { case '(': break; case '+': inputExprStack.push('+'); break; case '-': inputExprStack.push('-'); break; case '*': inputExprStack.push('*'); break; case '/': inputExprStack.push('/'); break; case ')': solveCurrentParenthesisOperation(); break; default: throw new LispExpressionEvaluator(item + " is not a legal expression operator"); } } } return Double.parseDouble(String.valueOf(inputExprStack.pop())); } //===================================================================== // DO NOT MODIFY ANY STATEMENTS BELOW //===================================================================== private static void evaluateExprTest(String s, LispExpressionEvaluator expr, String expect) { Double result; System.out.println("Expression " + s); System.out.printf("Expected result : %s\n", expect); expr.reset(s); try { result = expr.evaluate(); System.out.printf("Evaluated result : %.2f\n", result); } catch (LispExpressionEvaluatorException e) { System.out.println("Evaluated result :"+e); } System.out.println("-----------------------------"); } public static void main (String args[]) { LispExpressionEvaluator expr= new LispExpressionEvaluator(); String test1 = "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)) (+ 0))"; String test2 = "(+ (- 632) (* 21 3 4) (/ (+ 32) (* 1) (- 21 3 1)) (+ 0))"; String test3 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 1) (- 2 1 )) (/ 1))"; String test4 = "(+ (/2)(+ 1))"; String test5 = "(+ (/2 3 0))"; String test6 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 3) (- 2 1 ))))"; String test7 = "(+ (*))"; String test8 = "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)) (+ ))"; evaluateExprTest(test1, expr, "16.50"); evaluateExprTest(test2, expr, "-378.12"); evaluateExprTest(test3, expr, "4.50"); evaluateExprTest(test4, expr, "1.50"); evaluateExprTest(test5, expr, "Infinity or LispExpressionEvaluatorException"); evaluateExprTest(test6, expr, "LispExpressionEvaluatorException"); evaluateExprTest(test7, expr, "LispExpressionException"); evaluateExprTest(test8, expr, "LispExpressionException"); } }
LispExpressionEvaluatorException异常类
package PJ2; public class LispExpressionEvaluatorException extends RuntimeException { public LispExpressionEvaluatorException() { this(""); } public LispExpressionEvaluatorException(String errorMsg) { super(errorMsg); } }
项目配置文件project.iml
<?xml version="1.0" encoding="UTF-8"?> <module type="JAVA_MODULE" version="4"> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> <content url="file://$MODULE_DIR$"> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> </module>
问题分析与解决方案
核心问题点
- 缺少
LispExpressionException类:测试用例7、8期望抛出该异常,但当前代码中仅定义了LispExpressionEvaluatorException,未实现前者。 - 求值器错误继承异常类:
LispExpressionEvaluator继承LispExpressionEvaluatorException违反面向对象设计原则,导致逻辑混乱。 - 异常触发逻辑缺失:部分错误场景(如无操作数的运算符、除零、格式错误)未触发对应异常。
- 异常捕获范围不全:测试方法仅捕获
LispExpressionEvaluatorException,未处理LispExpressionException。
修复步骤
1. 创建LispExpressionException类
新建PJ2.LispExpressionException类:
package PJ2; public class LispExpressionException extends RuntimeException { public LispExpressionException() { this(""); } public LispExpressionException(String errorMsg) { super(errorMsg); } }
2. 修正求值器的继承关系
移除LispExpressionEvaluator对异常类的继承:
public class LispExpressionEvaluator { // 去掉extends LispExpressionEvaluatorException // 原有代码不变 }
3. 完善solveCurrentParenthesisOperation的异常触发逻辑
补充错误场景检测,抛出对应异常:
private void solveCurrentParenthesisOperation() { boolean isNumber = true; double endResult = 0; if(inputExprStack == null) { throw new LispExpressionEvaluatorException("表达式栈未初始化"); } String click = ""; while (isNumber) { if (!inputExprStack.empty()) { click = String.valueOf(inputExprStack.pop()); } else { throw new LispExpressionException("括号匹配错误或运算符缺失"); } try { Double number = Double.parseDouble(click); evaluationStack.push(number); } catch (NumberFormatException e) { isNumber = false; } } if (evaluationStack.size() == 0) { throw new LispExpressionException("运算符" + click + "缺少操作数"); } switch (click) { case "+": endResult = evaluationStack.pop(); while (!evaluationStack.empty()){ endResult +=evaluationStack.pop(); } break; case "-": endResult = evaluationStack.pop(); if(evaluationStack.size() == 0){ endResult = -endResult; } while (!evaluationStack.empty()){ endResult -=evaluationStack.pop(); } break; case "*": endResult = evaluationStack.pop(); while (!evaluationStack.empty()){ endResult *=evaluationStack.pop(); } break; case "/": endResult = evaluationStack.pop(); if(evaluationStack.size() == 0 && endResult != 0){ endResult = 1.0/endResult; } while (!evaluationStack.empty()){ double divisor = evaluationStack.pop(); if(divisor == 0) { throw new LispExpressionEvaluatorException("除零错误"); } endResult /= divisor; } break; default: throw new LispExpressionEvaluatorException("非法运算符:" + click); } inputExprStack.push(endResult); }
4. 扩展测试方法的异常捕获范围
修改evaluateExprTest,添加对LispExpressionException的捕获:
private static void evaluateExprTest(String s, LispExpressionEvaluator expr, String expect) { Double result; System.out.println("表达式 " + s); System.out.printf("预期结果 : %s\n", expect); expr.reset(s); try { result = expr.evaluate(); System.out.printf("求值结果 : %.2f\n", result); } catch (LispExpressionEvaluatorException e) { System.out.println("求值结果 :" + e); } catch (LispExpressionException e) { System.out.println("求值结果 :" + e); } System.out.println("-----------------------------"); }
5. 完善evaluate方法的格式检查
在方法末尾添加栈状态检查,确保表达式格式正确:
public double evaluate() { // 原有扫描逻辑不变 if(inputExprStack.size() != 1) { throw new LispExpressionException("表达式格式错误,存在未闭合括号或多余运算符"); } return Double.parseDouble(String.valueOf(inputExprStack.pop())); }
验证修复
完成修改后,测试用例5会抛出除零异常,测试用例6-8会抛出表达式格式/操作数缺失异常,所有测试用例均能按预期触发并打印异常。
内容的提问来源于stack exchange,提问作者wonder_9
相关产品推荐
相关产品推荐

