做業具體要求連接:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/997android
具體實現功能以下:ios
功能1:支持出題4個數的四則運算題目,全部題目要求做者有能力正確回答。(+10)git
功能2:在功能1的基礎上,支持括號。(+15)web
功能3:限定題目數量,「精美」打印輸出,且要避免重複,最好能輸出到.txt文件中。且對輸入題目數進行限定,題目數量必須是正整數。(+10)算法
功能4:支持分數出題和運算。(不完成此題不倒扣分數)編程
功能5:可把程序改爲GUI版/web版/移植爲android,ios版。dom
這次做業完成是以「結對編程」的形式完成,個人夥伴是劉淑霞,她的博客地址爲:http://www.cnblogs.com/liusx0303/學習
這篇博客主要由以下幾個方面講述:spa
1.每一個功能的重點,難點。.net
2.如何解決重點難點以及收穫
3.運行截圖
4.結對編程體會。
5.合做過程。
6.版本控制。
一,每一個功能的重點,難點
(1)功能一的重點難點
重點難點1:應該選擇什麼樣的輸入,操做數和運算符隨機產生仍是用戶本身輸入,若是隨機產生要如何操做,若是用戶本身輸入要以什麼樣的形式輸入
重點難點2:如何處理四則運算算式。
重點難點3:將輸入的結果與正確結果比較,而後按照要求輸出。
(2)功能二的重點難點
功能二的要求:在功能一要求的基礎上加上有括號的運算。
重點難點:加上有括號的運算,咱們當初分析的時候是用括號匹配的方法,括號優先級最高,優先算括號裏面的算式。
(3)功能三的重點難點
功能三的要求:輸入題目道數,而後輸出四則運算算式以及結果到.txt文件中,注意輸出結果右對齊,與算式有必定的距離。
重點難點:將輸出放到.txt文件中。
(4) 功能四的重點難點
功能四的要求:支持分數運算,不加括號,輸出也是用分數的形式輸出,例如1/2 + 2/3 +1+1=3 1/6。
重點難點:支持分數運算,經過通分來進行運算,結果是最簡分數(幾又幾分之幾)。
二,合做中如何解決重點難點以及收穫
(1)功能一:
由於要支持出題4個數的四則運算題目,針對的用戶是初中生,因此題目難度不能太過於簡單,也不能過於困難。若是題目隨機生成,有太大的隨機性,且容易產生重複,用隨機數自動生成四個數的四則運算也會比較麻煩,考慮的狀況會比較繁多。開始,咱們用random生成兩個數加減乘除的運算,運行成功,實現支持4個數的四則運算的時候,由於要考慮的狀況太過於複雜,寫完就400多行代碼了,且題目易重複。想一想功能一實現就這樣艱難。因而想經過本身輸入出題,而後讓人作的形式實現,且本身出題能夠避免重複。題以字符串的出現,而後對字符串進行處理,而後對題進行計算。
對字符串進行處理,判斷表達式格式是否正確的代碼實現以下:
//檢查表達式格式是否正確 public static boolean checkFormat(String str) { // 校驗是否以「=」結尾 if ('=' != str.charAt(str.length() - 1)) { return false; } // 校驗開頭是否爲數字或者「(」 if (!(isCharNum(str.charAt(0)) || str.charAt(0) == '(')) { return false; } char c; // 校驗 for (int i = 1; i < str.length() - 1; i++) { c = str.charAt(i); if (!isCorrectChar(c)) {// 字符不合法 return false; } if (!(isCharNum(c))) { if (c == '-' || c == '+' || c == '*' || c == '/') { if (c == '-' && str.charAt(i - 1) == '(') {// 1*(-2+3)的狀況 continue; } if (!(isCharNum(str.charAt(i - 1)) || str.charAt(i - 1) == ')')) {// 若符號前一個不是數字或者「)」時 return false; } } if (c == '.') { if (!isCharNum(str.charAt(i - 1)) || !isCharNum(str.charAt(i + 1))) {// 校驗「.」的先後是否位數字 return false; } } } } return isBracketCouple(str);// 校驗括號是否配對 }
(2)功能二:
對於在功能一的基礎上,實現括號。咱們是利用棧實現括號匹配算法。而且使用了map對運算符進行了優先級處理。
符號的優先級處理代碼以下:
public static final Map<Character, Integer> symLvMap = new HashMap<Character, Integer>();// 符號優先級map static { symLvMap.put('=', 0); symLvMap.put('-', 1); symLvMap.put('+', 1); symLvMap.put('*', 2); symLvMap.put('/', 2); symLvMap.put('(', 3); symLvMap.put(')', 1); }
括號匹配的代碼以下:
//校驗括號是否配對 public static boolean isBracketCouple(String str) { LinkedList<Character> stack = new LinkedList<Character>(); for (char c : str.toCharArray()) { if (c == '(') { stack.add(c); } else if (c == ')') { if (stack.isEmpty()) { return false; } stack.removeLast(); } } if (stack.isEmpty()) { return true; } else { return false; } }
(3)功能三:
1.對於輸入題目道數是正整數的判斷,不能是英文(test),負數(-100),浮點數(3.5)。開始是定義了一個int型的變量,而後對變量進行正整數判斷,把負整數去掉。
可是當輸入英文,負數和浮點數的時候,運行的時候報錯了。後來採用字符串的格式進行輸入,而後對字符串的進行在數值範圍的判斷。
判斷輸入題目道數是正整數的代碼以下:
//判斷輸入的題目數是否爲正整數 public boolean judgeInput(String str) { boolean flag=true; for(int j=0;j<str.length();j++) { if(!(str.charAt(j)>=48&&str.charAt(j)<=57)) { System.out.println("題目數量必須是 正整數。"); flag=true; break; } else { flag=false; } } return flag; }
2.將題目和答案輸出到.txt文件中
實現代碼以下:
//將表達式寫入文件answer.txt try { if (!file.exists()) { file.createNewFile(); } FileWriter writer = new FileWriter(file,true); if(true) { results = System.getProperty("line.separator")+results; } writer.write(results); writer.flush(); writer.close(); } catch (IOException ex) { ex.printStackTrace(); }
(4)功能四:
方法是先求出兩個分數分母的最小公倍數,通分後,再對兩個分子的加減乘除,最後約簡結果分數的分子和分母,即用分子分母的最大公約數分別除分子和分母。再按順序輸入分子和分母,在控制檯上輸出其運算結果。
求最大公約數的代碼以下:
static int gcd(int m,int n)
{ int t,r;//展轉相除法 if(m < n) { t = m; m = n; n = t; } while(n != 0) { r = m%n; m = n; n = r; } return m; }
求最小公倍數代碼以下:
static int lcm(int m,int n)
{ int i = gcd( m,n); int j = (m/i)*(n/i)*i; return j; }
收穫:
1.在制定代碼規範的時候,由於咱們都有本身的習慣,因此在制定規則時討論了較長時間,可是彼此爲對方考慮,都各自讓步,最終制定了兩我的都能接受的代碼風格規範。這告訴咱們,要多爲對方考慮一點,這樣才能使合做更愉快,後面實現的過程當中也證實了這一點。
2.在考慮實現出題的時候,我和霞都不約而同的用隨機數生成出題。以爲可簡單了,認爲一兩個小時就能完成功能一,開始實現起來兩個數的加減乘除很快就完成了,而後按照老師要求要完成四個數的加減乘除,實現起來狀況就很複雜了,咱們完成一個demo的時候就差很少500行代碼了,花費了3個多小時,而且有出題重複的狀況。後來就一塊兒討論用本身出題的方式解決,能夠避免重複,而且能夠控制難度。實現的過程,咱們讓結果返回double,由於除法確定會有小數的出現。在一塊兒討論實現的過程當中,知道了不要把一個問題看得太簡單,否則容易眼高手低,要明白需求,再開始作事。
3.在對輸入題目以字符串的形式寫表達式時,要對輸入的表達式作各類判斷,否則表達式會出錯,操做數是否是數字,操做數是否是「+,-,*,/」,最後是否是以等號結尾。一我的老是會疏忽不少小細節,幸運的是,我和霞結對編程,總能考慮到對方疏忽的一些小問題。
4.在結對編程的過程當中,一我的在編,另一我的在旁邊盯着,老是可以及時提醒對方觸犯的代碼規範和犯的語法錯誤,相互批評,指導,和交流,比一我的編程好玩多了,編程速度雖然沒有一我的快,可是兩我的編程的質量更高,錯誤更少。
5.功能3將結果輸出到.txt文件中,運行輸入表達式的時候,打開.txt文件一看結果都在,覺得本身成功了,可是可開心了,而後霞察覺文件的表達式不少,且有重複,咱們恍然大悟,知道本身原始數據沒有清空,而後兩我的尋找解決對策,後來決定在輸入題目語句後面將.txt賦空值,兩我的一塊兒發現和解決問題的過程真是很nice。
三,運行截圖
功能1,2截圖
功能3截圖:
四,結對編程體會
結對編程以前,我並無發現結對編程的好處,但在共同完成做業的時候,切身感覺到結對編程的好處。兩人合做的過程,是一段「美好且痛苦又幸福」的體驗。
在四個功能的實現過程當中,咱們碰見了不少沒有想到的困難。在碰見一個難點的時候,或者運行時出錯的時候,兩我的一塊兒想辦法解決,兩我的雖然都有不同的想法,可是都是爲了解決同一個問題,當誰的辦法可以解決問題的時候,咱們都特別開心。完成做業的同時,我得到了知識,也從對方的身上學到了不少,學習能力和思惟方式都獲得了進步,發現結對編程會使兩我的加在一塊兒,會達到1+1>2的效果。
五,合做過程
咱們結對編程是在軟件所220完成,附上咱們兩人結對編程的照片。
六,版本控制