20175205 結對編程項目-四則運算 階段總結

20175205 結對編程項目-四則運算 階段總結

1、需求分析(描述本身對需求的理解,以及後續擴展的可能性)

  • 實現一個命令行程序,要求:
    • 自動生成小學四則運算題目(加,減,乘,除)
      • 支持整數
      • 支持多運算符(好比生成包含100個運算符的題目)
      • 支持真分數
    • 統計正確率
  • 擴展需求
    • 文件:
      • 處理生成題目並輸出到文件
      • 完成題目後從文件讀入並判斷
    • 多語言支持:簡體中文繁體中文English
    • 生成題目去重

2、設計思路

- 第一階段:在沒開始一塊兒討論以前

在還沒坐在一塊兒討論方法以前,我本身大概想了一個框架,並給予實現,可是遇到了不少問題。html

  • 問題一:怎麼生成隨機數,和隨機符號?
  • 問題一的解決:java.lang.Math中包含了一個Math的類,其中的一個方法可用於生成隨機數,並且須要注意用此函數返回的是double型,大於等於 0.0 且小於 1.0,所以若要生成隨機符號,即要生成四個隨機數,每個隨機數對應輸出一個符號便可。
    java

  • 問題二:運行結果產生的隨機數和符號居然每次都是0
    git

  • 問題二的解決:出現問題以後我就用Debug調試,發現產生隨機數的地方出現了問題,原代碼是int num = (int)Math.random()*100,仔細一想,從左到右運算,先強轉後*100,所以產生的隨機數永遠是0,解決方法就是加一個括號int num = (int)(Math.random()*100)編程

  • 問題三:將String類型字符串s賦值爲null後,將字符串與其餘字符串拼接後獲得結果出現了null字符串與其餘字符鏈接的樣式
String s = null;
s  += "hello";
System.out.println(s);

-問題三的解決:先應用String.valueOf 得出s的value值,再經過StringBuilder拼接hello,所以將value與hello進行了拼接,參考博客數組

String s = null;
s = (new StringBuilder(String.valueOf(s))).append("hello").toString();
System.out.println(s);
  • 問題四:不能實現多個運算符和括號的插入,及如何將中綴表達式轉化爲後綴表達式的代碼實現

- 第二階段:我帶着對問題四的疑惑和結對夥伴一塊兒討論

  • 在和小夥伴的討論下,他給我了靈感,他告訴我既然我能夠產生一個式子包含一個運算符,那麼我把兩個算式拼在一塊兒不就完成了多運算符,我將這一想法付諸於實踐,可是發現兩個運算符之間的符號還沒辦法搞定,所以在咱們的討論下做出改進,能夠隨機產生某個數字之內的運算符號數choice,那麼這個四則運算就必定包含2*choice+1的字符,用這一個思想,完成了隨機產生多運算符的四則運算。
import java.util.Scanner;
public class Question {      //產生問題
    Question(){}
    void Question(int n){
        int num1,num2;    //兩個隨機數
        char c;          //隨機符號
        int result;
        int count=0;     //記錄共產生了幾個符號
        String s = "";
        int choice;
        Scanner in = new Scanner(System.in);
        RandomNum num = new RandomNum();
        RandomChar ch = new RandomChar();
        for(int i=1;i<=n;i++){                       //產生題目
            System.out.println("題目"+i+":");
            choice = (int)(Math.random()*5)+1;
            for(int j=1; j<=choice+1; j++){        //產生隨機數
                s = s+num.RandomNum();
                if(count<choice){
                    s = s+" "+ch.RandomChar()+" ";
                    count++;
                }
            }
            System.out.print(s+" = ");
            result = in.nextInt();
            s = "";
            count = 0;
        }
        System.out.println("完成"+n+"道題目");
    }

}
  • 完成了多個隨機運算符,可是還不能實現括號的隨機插入,這時候機智的小夥伴又給我提出了方案,num1 op1 num2 op2 num3 只要知足op1是+或-而 op2知足*或÷
    就能夠隨機的在num1和num2左右兩邊同時加括號
