1. 程式人生 > >C++ 中綴表示式的計算

C++ 中綴表示式的計算

一、思路:

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

執行結果: