以前寫過一個計算器 發表在此博客中(現在已刪除)
實現的太過於拉雜,今天再看的時候都不好意思了.代碼寫的亂七八糟,拉雜不堪,EvaluateExp()看了一會兒都不明白自己是怎嗎實現的..估計以前看到這代碼的童鞋更加迷茫...嘿嘿.不好意思
昨天寫了一個文章,中綴表達式轉後綴表達式, http://blog.csdn.net/qiuchengw/archive/2008/10/04/3016286.aspx
現在就用這個方式再實現計算器..
表達式一旦轉換成後綴表達式再進行計算就簡單的不得了.遇到一個符號就彈出離他最近的兩個操作數然後進行這個操作符指定的運算就ok了...運算完成後壓棧繼續掃描,依次重複...等到操作符沒有了.所有的運算也就結束了.結果也就出來了...不必再判斷優先級的什麼的了.括號什麼的也一併省略..爽吧.
其實在中綴轉後綴的時候就可以進行計算,表達式掃描完成,計算完成.
把昨天的代碼直接複製..修改..
- opt.push('#');
- int len = exp.length();
- for (int i = 0; i < len;)
- {
- char ch = exp.at(i);
- if (isalnum(ch))
- {
- long num = 0;
- while (isalnum(ch)) //轉換爲整數
- {
- num = (ch-'0') + num*10;
- if (++i >= len)
- break;
- ch = exp.at(i);
- }
- opd.push(num); // 操作數入棧
- }
- else // 操作符就判斷並壓棧
- {
- if (ch == '(') // 左括號直接壓棧
- opt.push(ch);
- else if (ch == ')') // 有括號就彈棧到直到遇到左括號
- {
- ch = opt.top(); // 取得棧頂操作符
- while(ch != '(') // 直到彈出左括號
- {
- OP(ch);
- opt.pop();
- ch = opt.top();
- }
- opt.pop(); // 彈出左括號
- }
- else
- {
- int thisPri = GetPri(ch); // 當前操作符優先級
- char prevOpt = opt.top(); // 上一個操作符
- int prevPri = GetPri(prevOpt); // 上一個操作符優先級
- while (thisPri <= prevPri)
- { //輸出棧中的操作符直到遇到比當前的操作符優先級更低的
- OP(prevOpt);
- opt.pop(); // 輸出後就彈出
- prevOpt = opt.top();
- prevPri = GetPri(prevOpt);
- }
- opt.push(ch); //當前操作符壓棧
- }
- i++;
- }
- }
- char ch = opt.top(); // 表達式掃描完後把棧中剩餘的操作符全部輸出
- while (ch != '#')
- {
- OP(ch);
- opt.pop();
- ch = opt.top();
- }
看到沒有和昨天的代碼幾乎沒有區別,只是在昨天 輸出的地方換成了運算 OP(const char &ch); 完成運算
要明白一點.表達式掃描完成,有可能操作符是壓棧了而未進行運行,(這由具體的表達式決定),因此最後要把操作符棧彈空,完成全部的運算....則此時操作數棧中的唯一的一個數就是運行結果了.
函數OP.實現如下. 參數 ch 是操作符
- void Caculator::OP(const char &ch)
- {
- long RightOperand = opd.top();
- opd.pop();
- long LeftOperand = opd.top(); // 這兩個操作數的順序不能錯
- opd.pop();
- switch(ch)
- {
- case '+':
- LeftOperand += RightOperand;
- break;
- case '-':
- LeftOperand -= RightOperand;
- break;
- case '*':
- LeftOperand *= RightOperand;
- break;
- case '/':
- if (RightOperand == 0) // 除數爲 0
- {
- cout<<"大哥啊,除數爲0了!"<<endl;
- system("pause");
- exit(1);
- }
- else
- LeftOperand /= RightOperand;
- default:
- cout<<"非法操作符!!----:"<<ch<<endl;
- system("pause");
- exit(1);
- }
- opd.push(LeftOperand); // 把求得的值壓入堆棧
- }
opd 是操作數棧,是一個類成員變量 .定義是 stack<long> opd; // 只能進行整數的運算
簡單吧...
關鍵是把表達式轉換成後綴的...
這個實現中未對錶達式是否合法進行判斷,所以非法的表達式會造成程序崩潰....表達式的檢查也可以在掃描的過程中完成的.
我就不寫了..
-------------------------------------------------------
編程羣, c,c++,mfc,java 58698324 歡迎加入
-----------------------------------------------------