藍橋杯 算法訓練 ALGO-156 表達式計算


算法訓練 表達式計算  
時間限制:1.0s   內存限制:256.0MB
問題描述
  輸入一個只包含加減乖除和括號的合法表達式,求表達式的值。其中除表示整除。
輸入格式
  輸入一行,包含一個表達式。
輸出格式
  輸出這個表達式的值。
樣例輸入
1-2+3*(4-5)
樣例輸出
-4
數據規模和約定
  表達式長度不超過100,表達式運算合法且運算過程都在int內進行。
 
題目解析:
  運算優先級: 括號 → 乘除 → 加減
  例如  1-2+3*(4-5)
    (1)計算(4-5),表達式變為  1-2+3*-1
    (2)計算 3*-1,表達式變為  1-2+-3
    (3)計算 1-2,表達式變為  -1+-3
    (4)計算 -1+-3,表達式變為  -4
    (5)結果  -4
  根據這一規律,我們首先在輸入的表達式兩端加上括號,使程序變為重復去計算括號中的子表達式。計算規則如同上例。   
 
示例代碼:
  1 import java.io.BufferedReader;
  2 import java.io.IOException;
  3 import java.io.InputStreamReader;
  4 
  5 public class Main {
  6     public static void main(String[] args) throws IOException {
  7         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  8         StringBuilder expression = new StringBuilder("("+br.readLine()+")");    //表達式,在輸入的表達式兩邊加上括號
  9         StringBuilder temp = new StringBuilder();                                //存放臨時表達式,即每次存放的都是任意一個括號中的子表達式
 10         while(true){
 11             int frontBrackets = expression.lastIndexOf("(");            //從表達式后邊開始搜索,找到最后一個"("
 12             int backBrackets = expression.indexOf(")", frontBrackets);  //從最后一個"("的位置開始往后搜索,找到與之對應的")"
 13             
 14             if(frontBrackets == -1)    break;    //若再無表達式需要計算,即expression只有一個整數時,跳出循環
 15             
 16             temp.append(expression.substring(frontBrackets + 1 , backBrackets));    //將此括號中的表達式存入temp
 17             expression.delete(frontBrackets, backBrackets + 1);        //在原始表達式中將括號連同其中的表達式刪除
 18             
 19             for(int i = 0; i < temp.length(); i++){        //從子表達式中找出運算符,根據運算原則,先乘除后加減
 20                 if(temp.charAt(i) == '*'){                //若找到 "*" ,調用calculation進行運算
 21                     calculation(temp , '*' , i);
 22                     i = 0;                                //運算完后,i清零,方便下一次從開始位置繼續尋找乘除運算符
 23                 }
 24                 
 25                 if(temp.charAt(i) == '/'){
 26                     calculation(temp , '/' , i);
 27                     i = 0;
 28                 }
 29             }
 30             
 31             for(int i = 0; i < temp.length(); i++){        //找完乘除運算符后,開始找加減雲算符
 32                 if(temp.charAt(i) == '+'){
 33                     calculation(temp , '+' , i);
 34                     i = 0;
 35                 }
 36                 
 37                 if(temp.charAt(i) == '-'){
 38                     calculation(temp , '-' , i);
 39                     i = 0;
 40                 }
 41             }
 42             
 43             expression.insert(frontBrackets, temp);        //運算完后,將結果插入在剛才刪除的括號位置,構成新的表達式,繼續循環計算
 44             temp.delete(0, temp.length());                //將temp清空,方便下一個表達式計算
 45             
 46         }
 47         
 48         System.out.println(expression);        //輸出結果
 49     }
 50     
 51     /**
 52      * 計算表達式
 53      * @param src      表達式
 54      * @param op       操作符
 55      * @param location    操作符在表達式中的位置
 56      */
 57     private static void calculation(StringBuilder src, char op, int location) {
 58         int x = 0;    //操作數1
 59         int y = 0;  //操作數2
 60         int sum = 0;// sum = x (op) y
 61         
 62         String check = "0123456789+-";    //檢測運算符兩邊的內容是否為其中數組或者正數或負數
 63         StringBuilder temp = new StringBuilder();    //存放運算符兩邊的字符
 64         
 65         if(location == 0)    return;        //若遇到子表示其中只有加減運算符這種情況,且遇到的第一個運算符其實是想表示一個正數或者負數的符號,則函數返回,繼續尋找下一個運算符
 66         
 67         int k = 0;  //搜索操作符左右兩邊的數
 68         for(k = location - 1; k >= 0 && check.contains(src.charAt(k) + ""); k--){    //從運算符左邊一個位置開始往前搜索,找到第一個操作數
 69             try{
 70                 //若數字前邊有兩個運算符,第一個是為了與前邊的數相連,第二個是為了表示這個數的正負,則跳出循環,執行后面的語句
 71                 //比如: 5+(7+-5*+10),搜索到5前邊時,先搜索到"-",發現前邊還有一個"+",此時temp中沒有運算符,則繼續執行,當搜索到"+"時,發現前邊沒有運算符了,就跳出循環
 72                 if((src.charAt(k) == '+' || src.charAt(k) == '-') && (src.charAt(k-1) != '+' || src.charAt(k-1) != '-' ))
 73                     break;
 74                 if(temp.charAt(0) == '+' || temp.charAt(0) == '-')
 75                     break;
 76                 
 77             }catch(Exception e){
 78 //                e.printStackTrace();    //不輸出異常,滿足題目輸出要求
 79             }
 80             
 81             temp.insert(0, src.charAt(k));    //每次都是從temp的開始位置插入內容,保證逆向搜索的內容能按照正常的順序存入temp
 82             src.deleteCharAt(k);            //刪除運算符前邊的那個數字,若有正負號,也一並刪除
 83         }
 84         
 85         x = Integer.parseInt(temp.toString());    //將搜索到的此數存入x
 86         temp.delete(0, temp.length());            //將temp清空
 87         
 88         for(k = k + 2; k < src.length() && check.contains(src.charAt(k) + ""); ){    //從運算符右邊一個位置開始往后搜索,找到第二個操作數,加2是因為上邊的循環語句在結束時自減了一次
 89             
 90             if((src.charAt(k) == '+' || src.charAt(k) == '-') && (temp.length() != 0))
 91                 break;
 92             
 93             temp.append(src.charAt(k));
 94             src.deleteCharAt(k);
 95         }
 96         
 97         y = Integer.parseInt(temp.toString());
 98         temp.delete(0, temp.length());
 99         
100         switch(op){
101             case '+':
102                 sum = x + y;
103                 src.deleteCharAt(k-1);        //刪除運算符
104                 src.insert(k-1, sum + "");    //將結果存入src的操作符位置(此時操作符兩邊的數已經從src中刪除,所以插入此位置相當於用結果代替子表達式,方便下一次運算)
105                 break;
106             
107             case '-':
108                 sum = x - y;
109                 src.deleteCharAt(k-1);
110                 src.insert(k-1, sum + "");
111                 break;
112                 
113             case '*':
114                 sum = x * y;
115                 src.deleteCharAt(k-1);
116                 src.insert(k-1, sum + "");
117                 break;
118                 
119             case '/':
120                 sum = x / y;
121                 src.deleteCharAt(k-1);
122                 src.insert(k-1, sum + "");
123                 break;
124             
125             default:
126                 break;
127         }
128     }
129 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM