Shunting-Yard算法在Java中实现错误输出和String索引超出范围?

时间:2015-03-31 22:31:09

标签: java indexing output shunting-yard

我正在实现Shunting-Yard算法并评估结果这是一个基于参考的实现,使用节点(一个用于运算符,一个用于操作数)和堆栈(一个用于运算符,一个用于操作数)。


输入文件包含(只是前几行):

5
5-3
5*(3+4)
7*3+5*6
2+5*(7+8)/3

输出:

53 = 53
53513 = 1
535152
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: 
String index out of range: 7
    at java.lang.String.charAt(String.java:646)
    at LabIII.main(LabIII.java:48)

Process completed.

主:

public class LabIII
{
public static String expr;
public static String line;

public static void main(String[] args) throws IOException
{       
    try
    {
        BufferedReader input = new BufferedReader(new FileReader("input.txt")); // Create input reader

        char token;
        int tokenI;
        char popOp;
        int popInt1;
        int popInt2;
        int result;

        while ((line = input.readLine()) != null) // While the input file still has a line with characters
        {
            operatorStack opStack = new operatorStack(); // Initalize the operator stack
            opStack.push(';');
            operandStack intStack = new operandStack();
            expr = line;
            int count = 1;

            while(count <= expr.length())
            {
                int index = count - 1;

                if(Character.isDigit(expr.charAt(index))) // If token is an operand
                {
                    tokenI = expr.charAt(index);
                    System.out.print(tokenI);
                    intStack.push(tokenI);
                    count++;
                }
                else
                {
                    token = expr.charAt(count);

                    if(token == ')')
                    {   
                        while(opStack.peek() != '(')
                        {
                            popOp = opStack.pop();
                            System.out.print(popOp);
                            popInt1 = intStack.pop();
                            popInt2 = intStack.pop();
                            result = evaluate(popInt1, popInt2, popOp);
                            intStack.push(result);                          
                        }
                        opStack.pop(); // Pop the "(" and discard it
                        count++;
                    }
                    else
                    {
                        while(inputPriority(token) <= stackPriority(opStack.peek()))
                        {
                            popOp = opStack.pop();
                            System.out.print(popOp);
                            popInt1 = intStack.pop();
                            popInt2 = intStack.pop();
                            result = evaluate(popInt1, popInt2, popOp);
                            intStack.push(result);
                        }
                        opStack.push(token);
                        count++;
                    }
                }
            }

            while (opStack.peek() != ';')
            {
                popOp = opStack.pop();
                System.out.print(popOp);
                popInt1 = intStack.pop();
                popInt2 = intStack.pop();
                result = evaluate(popInt1, popInt2, popOp);
                intStack.push(result);
            }

            System.out.print(" = " + intStack.pop());
            System.out.println();
            count = 0;              
        }
    }

    catch (IOException ex)
    {
        System.err.println("Exception:" + ex);
    }
}
}

operandStack(也是一个用于operatorStack。相同,只使用char而不是int):

public class operandStack
{
    int integ;
    NodeInt top;
    NodeInt temp;

    public operandStack() // Default constructor: empty stack
    {
        top = null;
    }

    public boolean isEmpty() // Returns true if the top of the stack is null
    {
        return top == null;
    }

    public void push(int integ) // Push an item onto the top of the stack
    {
        top = new NodeInt(integ, top);
    }

    public int pop()
    {
        NodeInt temp = top;
        top = top.getNext();
        return temp.getItem();
    }

    public void popAll()
    {
        top = null;
    }

    public int peek()
    {
        return top.getItem();
    }       
}

节点(也是一个用于操作数/整数):

public class Node{

private char item;
private Node next;

public Node(char newItem)
{
    item = newItem;
    next = null;
}

public Node(char newItem, Node nextNode)
{
    item = newItem;
    next = nextNode;
}

public char getItem()
{
    return item;
}

public void setNext(Node nextNode)
{
    next = nextNode;
}

public Node getNext()
{
    return next;
}
}

算法如下:

初始化运算符堆栈以包含';'(堆栈运算符的底部)

获取第一个令牌

虽然没有达到表达式的结尾

如果令牌是操作数,那么

打印令牌

将操作数推入操作数堆栈

否则,如果令牌是')'那么

虽然运算符堆栈的顶部不等于'('

弹出操作员堆栈

打印操作员

弹出操作数堆栈两次

将指定的操作应用于两个操作数

将操作结果推送到操作数堆栈

结束时

弹出'('并丢弃它

否则

而inputPriority(token)≤stackPriority(运算符堆栈的顶部)

弹出操作员堆栈

打印操作员

弹出操作数堆栈两次

将指定的操作应用于两个操作数

将操作结果推送到操作数堆栈

结束时

将令牌推送到操作员堆栈

获取下一个标记

结束时

虽然运算符堆栈的顶部不等于';'

弹出操作员堆栈

打印操作员

弹出操作数堆栈两次

将指定的操作应用于两个操作数

将操作结果推送到操作数堆栈

结束时

弹出操作数堆栈并打印结果

感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

token = expr.charAt(count);

这应该是

token = expr.charAt(index);

我不知道为什么你很难同时维护indexcount.这只会导致这样的麻烦。

答案 1 :(得分:1)

我想出了问题。还有另外两个问题:

首先,输入文件末尾有两个额外的空行,导致异常。

其次,tokenI = expr.charAt(index)将ASCII值分配给tokenI(例如,输入值5导致tokenI为53),所以我只需要减去48(ASCII值为0)来纠正问题。 tokenI = expr.charAt(index) - 48之后其他一切都落到了原地。

另外,正如@EJP所说,并不需要&#34;索引&#34;和&#34;计数&#34;变量,所以我删除了&#34; count&#34;并且只使用了&#34; index。&#34;