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

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

在這段時間的結對編程過程當中,我和個人組員一同編程,初步完成了項目的要求,如今我將階段性的成果作一個總結

1、需求分析

實現一個命令行程序,要求:git

  • 一、自動生成小學四則運算題目(加、減、乘、除)
  • 二、支持整數
  • 三、支持多運算符(好比生成包含100個運算符的題目)
  • 四、支持真分數
  • 五、統計正確率

從題目要求可知,咱們須要實現如下幾個功能:express

  • 隨機生成個四則運算題目,並可手動控制生成的題目數目
  • 能將計算的結果轉化爲分數
  • 自動計算生成題目的結果,並能判斷用戶輸入是否與運算結果相同

現階段已實現要求二、3,要求4雖已初步實現但仍存在一些問題,咱們將會在下一階段中實現全部項目要求的功能,並可拓展如下功能:編程

  • 隨機生成題目
  • 題目去重
  • 生成題目後從文件讀入並判題

2、設計思路

根據需求,考慮程序須要定義方法來實現中綴表達式轉後綴表達式、後綴式計算的功能,將結果轉換爲分數以及須要定義調用以上三種種方法並進行輸入輸出的主類,因而我將前兩種方法放入MyDC的類中,真數的支持放入Rational類中,主類設置爲MyDCTester。數組

一、將輸入的中綴表達式轉化爲後綴表達式

運用老師在博客中提供的法則:post

  • 若是遇到數字,咱們就直接將其輸出。
  • 若是遇到非數字時,若棧爲空或者該符號爲左括號或者棧頂元素爲括號,直接入棧。
  • 若是遇到一個右括號,持續出棧並輸出符號,直到棧頂元素爲左括號,而後將左括號出棧(注意,左括號只出棧,不輸出),右括號不入棧。
  • 若是遇到運算符號且棧非空,查看棧頂元素,若是棧頂元素的運算優先級大於或者等於該運算符號,則持續出棧,直到棧頂元素優先級小於該運算符。最後將該元素入棧。
  • 若是咱們讀到了輸入的末尾,則將棧中全部元素依次彈出。
    使用if-else以及switch語句在程序中實現該規律。
    在程序中我使用了字符串棧stacktwo,並定義了trans方法實現功能,代碼以下:
public String trans(String before){
        int i,j=0;
        char step[] = before.toCharArray();//將中綴式字符串轉化爲字符數組
        char after[] = new char[step.length];//用於接收轉化後的後綴式表達式
        for(i=0;i<step.length;i++) {
            if (step[i] >= '0' && step[i] <= '9') {//遇到數字
                after[j] = step[i];
                j++;
                if(i==(step.length)-1){//讀到了輸入的末尾
                    while(stacktwo.empty()==false) {
                        after[j]=stacktwo.pop();
                        j++;
                    }
                }
            }
            else if(stacktwo.empty()||step[i]=='('||stacktwo.peek()=='('||stacktwo.peek()==')') {//遇到非數字且棧爲空或者該符號爲左括號或者棧頂元素爲括號
                stacktwo.push(new Character(step[i]));
                if(i==(step.length)-1){
                    while(stacktwo.empty()==false) {
                        after[j]=stacktwo.pop();
                        j++;
                    }
                }
            }
            else if(step[i]==')') {//遇到一個右括號
                while (stacktwo.peek() != '(') {
                    after[j] = stacktwo.pop();
                    j++;
                }
                stacktwo.pop();
                if(i==(step.length)-1){
                    while(stacktwo.empty()==false) {
                        after[j]=stacktwo.pop();
                        j++;
                    }
                }
            }
            else {//遇到運算符號且棧非空
                switch (step[i]) {
                    case ADD:
                    case SUBTRACT:
                    {
                        while(stacktwo.peek()=='*'||stacktwo.peek()=='/'||stacktwo.peek()=='+'||stacktwo.peek()=='-'){
                            after[j]=stacktwo.pop();
                            j++;
                            if(stacktwo.empty()){
                                break;
                            }
                        }
                        stacktwo.push(step[i]);
                        break;
                    }
                    case MULTIPLY:
                    case DIVIDE:
                    {
                        while(stacktwo.peek()=='*'||stacktwo.peek()=='/'){
                            after[j]=stacktwo.pop();
                            j++;
                            if(stacktwo.empty()){
                                break;
                            }
                        }
                        stacktwo.push(step[i]);
                        break;
                    }
                }
                if(i==(step.length)-1){
                    while(stacktwo.empty()!=false) {
                        after[j]=stacktwo.pop();
                        j++;
                    }
                }
            }
        }
        String str = new String(after);
        return str;//將字符數組轉化爲字符串後返回
    }

