MathExamLv2——周世元211606348,許燕婷211606338

結對編程

211606348 周世元 211606338 許燕婷

1、預估與實際

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 100
• Estimate • 估計這個任務須要多少時間 10 10
Development 開發
• Analysis • 需求分析 (包括學習新技術) 30 30
• Design Spec • 生成設計文檔 30 70
• Design Review • 設計複審 10 10
• Coding Standard • 代碼規範 (爲目前的開發制定合適的規範) 10 20
• Design • 具體設計 20 20
• Coding • 具體編碼 500 300
• Code Review • 代碼複審 20 100
• Test • 測試(自我測試,修改代碼,提交修改) 200 300
Reporting 報告
• Test Repor • 測試報告 40 100
• Size Measurement • 計算工做量 15 10
• Postmortem & Process Improvement Plan • 過後總結, 並提出過程改進計劃 50 100
合計 1170

2、需求分析

小學一年級數學

· 數學一年級下學期 第五單元測試題
· 兩位數減兩位數 不退位減
· 兩位數減兩位數(退位減)
· 兩位數加兩位數(進位加)
· 兩位數加兩位數(不進位加)
· 兩位數減一位數(退位)
· 兩位數加一位數(進位)
· 兩位數減一位數、整十數(不退位)
· 小括號
· 兩位數加一位數、整十數(不進位)
· 整十數加、減整十數
· 整十數加、減整十數java

小學二年級數學

· 萬之內的加法和減法
· 求比一個數多幾的應用題
· 不連續進位加
· 連續進位加
· 加法的驗算
· 萬之內的加法和減法算法

我經過百度的方式瞭解到,小學三年級數學有以下的幾個特色:

  • 特色
    • 只有正整數運算
    • 沒學負數,不會小數運算
    • 只會運算1000之內的數
    • 小學二年級除了要知足一年級的要求,還要算僅限於九九乘法表的乘法與除法
    • 小學三年級進行四則混合運算,運算符在2~4個之間,能夠加括號,減法運算的結果不能有負數,除法運算除數不能爲0,不能有餘數。

輸入格式:

  • 程序需從命令行中接收兩個參數 年級 和 題目數量,分別用 -n 和 -grade 表示,這兩個參數的順序不限,當 n 爲 2 或 1 時,分別表明給 2 年級,1 年級出題

輸出格式:

  • 把題目和標準答案寫入out.txt文件,輸出的格式要求
  • 每道題目佔一行
  • 每道題的格式:
    • (1)題號:數字 + 一對英文括號;
    • (2)題目:數字、符號之間空一格;
    • (3)題號與題目之間也須要加一空格,行末不須要加空格。
    • (4)題目和標準答案分開輸出,先輸出全部題目,後輸出全部答案,答案的輸出格式與題目同樣。

通過分析,我認爲,這個程序應當:

  • 可接收2個參數:題目數量、年級
  • 會檢測出各類輸入參數的異常
  • 會根據傳入的年級生成對應需求的題目
  • 最後將題目答案輸出到out.txt文件
  • 採用代碼重構和分而治之的思想。
  • 各部分函數代碼給註釋,有明確的邏輯。
  • 程序運行中、文件輸出後要給明確的提示編程

    3、設計

