博主從今天起正式開始了研究生的學習生活,下午在上到現代軟件工程這門課的時候,老師留了個“大作業”讓我們體會軟件工程。。。說起來有點不好意思,博主雖然是某985高校軟件學院的,但是感覺學校的教學水平。。。還是遠比不上那幾所知名的學校,甚至我覺得像杭州電子科技大學這樣的有專長的學校,那樣的培養機制(應該有很多人刷過杭電的acm吧),培養出的學生的編程能力反而更強。
書歸正傳,“大作業”的需求是給小學生寫一個簡單的四則運算表達式計算器。我一看,臥槽,大二自學android的時候寫過一個類似的傻瓜APP啊,可惜當時不知道要將自己學到的知識進行整理和總結,也沒有把源碼留下來。不過好像老爸的手機裏還有那個應用哈哈,當時還顯擺呢。。。
其實四則運算的實現在大三學編譯原理的時候專門有提到過啊,只不過時間一長就全還給老師了。上網搜實現的時候發現了這篇博客,和編譯原理書上講的實現思路一模一樣。趕緊記下來以後留用。
-------------------------------------------------------原文分割--------------------------------------------------------------------------
本文實例講述了java實現任意四則運算表達式求值算法。分享給大家供大家參考。具體分析如下:
該程序用於計算任意四則運算表達式。如 4 * ( 10 + 2 ) + 1 的結果應該爲 49。
算法說明:
1. 首先定義運算符優先級。我們用一個map來保存優先級表
Map<String, Map<String, String>>
/**
* 查表得到op1和op2的優先級
* @param op1 運算符1
* @param op2 運算符2
* @return ">", "<" 或 "="
*/
public String priority(String op1, String op2) {
return priorityMap.get(op1).get(op2);
}
2. 掃描表達式字符串,每次讀入一個 token 進行處理。
使用兩個輔助棧:optStack用於保存運算符,numStack用於保存操作數. 我們用 '#' 作爲表達式的起始和結果標誌符。
讀入一個token,如果它是數字,則壓入numStack棧中;
如果它是運算符,則取出optStack棧的棧頂元素A,將 A 與 token 進行優先級比較。
如果 A < token,則將 token 壓入optStack棧。
如果 A = token,則說明 token和A是一對括號,此時將optStack棧的棧頂元素彈出。
如果 A > token,則從numStack中彈出2個操作數,從optStack中彈出1個運算符,並計算結果。
當optStrack棧爲空時(即棧頂元素爲 '#'),numStack棧的棧頂元素即爲表達式的值。
算法實現:
/**
* 算術表達式求值。
* 3 + 4 * 12 結果爲51
* @author whf
*
*/
public class EvaluateExpression {
// 運算符優先級關係表
private Map<String, Map<String, String>> priorityMap = new HashMap<String, Map<String, String>>();
private LinkedStack<String> optStack = new LinkedStack<String>();
// 運算符棧
private LinkedStack<Double> numStack = new LinkedStack<Double>();
// 操作數棧
/**
* 計算表達式
* @param exp 四則運算表達式, 每個符號必須以空格分隔
* @return
*/
public double calcualte(String exp) {
StringTokenizer st = new StringTokenizer(exp);
while (st.hasMoreTokens()) {
String token = st.nextToken();
process(token);
}
return numStack.pop();
}
/**
* 讀入一個符號串。
* 如果是數字,則壓入numStack
* 如果是運算符,則將optStack棧頂元素與該運算符進行優先級比較
* 如果棧頂元素優先級低,則將運算符壓入optStack棧,如果相同,則彈出左括號,如果高,則取出2個數字,取出一個運算符執行計算,然後將結果壓入numStack棧中
* @param token
*/
private void process(String token) {
while (false == "#".equals(optStack.getTop()) || false == token.equals("#")) {
// token is numeric
if (true == isNumber(token)) {
numStack.push(Double.parseDouble(token));
break;
// token is operator
} else {
String priority = priority(optStack.getTop(), token);
if ("<".equals(priority)) {
optStack.push(token);
break;
} else if ("=".equals(priority)) {
optStack.pop();
break;
} else {
double res = calculate(optStack.pop(), numStack.pop(), numStack.pop());
numStack.push(res);
}
}
}
}
/**
* 執行四則運算
* @param opt
* @param n1
* @param n2
* @return
*/
private double calculate(String opt, double n1, double n2) {
if ("+".equals(opt)) {
return n2 + n1;
} else if ("-".equals(opt)) {
return n2 - n1;
} else if ("*".equals(opt)) {
return n2 * n1;
} else if ("/".equals(opt)) {
return n2 / n1;
} else {
throw new RuntimeException("unsupported operator:" + opt);
}
}
/**
* 檢查一個String是否爲數字
* @param token
* @return
*/
private boolean isNumber(String token) {
int LEN = token.length();
for (int ix = 0 ; ix < LEN ; ++ix) {
char ch = token.charAt(ix);
// 跳過小數點
if (ch == '.') {
continue;
}
if (false == isNumber(ch)) {
return false;
}
}
return true;
}
/**
* 檢查一個字符是否爲數字
* @param ch
* @return
*/
private boolean isNumber(char ch) {
if (ch >= '0' && ch <= '9') {
return true;
}
return false;
}
/**
* 查表得到op1和op2的優先級
* @param op1 運算符1
* @param op2 運算符2
* @return ">", "<" 或 "="
*/
public String priority(String op1, String op2) {
return priorityMap.get(op1).get(op2);
}
/**
* 構造方法,初始化優先級表
*/
public EvaluateExpression() {
// initialize stack
optStack.push("#");
// initialize priority table
// +
Map<String, String> subMap = new HashMap<String, String>();
subMap.put("+", ">");
subMap.put("-", ">");
subMap.put("*", "<");
subMap.put("/", "<");
subMap.put("(", "<");
subMap.put(")", ">");
subMap.put("#", ">");
priorityMap.put("+", subMap);
// -
subMap = new HashMap<String, String>();
subMap.put("+", ">");
subMap.put("-", ">");
subMap.put("*", "<");
subMap.put("/", "<");
subMap.put("(", "<");
subMap.put(")", ">");
subMap.put("#", ">");
priorityMap.put("-", subMap);
// *
subMap = new HashMap<String, String>();
subMap.put("+", ">");
subMap.put("-", ">");
subMap.put("*", ">");
subMap.put("/", ">");
subMap.put("(", "<");
subMap.put(")", ">");
subMap.put("#", ">");
priorityMap.put("*", subMap);
// /
subMap = new HashMap<String, String>();
subMap.put("+", ">");
subMap.put("-", ">");
subMap.put("*", ">");
subMap.put("/", ">");
subMap.put("(", "<");
subMap.put(")", ">");
subMap.put("#", ">");
priorityMap.put("/", subMap);
// (
subMap = new HashMap<String, String>();
subMap.put("+", "<");
subMap.put("-", "<");
subMap.put("*", "<");
subMap.put("/", "<");
subMap.put("(", "<");
subMap.put(")", "=");
//subMap.put("#", ">");
priorityMap.put("(", subMap);
// )
subMap = new HashMap<String, String>();
subMap.put("+", ">");
subMap.put("-", ">");
subMap.put("*", ">");
subMap.put("/", ">");
//subMap.put("(", "<");
subMap.put(")", ">");
subMap.put("#", ">");
priorityMap.put(")", subMap);
// #
subMap = new HashMap<String, String>();
subMap.put("+", "<");
subMap.put("-", "<");
subMap.put("*", "<");
subMap.put("/", "<");
subMap.put("(", "<");
//subMap.put(")", ">");
subMap.put("#", "=");
priorityMap.put("#", subMap);
}
}
程序測試:
String exp = "4 * ( 10 + 2 ) + 1 #";
EvaluateExpression ee = new EvaluateExpression();
out.println(ee.calcualte(exp));
運行結果爲 49。
希望本文所述對大家的C++程序設計有所幫助。
喜歡的話可以掃描左側二維碼隨意打賞哈~支付寶微信都可以,歡迎看看我的其他文章~