今天花了大概四個小時時間,用棧(stack)實現了「任意表示式的值計算」的問題。
c++ 比 c 好的一點就是,c++ 的stl定義了大量的資料型別和演算法,相比於 c 更加視覺化。
實現這個的基本思路很簡單:分成兩部分完成。兩個主要函式:
string shorten(string m) 把 string m 由中綴式變為右綴式,double calculate(string s) 計算右綴式的表示式值。
數字寫入右綴式m很簡單,不過別忘了用個符號把數字分開。我選擇的是$。
比較難的地方是shorten函式,分析怎樣把 string m 變為右綴式。可能的計算有這麼幾種:+,-,*,/,()。於是我通過列表的方式來分析:
+|- *|/ ( 空
+|- m+=c m+=c push push
*|/ push m+=c push push
( push push push push
) m+=c m+=c m+=c ***x (***x表示不可能發生的情況)
豎行是操作符,橫行是對應每乙個豎行可能遇到的情況,「空」代表棧為空。push表示入棧,m+=c表示元素出棧,寫入表示式(右綴式)m。
其實列表的原則挺簡單的:
1. 把「(」看做開闢一次新的棧(從「(」開始算,忽視之前的元素,直到「)」被取消);
2. 元素a遇到相同或更高優先順序的,棧頂元素c出棧,給右綴表示式m;再次對比;直到遇到更高優先順序的,元素a入棧;
3. 「)」出現的時候,之前所有元素依次出棧,寫入m,直到「(」;
4. 在數字都加入右綴表示式之後,棧中所有元素依次出棧,寫入m,直到棧為空。
關鍵就是 2、3條,我花了好久才總結出來的規律。順便說下,列表法真的是很好的分析問題的方式,不重不漏還簡練。
然後進行右綴表示式的計算,這個比較簡單:數字依次入棧,遇到操作符後對棧頂的兩個元素進行順序操作(倒數第二個 +-*/ 倒數第乙個),然後把這兩個元素換成新的結果。如此迴圈即可。
原題目要求用int即可,但用int必然會造成除法的不精確。所以考慮用double型別,並且在讀取的時候可以支援小數點。記得是有直接轉化的函式,但忘了,所以自己寫啦,命名為 str2double(string s)。有個dec變數決定計算整數部分還是小數部分,詳細可參見函式。
這次實踐這個程式還有個小收穫,是在我無數次的debug之中:可以在某些關鍵步驟(比較容易發現bug的地方)加上輸出語句,這樣可以判斷程式是否執行過了這些關鍵地方。
還有,順便提一下,「模組化」的思想真的很重要,不然在進行一些小改動時,那種「牽一髮而動全身」的感覺很焦慮、很凌亂。
#include #include #include #include using namespace std;
bool isone(char c)
bool istwo(char c)
string shorten(string m){
stacks;
string sur;
int i;
char w;
sur;
for(i=0;inum;
string temp;
int i;
for(i=0;i> mid;
sur = shorten(mid);
cout << "successfully executed! the right hand operator expression is: " << endl;
cout << sur << endl;
cout << "the result is: " <
學習部落格 jcbd實現任意表都可以查詢單個案例
就反正用泛型把這個方法改進了下,可以讓表都能查詢了 public t getinstance class clazz,string sql,object args throws exception 這是表示資料庫結果集的資料表 resultset rs ps.executequery 接下去獲取結果...
棧實現表示式求值(C
為了實現用棧計算算數表示式的值,需設定兩個工作棧 用於儲存運算子的棧opter,以及用於儲存運算元及中間結果的棧opval。演算法基本思想如下 1 首先將運算元棧opval設為空棧,而將 作為運算子棧opter的棧底元素,這樣的目的是判斷表示式是否求值完畢。2 依次讀入表示式的每個字元,表示式須以 ...
C語言如何實現任意數相乘
基本思路 用int型陣列num的某一位乘以另外乙個int陣列num1的所有位,然後將值暫時放在int型陣列num2,陣列num從第零位開始乘,直到最後一位,每移動一位,陣列num2裡面的資料更新一次。任意兩個小於100位數相乘,修改max值可實現更大的數相乘 include include defi...