軟工第二次做業——熟悉使用工具

GIT地址 個人GITHUB地址
GIT用戶名 NyimaC
學號後五位 61111
博客地址 個人博客地址
做業連接 連接

Part1.環境配置

由於以前已經用JAVA寫過程序,因此環境是已經配好了的,在此沒有遇到太大的問題。
JAVA版本是JAVA8.0 編譯器使用的是IDEAjava


Part2.代碼編寫

編碼題目:

阿超家裏的孩子上小學一年級了,這個暑假老師給家長們佈置了一個做業:家長天天要給孩子出一些合理的,但要有些難度的四則運算題目,而且家長要對孩子的做業打分記錄。git

做爲程序員的阿超心想,既然天天都須要出題,那何不作一個能夠自動生成小學四則運算題目與解決題目的命令行 「軟件」呢。他把老師的話翻譯一下,就造成了這個軟件的需求:程序員

程序接收一個命令行參數 n,而後隨機產生 n 道加減乘除(分別使用符號+-*/來表示)練習題,每一個數字在 0 和 100 之間,運算符在 2 個 到 3 個之間。github

因爲阿超的孩子才上一年級,並不知道分數。因此軟件所出的練習題在運算過程當中不得出現非整數,好比不能出現 3÷5+2=2.6 這樣的算式。編程

練習題生成好後,將生成的 n 道練習題及其對應的正確答案輸出到一個文件 subject.txt 中。數據結構

使用語言:JAVA

與題目不一樣的地方的聲明:

一、運算符存在差別。題目上的是(+-*/) 個人是(+-×÷)dom

二、個人文件名爲「題目.txt」編程語言

編碼思路:

思惟導圖:

代碼部分(主要部分):

"Talk is cheap. Show me the code."函數

結構單元測試

生成題目的類

public class FormulaMakerTest {
/**
 * 生成題目的類
 */

public LinkedList<String> questionMaker(int total)
{
    //用於存放生成的運算式
    String[] formulas = new String[total];
    LinkedList<String> questionList = new LinkedList<>();
    Numbers numbers = new Numbers();
    OperationImpl operation = new OperationImpl();
    OperationStringImpl operationString = new OperationStringImpl();

    //循環開始的參數(一個用於外循環,一個用於循環)
    int start1;
    int start2;
    //用於保存每次運算的結果
    int result;
    //用於標識運算是否會出現小數
    int judge = 0;
    for(start1=0; start1<total; start1++) {
        //標識結果集的下標
        //生成隨2~3個的運算符
        numbers.operationNumber = (int)(2+Math.random()*(3-2+1));
        //存放每次運算的結果集
        //生成3~4個參與運算的數字
        numbers.numbers = new Integer[numbers.operationNumber+1];
        for(start2=0; start2<=numbers.operationNumber; start2++) {
            numbers.numbers[start2] = (int)(0+Math.random()*(100-0+1));
        }
        //生成運算符
        numbers.operations = new Integer[numbers.operationNumber];
        for(start2=0; start2<numbers.operationNumber; start2++) {
            numbers.operations[start2] = (int)(1+Math.random()*(4-1+1));
        }
        //運算此表達式的運算結果(重點)
        //一、判斷此算式是否知足條件(主要看除法是否知足)
        for(start2=0; start2<numbers.operationNumber; start2++){
            if(numbers.operations[start2] == 4) {
                if(!operation.judgeDivision(numbers.numbers[start2], numbers.numbers[start2+1])) {
                    //不知足 從新生成算式
                    judge++;
                }else {
                    continue;
                }
            }
        }
        //若知足除法後無小數,則此算式成立
        //算式中沒有小數,能夠生成表達式並打印
        if(judge == 0) {
            //算式中沒有小數,能夠生成表達式並打印
            formulas[start1] = operationString.operationSplicing(numbers.operationNumber, numbers.numbers, numbers.operations);
            System.out.println(formulas[start1]);
        }else {
            judge = 0;
            start1--;
            continue;
        }

        //調用計算函數計算結果
        CalculateMaker maker = new CalculateMaker();
        java.util.Queue<String> queue = new LinkedList<>();
        queue = maker.calculateResult(numbers.numbers, numbers.operations);
        result = maker.calculate(queue);
        formulas[start1] += String.valueOf(result);
        questionList.add(formulas[start1]);
    }
    return questionList;
    }
}

