1. 程式人生 > >C++實現任意表達式求值(棧)

C++實現任意表達式求值(棧)

今天花了大概四個小時時間,用棧(stack)實現了任意表達式的值計算的問題。

C++ 比 C 好的一點就是,C++ 的STL定義了大量的資料型別和演算法,相比於 C 更加視覺化。

實現這個的基本思路很簡單:分成兩部分完成。兩個主要函式:

string shorten(string m) 把 string m 由中綴式變為右綴式,double calculate(string s) 計算右綴式的表示式值。

數字寫入右綴式m很簡單,不過別忘了用個符號把數字分開。我選擇的是$。

比較難的地方是shorten函式,分析怎樣把 string m 變為右綴式。可能的計算有這麼幾種:+,-,*,/,()。於是我通過列表的方式來分析:

+|-*|/(空

+|-m+=cm+=cpushpush

*|/pushm+=cpushpush

(pushpushpushpush

)m+=cm+=cm+=cXXXX(XXXX表示不可能發生的情況)

豎行是操作符,橫行是對應每一個豎行可能遇到的情況,代表棧為空。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的地方)加上輸出語句,這樣可以判斷程式是否執行過了這些關鍵地方。

還有,順便提一下,模組化的思想真的很重要,不然在進行一些小改動時,那種牽一髮而動全身的感覺很焦慮、很凌亂。

相關推薦

C++實現任意表達

今天花了大概四個小時時間,用棧(stack)實現了“任意表達式的值計算”的問題。 C++ 比 C 好的一點就是,C++ 的STL定義了大量的資料型別和演算法,相比於 C 更加視覺化。 實現這個的基本思路很簡單:分成兩部分完成。兩個主要函式: string shorten(

表達二叉樹方法/C++語言描述

urn sse 二叉 返回 新的 求值 calc ken node   二叉樹方法求值對運算數處理的方法與棧方法求值不太相同,除了將字符串中的運算數轉換為浮點類型外,還需要生成新的節點: 1 void Calculator::dealWithNumber(char *&

奇怪的表達 java實現

name 所在 cas 生活 div img num rar java 題目參考:http://blog.csdn.net/fuxuemingzhu/article/details/68484749 問題描述; 題目描述: 常規的表達式求值,我們都會根據計算的優先級來計算。

表達數據結構書上的應用之中的一個

ble code 進行 。。 bre atoi 麻煩 scanf ios 主要內容:表達式求值。提交nyoj通過。。。 思路:主要就是一個開兩個棧,然後一個操作符棧。一個操作數棧。。 我的代碼例如以下(比較簡潔): /***** Author Gery *

C++後綴表達

若是 ascii 思想 mes else == cout 區分 tca #include <iostream> #include <stack> using namespace std; int cal(int a,int b,char c){

表達NOIP2013 普及組第二題

tool ber 算術表達式 class 整數 括號 給定 編程 解釋 描述 給定一個只包含加法和乘法的算術表達式,請你編程計算表達式的值。 格式 輸入格式 輸入僅有一行,為需要你計算的表達式,表達式中只包含數字、加法運算符“+”和乘法運算符“*”,且沒有括號,所有參與運算

表達無括號

code ESS truct alc expr 計算 利用 一個 一次 對於自然數的表達式求值,操作有加、減、乘、除和冪運算,分別用+,-, *, /,^來表示,為方便運算,加入#運算符,其運算優先級最低,由於運算符優先級不一樣,可以利用棧實現此操作。 算法思想 (1)規定

nyoj 35-表達(stack, 的應用)

input cep code cal 比較 else submit cst 保留 35-表達式求值 內存限制:64MB 時間限制:3000ms Special Judge: No

C++基礎知識--左--邏輯表達優化--逗號運算符與表示式

-- 沒有 加減乘除 p s 能夠 表示 操作 逗號 因此 一、C++左值右值概念   左值:c++將變量名代表的單元稱為左值,而將變量的值稱為右值,左值必須是內存中可以訪問且可以合法修改的對象,因此只能是變量名,而不能是常量或表達式。即左值可以尋址。   右值:將變量的值

網易2017春招筆試真題編程題集合8——奇怪的表達

next ann new switch 運算 ase 自己 lin pri 常規的表達式求值,我們都會根據計算的優先級來計算。比如*/的優先級就高於+-。但是小易所生活的世界的表達式規則很簡單,從左往右依次計算即可,而且小易所在的世界沒有除法,意味著表達式中沒有/,只有(+

表達的遞歸實現,順便復習編譯原理

float div 漏洞 git -1 mage res 功能 做的   本次試驗的內容是四則運算——或者說表達式求值,我對此並不陌生,也曾用不同語言分別實現過,但都是利用“棧”實現的相關功能,對於這一問題的遞歸實現我還是第一次嘗試。兩種實現方式各有優劣,這裏不再展開。  

7-21 前綴表達25 分

str 掃描 元素 class pos 求值 gpo blog body 前綴表達式的計算機求值:從右至左掃描表達式,遇到數字時,將數字壓入堆棧,遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(棧頂元素 op 次頂元素),並將結果入棧;重復上述過程直到表達式最左

使用實現表達

操作數棧 整數 test 不為 彈出 字符串 ios 優先 its 看書學了一晚上這個內容,終於實現了 分為三個步驟:   0. 檢查輸入是否有誤(因為輸入其他的非預期字符,程序就會崩潰,我就試著加了一個檢查輸入的函數)   1. 先將正常的中綴表達式轉換為後綴表達式

南陽 oj 表達 題目35 數據結構 NYO題目鏈接

pro lin sum tof line 就會 南陽 scan art ?? 建議不會的看別人的代碼自己在之上模擬一遍,僅僅要耐心模擬就會做出來 題目鏈接:http://acm.nyist.net/JudgeOnline/problem.php?pid=35 #in

表達

i++ ont string amp nbsp 運算符 讀取數據 字符 等等 Problem Description Dr.Kong設計的機器人卡多掌握了加減法運算以後,近期又學會了一些簡單的函數求值,比方,它知道函數min(20,23)的值是20 ,add(10,98

POJ 2106 Boolean Expression 表達

ret get 題意 col pair 下一個 pop spa def 題意:給出布爾表達式求值? 插入數字時,若有!則更新.遇到右括號彈出知道左括號,左括號前有‘!‘則更新, 其余和中綴表達式一樣,遇到下一個運算符時 若操作棧中運算符優先級大,則先算. #include

應用二(表達)

表達式求值 分享 問題 3.2 依次 滿足 pre index 拼接 問題;設計一個程序,演示用算符優先法對算術表達式求值的過程。利用算符優先關系,實現對算術四則混合運算表達式的求值。(1)輸入的形式:表達式,例如3+2*6-4 包含的運算符只能有‘+‘ 、‘-‘

Dijkstra的雙算術表達算法

pre ble alua nbsp 算術 如果 ack 壓入 rar 1 public static double evaluate(String inStr) { 2 Stack<String> ops = new Sta

表達NOIP2011 普及組第四題

兩種 可能 完成 表示 請問 字符 syn http 數字0 描述 對於 1 位二進制變量定義兩種運算:運算的優先級是:1. 先計算括號內的,再計算括號外的。2. “×”運算優先於“⊕”運算,即計算表達式時,先計算×運算,再計算⊕運算。 例如:計算表達式A⊕B × C 時,

洛谷 P1981 表達

tdi 上一個 div bad open 算術 reg string font P1981 表達式求值 題目描述 給定一個只包含加法和乘法的算術表達式,請你編程計算表達式的值。 輸入輸出格式 輸入格式: 輸入文件為 expr.