1. 設計思路

  • 這個程序有2個類,7個函數,功能以下:
  • 主類和內部類
    • 內部類:Node (用來存儲後綴表達式)
  • 主函數
    • 主函數裏調用check()函數排除輸入參數的各類問題
    • 主函數裏判斷當前輸入參數的年級,根據年級執行不一樣的題目生成器
    • 主函數里根據對應的年級調用init3()函數初始化三年級題目和答案
    • 主函數里根據對應的年級調用init1_2()函數初始化一、2年級題目和答案
    • 主函數裏調用OutPutFile()函數將題目和答案輸出到out.txt文件中
  • check()函數用來排除輸入參數的各類問題,函數流程以下:
    • 判斷輸入的參數的長度(只能爲4)
    • 判斷是否用-n 和-grade做爲標識符
    • 取出參數的前導0(相似0000001的狀況)
    • 檢查參數題目數量必須都是數字
    • 檢測年級參數是不是1-3
    • 判斷題目的數量是否爲正整數
  • init3()函數用來生成題目和答案,函數流程以下:
    • 生成3個可變字符串
    • 隨機生成2-4個運算符(必須有2個不一樣)
    • for循環生成題目
    • 隨機在+、-運算符左右邊的數字分別生成2個括號
    • 將隨機生成的題目丟用逆波蘭表達式算出答案並保存
    • 將題目和答案拼接成字符串
  • init1_2()函數用來生成題目和答案,函數流程以下:
    -直接引用1.2年級的題目生成器
  • CalPoland()函數
    • 實現逆波蘭表達式
  • ShuntYardAlgo()函數
    • 實現調度場算法
  • OutPutFile()函數
    • 將題目和答案輸出到out.txt文件
  • 函數流程圖:
  • 算法的關鍵:
    • 判斷輸入的參數是否合法,對於不合法的各類狀況需給予提示
    • 生成帶括號的四則運算的題目是否知足教學大綱的要求

2. 實現方案

寫出具體實現的步驟數組

  • 準備工做:
    • 先在Github上Fork廠庫,並克隆到本地
    • 編寫MathExam.java
    • 在三年級題目的基礎上改進邏輯並增長1.2年級出題功能
    • 重構代碼,並增長註釋
    • 代碼測試
  • 技術關鍵點:
    • 生成帶括號的四則運算
    • 拼接可變字符串
    • 按需求產生隨機數
    • 按需求產生隨機運算符和括號
    • 輸入參數的各類判斷
    • 逆波蘭表達式
    • 調度場算法
    • 文件io流

4、編碼

編碼過程:

  • main函數:
    • 調用check()函數判斷輸入參數是否有異常
    • 沒有異常的狀況下判斷年級
    • 若是是1.2年級就將4個當前輸入的參數,刪除2個標識符其他封裝在一個數組中傳給init1_2()函數中進行1.2年級題目初始化.並調用outPutFile()函數輸出out.txt文件。
    • 若是是3年級就直接調用init3()函數中進行3年級題目初始化.並調用outPutFile()函數輸出out.txt文件。
  • init3()函數:
    • 建立1個可變字符串str1用於拼接答案
    • 建立1個for循環
      • 循環內生成2個隨機數
      • 用str拼接題目
      • 用條件判斷語句判斷當前的運算符並算出答案
      • str1拼接答案
      • str1拼接到str尾部
  • init1_2()函數:
    • 和做業1的init()函數功能相同

遇到的問題:

  • 帶括號的四則運算如何生成

查閱別人的博客並無找到帶括號的四則運算。而後我就先試着生成隨機的沒有括號的四則運算,完成任務後我再考慮如何加上括號,設計了很久終於加了一些if判斷而且生成了帶括號的四則運算了。app

  • 如何算出題目的答案

1. 調試日誌

  • ShuntYardAlgo()函數,字符串傳入報數組躍界,字符串轉字符傳入不會報錯。

解決:這是我本次開發浪費最多時間調試的bug。緣由知道後其實很簡單,字符串轉字符我沒用str.toCharrArrays()這個方法,而是本身開闢一個char[100],默認溫馨化是0。當遍歷字符串末尾的時候天然就躍界報錯了。dom

  • 如何生成帶括號的四則運算

解決:當時在這個地方也困擾了我好久,一步步的增長判斷,隨機安排括號,因爲很差控制括號出現的位置我調試了好久才生成帶括號的四則運算函數

2. 關鍵代碼