棧進行四則運算的類

public class CalculateMaker {
/**
 * 用於得到後綴表達式
 * @return
 */
public Queue<String> calculateResult(Integer[] num, Integer[] operations) {
    //用於存放以前的算式
    Queue<String> queue1 = new LinkedList<>();
    //用於存放後綴表達式
    Queue<String> queue2 = new LinkedList<>();
    int i;
    //把運算式放入隊列
    for(i=0; i<num.length; i++) {
        queue1.offer(String.valueOf(num[i]));
        if(i<operations.length){
            switch (operations[i]){
                case 1:
                    queue1.add("+");
                    break;
                case 2:
                    queue1.add("-");
                    break;
                case 3:
                    queue1.add("×");
                    break;
                case 4:
                    queue1.add("÷");
                    break;
                default:
                    break;
            }
        }
    }

    //用於存放運算符
    Stack<String> stack = new Stack<>();
    //用於標註隊列中運算符的位置
    i = 2;
    while(!queue1.isEmpty()) {
        //此位置是運算符
        if(i%2==1) {
            i++;
            int num1, num2;
            //把運算符放進去
            if(stack.empty()) {
                stack.push(queue1.poll());
            }else {
                //取隊首元素的值(用Unicode碼來判斷,加減號的值小於100,乘除號的值大於100)
                num1 = Translate.translateToInt(queue1.poll());
                if(num1<100) {
                    while (!stack.isEmpty()) {
                        queue2.offer(stack.pop());
                    }
                    stack.push(Translate.translateToString(num1));
                }else {
                    num2 = Translate.translateToInt(stack.peek());
                    if(num2<100) {
                        stack.push(Translate.translateToString(num1));
                    }else {
                        queue2.offer(stack.pop());
                        if(stack.isEmpty()) {
                            stack.push(Translate.translateToString(num1));
                        }else {
                            while(!stack.isEmpty()) {
                                if(stack.isEmpty()) {
                                    stack.push(Translate.translateToString(num1));
                                    break;
                                }
                                num2 = Translate.translateToInt(stack.peek());
                                if(num2<100) {
                                    stack.push(Translate.translateToString(num1));
                                    break;
                                }else {
                                    queue2.offer(stack.pop());
                                }
                            }
                        }
                    }
                }
            }
        }else {
            i++;
            queue2.offer(queue1.poll());
            if(queue1.isEmpty()){
                while(!stack.isEmpty()) {
                    queue2.offer(stack.pop());
                }
            }
        }
    }
    //打印後綴表達式並返回
    return queue2;
}

/**
 * 根據後綴表達式計算結果
 * @param queue2
 * @return
 */
public int calculate(Queue queue2) {
    /**
     * 用於進行後綴計算
     */
    OperationImpl operation = new OperationImpl();
    //保存計算結果
    int x = 0;
    int y = 0;
    int result = 0;
    Stack<String> stack = new Stack<>();
    stack.push((String)queue2.poll());
    while(!queue2.isEmpty()) {

        String str = (String) queue2.poll();
        //遇到運算符,出棧運算,結果入棧
        if(!operation.judgeOperation(str)) {
            stack.push(str);
        }else {
                 y = Integer.valueOf(stack.pop());
                 x = Integer.valueOf(stack.pop());
                 result = operation.calculateNumber(x, y, str);
                 stack.push(String.valueOf(result));
                 //若是最終只有一個元素,則爲計算的結果
                 if(stack.size() == 1 && queue2.isEmpty()) {
                    return Integer.valueOf(stack.pop());
                }
        }
    }
    return y;
}

}

主函數

