2012-10-10 37 views
0

好吧,所以我有這個代碼將中綴表達式轉換爲後綴表達式。有用!除了我希望它能夠處理諸如「2 + * 5」或「單詞字」之類的錯誤。我將如何做到這一點?謝謝!Java代碼,添加異常?

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

} 
+0

是什麼目前做壞的輸入數據? – nneonneo

+0

如何使用'try catch'而不是'throws' –

+0

輸入錯誤的數據並且控制檯充滿錯誤 – Becksters

回答

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

看起來它正常退出壞輸入。你可以改變行爲。輸入驗證完成後:您可以從中綴轉換爲後綴。

唯一要注意的是,輸入必須分開數字和運算與單個(空格) 實施例有效輸入:10 + 20 + 30 + 40 + 50 - 30 - 20 例INVALID輸入:10 + 20 + 30 + 40 + 50-30-20

+0

我該怎麼做?我對創建異常知之甚少 – Becksters

+0

@Becksters長話短說:如果在閱讀String時(如錯誤的符號或字母)發現* odd *,那麼就拋出一個'Exception'。 Prototype只是在閱讀(驗證)String時添加一種模式,但您可以使用另一種模式。 –

+0

要創建一個異常,請創建一個擴展「Exception」類的類。要編寫這個語法,只需閱讀遞歸下降解析器。他們很容易實現。 –

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"); 

     } 

瞭解更多關於handling exceptions

+0

在方法中拋出錯誤並在使用它的類中捕獲它會更好。通過這種方式,您的方法將變得更加清晰,並讓其他圖層處理錯誤:記錄,用消息顯示花哨的窗口,或者您在應用程序中使用的任何技術。 –

+0

你是否建議整個'InToPostfix.class'重新分配? –

+0

如果你想要一個良好的,乾淨的和可維護的代碼,當你剛剛打開課程時就會發光,是的。不要害怕做任何事情來銳化你的代碼並提高你的能力(至少你已經沒時間了,你應該提出第一件只是工作的東西,但IMO仍然不同意這個圓括號)。 –