2012-10-10 74 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仍然不同意这个圆括号)。 –