二、後綴式表達式的運算。

老師給的連接中已經明確給出了計算的方法,方法以下:學習

  • 設置一個操做數棧,開始棧爲空;
  • 從左到右掃描後綴表達式,遇操做數,進棧;
  • 若遇運算符,則從棧中退出兩個元素,先退出的放到運算符的右邊,後退出的放到運算符左邊,運算後的結果再進棧,直到後綴表達式掃描完畢。
    在程序中我以老師給的代碼例子爲基礎,加以本身的理解,使用了整型棧stack,並定義了evaluate以及evalSingleOp方法來實現功能,代碼以下:
public int evaluate(String expr) {//計算後綴式的值
        int op1, op2, result = 0,i;
        char token[]=expr.toCharArray();//將後綴式字符串轉化爲字符數組
        for(i=0;i<token.length;i++){
            if (token[i]=='+' || token[i]=='-' || token[i]=='*' || token[i]=='/') {//對每一個字符進行分析,若是是運算符就取出棧頂開始的兩個數
                op2 = stack.pop();
                op1 = stack.pop();
                result = evalSingleOp(token[i], op1, op2);//將棧中取出的兩個數進行運算
                stack.push(new Integer(result));//將結果壓棧
            } else//爲數字時直接進棧
                stack.push(new Integer((int)(token[i]-'0')));
        }

        return result;//返回計算結果
    }

    private int evalSingleOp(char operation, int op1, int op2) {//對棧中取出的兩個數進行四則運算,operation爲後綴式中的運算符號
        int result = 0;

        switch (operation) {
            case ADD:
                result = op1 + op2;
                break;
            case SUBTRACT:
                result = op1 - op2;
                break;
            case MULTIPLY:
                result = op1 * op2;
                break;
            case DIVIDE:
                result = op1 / op2;
        }

        return result;//返回運算結果
    }

三、支持真分數

咱們經過學習教材上第100頁的例子22封裝了有理數類Rational,實現了對真分數的支持。
代碼以下:測試

public class Rational {
    int numerator = 1;//分子
    int denominator = 1;//分母
    void setNumerator(int a) {//設置分子
        int c = f(Math.abs(a), denominator);//計算最大公約數
        numerator = a / c;
        denominator = denominator / c;
        if (numerator < 0 && denominator < 0) {
            numerator = -numerator;
            denominator = -denominator;
        }
    }
    void setDenominator(int b) {//設置分母
        int c = f(numerator, Math.abs(b));//計算最大公約數
        numerator = numerator / c;
        denominator = b / c;
        if (numerator < 0 && denominator < 0) {
            numerator = -numerator;
            denominator = -denominator;
        } else if (numerator > 0 && denominator < 0) {
            numerator = -numerator;
            denominator = -denominator;
        }
    }

    int getNumerator() {
        return numerator;
    }

    int getDenominator() {
        return denominator;
    }

    int f(int a, int b) {//求a,b的最大公約數
        if (a == 0) {
            return 1;//c爲分母不能爲0
        }
        if (a < b) {//令a>b
            int c = a;
            a = b;
            b = c;
        }
        int r = a % b;
        while (r != 0) {
            a = b;
            b = r;
            r = a % b;
        }
        return b;
    }

    Rational add(Rational r) {//加法運算
        int a = r.getNumerator();//返回有理數r的分子
        int b = r.getDenominator();//返回有理數r的分母
        int newNumerator = numerator * b + denominator * a;//計算出新分子
        int newDenominator = denominator * b;//計算出新分母
        Rational result = new Rational();
        result.setNumerator(newNumerator);
        result.setDenominator(newDenominator);
        return result;
    }