public static void main(String[] args) {
    //輸入想要的題目數
    System.out.println("請輸入想要建立題目的數目:");
    //生成題目的數目
    Scanner scanner = new Scanner(System.in);
    int total = scanner.nextInt();
    //生成題目生成器
    FormulaMakerTest maker = new FormulaMakerTest();
    //題目集
    LinkedList<String> questionList =   maker.questionMaker(total);
    System.out.println(questionList);
    //將題目存入文件中
    FileWriting writing = new FileWriting();
    writing.WriteStringToFile(questionList);
}

控制檯打印的題目

文件中保存的題目


Part3.使用github克隆項目以及提交代碼

下載與安裝

官網上下確實有點慢,找同窗要的其餘資源下的。

配置我的信息

指令:

git config --global user.name "用戶名"

git config --global user.email 郵箱

克隆項目

進入這裏
點這裏,複製這裏的url

在Git的文件夾下建立一個新的文件夾,在新的文件夾內右鍵選擇Git Bash Here, 而後再在界面上輸入git clone + 剛纔複製網址,即 https://github.com/Cherish599/AchaoCalculator

提交代碼

成功後便會多出一個文件夾,在裏面建立一個和本身github用戶名一致的文件,將程序源碼放進去。

而後轉到AchaoCalculator文件目錄下(cd 文件的路徑)
而後輸入git add . , 再輸入git commit -m "分支名稱",最後輸入 輸入 git push,在這裏會彈出框讓你輸入GitHub的用戶名和密碼便可

最後在GitHub上就能看到你提交的文件啦

遇到的問題

一、第一次接觸GitHub,大可能是看着教程操做的,之後須要多多熟悉

二、不少指令不熟悉,有的教程上的地方我用起來會出現錯誤,在其餘地方找了解決的辦法


Part4.單元測試

由於在編程過程當中有不少須要單元測試的地方,也有不少bug須要及時修改,因此沒有細緻的記錄,在此簡單的描述一下

JAVA的單元測試能夠基於Junit,並須要在測試的方法前加上@Test註解且測試方法不能存在參數

同時也能夠基於main()方法來測試,並在須要的地方輸出語句

主要遇到的問題

一、表達式的生成(字符串的拼接)出現錯誤。由於運算符是運用1~4的隨機數來保存的,因此生成算式時須要轉化爲加減乘除對應的符號,思考後得以解決。

二、後綴表達式生成出現錯誤。由於對中綴表達式轉化爲後綴表達式的理解還存在一些誤差。在仔細閱讀概念,並不斷得打印後綴表達式後,找出了代碼中出現的問題,最後得以解決

三、獲得後綴表達式後計算結果出現錯誤。後綴表達式存在一個隊列中,隊列中元素的出隊,以及數字元素的壓棧、出棧操做出現問題。在條件語句中屢次進行打印操做後,找出了錯誤出現的位置,找到緣由,最終得以解決。

四、若是除法存在小數如何解決。我才用的方法是將這次循環做廢,即將循環因子的值減一,並不進行拼接操做。


Part5.迴歸測試

單元測試時會存在許多問題,解決了這些問題,也就是進行了迴歸測試,一樣在編程過程當中有不少的迴歸測試,因此沒有過多去記錄

這是進行單元測試後,再進行迴歸測試才得出的判斷運算結果是否爲小數的方法。

得出的判斷方法:看兩個整數相除後的結果與其強轉成浮點型後的結果是否同樣,同樣則是整數,反之則是小數


Part6.總結

說實話感受此次做業仍是頗有難度的。主要是編寫代碼部分就須要大量的時間與精力。數據結構在學棧的部分學習過四則運算優先級判斷,可是當時沒有用代碼實現,因此還花時間去學習了一下。

學習Git的使用過程當中,好在有不少文章能夠參考,雖然陌生可是操做起來仍是比較容易。

環境由於是之前就配好的,同時單元測試和迴歸測試其實在代碼的編寫中以及有所使用了,這方面進行的仍是比較順利。

總之此次做業仍是讓我收穫頗豐,不管是對編程語言JAVA,仍是數據結構中棧和隊列,以及Git的使用都獲得了很好的練習

相關文章
相關標籤/搜索