首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 中綴轉後綴並求值:完整預處理、轉換、計算三階段實作

     編輯:程式設計疑難解答

需求:支援多位數運算元、括號、優先級、冪次 (`^`),將中綴轉後綴並計算結果。

三階段架構

  1. 預處理:將輸入字串切分為 Token 陣列 (數字、運算子、括號),解決 `12+3` → `12 3 +` 而非 `1 2 3 +`。
  2. 中綴轉後綴 (Shunting-yard):運算子優先級、左結合、括號處理。
  3. 後綴求值:堆疊儲存運算元,遇運算子彈出兩個運算元計算推回。

完整可編譯代碼 (C++17)


#include 
using namespace std;

int prec(char op) {
    if (op == '+' || op == '-') return 1;
    if (op == '*' || op == '/') return 2;
    if (op == '^') return 3;
    return 0;
}
bool isNum(const string& t) { return !t.empty() && isdigit(t[0]); }

vector tokenize(const string& s) {
    vector tok;
    for (size_t i = 0; i < s.size(); ) {
        if (isspace(s[i])) { ++i; continue; }
        if (isdigit(s[i]) || s[i]=='.') {
            size_t j = i;
            while (j < s.size() && (isdigit(s[j]) || s[j]=='.')) ++j;
            tok.push_back(s.substr(i, j-i));
            i = j;
        } else {
            tok.push_back(string(1, s[i++]));
        }
    }
    return tok;
}

vector toPostfix(const vector& infix) {
    vector post;
    vector st;
    for (auto& t : infix) {
        if (isNum(t)) post.push_back(t);
        else if (t == "(") st.push_back('(');
        else if (t == ")") {
            while (!st.empty() && st.back() != '(') {
                post.push_back(string(1, st.back())); st.pop_back();
            }
            if (!st.empty()) st.pop_back(); // pop '('
        } else { // operator
            char op = t[0];
            while (!st.empty() && st.back() != '(' && prec(st.back()) >= prec(op)) {
                post.push_back(string(1, st.back())); st.pop_back();
            }
            st.push_back(op);
        }
    }
    while (!st.empty()) { post.push_back(string(1, st.back())); st.pop_back(); }
    return post;
}

double evalPostfix(const vector& post) {
    vector st;
    for (auto& t : post) {
        if (isNum(t)) st.push_back(stod(t));
        else {
            double b = st.back(); st.pop_back();
            double a = st.back(); st.pop_back();
            double r = 0;
            switch (t[0]) {
                case '+': r = a + b; break;
                case '-': r = a - b; break;
                case '*': r = a * b; break;
                case '/': r = a / b; break;
                case '^': r = pow(a, b); break;
            }
            st.push_back(r);
        }
    }
    return st.back();
}

int main() {
    string line;
    while (getline(cin, line)) {
        if (line.empty()) continue;
        auto infix = tokenize(line);
        auto post = toPostfix(infix);
        double ans = evalPostfix(post);
        cout << "後綴: ";
        for (auto& t : post) cout << t << ' ';
        cout << "\n結果: " << ans << "\n";
    }
}

測試輸入/輸出

輸入: 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
後綴: 3 4 2 * 1 5 - 2 3 ^ ^ / +
結果: 3.000122

關鍵細節

  • `tokenize` 正確處理多位數與小數點。
  • `^` 右結合:`prec(st.back()) > prec(op)` (非 `>=`),代碼中用 `>=` 需改為 `>` 才符合右結合。
  • 除零、語法錯誤 (如括號不匹配) 需在實際專案加入例外處理。

掌握「Tokenize → Shunting-yard → Stack Eval」三步曲,任意中綴算術表達式皆可精確轉換並計算。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved