1. 程式人生 > >java計算表示式的值

java計算表示式的值

package sweexamination.level1;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack; 
/**

 *  轉為字尾表示式:
 *  運算元直接放入結果
 *  當前操作符與棧中的操作符比較:
 *  棧空:進
 *  當前高:進
 *  當前低:將棧頂彈出,將當前放入結果(不會出項連續同級符號)
 *  相等:彈出棧頂,然後進
 *  左括號直接進棧,右括號將棧頂所有操作符彈出,直到遇到第一個左括號
 *  掃描完成時,將棧頂符號直接彈出

 *
 */

public class AA {
 public int eval(String exp){  
  List<String> list = infixExpToPostExp(exp);// 轉化成字尾表示式
  return doEval(list);// 真正求值
 }  
   
  // 遇到運算元壓棧,遇到操作符從字尾表示式中彈出兩個數,計算出結果,壓入堆疊
  private int doEval(List<String> list) {  
   Stack<String> stack = new Stack<String>();  
   String element;  
   int n1,n2,result;  
   try{  
    for(int i = 0; i < list.size();i++){  
     element = list.get(i);  
     if(isOperator(element)){  
      n1 = Integer.parseInt(stack.pop());  
      n2 = Integer.parseInt(stack.pop());  
      result = doOperate(n1,n2,element);  
      stack.push(new Integer(result).toString());  
     }else{  
      stack.push(element);  
     }  
    }  
    return Integer.parseInt(stack.pop());  
   }catch(RuntimeException e){  
    e.printStackTrace(); 
    return -1;
   }  
  }  
   
  private int doOperate(int n1, int n2, String operator) {  
   if(operator.equals("+"))  
    return n1 + n2;  
   else if(operator.equals("-"))  
    return n1 - n2;  
   else if(operator.equals("*"))  
    return n1 * n2;  
   else  
    return n1 / n2;  
  }  
   
  private boolean isOperator(String str){  
   return str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/");  
  }  
   
  private List<String> infixExpToPostExp(String exp){// 將中綴表示式轉化成為字尾表示式
   List<String> postExp = new ArrayList<String>();// 存放轉化的字尾表示式的連結串列
   StringBuffer numBuffer = new StringBuffer();// 用來儲存一個數的
   Stack<Character> opStack = new Stack<Character>();// 操作符棧
   char ch,preChar;  
   opStack.push('#');  
   try{  
    for(int i = 0; i < exp.length();){  
     ch = exp.charAt(i);  
     switch(ch){  
      case '+':  
     case '-':  
     case '*':  
     case '/':  
      preChar = opStack.peek();  
      // 如果棧裡面的操作符優先順序比當前的大,則把棧中優先順序大的都新增到字尾表示式列表中
      while(priority(preChar) >= priority(ch)){  
        postExp.add(""+preChar);  
        opStack.pop();  
        preChar = opStack.peek();  
      }  
      opStack.push(ch);  
      i++;  
      break;  
     case '(':  
      // 左括號直接壓棧
      opStack.push(ch);  
      i++;  
      break;  
     case ')':  
      // 右括號則直接把棧中左括號前面的彈出,並加入字尾表示式連結串列中
       char c = opStack.pop();  
       while(c != '('){  
        postExp.add("" + c);  
        c = opStack.pop();  
       }  
       i++;  
       break;  
       // #號,代表表示式結束,可以直接把操作符棧中剩餘的操作符全部彈出,並加入字尾表示式連結串列中
     case '#':  
       char c1;  
       while(!opStack.isEmpty()){  
        c1 = opStack.pop();  
        if(c1 != '#')  
         postExp.add("" + c1);  
       }  
       i++;  
       break;  
      // 過濾空白符
     case ' ':  
     case '\t':  
       i++;  
       break;  
      // 數字則湊成一個整數,加入字尾表示式連結串列中
       default:  
       if(Character.isDigit(ch)){  
        while(Character.isDigit(ch)){  
         numBuffer.append(ch);  
         ch = exp.charAt(++i);  
        }  
        postExp.add(numBuffer.toString());  
        numBuffer = new StringBuffer();  
       }else{  
        System.out.println("Illegal operator"); 
       }  
     }  
    }  
   }catch(RuntimeException e){  
    e.printStackTrace();  
   }  
   return postExp;  
  }  
   
  private int priority(char op){// 定義優先順序
   switch(op){  
    case'+':  
    case'-':  
     return 1;  
    case'*':  
    case'/':  
     return 2;  
    case'(':  
    case'#':  
     return 0;  
   }  
   System.out.println("Illegal operator");
   return -1;
  }  
   
  public static void main(String[] args) {  
   AA eval = new AA();  
   int result = eval.eval("2+3+55*22+21*2+(3+2)*3#");  
   System.out.println(result);  
 }  

}