前記
女朋友說:“高數好難,看我最近挺辛苦的,你送我一個禮物給我,讓我開心一下吧。你猜猜我想要什麼。”
我想了半天,從書到鞋子到電子產品最後到生活用品,感覺什麼都不缺,然後和她說:“你說要送啥,我就送啥吧”
她堅持要我猜:“不行,你一定要說一個禮物,並且這個禮物要你親手做的”
於是,我認真了起來,拿起手機,上淘寶逛了幾分鐘,但還是沒能想出來缺點什麼,最後實在沒辦法了:“這樣吧,如果你實在想讓我送東西,那我幫你寫一個計算器吧”
文章的標題只是噱頭,作爲熱愛交流技術的學習者,我們應該腳踏實地,所以我會保證文章的內容都是乾貨!
設計原理
根據輸入中綴算術表達式,利用棧幀結構,實現轉換成後綴表達式輸出,再對該後綴表達式求值計算輸出結果。最終設計出一個計算器。
適用範圍:+ - * / % 整數 小數 負數
設計思想
邏輯設計
- 建立兩個棧,棧stack和棧Node
- stack棧用於儲存字符數組,以字符形式存儲中綴表達式的元素。
- Node棧用於儲存雙精度浮點型的數組,用於存儲中綴表達式的元素值和各元素運算操作後的值。
- 設計以下兩個函數和相應的入棧出棧操作。
函數名 | 參數 | 作用 |
---|---|---|
Mtf_function() | char *p1,char *mid,char *final | 用於中綴轉後綴 |
Caculate() | stack *M,char *final | 計算後綴表達式值 |
Mtf_function()函數設計
(棧爲stack)
(1)如果遇到操作數,直接將其輸出。
(2)如果遇到操作符,則我們將其放入到棧中,遇到左括號時將其放入棧中。
(3)如果遇到一個右括號,則將棧元素彈出,將彈出的操作符輸出直到遇到左括號爲止。注意,左括號只彈出並不輸出。
(4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,從棧中彈出元素直到遇到發現更低優先級的元素(或者棧爲空)爲止。彈出完這些元素後,纔將遇到的操作符壓入到棧中。有一點需要注意,只有在遇到" ) “的情況下我們才彈出” ( “,其他情況我們都不會彈出” ( "。
(5)如果讀到了輸入的末尾,則將棧中所有元素依次彈出。
Caculate()函數設計
(棧爲Node棧)
1)遍歷表達式,遇到的數字首先放入棧中
2)接着讀到運算操作符如“+”,則彈出棧頂元素和下一個元素,執行相應的運算操作,並將計算結果壓入到棧中。
3)讀到下一個元素,將其直接放入棧中。
4)讀到下一個元素如“”,彈出棧頂元素和下一個元素,執行85,執行相應的運算操作,並將計算結果壓入到棧中……以此類推。最後求的值存在棧頂上。
對於小數點的處理算法
- 原理:先將小數化爲整數,然後除以10的相應權重。建立一個循環,令小數的值sum初始化0,10的相應權重j=0,判斷小數點後的字符數組元素是否屬於0-9,若是,將小數點後移,sum = sum * 10 + 元素所對應的值,10的相應權重j加一,直到下一個元素不屬於0-9。
- 具體算法如下
對於負號的處理
負號的出現位置是字符數組的第一個元素或左括號後面的元素。爲避免與減號“-”混淆,通過判斷字符數組的第一個元素或左括號後面的元素是否爲“-”找出負號,並替換成“M”。中綴轉後綴時若元素爲“M”則輸出“-”。計算後綴的值時若元素爲“M”,則之後的元素值(包括小數)轉換爲相反數後進行操作。
主程序流程圖和各模塊調用關係
物理設計
-
基於在內存開闢連續存儲空間數組實現,C聲明定義字符棧幀結構,包含字符數組,用於中綴轉後綴表達式
-
相應的節點的含義
-
進出棧操作
-
C聲明定義整型棧幀結構,包含整型數組,用於計算後綴表達式求值。
-
相應的節點的含義
-
進出棧操作
測試
- 測試用例
- 測試結果
源代碼(帶註釋)
代碼寫的是C語言版,後續有時間會補上java版
github代碼鏈接