1. 程式人生 > >4-2 四則運算_單元測試

4-2 四則運算_單元測試

過程 表達 targe tar exp 優先級 收獲 數字 元素

單元測試git地址:https://coding.net/u/huangzy_95/p/f4/git/tree/master

要求1 對每個功能,先給出測試用例,然後再編碼功能。請註意把測試用例視為功能需求完成的檢驗指標。

要求2 在博客報告測試用例全部fail 到 全部pass 的過程,報告事實 (fail到修改代碼或者測試用例,到pass) 以及收獲。 除了最初的框架,測試用例中存在一次性pass沒有經過fail的,也報告一次性通過,給出如此優秀地實現了這部分功能的代碼。

初識單元測試,因水平有限,部分功能代碼測試框架沒有編寫成功導致部分功能雖然可實現但是無法順利進行單元測試。

功能1. 四則運算支持出題4個數的四則運算題目。

測試用例如下圖:

技術分享

單元測試:

技術分享

實現功能1的主要代碼:

// 運算符優先級表 
// ‘+‘ ‘-‘ ‘*‘ ‘/‘ ‘(‘ ‘)‘ ‘#‘ 
unsigned char Prior[7][7] =
{
    /*‘+‘*/>, >, <, <, <, >, >,
    /*‘-‘*/>, >, <, <, <, >, >,
    /*‘*‘*/>, >, >, >, <, >, >,
    
/*‘/‘*/>, >, >, >, <, >, >, /*‘(‘*/<, <, <, <, <, =, , /*‘)‘*/>, >, >, >, , >, >, /*‘#‘*/<, <, <, <, <, , =, }; typedef struct StackChar { char c; struct StackChar *next; }SC;
//StackChar類型的結點SC typedef struct StackFloat { float f; struct StackFloat *next; }SF; //StackFloat類型的結點SF SC *Push(SC *s, char c) //SC類型的指針Push,返回p { SC *p = (SC*)malloc(sizeof(SC)); p->c = c; p->next = s; return p; } SF *Push(SF *s, float f) //SF類型的指針Push,返回p { SF *p = (SF*)malloc(sizeof(SF)); p->f = f; p->next = s; return p; } SC *Pop(SC *s) //SC類型的指針Pop { SC *q = s; s = s->next; free(q); return s; } SF *Pop(SF *s) //SF類型的指針Pop { SF *q = s; s = s->next; free(q); return s; } float Operate(float a, unsigned char theta, float b) //計算函數Operate { switch (theta) { case +: return a + b; case -: return a - b; case *: return a*b; case /: return a / b; default: return 0; } }

代碼實現效果如下圖:

技術分享

功能2. 支持括號

測試用例:

技術分享

單元測試:

技術分享

技術分享

實現功能2的主要代碼:

char OPSET[OPSETSIZE] = { +, -, *, /, (, ), # };
Status In(char Test, char *TestOp)
{
    int Find = false;
    for (int i = 0; i< OPSETSIZE; i++)
    {
        if (Test == TestOp[i])
            Find = true;
    }
    return Find;
}

Status ReturnOpOrd(char op, char *TestOp)
{
    for (int i = 0; i< OPSETSIZE; i++)
    {
        if (op == TestOp[i])
            return i;
    }
}

char precede(char Aop, char Bop)
{
    return Prior[ReturnOpOrd(Aop, OPSET)][ReturnOpOrd(Bop, OPSET)];
}

// 算術表達式求值的算符優先算法  
// 設OPTR和OPND分別為運算符棧和運算數棧,OP為運算符集合 
float EvaluateExpression(char* MyExpression)
{

    SC *OPTR = NULL;       // 運算符棧,字符元素   
    SF *OPND = NULL;       // 運算數棧,實數元素   
    char TempData[20];
    float Data, a, b;
    char theta, *c, Dr[] = { #, \0 };
    OPTR = Push(OPTR, #);
    c = strcat(MyExpression, Dr);
    strcpy(TempData, "\0");//字符串拷貝函數   
    while (*c != # || OPTR->c != #)
    {
        if (!In(*c, OPSET))
        {
            Dr[0] = *c;
            strcat(TempData, Dr);           //字符串連接函數   
            c++;
            if (In(*c, OPSET))
            {
                Data = atof(TempData);       //字符串轉換函數(double)   
                OPND = Push(OPND, Data);
                strcpy(TempData, "\0");
            }
        }
        else    // 不是運算符則進棧   
        {
            switch (precede(OPTR->c, *c))
            {
            case <: // 棧頂元素優先級低   
                OPTR = Push(OPTR, *c);
                c++;
                break;
            case =: // 脫括號並接收下一字符   
                OPTR = Pop(OPTR);
                c++;
                break;
            case >: // 退棧並將運算結果入棧   
                theta = OPTR->c; OPTR = Pop(OPTR);
                b = OPND->f; OPND = Pop(OPND);
                a = OPND->f; OPND = Pop(OPND);
                OPND = Push(OPND, Operate(a, theta, b));
                break;
            } //switch  
        }
    } //while   
    return OPND->f;
} //EvaluateExpression  
  //符號生成

代碼實現效果如下圖:

技術分享

功能3. 限定題目數量,"精美"打印輸出,避免重復

測試用例:

技術分享

實現功能3的主要代碼:

//判斷是否重復
        for (j = 0; j < i; j++)
        {
            if (Equation[j] == Equation[i])
            {
                i = i - 1;
                repeat = 1;
                break;
            }
        }

        if (repeat != 1)//若不重復,則輸出 
        {
            cout << Equation[i] << "=";
            //判斷結果是否正確
            cin >> InputAns;
            Answer = get_ans(Equation[i]);
            Answer *= 100;
            int temp = (int)Answer;
            Answer = ((double)temp) / 100.00;
            if (InputAns == Answer)
            {
                cout << "Correct answer!";
                right++;
            }
            else
            {
                cout << "Wrong answer!The correct answer is";
                cout << setprecision(2) << fixed << Answer;
                wrong++;
            }
            cout << endl;
        }
    }

代碼實現效果如下圖:

技術分享

功能4. 支持分數出題和運算

測試用例:

技術分享

實現功能4的主要代碼:

//把數字轉換成字符串型
string int_string(int number)
{
    char str[200];
    itoa(number, str, 10);
    string str_ = str;
    return str_;
}

//真分數合成一個字符串
string combination1(string str1, string str2, char k)
{
    string equation;
    equation = ( + str1 + k + str2 + );
    return equation;
}

//新生成一個數
string create_num(int proper_fs, int range)
{
    int num, num1, num2, fs;
    string str_num, str_num1, str_num2;
    num = random() % range + 1;
    str_num = int_string(num);
    if (proper_fs == 1)
    {
        fs = random() % 3;
        if (fs == 1)//判斷是否生成真分數  
        {
            for (;;)
            {
                num1 = random() % range + 1;
                num2 = random() % range + 1;
                if (num1<num2) break;
            }
            str_num1 = int_string(num1);
            str_num2 = int_string(num2);
            str_num = combination1(str_num1, str_num2, /);
        }
    }
    return str_num;
}

//運算式轉換成一個字符串
string combination(string str1, string str2, char k)
{
    string equation;
    equation = str1 + k + str2;
    return equation;
}

//得出正確答案 
float get_ans(string str)
{
    int len;
    float ans;
    len = str.length();
    //char num[len];
    char *num = new char[len];
    for (int j = 0; j<len; j++)
    {
        num[j] = str[j];
    }
    //用堆棧解決。。。 
    ans = EvaluateExpression(num);
    return ans;
}

代碼實現效果如下圖:

技術分享

4-2 四則運算_單元測試