C++ 中綴表示式的計算
阿新 • • 發佈:2019-01-07
一、思路:
1.輸入表示式的字元,如果不是換行符\n,判斷是什麼字元;如果是換行符結束;
2.判斷輸入的字元如果是數字,那就要判斷後面是否是數字,如果是就不斷掃描組成一個整數(暫不考慮負數和小數);
3.如果是左括號,直接進符號棧;
4.如果是操作運算子,與符號棧的棧頂元素比較優先順序:如果高就壓入棧;
低,就取出符號棧頂的元素和數棧中的棧頂兩個數進行運算,然後把結果壓回到數棧中;
接著,再判斷符號棧頂的元素和當前輸入的符號繼續比較優先順序,重複前面步驟,直到棧空或者輸入的符號優先順序高;
5.如果是右括號,把符號棧棧頂的元素取出,如果不是左括號,就取出數棧棧頂的兩個數進行相應的運算,把結果壓回到數棧
中,直到符號棧中取出的符號是左括號;
6.當輸入完表示式時,判斷符號棧是否為空:
不為空,把符號棧棧頂的元素和數棧棧頂的兩個數取出進行相應的運算,把結果壓回到數棧中,直到符號棧為空。
那最終的結果會存在數棧的棧頂。
二、實現程式:
// 中綴表示式的計算 // 測試:2*(3+4) // 6+2*3/4 // 輸出:2*(3+4)=14 // 6+2*3/4=7 #include <iostream> #include <stack> // 判斷是否是操作符 bool isOperator(char ch) { if(ch == '+' || ch == '-' || ch == '*' || ch == '/') return true; return false; // 否則返回false } // 獲取優先順序 int getPriority(char ch) { int level = 0; // 優先順序 switch(ch) { case '(': level = 1; break; case '+': case '-': level = 2; break; case '*': case '/': level = 3; break; default: break; } return level; } // 進行相應的計算 int Calculate(char ch, int a, int b) { int result = 0; switch(ch) { case '+': result = b + a; break; case '-': result = b - a; break; case '*': result = b * a; break; case '/': if(a == 0) { std::cerr << "除數不能為0。\n"; exit(1); // 強制終結程式 } else result = b / a; break; default: break; } // switch結束 return result; // 返回計算得到的結果 } int main(int argc, const char * argv[]) { // insert code here... std::stack<int> m_integer; // 數棧 std::stack<char> op; // 操作符棧 char ch, c; // ch儲存輸入的字元,c儲存操作符棧頂的元素 int num, result, a, b; // result儲存計算的結果,a,b儲存從數棧中取出的兩個數 while(1) { std::cin.get(ch); while(ch != '\n') { std::cout << ch; // 輸出接收到的字元 if(isdigit(ch)) { // 如果是數字 num = 0; do { num = num * 10 + (ch - '0'); // ch - '0'根據ASCAII碼,字元與數字之間的轉換關係 std::cin.get(ch); if(isdigit(ch)) // 防止出現2個或者多個數字組成的數,要輸出數字 std::cout << ch; }while(isdigit(ch)); m_integer.push(num); // 存到數棧中 } else if(ch == '(') { // (:左括號 op.push(ch); std::cin.get(ch); // 讀取下一個字元 } else if(isOperator(ch)) { // 操作符 if(op.empty()) {// 如果棧空,直接壓入棧 op.push(ch); std::cin.get(ch); // 讀取下一個字元 } else { // 比較棧op頂的操作符與ch的優先順序 // 如果ch的優先順序高,則直接壓入棧 // 否則,推出棧中的操作符,直到操作符小於ch的優先順序,或者遇到(,或者棧已空 while(!op.empty()) { c = op.top(); if(getPriority(ch) <= getPriority(c)) { // 優先順序低或等於 // 取出棧中操作符和數棧中兩個數進行運算,再將結果放回數棧 result = 0; a = m_integer.top(); // 第二個運算元,因為棧是後進先出 m_integer.pop(); b = m_integer.top(); // 第一個運算元 m_integer.pop(); result = Calculate(c, a, b); // 計算 m_integer.push(result); // 把計算結果壓入棧中 op.pop(); // 操作符出棧 } else // ch優先順序高於棧中操作符 break; } // while結束 op.push(ch); // 防止不斷的推出操作符,最後空棧了;或者ch優先順序高了 std::cin.get(ch); } // else } else if(ch == ')') { // 如果是右括號,一直推出棧中操作符,直到遇到左括號( while(op.top() != '(') { c = op.top(); // 取出棧頂操作符 result = 0; a = m_integer.top(); // 第二個運算元,因為棧是後進先出 m_integer.pop(); b = m_integer.top(); // 第一個運算元 m_integer.pop(); result = Calculate(c, a, b); // 計算 m_integer.push(result); // 把計算結果壓入棧中 op.pop(); // 把操作符推出棧 } op.pop(); // 把左括號(推出棧 std::cin.get(ch); } else // 如果是空白符,就進行下一個字元的處理 std::cin.get(ch); } // 第二個while結束 while(!op.empty()) { // 當棧不空,繼續取出操作符進行計算 c = op.top(); // 取出棧頂操作符 result = 0; a = m_integer.top(); // 第二個運算元,因為棧是後進先出 m_integer.pop(); b = m_integer.top(); // 第一個運算元 m_integer.pop(); result = Calculate(c, a, b); // 計算 m_integer.push(result); // 把計算結果壓入棧中 op.pop(); // 把操作符推出棧 } std::cout << "=" << m_integer.top() << "\n"; m_integer.pop(); flush(std::cout); } // 第一個while結束 return 0; }
執行結果: