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);
我不知道你为什么要维护index
和count.
这只会导致这样的麻烦。
我发现了问题。还有另外两个问题:
首先,输入文件末尾有两个额外的空行,导致异常。
其次,tokenI = expr.charAt(index)
将 ASCII 值分配给 tokenI(例如,输入值 5 导致 tokenI 为 53),所以我只需要减去 48(0 的 ASCII 值)纠正问题。 tokenI = expr.charAt(index) - 48
其他一切都在那之后就位了。
此外,正如@EJP 所说,不需要 "index" 和 "count" 变量,所以我删除了 "count" 并只使用了 "index."
我正在实施调车场算法并评估结果这是一个基于引用的实施,使用节点(一个用于运算符,一个用于操作数)和堆栈(一个用于运算符,一个用于操作数)。
输入文件包含(仅前几行):
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);
我不知道你为什么要维护index
和count.
这只会导致这样的麻烦。
我发现了问题。还有另外两个问题:
首先,输入文件末尾有两个额外的空行,导致异常。
其次,tokenI = expr.charAt(index)
将 ASCII 值分配给 tokenI(例如,输入值 5 导致 tokenI 为 53),所以我只需要减去 48(0 的 ASCII 值)纠正问题。 tokenI = expr.charAt(index) - 48
其他一切都在那之后就位了。
此外,正如@EJP 所说,不需要 "index" 和 "count" 变量,所以我删除了 "count" 并只使用了 "index."