package MathTest;
import java.lang.*;
import java.util.Scanner;
public class Question {      //產生問題
    Question(){}
    void Question(int n){
        int num1,num2;    //兩個隨機數
        char c;          //隨機符號
        int result;
        int count=0;     //記錄共產生了幾個符號
        String s = "";
        String str[] = new String[100];
        String ZZ = "";
        int choice;
        int e=100;   //多少範圍之內的加減乘除
        Scanner in = new Scanner(System.in);
        RandomNum num = new RandomNum();
        RandomChar ch = new RandomChar();
        for(int i=1;i<=n;i++){                       //產生題目
            System.out.println("題目"+i+":");
            choice = num.RandomNum(5)+1;
            for(int j=1; j<=choice+1; j++){        //產生隨機數
                s = s+num.RandomNum(e);
                if(count<choice){
                    s = s+" "+ch.RandomChar()+" ";
                    count++;
                }

            }
            switch ((num.RandomNum(2))){
                case 0:
                    System.out.print(s+" = ");
                    break;
                case 1:
                    if(choice>1){
                        str = s.split(" ");   //字符串轉化爲字符串數組
                        for(int k=1;k!=str.length-2;k=k+2){
                            if((str[k].equals("+")||str[k].equals("-"))&&(str[k+2].equals("*")||str[k+2].equals("÷"))){
                                for(int q=0;q<k-1;q++)
                                    ZZ = ZZ+str[q];

                                ZZ =ZZ+ "(";
                                for(int p=k-1;p<k+2;p++)
                                    ZZ = ZZ+str[p];
                                ZZ = ZZ+")";
                                for(int m=k+2;m<str.length;m++)
                                    ZZ = ZZ+str[m];
                            }
                        }
                        if(ZZ=="")
                            System.out.print(s+" = ");
                        else
                            System.out.print(ZZ+" = ");
                        break;
                    }
                    else{
                        System.out.print(s+" = ");
                        break;
                    }
            }
            result = in.nextInt();
            s = "";
            str = null;
            ZZ = "";
            count = 0;
            choice = 0;
        }
        System.out.println("完成"+n+"道題目");
    }

}
  • 計算式的問題解決後,咱們就着手於如何讓計算機算出正確答案,也就是如何將產生的中綴表達式轉變成後綴表達式讓計算機計算。根據上學期離散課上所學的逆波蘭符號法,二叉樹的應用這一部分知識,參考博客,總結出:中綴轉後綴的方法
    利用兩個棧S1,S2:其中S1存放操做符,S2存放操做數
    從左往右遍歷中綴表達式,若是遇到數字,則放入S2中,若是遇到操做符,則放入S1中。在放操做符的時候有必定的規則,若是棧爲空或棧頂元素爲(,則直接壓棧。若是是(,也直接壓棧;若是棧頂元素爲普通操做符,則比較優先級,若是待壓棧的操做符比棧頂操做符優先級高,則直接壓棧,不然將S1中的棧頂元素出棧,並壓入S2中,再接着比較S1棧頂元素的優先級。若是遇到),則依次彈出S1棧頂的運算符,並壓入S2,直到遇到左括號爲止,此時將這一對括號丟棄。最後將S1中剩餘的運算符依次彈出並壓入S2,逆序輸出S2(從棧底到棧頂)便獲得了後綴表達式。(注意:等號的優先級最低,由於要到最後才進行賦值操做)

3、總結思路

  • 首先解決怎麼生成隨機數,及隨機運算符的問題
  • 怎麼產生多個隨機運算符
  • 括號怎麼隨機插入四則運算中
  • 如何讓計算機計算中綴表達式

4、實現過程當中的關鍵代碼解釋

  • 產生題目的代碼
for (int j = 1; j <= choice + 1; j++) {        //產生題目,一共應該2*choice+1個元素
                s = s + num.RandomNum(e);                      //產生一個數字
                if (count < choice) {
                    s = s + " " + ch.RandomChar() + " ";             //在原基礎上再產生字符
                    count++;
                }
            }
  • 隨機產生括號的代碼
switch (num.RandomNum(2)) {      //隨機產生括號
                case 0:                    //不帶括號
                    key = com.stringToArithmetic(s);
                    System.out.print(s + " = ");
                    break;
                case 1:                     //帶括號
                    if (choice > 1) {
                        str = s.split(" ");   //字符串轉化爲字符串數組
                        Stack<String> Z = new Stack<String>();
                        String temp = new String();
                        for (int k=0; k!=str.length-2; k++) {                 //遍歷前length-2個元素
                            if ((str[k].equals("+") || str[k].equals("-"))) {            //若是是加減
                                int b = k+2;
                                int a = k+1;
                                if (str[b].equals("*") || str[b].equals("÷")) {             //下一個符號是乘除
                                    temp = Z.pop();
                                    Z.push("(");
                                    Z.push(temp);
                                    Z.push(str[k]);
                                    Z.push(str[a]);
                                    Z.push(")");
                                    k++;
                                    a = k;
                                    b = k;
                                } else                                                     //下一個符號是加減
                                    Z.push(str[k]);
                                }
                            else                          //若是是乘除數字就直接入棧
                                Z.push(str[k]);
                        }
                        for(int m=str.length-2;m<str.length;m++)
                            Z.push(str[m]);
                        String[] ZZ = new String[Z.size()];
                        int p = Z.size() - 1;
                        while (Z.size() != 0) {        //將棧中的元素放到數組中
                            temp = Z.pop();
                            ZZ[p] = temp;
                            p--;
                        }
                        String t = new String();
                        t = "";
                        for (int q = 0; q < ZZ.length; q++)
                            t = t + ZZ[q] + " ";
                        key = com.stringToArithmetic(t);
                        System.out.print(t + " = ");
                        ZZ = null;
                        t = "";
                        break;
                    }
                    else{
                        key = com.stringToArithmetic(s);
                        System.out.print(s + " = ");
                        break;
                    }
            }
  • 將中綴表達式轉換爲後綴表達式
public static String infixToSuffix(String exp) {
        Stack<String> s = new Stack<String>();         // 建立操做符堆棧
        String suffix = "";            // 要輸出的後綴表達式字符串
        String str[] = exp.split(" ");
        int length = str.length; // 輸入的中綴表達式的長度
        String temp="";
        for (int i = 0; i < length; i++) {            // 對該中綴表達式的每個字符並進行判斷
            switch (str[i]) {
                case " ":break;           // 忽略空格
                case "(":
                    s.push(str[i]);                  // 若是是左括號直接壓入堆棧
                    break;
                case "+":
                case "-":
                    if(s.size() != 0){          // 碰到'+' '-',將棧中的全部運算符所有彈出去,直至碰到左括號爲止,輸出到隊列中去
                        temp = s.pop();
                        if (temp.equals("(")) {     // 將左括號放回堆棧,終止循環
                            s.push(temp);
                            s.push(str[i]);
                            break;
                        }
                        else{
                            s.push(str[i]);
                            suffix = suffix+temp+" ";
                            break;
                        }
                    }
                    else{
                        s.push(str[i]);      // 說明是當前爲第一次進入或者其餘前面運算都有括號等狀況致使棧已經爲空,此時須要將符號進棧
                        break;
                    }
                    // 若是是乘號或者除號,則彈出全部序列,直到碰到加好、減號、左括號爲止,最後將該操做符壓入堆棧
                case "*":
                case "/":
                    if(s.size()!=0){
                        temp = s.pop();
                        if(temp.equals("+")||temp.equals("-")||temp.equals("(")){
                            s.push(temp);
                            s.push(str[i]);
                            break;
                        }
                        else{
                            s.push(str[i]);
                            suffix = suffix+temp+" ";
                            break;
                        }
                    }
                    else {
                        s.push(str[i]);     //當前爲第一次進入或者其餘前面運算都有括號等狀況致使棧已經爲空,此時須要將符號進棧
                        break;
                    }
                    // 若是碰到的是右括號,則距離棧頂的第一個左括號上面的全部運算符彈出棧並拋棄左括號
                case ")":
                    while (!s.isEmpty()) {
                        temp = s.pop();
                        if (temp.equals("(")) {
                            break;
                        } else {
                            suffix = suffix+temp+" ";
                        }
                    }
                    break;
                // 默認狀況,若是讀取到的是數字,則直接送至輸出序列
                default:
                    suffix = suffix+str[i]+" ";
                    break;
            }

        }
        // 若是堆棧不爲空,則把剩餘運算符一次彈出,送至輸出序列
        while (s.size() != 0) {
            suffix = suffix+s.pop()+" ";
        }
        //
        return suffix;
    }

5、測試方法

6、運行過程截圖

7、代碼託管地址

代碼託管app

8、對結對的小夥伴作出評價

第一次體驗結對變成很是有意思,在編程過程當中,我認爲我扮演的角色就像《飛馳人生》的駕駛員,主要負責前進,踩油門,也就是編寫代碼;而小夥伴扮演的角色就是副駕駛,個人眼睛,爲我指明方向,尤爲在我瓶頸不知如何是好的時候,小夥伴就會提出新的思路,讓我能夠繼續編寫。

9、總結

在此次結對編程中,我遇到了很是多問題,都很是讓人頭疼,好多天晚上都是帶着問題睡覺,次日早上就早早起來改代碼,努力想完成一份健全正確的代碼,在這個過程當中我體會到不同的快樂;並且每遇到一個問題,我不得不查相關知識,紙上得來終覺淺,我將一些思想實現的過程學到了會多知識,好比String類字符數組不能直接改變下標,經過學習中綴轉後綴的思想,將其代碼實現。在編程過程當中遇到各類問題,更加熟練的學會用Debug調試,找出錯誤並加以改正。此次編程很是有趣,準備着手下週的任務。框架

10、預估與實際

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

11、參考

中綴表達式的計算:>http://www.javashuo.com/article/p-nwvfbphc-bo.htmldom

相關文章
相關標籤/搜索