我正在用 java 制作一个 lisp 表达式求值器。在我的输出窗口(见下文)中,我的主要方法中收到多个错误。谁能解释为什么会发生这些错误?
evaluateCurrentOperation
调用Double.valueOf
并给它一个字符串。它给它一个字符串“+”,它的双精度格式不正确。我该如何解决?
输出窗口:
[
(java.lang.NumberFormatException: For input string: "+"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1222)
at java.lang.Double.valueOf(Double.java:475)
at SimpleLispExpressionEvaluator.evaluateCurrentOperation(SimpleLispExpressionEvaluator.java:63)
at SimpleLispExpressionEvaluator.evaluate(SimpleLispExpressionEvaluator.java:242)
at SimpleLispExpressionEvaluator.evaluateExprTest(SimpleLispExpressionEvaluator.java:269)
at SimpleLispExpressionEvaluator.main(SimpleLispExpressionEvaluator.java:283)
]
代码:
import java.util.*;
public class SimpleLispExpressionEvaluator {
// Current input Lisp expression
private String inputExpr;
// Main expression stack & current operation stack, see algorithm in
// evaluate()
private Stack<Object> exprStack;
private Stack<Double> currentOpStack;
// default constructor
// set inputExpr to ""
// create stack objects
public SimpleLispExpressionEvaluator() {
// add statements
inputExpr = "";
exprStack = new Stack<Object>();
currentOpStack = new Stack<Double>();
}
// default constructor
// set inputExpr to inputExpression
// create stack objects
public SimpleLispExpressionEvaluator(String inputExpression) {
// add statements
inputExpr = inputExpression;
exprStack = new Stack<Object>();
currentOpStack = new Stack<Double>();
}
// set inputExpr to inputExpression
// clear stack objects
public void reset(String inputExpression) {
// add statements
inputExpr = inputExpression;
exprStack.clear();
currentOpStack.clear();
}
// This function evaluate current operator with its operands
// See complete algorithm in evaluate()
//
// Main Steps:
// Pop operands from exprStack and push them onto
// currentOpStack until you find an operator
// Apply the operator to the operands on currentOpStack
// Push the result into exprStack
//
private void evaluateCurrentOperation() {
// add statements
char thing = '0';
double result = 0;
do {
Object obj = exprStack.pop();
String a = obj.toString();
double b = Double.valueOf(a).doubleValue();
currentOpStack.push(b);
String grab = exprStack.peek().toString();
if (grab.length() > 1) {
continue;
}
else {
thing = grab.charAt(0);
}
if (thing == '+' || thing == '-' || thing == '/' || thing == '*') {
exprStack.pop();
break;
}
} while (thing != '%');
switch (thing) {
case '+':
while (currentOpStack.isEmpty() != true) {
result += (double) currentOpStack.pop();
}
break;
case '-':
Object obj0 = currentOpStack.pop();
String a0 = obj0.toString();
double b0 = Double.valueOf(a0).doubleValue();
if (currentOpStack.isEmpty() != true) {
result = b0;
} else {
result = -(b0);
}
while (currentOpStack.isEmpty() != true) {
result -= (double) currentOpStack.pop();
}
break;
case '/':
if (currentOpStack.size() == 1) {
if (currentOpStack.peek() == 0) {
throw new RuntimeException("Cannot divide by zero");
}
result = (1 / ((double) currentOpStack.pop()));
break;
} else {
Object obj1 = currentOpStack.pop();
String a1 = obj1.toString();
double b1 = Double.valueOf(a1).doubleValue();
if (currentOpStack.isEmpty() != true) {
result = b1;
} else {
result = -(b1);
}
while (currentOpStack.isEmpty() != true) {
result -= (double) currentOpStack.pop();
}
break;
}
case '*':
Object obj2 = currentOpStack.pop();
String a2 = obj2.toString();
double b2 = Double.valueOf(a2).doubleValue();
result = b2;
while (currentOpStack.isEmpty() != true) {
result *= (double) currentOpStack.pop();
}
break;
default:
throw new IndexOutOfBoundsException(
"The next node does not work in this program");
}
exprStack.push(result);
}
/**
* This function evaluates current Lisp expression in inputExpr It return
* result of the expression
*
* The algorithm:
*
* Step 1 Scan the tokens in the string. Step 2 If you see an operand, push
* operand object onto the exprStack Step 3 If you see "(", next token
* should be an operator Step 4 If you see an operator, push operator object
* onto the exprStack Step 5 If you see ")",
*
* do steps 6,7,8 in evaluateCurrentOperation() : Step 6 Pop operands and
* push them onto currentOpStack until you find an operator Step 7 Apply the
* operator to the operands on currentOpStack Step 8 Push the result into
* exprStack Step 9 If you run out of tokens, the value on the top of
* exprStack is is the result of the expression.
*/
public double evaluate() {
// only outline is given...
// you need to add statements/local variables
// you may delete or modify any statements in this method
double result;
// use scanner to tokenize inputExpr
Scanner inputExprScanner = new Scanner(inputExpr);
// Use zero or more white space as delimiter,
// which breaks the string into single character tokens
inputExprScanner = inputExprScanner.useDelimiter("\\s*");
// Step 1: Scan the tokens in the string.
while (inputExprScanner.hasNext()) {
// Step 2: If you see an operand, push operand object onto the
// exprStack
if (inputExprScanner.hasNextInt()) {
// This force scanner to grab all of the digits
// Otherwise, it will just get one char
String dataString = inputExprScanner.findInLine("\\d+");
exprStack.push(dataString);
// more ...
}
else {
// Get next token, only one char in string token
String nextEntry = inputExprScanner.next();
char entity = nextEntry.charAt(0);
String nextToken;
switch (entity) {
// Step 3: If you see "(", next token should an operator
case '(':
nextEntry = inputExprScanner.next();
entity = nextEntry.charAt(0);
// Step 4: If you see an operator, push operator object onto
// the
// exprStack
if (entity == '+') {
exprStack.push(nextEntry);
}
else if (entity == '-') {
exprStack.push(entity);
}
else if (entity == '*') {
exprStack.push(entity);
}
else {
exprStack.push(nextEntry);
}
// Step 5: If you see ")" do steps 6,7,8 in
// evaluateCurrentOperation() :
case ')':
evaluateCurrentOperation();
break;
default: // error
throw new SimpleLispExpressionEvaluatorException(entity
+ " is not a legal expression operator");
} // end switch
} // end else
} // end while
// Step 9: If you run out of tokens, the value on the top of exprStack
// is the result of the expression.
Object obj4 = exprStack.pop();
String str4 = obj4.toString();
double d3 = Double.valueOf(str4).doubleValue();
return d3;
}
// =====================================================================
// This static method is used by main() only
private static void evaluateExprTest(String s,
SimpleLispExpressionEvaluator expr) {
Double result;
System.out.println("Expression " + s);
expr.reset(s);
result = expr.evaluate();
System.out.printf("Result %.2f\n", result);
System.out.println("-----------------------------");
}
// define few test cases, exception may happen
public static void main(String args[]) {
SimpleLispExpressionEvaluator expr = new SimpleLispExpressionEvaluator();
String test1 = "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))";
String test2 = "(+ (- 632) (* 21 3 4) (/ (+ 32) (* 1) (- 21 3 1)))";
String test3 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 1) (- 2 1 )))";
String test4 = "(+ (/2))";
String test5 = "(+ (/2 3 0))";
String test6 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 3) (- 2 1 )))";
evaluateExprTest(test1, expr);
evaluateExprTest(test2, expr);
evaluateExprTest(test3, expr);
evaluateExprTest(test4, expr);
evaluateExprTest(test5, expr);
evaluateExprTest(test6, expr);
}
}