public static StringBuffer init3(String[] args) throws Exception {
        int m = 1;
        int l = 1;
        String str = null;
        // 生成2個字符串用於拼接題目和答案
        StringBuffer strbuf = new StringBuffer();
        StringBuffer strbuf1 = new StringBuffer();
        StringBuffer strbuf2 = new StringBuffer();
        // random用於隨機生成題目中的操做數
        int random = 0;
        // int flag=5;
        // 將四種運算符放入數組
        String[] strop = { "+", "-", "x", "÷" };
        // 將隨機生成的2-4個運算符存入ostr數組
        String[] ostr = new String[4];
        int w = Integer.valueOf(args[args[0].equals("-n") ? 1 : 3]);
        for (int i = 0; i < w; i++) {
            // 隨機生成的2-3個運算符
            int operator = (int) (Math.random() * 3) + 2;
            int k = 0;
            // 隨機生成運算符號(至少有2種不一樣運算符號)
            for (int j = 0; j < operator; j++) {
                k = (int) (Math.random() * 4);
                ostr[j] = strop[k];
                if (operator == 2 && j == 1) {
                    // 控制在只有2個運算符的狀況下2個運算符號必定不一樣
                    while (ostr[0] == ostr[1]) {
                        k = (int) (Math.random() * 4);
                        ostr[0] = strop[k];
                    }
                }
            }
            int flag1 = 1;
            int flag = 1;
            for (int j = 0; j < operator + 1; j++) {
                if (operator == 4)
                    // 若是運算符有+-就自動生成括號運算符
                    if (j < operator && (ostr[j].equals("+") || ostr[j].equals("-")) && flag == 1) {
                        strbuf.append("( ");
                        flag = 0;// 判斷是否加了左括號0表明已近加了
                        flag1 = 0;// 判斷是否能夠加右括號了
                    }
                random = (int) (Math.random() * 101);
                if (j == operator) {
                    // 最後一個隨機數的末尾不加空格
                    if (flag == 0 && flag1 == 1) {
                        strbuf.append(random + " )");
                        flag1 = 0;
                        flag = 100;
                    } else {
                        strbuf.append(random);
                        if (flag == 0) {
                            // 在最後一個數後面加上右括號
                            flag1 = 1;
                        }
                    }
                } else {
                    if (flag == 0 && flag1 == 1) {
                        strbuf.append(random + " )" + " ");
                        flag1 = 0;
                        flag = 100;
                    } else {
                        strbuf.append(random + " ");
                        if (flag == 0) {
                            // 在下一次循環當中能夠加入右括號
                            flag1 = 1;
                        }
                    }
                }
                if (j < operator)
                    strbuf.append(ostr[j] + " ");
            }
            l = 1;
            // 從新初始化數組
            ostr = new String[4];
            //
            MathExam mathExam = new MathExam();
            mathExam.Init();
            str = strbuf.toString();

            char[] charArray = str.toCharArray();
            double shuntYardAlgo = mathExam.ShuntYardAlgo(charArray);
            String vf = String.valueOf(shuntYardAlgo);
            boolean matches = vf.matches("\\d+.[0]?");
            if (matches) {

                // strbuf2用於拼接題目
                strbuf2.append("(" + m + ")" + " " + strbuf + "\r\n");
                // strbuf1用於拼接答案
                strbuf1.append("(" + m + ")" + " " + strbuf + " " + "=" + " " + (int) shuntYardAlgo + "\r\n");
                m++;
                l = 0;
            }
            strbuf = new StringBuffer();
            if (l != 0)
                i--;
        }
        strbuf2.append("\r\n");
        strbuf2.append(strbuf1);
        return strbuf2;
    }

3. 代碼規範

