所謂表示式求值,就是寫乙個微型計算器。例如輸入:(1+9)* 2 / 2 - 1,輸出9。對於這樣的問題,我們一般利用棧,模擬數**算來完成。為了簡化問題,在繼續下面的分析之前,先在此作個約定:本文只討論+-*/()
基本的四則運算,另外不對意外出現的符號(例如^)和不符合規範的數學表示式(例如2*-1)做異常處理。
我們用乙個字元陣列(即char s[1000])來儲存數學表示式,定義乙個全域性變數g_pos表示s[ ]的下標,下標從0開始。首先我們定義兩個棧,optr和opnd,分別儲存運算子和運算數,遇到運算數直接放進opnd;遇到運算子,分四種情況:
(1)遇到負號;
(2)遇到右括號;
(3)遇到左括號;
(4)遇到+-*/;
前三種情況容易理解,這裡就談下第四種情況。我們都知道四則運算是遵循先乘除再加減的(例如2*3+1),因此對於每個運算子,我們都要和optr的棧頂符號等級比較,如果這個符號的等級比optr棧頂符號等級高,什麼也不做,直接放進棧;如果小於等於,就需要把opnd的棧頂兩個數字抽出來,進行計算。這裡有個問題,在遇到第乙個運算子時,此時optr為空,而我們又需要與optr棧頂運算子比較等級,這時候怎麼辦?為了解決這個問題,我們在初始化optr的時候,放進乙個#,設定其等級為最低。
看到這裡你可能還存有乙個疑問,如何判定符號-時負號還是減號?例如-1+2 和 5-1+2。
分析發現,出現負號只有兩種情況:
(1)左邊是左括號,例如(-1+5*3);
(2)字串的第乙個字元,例如-5*6-1。
為了方便**書寫,若出現負號,就在運算數棧加入乙個數字0(這也就是下面**裡出現bool值is_minus的原因),即轉化一下表示式,例如-1+2轉化為0-1+2。
/**
* * author 劉毅(limer)
* date 2017-02-24
* mode c++
*/#include
#include
#include
#include
#include
using
namespace
std;
char s[1000];
int g_pos;//字元陣列的下標
/* 字元轉數字 */
double translation(int & pos)
if (s[pos] == '.')
}return integer + remainder;
}/* 返回運算子級別 */
int getlevel(char ch);}
/* 對兩個數進行運算 */
double operate(double a1, char op, double a2);}
/* 利用兩個棧進行模擬計算 */
double compute()
//2. 是右括號 )
else
if (s[g_pos] == ')')
optr.pop(); //刪除'('
}//3. 數字
else
if (s[g_pos] >= '0' && s[g_pos] <= '9')
//4. ( 左括號
else
if (s[g_pos] == '(')
//5. + - * / 四種
else
optr.push(s[g_pos]);
g_pos++;}}
while (optr.top() != '#')
return opnd.top();
}int main()
**我的個人部落格:
表示式求值
程式的說明見清華大學出版社 資料結構 c語言版 include include define stack init size 40 define stackincrement 20 define ok 1 define false 0 typedef structs stack typedef st...
表示式求值
既然是表示式求值,自然需要在記憶體中儲存計算結果以及中間值。在 用c語言寫直譯器 一 中提過 變數要求是若型別,而 c 語言中的 view plaincopy to clipboardprint?in basic io.h define memery size 26 typedef enum var...
表示式求值
寫了乙個下午,各種糾結,各種問,終於搞明白了。但是自己還是想出來的一點東西的。很爽歪歪的,哈哈。先貼第一次的 include include include include include includeusing namespace std char data 7 7 int sign char ...