出于某种原因,我的程序似乎一直在崩溃,因为它读取了一个令牌错误。在第362行和第363行,它读取令牌[i],无论发生什么事情,它似乎都将其视为& #39;('字符,即使它显然没有。如果我输入类似100 *(5 + 5)的内容,它会在i = 2之后调用递归0 *(5 + 5)而不是正确地去i = 4并且调用它(5 + 5)。任何帮助调试都会很棒!
package apps;
import java.io.IOException;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.StringTokenizer;
import structures.Stack;
public class Expression {
/**
* Expression to be evaluated
*/
String expr;
/**
* Scalar symbols in the expression
*/
ArrayList<ScalarSymbol> scalars;
/**
* Array symbols in the expression
*/
ArrayList<ArraySymbol> arrays;
/**
* Positions of opening brackets
*/
ArrayList<Integer> openingBracketIndex;
/**
* Positions of closing brackets
*/
ArrayList<Integer> closingBracketIndex;
/**
* String containing all delimiters (characters other than variables and constants),
* to be used with StringTokenizer
*/
public static final String delims = " \t*+-/()[]";
/**
* Initializes this Expression object with an input expression. Sets all other
* fields to null.
*
* @param expr Expression
*/
public Expression(String expr) {
this.expr = expr;
scalars = null;
arrays = null;
openingBracketIndex = null;
closingBracketIndex = null;
}
/**
* Matches parentheses and square brackets. Populates the openingBracketIndex and
* closingBracketIndex array lists in such a way that closingBracketIndex[i] is
* the position of the bracket in the expression that closes an opening bracket
* at position openingBracketIndex[i]. For example, if the expression is:
* <pre>
* (a+(b-c))*(d+A[4])
* </pre>
* then the method would return true, and the array lists would be set to:
* <pre>
* openingBracketIndex: [0 3 10 14]
* closingBracketIndex: [8 7 17 16]
* </pe>
*
* See the FAQ in project description for more details.
*
* @return True if brackets are matched correctly, false if not
*/
public boolean isLegallyMatched()
{
Stack<Character> brack = new Stack<Character>();
Stack<Integer> opens = new Stack<Integer>();
openingBracketIndex = new ArrayList<Integer>();
closingBracketIndex = new ArrayList<Integer>();
char x;
char y;
String expr = this.expr;
for(int i=0; i<expr.length(); i++)
{
x = expr.charAt(i);
if(x!='(' && x!= '[' && x!=')' && x!=']')
{
continue;
}
if(x=='(' || x== '[')
{
opens.push(i);
brack.push(x);
}
else if(x==')' || x==']')
{
closingBracketIndex.add(i);
if(opens.isEmpty())
{
return false;
}
openingBracketIndex.add(opens.pop());
if(brack.isEmpty())
{
return false;
}
y = brack.pop();
if(y=='(' && x==')')
{
continue;
}
else if(y=='[' && x==']')
{
continue;
}
else if(y=='{' && x=='}')
{
continue;
}
else
{
return false;
}
}
}
if(!brack.isEmpty())
{
return false;
}
selectionSort(openingBracketIndex);
if(openingBracketIndex.isEmpty()!= true)
{
System.out.print("Opening Bracket Index: [ ");
for(int i=0;i<openingBracketIndex.size(); i++)
{
System.out.print(openingBracketIndex.get(i) + " ");
}
System.out.print("]");
System.out.println();
System.out.print("Closing bracket Index: [ ");
for(int i=0;i<openingBracketIndex.size(); i++)
{
System.out.print(closingBracketIndex.get(i) + " ");
}
System.out.println("]");
}
return true;
}
/**
* Populates the scalars and arrays lists with symbols for scalar and array
* variables in the expression. For every variable, a SINGLE symbol is created and stored,
* even if it appears more than once in the expression.
* At this time, values for all variables are set to
* zero - they will be loaded from a file in the loadSymbolValues method.
*/
public void buildSymbols()
{
scalars = new ArrayList<ScalarSymbol>();
arrays = new ArrayList<ArraySymbol>();
for(int i=0;i<expr.length();i++)
{
String symb = "";
while(i<expr.length() && Character.isLetter(expr.charAt(i)))
{
symb = symb + expr.charAt(i);
i++;
}
if(i==expr.length())
{
i--;
}
if(expr.charAt(i) == '[')
{
ArraySymbol arr = new ArraySymbol(symb);
boolean dupe = checkArrDupes(arr, arrays);
if(symb!="" && dupe == true)
{
arrays.add(arr);
}
}
else
{
ScalarSymbol scal = new ScalarSymbol(symb);
boolean dupe = checkScalDupes(scal,scalars);
if(symb!="" && dupe==true)
{
scalars.add(scal);
}
}
}
// COMPLETE THIS METHOD
}
/**
* Loads values for symbols in the expression
*
* @param sc Scanner for values input
* @throws IOException If there is a problem with the input
*/
public void loadSymbolValues(Scanner sc)
throws IOException {
while (sc.hasNextLine()) {
StringTokenizer st = new StringTokenizer(sc.nextLine().trim());
int numTokens = st.countTokens();
String sym = st.nextToken();
ScalarSymbol ssymbol = new ScalarSymbol(sym);
ArraySymbol asymbol = new ArraySymbol(sym);
int ssi = scalars.indexOf(ssymbol);
int asi = arrays.indexOf(asymbol);
if (ssi == -1 && asi == -1) {
continue;
}
int num = Integer.parseInt(st.nextToken());
if (numTokens == 2) { // scalar symbol
scalars.get(ssi).value = num;
} else { // array symbol
asymbol = arrays.get(asi);
asymbol.values = new int[num];
// following are (index,val) pairs
while (st.hasMoreTokens()) {
String tok = st.nextToken();
StringTokenizer stt = new StringTokenizer(tok," (,)");
int index = Integer.parseInt(stt.nextToken());
int val = Integer.parseInt(stt.nextToken());
asymbol.values[index] = val;
}
}
}
}
/**
* Evaluates the expression, using RECURSION to evaluate subexpressions and to evaluate array
* subscript expressions.
*
* @return Result of evaluation
*/
public float evaluate()
{
printScalars();
printArrays();
String expr = this.expr;
System.out.println("Hello");
float result = evaluate(expr, 0);
return result;
}
public float evaluate(String base, int brackIndex)
{
System.out.println("Method Start");
Stack<Float> numStack = new Stack<Float>();
Stack<String> opStack = new Stack<String>();
Stack<String> op2Stack = new Stack<String>();
Stack<Float> num2Stack = new Stack<Float>();
float x;
float y;
float result;
int swag = findParenIndexes(base);
Stack<Integer> open = new Stack<Integer>();
Stack<Integer> close= new Stack<Integer>();
for(int i=0;i<base.length();i++)
{
if(open.size()==1 && close.size()==1)
{
System.out.println(open.pop() + " " + close.pop());
break;
}
if(base.charAt(i)=='(' || base.charAt(i)=='[')
{
open.push(i);
}
if(base.charAt(i)==')'|| base.charAt(i)==']')
{
open.pop();
close.push(i);
}
}
String expr = base;
String orig = this.expr;
for(int i=0;i<scalars.size();i++)
{
expr = expr.replaceAll(scalars.get(i).name, scalars.get(i).value + "");
}
System.out.println(expr);
StringTokenizer st = new StringTokenizer(expr,delims,true);
String[] tokens = new String[st.countTokens()];
int z=0;
while(st.hasMoreTokens())
{
tokens[z] = st.nextToken();
z++;
}
for(int i=0;i<tokens.length;i++)
{
System.out.println(tokens[i]);
}
for(int i=0;i<tokens.length;i++)
{
String currToken = tokens[i];
if(isNumeric(currToken))
{
numStack.push(Float.parseFloat(currToken));
System.out.println("Number pushed to stack.");
}
if(currToken.charAt(0)=='+')
{
opStack.push(currToken);
System.out.println("+ pushed to stack.");
}
else if(currToken.charAt(0)=='-')
{
opStack.push(currToken);
System.out.println("- pushed to stack.");
}
else if(currToken.charAt(0)=='*')
{
System.out.println("Multiplying...");
System.out.println("Current bracket index is "+ brackIndex);
x = numStack.pop();
i++;
String next = tokens[i];
if(next.charAt(0)=='(')
{
try{
System.out.println("Evaluating " + expr.substring(i+1, swag));
}
catch(Exception e)
{
swag = findParenIndexes(expr.substring(swag,expr.length()));
}
System.out.println("i: " + i + " swag: ") ;
y=evaluate(expr.substring(i+1, swag), brackIndex+1);
result = x*y;
System.out.println("Multiplication worked - evaluate() returned " + result + " and jumped to the "+closingBracketIndex.get(brackIndex)+" index");
i = swag;
System.out.println("i: " + i);
numStack.push(result);
}
if(isNumeric(next))
{
y = Float.parseFloat(next);
result = x*y;
System.out.println(result + " pushed to stack");
numStack.push(result);
}
}
else if(currToken.charAt(0)=='/')
{
System.out.println("Dividing...");
x = numStack.pop();
i++;
String next = tokens[i];
if(next.charAt(0)== '(')
{
y=evaluate(expr.substring(i+1, swag), brackIndex+1);
i = swag;
}
else
{
y = Float.parseFloat(next);
}
if(y==0)
{
System.out.println("Divide by Zero encountered! Please check your input");
throw new IllegalArgumentException();
}
result = x/y;
System.out.println(result + " pushed to stack");
numStack.push(result);
}
else if(currToken.charAt(0)=='(')
{
System.out.println("Evaluating parentheses and adding the term to the stack.");
numStack.push(evaluate(expr.substring(i+1,swag), brackIndex+1));
System.out.println("Jumping to " + swag);
i = swag;
System.out.println("i: " + i);
}
if(arrays.contains(currToken))
{
System.out.println("array variable detected. looking up" + currToken);
int k = arrays.indexOf(currToken);
int cool = arrays.get(k).values[10];
}
// 5+(5*6+(5*3)-4)-9
}
// (a+(b-c))*(d+4)
while(!opStack.isEmpty())
{
op2Stack.push(opStack.pop());
}
while(!numStack.isEmpty())
{
num2Stack.push(numStack.pop());
}
while(op2Stack.isEmpty() == false)
{
String currOp = op2Stack.pop();
if(currOp.charAt(0) == '+')
{
x = num2Stack.pop();
y = num2Stack.pop();
System.out.println("adding "+ x +" and "+ y);
result = x+y;
System.out.println(result + " pushed to stack");
num2Stack.push(result);
if(!opStack.isEmpty())
System.out.println("next op... " + op2Stack.peek());
}
if(currOp.charAt(0) == '-')
{
System.out.println("subtracting...");
x = num2Stack.pop();
y = num2Stack.pop();
result = x-y;
System.out.println(result + " pushed to stack");
num2Stack.push(result);
if(!opStack.isEmpty())
System.out.println("next op... " + op2Stack.peek());
}
}
Float end = num2Stack.pop();
System.out.println("pls work - " + end);
return end;
}
private int findParenIndexes(String expr)
{
Stack<Integer> open = new Stack<Integer>();
Stack<Integer> close = new Stack<Integer>();
for(int i = 0;i<expr.length();i++)
{
if(expr.charAt(i)=='(' || expr.charAt(i)==']')
{
open.push(i);
}
if(expr.charAt(i)==')' || expr.charAt(i)==']')
{
close.push(i);
if(open.size()==1)
{
return close.pop();
}
open.pop();
}
}
return 0;
// COMPLETE THIS METHOD
}
private static boolean isNumeric(String str)
{
try
{
float f = Float.parseFloat(str);
}
catch(Exception e)
{
return false;
}
return true;
}
// test 5*(2+6-(5*3)-6)
/**
* Utility method, prints the symbols in the scalars list
*/
public void printScalars() {
for (ScalarSymbol ss: scalars) {
System.out.println(ss);
}
}
/**
* Utility method, prints the symbols in the arrays list
*/
public void printArrays()
{
for (ArraySymbol as: arrays)
{
System.out.println(as);
}
}
private boolean checkArrDupes(ArraySymbol sym, ArrayList<ArraySymbol> list)
{
if(list.size()!=0)
{
for(int i=0;i<list.size();i++)
{
if(sym==list.get(i))
{
return false;
}
}
}
return true;
}
private boolean checkScalDupes(ScalarSymbol sym, ArrayList<ScalarSymbol> list)
{
if(list.size()!=0)
{
for(int i=0;i<list.size();i++)
{
if(sym==list.get(i))
{
return false;
}
}
}
return true;
}
private void selectionSort(ArrayList<Integer> data)
{
if (data == null)
return;
if (data.size() == 0 || data.size() == 1)
return;
int smallestIndex;
int smallest;
for (int i = 0; i < data.size(); i++)
{
smallest = data.get(i);
smallestIndex = i;
for (int z = i + 1; z < data.size(); z++)
{
if (smallest > data.get(z))
{
// update smallest
smallest = data.get(z);
smallestIndex = z;
}
}
if (smallestIndex != i)
{
int temp = data.get(i);
data.set(i, data.get(smallestIndex));
data.set(smallestIndex, temp);
temp = closingBracketIndex.get(i);
closingBracketIndex.set(i,closingBracketIndex.get(smallestIndex));
closingBracketIndex.set(smallestIndex,temp);
}
}
}
}