0

好的,所以我有这段代码可以将中缀表达式转换为后缀表达式。有用!除了我希望它能够处理诸如“2+*5”或“wordswordswords”之类的错误。我该怎么做?谢谢!

package InToPostfix;

import java.io.IOException;
import javax.script.*;


/** Translates an infix expression to a postfix expression.  
 * 
 * @author Becky Hogan
 *
 */


public class InToPost {
  private Stack theStack;

  private String input;

  private String output = "";

  public static void main(String[] args) throws Exception {
    String input = "";
    String output;
    Object evaluated;
    InToPost theTrans = new InToPost(input);
    output = theTrans.evalOp(); 
    InToPost result= new InToPost(input);
    evaluated= result.evaluate(input);
    System.out.println("Prefix is " + input + '\n');
    System.out.println("Postfix is " + output + '\n');
    System.out.println("The value:");
    System.out.println(evaluated);

  }

/** InToPost Method initiates the stack
 * 
 * @param in the expression string
 */

  public InToPost(String in) {
    input = in;
    int stackSize = input.length();
    theStack = new Stack(stackSize);
  }

  /** evaluate Method evaluates the mathematical expression
   * 
   * @param aString the expression string
   * @return an object obj, the answer
   * @throws Exception 
   */

  public Object evaluate(String aString) throws Exception {
    // create a script engine manager
    ScriptEngineManager factory = new ScriptEngineManager();
    // create a JavaScript engine
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    // evaluate JavaScript code from String
    Object obj = engine.eval(aString);
    return(obj);
    }

  /** evalOp Method decides what to do with the indexed character depending on if it is an operand or operator
   * 
   * @return the postfix
   * @throws Exception
   */


  public String evalOp() throws Exception {
    for (int j = 0; j < input.length(); j++) {
      char ch = input.charAt(j);
      switch (ch) {
      case '+': 
      case '-':
        processOperator(ch, 1); 
        break; //   (precedence 1)
      case '*': // it's * or /
      case '/':
        processOperator(ch, 2); // go pop operators
        break; //   (precedence 2)
      case '(': // it's a left paren
        theStack.push(ch); // push it
        break;
      case ')': // it's a right paren
    gotParen(ch); // go pop operators
    break;
  default: // must be an operand
      if(!Character.isJavaIdentifierPart(ch) && !Character.isDigit(ch)){
          throw new Exception
            ("Unexpected Character Encountered");

      }
    output = output + ch; // write it to output
    break;
  }
}
while (!theStack.isEmpty()) {
  output = output + theStack.pop();

}
return output; // return postfix
  }

  /** Method to determine the precedence of operators.
   * 
   * @param opThis the character in the string
   * @param prec1 precedence of previous operator
   */

  public void processOperator(char opThis, int prec1) {
    while (!theStack.isEmpty()) {
      char opTop = theStack.pop();
      if (opTop == '(') {
        theStack.push(opTop);
        break;
      }// it's an operator
      else {// precedence of new op
        int prec2;
        if (opTop == '+' || opTop == '-')
          prec2 = 1;
        else
          prec2 = 2;
        if (prec2 < prec1) // if prec of new op less
        { //    than prec of old
          theStack.push(opTop); // save newly-popped op
          break;
        } else
          // prec of new not less
          output = output + opTop; // than prec of old
      }
}
theStack.push(opThis);
  }

  /** gotParen Method gets the previous operator
   * 
   * @param ch the character in the string
   */

  public void gotParen(char ch){ 
while (!theStack.isEmpty()) {
  char chx = theStack.pop();
  if (chx == '(') 
    break; 
  else
    output = output + chx; 
}
  }

/**Stack class holds attributes for the stack needed for this assignment
 * 
 * @author Becky Hogan
 *
 */
  class Stack {
private int maxSize;

private char[] stackArray;

private int top;

public Stack(int max) {
  maxSize = max;
  stackArray = new char[maxSize];
  top = -1;
}

public void push(char j) {
  stackArray[++top] = j;
}

public char pop() {
  return stackArray[top--];
}

public char peek() {
  return stackArray[top];
}

public boolean isEmpty() {
  return (top == -1);
}
  }

}
4

2 回答 2

3

这需要有一个语法解析器规则。按照这种格式写一个:

EXPR: NUMBER OPERATOR NUMBER | NUMBER OPERATOR EXPR;
OPERATOR: '+' | '-'| '*' | '/';
NUMBER: [0-9]+

如果它不匹配规则,那么它是一个解析错误。

示例代码:(未测试):

class BadGrammarException extends Exception{

    /**
     * 
     */
    private static final long serialVersionUID = -2174692292489186639L;

}
class Validator{
   public boolean isValid(String s)
   {
       if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")){
           return true;
       }else{
       try{
           Integer.parseInt(s);
       }catch(Exception e){
           return false;
       }
       }
       return true;
   }
}

class GrammarValidator{
    private final int NUMBER = 0;
    private final int OPERATOR = 1;
    private int state = NUMBER;
    public boolean isValidGrammatically(String line) throws BadGrammarException{
        String[] tokens = line.split(" ");
        boolean flag = true;
        for(String p:tokens){
            if(new Validator().isValid(p)){
                /*everything is ok, token is valid*/
            }else{
                throw new BadGrammarException();
            }
        }
        for(String p:tokens){
            if(checkGrammar(p) == false){
                flag = false;
            }else{

            }
        }
        return flag;
    }

    public boolean checkGrammar(String p) throws BadGrammarException{
        if(state == NUMBER){
            /*expecting integer*/
            try{
                Integer.parseInt(p);
            }catch(Exception e){
                throw new BadGrammarException();
            }
            state = OPERATOR;
            return true;
        }
        if(state == OPERATOR){
            /*expecting operator*/
            if(p.equals("+") || p.equals("-") || p.equals("*") || p.equals("/")){
                       state = NUMBER;
                       return true;
                 }else{
                     throw new BadGrammarException();
                 }
        }/*unknown state*/
        return false;
    }
}

我用以下代码测试了上面的代码:

public class Main{
    public static void main(String[] args){
       Scanner scan = new Scanner(System.in);
       while(true){
       System.out.println("CHECK >");
       String line = scan.nextLine();
       try{
         if(new GrammarValidator().isValidGrammatically(line)){
            System.out.println("Valid");
         }
       }catch(BadGrammarException be){
           break;
       }
       }
    }
}

看起来它在输入错误时优雅地退出。不过,您可以更改行为。验证输入后:您可以从中缀转换为后缀。

唯一需要注意的是,输入必须用单个(空格)分隔 NUMBERS 和 OPERATORS 示例有效输入:10 + 20 + 30 + 40 + 50 - 30 - 20 示例无效输入:10+20+30+40+50- 30-20

于 2012-10-10T06:37:37.947 回答
0

您可以将潜在风险代码包含在 try-catch 块中。

try {
   InToPost theTrans = new InToPost(input);
   output = theTrans.evalOp(); 
   InToPost result= new InToPost(input);
   evaluated= result.evaluate(input);
} catch (Exception e) {
   System.out.println(e.getMessage());
}

例如,当发生逻辑错误时,您可以抛出异常。就像你在这里所做的那样:

if(!Character.isJavaIdentifierPart(ch) && !Character.isDigit(ch)){
          throw new Exception
            ("Unexpected Character Encountered");

      }

阅读有关处理异常的更多信息

于 2012-10-10T06:47:59.833 回答