为什么我从代码中得到`EmptyStackException?

时间:2014-03-28 22:31:37

标签: java exception stack postfix-notation infix-notation

public class ShuntingYard
{
    public String infix2postfix(String infix)
    {
        Stack<String> s = new Stack<String>();
        String[] tokens = infix.split(" ");

        StringBuilder output = new StringBuilder();

        Integer plus = Integer.getInteger("+", 1);
        Integer minus =Integer.getInteger("-", 1);
        Integer multiply = Integer.getInteger("*", 2);
        Integer divide = Integer.getInteger("/", 2);
        Integer exponent = Integer.getInteger("^", 3);

        for (int i = 0; i < tokens.length; i++)
        {
            if (tokens[i].matches("[0-9]"))
            {
                output.append(tokens[i] + " ");
            }
            else if (tokens[i].equals("+") || tokens[i].equals("-") || tokens[i].equals("*") || tokens[i].equals("/") 
                    || tokens[i].equals("^"))
            {
                int a = plus.intValue();
                int b = minus.intValue();
                int c = multiply.intValue();
                int d = divide.intValue();
                int e = exponent.intValue();

                if (s.isEmpty() == false && tokens[i].valueOf(a).compareTo(s.peek()) >= 0|| 
                s.isEmpty() == false && tokens[i].valueOf(b).compareTo(s.peek()) >= 0 || 
                s.isEmpty() == false && tokens[i].valueOf(c).compareTo(s.peek()) >= 0 || 
                s.isEmpty() == false && tokens[i].valueOf(d).compareTo(s.peek()) >= 0 ||
                s.isEmpty() == false && tokens[i].valueOf(e).compareTo(s.peek()) >= 0)
                {
                    output.append(s.peek() + " ");
                    s.pop();
                }
                s.push(tokens[i]);
            }
            else if (tokens[i].equals("("))
            {
                s.push(tokens[i]);
            }
            else if(tokens[i].equals(")"))
            {
                while (!(s.peek().equals("(")))
                {
                    output.append(s.pop());
                }
                if (s.isEmpty() == true)
                {
                    System.out.println("Error: mismatching parentheses");
                }
                s.pop();
            }
        }

        for (int i = 0; s.isEmpty() == false; i++)
        {
            if(s.peek().equals("(") || s.peek().equals(")"))
            {
                System.out.println("Error: mismatching parentheses");
            }
            output.append(s.pop());
        }
        return output.toString();
    }
}

@Test
public void infix2postfixTest()
{

 assertEquals("3 4 5 6 - 7 * 8 / + - 9 *", s.infix2postfix("3 * ( 4 + ( 5 - 6 ) * 7 / 8 ) - 9"));
}

当我运行ShuntingYard测试时,发布了第二个代码,我得到一个指向此行的EmptyStackException

while (!(s.peek().equals("(")))

但逻辑对我有意义,我说如果令牌是&#34;)&#34;,那么虽然堆栈顶部不是&#39; ta&#34;(& #34;将堆栈的顶部附加到输出并将其从堆栈中删除。我在这里遗漏了什么吗?

这是我的堆栈偷看方法:

public T peek()
{
    if (isEmpty() == true)
    {
        throw new java.util.EmptyStackException();
    }

    return stack.get(stack.size()-1);
}

1 个答案:

答案 0 :(得分:0)

你一直弹出并偷看Stack而不先检查它是否为空。偷看或弹出空堆栈会生成您获得的EmptyStackException。正如您所指出的那样,Stack类会检查isEmpty()中的peek(),但它只会生成EmptyStackException。作为peek()的来电者,您有责任先自己检查isEmpty()!如果你不这样做,那么你已经为Stack创造了一个不可能的情况 - 如果没有任何东西可以从空{{1}中偷看,它就无法向你展示一个偷看的结果。 }!

你应该替换:

Stack

类似于:

else if(tokens[i].equals(")"))
{
    while (!(s.peek().equals("(")))
    {
        output.append(s.pop());
    }
    if (s.isEmpty() == true)
    {
        System.out.println("Error: mismatching parentheses");
    }
    s.pop();
}

修复程序的实现方式可能与我的示例不同。但是要说的是,在致电else if(tokens[i].equals(")")) { while(!s.isEmpty()) { if(s.peek().equals("(")) { s.pop(); if(s.isEmpty())//we just popped so the while check no longer applies { System.out.println("Error: mismatching parentheses"); } } else { output.append(s.pop()); } } } isEmpty()之前,您必须先检查peek()

作为补充说明,我想指出用于打印不匹配括号错误的原始代码无法访问。 if语句结束后执行if语句,当while语句结束时,保证s pop()非空!该保证使后续的pop调用安全,但也意味着永远不会执行错误消息。我修复了我的示例中的其他错误,但我想更详细地解释它,否则您可能不会注意到。