請給出本次實驗使用的代碼規範:單元測試

  • 第一條代碼中的命名均不如下劃線或美圓符號開始,也不一下劃線或美圓符號結束。
  • 第二條代碼中的命名嚴禁使用拼音與英文混合的方式,更不容許直接使用中文的方式。
  • 第三條類名使用UpperCamelCase風格,可是如下情形例外:DO / DTO / VO / AO / PO 等。
  • 第四條方法名、參數名、成員變量、局部變量都統一使用 lowerCamelCase 風格,必須遵循駝峯形式。
  • 第五條變量和常量的命名方式:非公有(private/protected/default)變量前面要加上小寫m;
  • 第六條類型與中括號緊挨相連來定義數組。正例:定義整形數組 int[] arrayDemo;並人工檢查代碼是否符合規範
  • 第七條杜絕徹底不規範的縮寫,避免忘文不知義。反例:AbstractClass「縮寫」命名成AbsClass;condition「縮寫」命名成 condi,此類隨意縮寫嚴重下降了代碼的可閱讀性。
  • 第八條爲了達到代碼本身自解釋的目標,任何自定義編程元素在命名時,使用精良完整的單詞組合來表達其意。可是有些名稱實在過於長,這個能夠適當的縮寫,不要忘文不知義就能夠。這個不是客觀的規定。
  • 第九條不容許任何魔法值(即未經預先定義的常量)直接出如今代碼中。
  • 第十條大括號的使用約定。若是是大括號內爲空,則簡介地寫成{}便可,不須要換行;若是是非空代碼塊則:
    • 左大括號前不換行。
    • 左大括號後換行。
    • 右大括號前換行。
    • 右大括號後還有 else 等代碼則不換行;表示終止的右大括號後必須換行。


5、測試

測試 預期結果 實際結果
不輸入參數 -grade和-n標識符錯誤!! -grade和-n標識符錯誤!!
只輸入一個參數:100 -grade和-n標識符錯誤!! -grade和-n標識符錯誤!!
-n 10 -grade 1 題目已經生成,詳情請見out.txt 題目已經生成,詳情請見out.txt
-n 10.5 -grade 1 請輸入正整數 請輸入正整數
-n ascc -grade 2 請輸入正整數 請輸入正整數
-n 10 -grade vsdv 年級參數錯誤,只能在[1~3]之內 年級參數錯誤,只能在[1~3]之內
-n 00001 -grade 3 題目已經生成,詳情請見out.txt 題目已經生成,詳情請見out.txt
-n 1000 -grade 2.3 年級參數錯誤,只能在[1~3]之內 年級參數錯誤,只能在[1~3]之內
-n 10 -grade 002 題目已經生成,詳情請見out.txt 題目已經生成,詳情請見out.txt
-n 10000 -grade 3 題目已經生成,詳情請見out.txt 題目已經生成,詳情請見out.txt
-n -1 -grade 3 請輸入正整數 請輸入正整數
1000 -n -grade 2 -grade和-n標識符錯誤!! -grade和-n標識符錯誤!!
-n 10 -grade -3 年級參數錯誤,只能在[1~3]之內 年級參數錯誤,只能在[1~3]之內
-n 1000 2 -grade -grade和-n標識符錯誤! -grade和-n標識符錯誤!
-grade 2 -n 1000 題目已經生成,詳情請見out.txt 題目已經生成,詳情請見out.txt
-grade 0.1 -n 800 年級參數錯誤,只能在[1~3]之內 年級參數錯誤,只能在[1~3]之內
-grade a1 -n 10 年級參數錯誤,只能在[1~3]之內 年級參數錯誤,只能在[1~3]之內
-grade 001 -n 20 題目已經生成,詳情請見out.txt 題目已經生成,詳情請見out.txt
-grade 1 -n 0000000002 題目已經生成,詳情請見out.txt 題目已經生成,詳情請見out.txt
-grade 0.1 -n 0.1 請輸入正整數 請輸入正整數
-n a1 -grade a1 請輸入正整數 請輸入正整數

6、總結

作這個前首先要作好前期的準備,知道小學生都須要什麼樣的題目,再繼續想好加減乘除每個的簡單算法

此次做業的收穫是我弄懂逆波蘭函數和調度法

拿到項目前必定要先分析需求,構思大體方向

再說說對結對編程的見解吧!在從最初的構思階段到最後的編寫代碼測試代碼結束,都須要兩我的不斷的配合,不斷的去交流兩我的的想法,而後經過想法的整合,調整出一段更爲優質的代碼。

團隊協做,能夠提升寫代碼質量和效率。寫代碼過程也是一種基礎的累積,對於不會的東西就去搜素學習,把知識基礎變爲本身的。兩我的互幫互助,實現「1+1」可以大於2的成果。

相關文章
相關標籤/搜索