1. 程式人生 > >C++ 中綴表示式轉字尾表示式

C++ 中綴表示式轉字尾表示式

一、思路:和中綴表示式的計算類似,只不過不用計算,把表示式輸出即可

      1.用字元陣列儲存整行輸入的中綴表示式;

      2.接著從字元陣列的0位置開始判斷字元,如果是數字,那就要判斷後面是否是數字,如果是就不斷掃描組成一個整數

        (暫不考慮負數和小數),最終組成一個整數,然後輸出這個數(因為不用計算,所以直接輸出即可);

      3.如果是左括號,直接進符號棧;

      4.如果是操作運算子,與符號棧的棧頂元素比較優先順序:如果高就壓入棧;

                低,就取出符號棧頂的元素輸出;

                接著,再判斷符號棧頂的元素和當前的運算子號繼續比較優先順序,重複前面步驟,直到棧空或者當前的符號優先順序高;

      5.如果是右括號,把符號棧棧頂的元素取出,如果不是左括號,把取出的運算子輸出,接著取符號棧棧頂的元素,直到符號棧

         中取出的符號是左括號;

      6.當掃描完字元陣列時,判斷符號棧是否為空:

                不為空,把符號棧棧頂的元素取出,輸出到視窗,直到符號棧為空。

 

二、實現程式:

//  中綴表示式轉字尾表示式
//  操作符:+、-、*、/、%
//  輸入:可以用cin.getline(arr, 250)或者cin.get(ch) && ch != '\n'
//  測試資料:輸入格式:(注意:不能有中文的操作符)
//           2+(3+4)*5
//           16+2*30/4
//      輸出格式:
//          2 3 4 + 5 * +
//          16 2 30 * 4 / +

#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 main(int argc, const char * argv[]) {
    // insert code here...
    int num;
    char arr[250]; // 一個一個的讀取表示式,直到遇到'\0'
    std::stack<char> op; // 棧op:儲存操作符
    
    while(1) {
        std::cin.getline(arr,250);
        int len, i;
        char c; // c儲存從棧中取出的操作符
        
        len = (int)strlen(arr); // strlen()輸出的是:unsigned long型別,所以要強制轉換為int型別
        i = 0;
        while(i < len) {
            if(isdigit(arr[i])) { // 如果是數字
                num = 0;
                do {
                    num = num * 10 + (arr[i] - '0'); // ch - 48根據ASCAII碼,字元與數字之間的轉換關係
                    i++; // 下一個字元
                }while(isdigit(arr[i]));
                std::cout << num << " ";
            } else if(arr[i] == '(') { // (:左括號
                op.push(arr[i]);
                i++;
            } else if(isOperator(arr[i])) { // 操作符
                if(op.empty()) {// 如果棧空,直接壓入棧
                    op.push(arr[i]);
                    i++;
                }
                else {
                    // 比較棧op頂的操作符與ch的優先順序
                    // 如果ch的優先順序高,則直接壓入棧
                    // 否則,推出棧中的操作符,直到操作符小於ch的優先順序,或者遇到(,或者棧已空
                    while(!op.empty()) {
                        c = op.top();
                        if(getPriority(arr[i]) <= getPriority(c)) {
                            // 優先順序低或等於
                            std::cout << c << " ";
                            op.pop();
                        } else // ch優先順序高於棧中操作符
                            break;
                    } // while結束
                    op.push(arr[i]); // 防止不斷的推出操作符,最後空棧了;或者ch優先順序高了
                    i++;
                } // else
            } else if(arr[i] == ')') { // 如果是右括號,一直推出棧中操作符,直到遇到左括號(
                while(op.top() != '(') {
                    std::cout << op.top() << " ";
                    op.pop();
                }
                op.pop(); // 把左括號(推出棧
                i++;
            } else // 如果是空白符,就進行下一個字元的處理
                i++;
        } // 第二個while結束
        while(!op.empty()) { // 當棧不空,繼續輸出操作符
            std::cout << op.top() << " ";
            op.pop();
        }
        std::cout << std::endl;
        flush(std::cout);
    } // 第一個while結束
    return 0;
}

執行結果: