根据标题,对于这个程序,我们将使用“两个堆栈来评估来自InputStream的中缀算术表达式。它不应该创建一个完整的后缀表达式;它应该以流水线方式转换和评估,一次通过。“
package cs445.a2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class InfixExpressionEvaluator {
// Tokenizer to break up our input into tokens
StreamTokenizer tokenizer;
// Stacks for operators (for converting to postfix) and operands (for
// evaluating)
StackInterface<Character> operatorStack;
StackInterface<Double> operandStack;
/**
* Initializes the evaluator to read an infix expression from an input
* stream.
* @param input the input stream from which to read the expression
*/
public InfixExpressionEvaluator(InputStream input) {
// Initialize the tokenizer to read from the given InputStream
tokenizer = new StreamTokenizer(new BufferedReader(
new InputStreamReader(input)));
// StreamTokenizer likes to consider - and / to have special meaning.
// Tell it that these are regular characters, so that they can be parsed
// as operators
tokenizer.ordinaryChar('-');
tokenizer.ordinaryChar('/');
// Allow the tokenizer to recognize end-of-line, which marks the end of
// the expression
tokenizer.eolIsSignificant(true);
// Initialize the stacks
operatorStack = new ArrayStack<Character>();
operandStack = new ArrayStack<Double>();
}
/**
* Parses and evaluates the expression read from the provided input stream,
* then returns the resulting value
* @return the value of the infix expression that was parsed
*/
public Double evaluate() throws ExpressionError {
// Get the first token. If an IO exception occurs, replace it with a
// runtime exception, causing an immediate crash.
try {
tokenizer.nextToken();
} catch (IOException e) {
throw new RuntimeException(e);
}
// Continue processing tokens until we find end-of-line
while (tokenizer.ttype != StreamTokenizer.TT_EOL) {
// Consider possible token types
switch (tokenizer.ttype) {
case StreamTokenizer.TT_NUMBER:
// If the token is a number, process it as a double-valued
// operand
processOperand((double)tokenizer.nval);
break;
case '+':
case '-':
case '*':
case '/':
case '^':
// If the token is any of the above characters, process it
// is an operator
processOperator((char)tokenizer.ttype);
break;
case '(':
case '[':
// If the token is open bracket, process it as such. Forms
// of bracket are interchangeable but must nest properly.
processOpenBracket((char)tokenizer.ttype);
break;
case ')':
case ']':
// If the token is close bracket, process it as such. Forms
// of bracket are interchangeable but must nest properly.
processCloseBracket((char)tokenizer.ttype);
break;
case StreamTokenizer.TT_WORD:
// If the token is a "word", throw an expression error
throw new ExpressionError("Unrecognized token: " +
tokenizer.sval);
default:
// If the token is any other type or value, throw an
// expression error
throw new ExpressionError("Unrecognized token: " +
String.valueOf((char)tokenizer.ttype));
}
// Read the next token, again converting any potential IO exception
try {
tokenizer.nextToken();
} catch(IOException e) {
throw new RuntimeException(e);
}
}
// Almost done now, but we may have to process remaining operators in
// the operators stack
processRemainingOperators();
// Return the result of the evaluation
// TODO: Fix this return statement
return null;
}
/**
* This method is called when the evaluator encounters an operand. It
* manipulates operatorStack and/or operandStack to process the operand
* according to the Infix-to-Postfix and Postfix-evaluation algorithms.
* @param operand the operand token that was encountered
*/
void processOperand(double operand) {
// TODO: Complete this method
}
/**
* This method is called when the evaluator encounters an operator. It
* manipulates operatorStack and/or operandStack to process the operator
* according to the Infix-to-Postfix and Postfix-evaluation algorithms.
* @param operator the operator token that was encountered
*/
void processOperator(char operator) {
// TODO: Complete this method
}
/**
* This method is called when the evaluator encounters an open bracket. It
* manipulates operatorStack and/or operandStack to process the open bracket
* according to the Infix-to-Postfix and Postfix-evaluation algorithms.
* @param openBracket the open bracket token that was encountered
*/
void processOpenBracket(char openBracket) {
// TODO: Complete this method
}
/**
* This method is called when the evaluator encounters a close bracket. It
* manipulates operatorStack and/or operandStack to process the close
* bracket according to the Infix-to-Postfix and Postfix-evaluation
* algorithms.
* @param closeBracket the close bracket token that was encountered
*/
void processCloseBracket(char closeBracket) {
// TODO: Complete this method
}
/**
* This method is called when the evaluator encounters the end of an
* expression. It manipulates operatorStack and/or operandStack to process
* the operators that remain on the stack, according to the Infix-to-Postfix
* and Postfix-evaluation algorithms.
*/
void processRemainingOperators() {
// TODO: Complete this method
}
/**
* Creates an InfixExpressionEvaluator object to read from System.in, then
* evaluates its input and prints the result.
* @param args not used
*/
public static void main(String[] args) {
System.out.println("Infix expression:");
InfixExpressionEvaluator evaluator =
new InfixExpressionEvaluator(System.in);
Double value = null;
try {
value = evaluator.evaluate();
} catch (ExpressionError e) {
System.out.println("ExpressionError: " + e.getMessage());
}
if (value != null) {
System.out.println(value);
} else {
System.out.println("Evaluator returned null");
}
}
}
我迷失了如何实现“void processOperand(double operand)”方法(现在只需要担心这个方法)。我知道如何使用数字/变量转换Infix到Postfix,但我不明白如何编码部分。有人能给我一个如何启动这个方法的提示吗?我还包括StackInterface类,它包含所有的push,pop,peek等。方法。
package cs445.a2;
import java.util.EmptyStackException;
public interface StackInterface<E> {
/** Adds a new entry to the top of this stack.
* @param newEntry An object to be added to the stack */
public void push(E newEntry);
/** Removes and returns this stack's top entry.
* @return The object at the top of the stack.
* @throws EmptyStackException if the stack is empty. */
public E pop() throws EmptyStackException;
/** Retrieves this stack's top entry.
* @return The object at the top of the stack.
* @throws EmptyStackException if the stack is empty. */
public E peek() throws EmptyStackException;
/** Detects whether this stack is empty.
* @return True if the stack is empty. */
public boolean isEmpty();
/** Removes all entries from this stack. */
public void clear();
}