Java 中的调车场算法实现给出不正确的输出和超出范围的字符串索引?

Shunting-Yard Algorithm Implementation in Java giving incorrect output and String index out of range?

我正在实施调车场算法并评估结果这是一个基于引用的实施,使用节点(一个用于运算符,一个用于操作数)和堆栈(一个用于运算符,一个用于操作数)。


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

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();
    }       
}

节点(也是 operands/integers 的一个):

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;
}
}

算法如下:

初始化运算符栈以包含‘;’(栈底运算符)

获得第一个令牌

未到达表达式末尾时

如果令牌是一个操作数则

打印令牌

将操作数压入操作数栈

否则如果令牌是')'则

而运算符栈顶不等于‘(’

弹出运算符栈

打印运算符

两次弹出操作数栈

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

将运算结果压入操作数栈

结束时

弹出“(”并丢弃它

其他

while inputPriority(token) ≤ stackPriority(算子栈顶)

弹出运算符栈

打印运算符

两次弹出操作数栈

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

将运算结果压入操作数栈

结束时

将令牌压入运算符栈

获取下一个令牌

结束时

而运算符栈顶不等于‘;’

弹出运算符栈

打印运算符

两次弹出操作数栈

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

将运算结果压入操作数栈

结束时

弹出操作数栈并打印结果

感谢任何帮助。

token = expr.charAt(count);

这应该是

token = expr.charAt(index);

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

我发现了问题。还有另外两个问题:

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

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

此外,正如@EJP 所说,不需要 "index" 和 "count" 变量,所以我删除了 "count" 并只使用了 "index."