#include <iostream> #include <cmath> // pow() #include <stack> // stack<T> #include <algorithm> // remove() #include <stdexcept> // runtime_error #include <string> // string using std::string; // 返回運算子的優先順序,值越大,優先順序越高 inline size_t precedence(const char op) { if (op == '+' || op == '-') return 1; if (op == '*' || op == '/') return 2; if (op == '^') return 3; throw std::runtime_error{ string {"表達中包含無效的運算子"} +op }; } // 計算 double execute(std::stack<char>& ops, std::stack<double>& operands) { double result{}; double rhs{ operands.top() }; // 得到右運算元 operands.pop(); double lhs{ operands.top() }; // 得到做運算元 operands.pop(); switch (ops.top()) // 根據兩個運算元之間的運算子,執行相應計算 { case '+': result = lhs + rhs; break; case '-': result = lhs - rhs; break; case '*': result = lhs * rhs; break; case '/': result = lhs / rhs; break; case '^': result = std::pow(lhs, rhs); break; default: throw std::runtime_error{ string{"invalid operator: "} +ops.top() }; } ops.pop(); //計算完成後,該運算子要彈棧 operands.push(result);//將新計算出來的結果入棧 return result; } int main() { std::stack<double> operands; //儲存表示式中的運算子 std::stack<char> operators; //儲存表示式中的數值 string exp; //接受使用者輸入的表示式文字 try { while (true) { std::cout << "輸入表示式(按Enter結束):" << std::endl; std::getline(std::cin, exp, 'n'); if (exp.empty()) break; //移除使用者輸入表示式中包含的無用的空格 exp.erase(std::remove(std::begin(exp), std::end(exp), ' '), std::end(exp)); size_t index{}; //每個表示式必須以數位開頭,index表示該數位的位數 operands.push(std::stod(exp, &index)); // 將表示式中第一個數位進棧 std::cout << index << std::endl; while (true) { operators.push(exp[index++]); // 將運算子進棧 size_t i{}; operands.push(std::stod(exp.substr(index), &i)); //將運算子後的數位也進棧,並將數位的位數賦值給 i。 index += i; //更新 index if (index == exp.length()) { while (!operators.empty()) //如果 operators不為空,表示還沒有計算完 execute(operators, operands); break; } //如果表示式還未遍歷完,但子表示式中的運算子優先順序比其後面的運算子優先順序大,就先計算當前的子表示式的值 while (!operators.empty() && precedence(exp[index]) <= precedence(operators.top())) execute(operators, operands); } std::cout << "result = " << operands.top() << std::endl; } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } std::cout << "計算結束" << std::endl; return 0; }下面是一些範例輸出:
輸入表示式(按Enter結束):
5*2-3
result = 7
輸入表示式(按Enter結束):
4+4*2
result = 12
輸入表示式(按Enter結束):↙ <--鍵入Enter
計算結束
2) 繼續判斷後續是否還有表示式,由於還有“+1”,則取 operators 棧頂運算子 * 和 + 運算子做優先順序比較,顯然前者的優先順序更高,此時將 operands 棧頂的 2 個元素(2 和 3)取出並彈棧,同時將 operators 棧頂元素(*)取出並彈棧,計算它們組成的表示式 2*3,並將計算結果再入 operands 棧。此時,operands 中從棧頂依次儲存的是 3、2、5,operators 容器中從棧頂依次儲存的是 *、-。
3) 由於 operator 容器不空,因此繼續取新的棧頂運算子“-”和“+”做優先順序比較,由於它們的優先順序是相同的,因為繼續將 operands 棧頂的 2 個元素(5 和 6)取出並彈棧,同時將 operators 棧頂元素(-) 取出並彈棧,計算它們組成的表示式“5-6”,並將計算結果 -1 再入 operands 棧。計算到這裡,operands 中從棧頂依次儲存的是 6、5,operators 中從棧頂依次儲存的是 -。
4)由於此時 operator 棧為空,因此將後續“+1”表示式中的 1 和 + 分別進棧。由於後續再無其他表示式,此時就可以直接取 operands 位於棧頂的 2 個元素(-1 和 1),和 operator 的棧頂運算子(+),執行 -1+1 運算,並將計算結果再入 operands 棧。此時,operands 中從棧頂依次儲存的是 -1,operator 為空。