1. 程式人生 > >通過入棧出棧實現數學表示式的計算

通過入棧出棧實現數學表示式的計算

#include <iostream>
#include <stack>
#include <string>
#include <cstring>
using namespace std;

class Exp {
    stack<char> ops; // 運算子棧
    stack<double> ds; // 資料棧
    double v, lh, rh; // 計算結果和臨時變數
    char op; // 讀取運算子
public:
    double calinput() { //讀取並計算表示式,直到結束為止
        do
{ readdata(); //讀取資料 skipspace(); //跳過空白 } while (readop()); //讀取運算子 calremain(); //處理棧中剩餘的運算子 return v; } //讀取資料 void readdata() { while (!(cin >> v)) { //讀取資料失敗,應該是左括號 cin.clear(); cin >> op; //讀取必須是左括號 if
(op != '(') { throw string("在該出現數值的地方遇到了") + op; } ops.push(op); } ds.push(v); } //跳過空格 void skipspace() { //cin.peek()檢視不取走 while (cin.peek() == ' ' || cin.peek() == '\t') { cin.ignore(); } } //讀取運算子,可能遇到右括號')'或者換行符'\n'
bool readop() { while ((op = cin.get()) == ')') { while (ops.top() != '(') { //找棧裡左括號'(' rh = ds.top(); //從棧中取出右運算元 ds.pop(); lh = ds.top(); //從棧中取出左運算元 ds.pop(); ds.push(cal(lh, ops.top(), rh)); //取出運算子,計算左右運算元 ops.pop(); } ops.pop(); //丟棄找到的左括號'(' } if (op == '\n') { return false; } if (strchr("+-*/", op) == NULL) { //無效運算子 throw string("無效運算子") + op; } while (!ops.empty() && ops.top() != '(' && !prior(op, ops.top())) { rh = ds.top(); ds.pop(); lh = ds.top(); ds.pop(); ds.push(cal(lh, ops.top(), rh)); ops.pop(); } ops.push(op); return true; } void calremain() { while (!ops.empty()) { rh = ds.top(); ds.pop(); lh = ds.top(); ds.pop(); ds.push(cal(lh, ops.top(), rh)); ops.pop(); } if (ds.size() != 1) { throw string("無效的表示式"); } v = ds.top(); ds.pop(); } double cal(double lh, char op, double rh) { return op == '+' ? lh + rh : op == '-' ? lh - rh : op == '*' ? lh * rh : lh / rh; } bool prior(char o1, char o2) { return (o1 != '+' && o1 != '-' && o2 != '*' && o2 != '/'); } }; int main(int argc, char** argv) { Exp e; try { cout << e.calinput() << endl; } catch (const string& e) { cout << e << endl; } return 0; }