    Rational sub(Rational r) {//減法運算
        int a = r.getNumerator();
        int b = r.getDenominator();
        int newNumerator = numerator * b - denominator * a;
        int newDenominator = denominator * b;
        Rational result = new Rational();
        result.setNumerator(newNumerator);
        result.setDenominator(newDenominator);
        return result;
    }

    Rational muti(Rational r) {//乘法運算
        int a = r.getNumerator();
        int b = r.getDenominator();
        int newNumerator = numerator * a;
        int newDenominator = denominator * b;
        Rational result = new Rational();
        result.setNumerator(newNumerator);
        result.setDenominator(newDenominator);
        return result;
    }

    Rational div(Rational r) {//除法運算
        int a = r.getNumerator();
        int b = r.getDenominator();
        Rational result = new Rational();
        if (a == 0) {
            System.out.println("分母不能爲0");
            result.setNumerator(0);
            System.exit(0);
        } else {
            int newNumerator = numerator * b;
            int newDenominator = denominator * a;
            result.setNumerator(newNumerator);
            result.setDenominator(newDenominator);
        }
        return result;
    }
}

四、調用方法並實現輸入輸出

現階段爲減小程序調試的難度,咱們使用了老師在博客中提供的代碼,但老師提供的代碼沒法實現隨機生成題目、支持真分數以及統計正確率的功能,因而咱們作出了修改,使得程序能夠支持分數輸出,在接下來的編程中咱們會根據需求對這部分代碼進行從新編寫。編碼

public class MyDCTester {
    public static void main(String[] args) {

        String expression, again;

        Rational result=new Rational();

        try {
            Scanner in = new Scanner(System.in);

            do {
                MyDC evaluator = new MyDC();
                System.out.println("Enter a valid postfix expression: ");
                expression = in.nextLine();//輸入運算表達式
                result = evaluator.evaluate(evaluator.trans(expression));//調用trans方法以及evaluate方法進行轉化以及輸出計算結果
                System.out.println();
                int a=result.getNumerator();
                int b=result.getDenominator();
                if (b==1){//分數轉換
                    System.out.println("result="+a);
                }
                else{
                    System.out.println("result="+a+"/"+b);
                }
                System.out.print("Evaluate another expression [Y/N]? ");//詢問用戶是否再次計算
                again = in.nextLine();
                System.out.println();
            }
            while (again.equalsIgnoreCase("y"));
        } catch (Exception IOException) {
            System.out.println("Input exception reported");
        }

五、UML類圖

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

我已在設計思路部分給出了設計思路並對關鍵代碼進行了註釋。lua

4、運行過程截圖

5、代碼託管地址

碼雲連接命令行

6、遇到的困難及解決方法

到目前爲止的困難主要在於實現中綴表達式轉化爲後綴表達式以及分數的轉化,我將一些細節的問題寫在了下面。

  • 問題一:不知如何將字符串轉化爲字符數組
  • 問題一解決辦法:翻書時注意到書上第八章的toCharArray()方法能夠實現該轉化過程。
  • 問題二:在命令行中編譯程序時遇到如圖所示的問題
  • 問題二解決辦法:使用-Xlint:deprecation命令進行編譯,找到問題並修改。

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

個人結對搭檔是江野,在合做的過程當中我是牽頭人,他也積極響應個人號召,在編程過程當中咱們互相學習,在遇到困難時一塊兒討論解決辦法。但願能在之後的任務中繼續合做,也但願搭檔能更加積極地參與到項目中。

8、PSP

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃
· Estimate · 估計這個任務須要多少時間 15 30
Development 開發
· Analysis · 需求分析 (包括學習新技術) 25 35
· Design Spec · 生成設計文檔 30 30
· Design Review · 設計複審 (和同事審覈設計文檔) 20 30
· Coding Standard · 代碼規範 (爲目前的開發制定合適的規範) 35 45
· Design · 具體設計 60 80
· Coding · 具體編碼 150 200
· Code Review · 代碼複審 30 35
· Test · 測試(自我測試,修改代碼,提交修改) 20 35
Reporting 報告 60 80
· Size Measurement · 計算工做量 10 20
· Postmortem & Process Improvement Plan · 過後總結, 並提出過程改進計劃 20 20
合計 475 640
相關文章
相關標籤/搜索