我不确定这个代码在哪里出错了,所以我希望能够让一些更有经验的人为我审查它。
这是我的Stack Trace:
input an expression string:(+ 1 2)
Evaluate expression #1 :(+ 1 2)
Exception in thread "main" java.util.EmptyStackException
at java.util.Stack.peek(Stack.java:102)
at PJ2.SimpleLispExpressionEvaluator.evaluateCurrentOperation(SimpleLispExpressionEvaluator.java:126)
at PJ2.SimpleLispExpressionEvaluator.evaluate(SimpleLispExpressionEvaluator.java:235)
at PJ2_Test.main(PJ2_Test.java:42)
Java Result: 1
这是第126行:
while(tokenStack.peek() instanceof Double){
这是第235行:
evaluateCurrentOperation();
这是我目前的代码:
import java.util.*;
public class StackCalculator{
private String currentExpression;
// Main expression stack, see algorithm in evaluate()
private Stack<Object> tokenStack;
public SimpleLispExpressionEvaluator()
{
tokenStack = new Stack();
currentExpression = "";
}
// constructor with an input expression
public SimpleLispExpressionEvaluator(String inputExpression)
{
tokenStack = new Stack();
tokenStack.push(inputExpression);
currentExpression = inputExpression;
}
public void reset(String inputExpression)
{
currentExpression = inputExpression;
//tokenStack.clear();
//tmpStack.clear();
//not working for some reason
}
// This function evaluates current operator with its operands
// See complete algorithm in evaluate()
//
// Main Steps:
// Pop operands from tokenStack and push them onto
// tmpStack until you find an operator
// Apply the operator to the operands on tmpStack
// Push the result into tokenStack
//
private void evaluateCurrentOperation()
{
Stack<Double> tmpStack=new Stack<Double>();
double a=0.0;
while(!tokenStack.isEmpty()){
while(!tokenStack.isEmpty()){
if(tokenStack.peek() instanceof Double){
tmpStack.push((Double)tokenStack.pop());
}else if(tokenStack.peek() instanceof Character){
if(!tokenStack.isEmpty()){
switch((Character)tokenStack.pop()){
case '+':
while(!tmpStack.isEmpty()){
a += tmpStack.pop();
}
tokenStack.push(a);
break;
case '-':
while(!tmpStack.isEmpty()){
a -= tmpStack.pop();
}
tokenStack.push(a);
break;
case '*':
while(!tmpStack.isEmpty()){
a *= tmpStack.pop();
}
tokenStack.push(a);
break;
case '/':
while(!tmpStack.isEmpty()){
a /= tmpStack.pop();
}
tokenStack.push(a);
break;
}
}
}
}
/**
*
* The algorithm:
*
* Step 1 Scan the tokens in the string.
* Step 2 If you see an operand, push operand object onto the tokenStack
* Step 3 If you see "(", next token should be an operator
* Step 4 If you see an operator, push operator object onto the tokenStack
* Step 5 If you see ")" // steps in evaluateCurrentOperation() :
* Step 6 Pop operands and push them onto tmpStack until you find an operator
* Step 7 Apply the operator to the operands on tmpStack
* Step 8 Push the result into tokenStack
* Step 9 If you run out of tokens, the value on the top of tokenStack is the result of the expression.
*/
public double evaluate()
{
Scanner currentExpressionScanner = new Scanner(currentExpression);
double finRes = 0.0;
currentExpressionScanner = currentExpressionScanner.useDelimiter("\\s*");
// Step 1: Scan the tokens in the string.
while (currentExpressionScanner.hasNext())
{
// Step 2: If you see an operand, push operand object onto the tokenStack
if (currentExpressionScanner.hasNextInt())
{
// This force scanner to grab all of the digits
// Otherwise, it will just get one char
String dataString = currentExpressionScanner.findInLine("\\d+");
tokenStack.push(Double.parseDouble(dataString));
}
else
{
// Get next token, only one char in string token
String aToken = currentExpressionScanner.next();
//System.out.println("Other: " + aToken);
char item = aToken.charAt(0);
switch (item)
{
// Step 3: If you see "(", next token should be an operator
case '(':
String nextToken = currentExpressionScanner.next();
if(!nextToken.equals("+")&&!nextToken.equals("- ")&&!nextToken.equals("*")&&!nextToken.equals("/")){
throw new LispExpressionException("After this " + item + " should be an operator");
}
break;
// Step 4: If you see an operator, push operator object onto the tokenStack
case '+':
tokenStack.push(item);
break;
case '*':
tokenStack.push(item);
break;
case '-':
tokenStack.push(item);
break;
case '/':
tokenStack.push(item);
break;
// Step 5: If you see ")" // steps in evaluateCurrentOperation() :
case ')':
evaluateCurrentOperation();
break;
default: // error
throw new LispExpressionException(item + " 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 tokenStack is
// the result of the expression.
// return result
while(!tokenStack.isEmpty()){
if(tokenStack.peek() instanceof Character){
throw new LispExpressionException(tokenStack.pop() + " is not a number!");
}else{
finRes = (Double)tokenStack.pop();
}
}
return finRes; // return correct answer!
}
答案 0 :(得分:1)
好吧,看看你的代码,这似乎很明显。如果tokenStack
仅包含双精度数,那么当您继续从中移除对象时,它最终将变为空。当它为空时,peek()
调用将抛出异常。
while(tokenStack.peek() instanceof Double){
tmpStack.push((Double)tokenStack.pop());
}
答案 1 :(得分:0)
难道不是很明显吗?堆栈是空的,你正试图窥视它,这就是这个错误告诉你的。不知怎的,在你试图偷看它之前,你实际上并没有把任何东西推到堆叠上。
http://docs.oracle.com/javase/7/docs/api/java/util/EmptyStackException.html