1. 程式人生 > >結對編程-人和代碼都長得好看系列

結對編程-人和代碼都長得好看系列

1年 return subst ostream 函數 std main all 還需

  說實話,看本人隊友的代碼已有1年之余,也幫忙上刀山下火海不辭勞苦為她找BUG,有時找了n個小時就是因為把i達成了1,==打成了=,然而憑心而論此人代碼武功高強,內力深厚,不僅人長得漂亮而且代碼風格確實登得大雅之堂,括號該對稱就對稱,該縮進就縮進,除了註釋略微不多讓本人略感頭疼外,一切都非常...真香。

  隊友采用C++編寫,在dev上跑,說起代碼,那是和本人一樣好看,比如隊友把代碼分成幾個模塊,(在鄙人強烈建議下)將其變成了工程,整個工程由5個文件組成:

  1. main.cpp:除了實現的主函數文件
  2. logIn.h:存儲登錄信息頭文件,用戶信息存於其中,可增加或修改用戶信息
  3. question.h:三個函數question1()、question2()、question3()分別用於生成小學,初中和高中的題目
  4. sign.h:三個函數sign1()、sign2()、sign3()分別用於生成小學初中高中需求的運算符
  5. search.h:用於查找該用戶文件夾下所有的文件

雖然sign.h,logln.h(對你沒看錯是logln不是login)模塊略微有湊工程之嫌疑,比如他們長下面這樣:

#include<iostream>
#include<fstream>
#include<string>
#include<cstdlib>
#include<ctime>
#include<cstdlib>
using namespace std;

char sign1(int n) {//生成小學運算符 // srand((unsigned)time(NULL)); char s1[] = {+ , - , * , /} ; return s1[n]; } string sign2(int n) {//生成初中運算符 string s2[] = { "^2" , ""} ; return s2[n]; } string sign3(int n) {//生成高中運算符 string s3[] = { "sin" , "cos" , "tan"} ; return s3[n]; }

和:

#include<iostream>
#include<fstream>
#include<string>
#include<cstdlib>
#include<ctime>
#include<cstdlib>
using namespace std;

int logIn(string name , string password)
{//判斷用戶名和密碼是都正確,返回1為小學用戶,2為初中用戶,3為高中用戶 
    if((name == "張三1" || name == "張三2" || name == "張三3" )&& password == "123")
        return 1;
    else if((name == "李四1" || name == "李四2" || name == "李四3" )&& password == "123")
        return 2;
    else if((name == "王五1" || name == "王五2" || name == "王五3" )&& password == "123")
        return 3; 
    else
        return 0; 
}

  但是代碼從整體上看可以說是相當的規範。

  好的,讓我們重新把目光放到代碼的算法部分,由於我用的python寫的,確實不知道C++寫UI的切膚之痛,所以UI部分我們暫且不論,控制臺稍後再說,我們看核心部分如何操作,生成小學題目代碼如下:

string question1() //生成小學題目 
{
    string s = "";
    char str[10];
    srand((unsigned)time(NULL));
    int n1 = 0 , n2 = 0 , n3 = 0;
    int flag = 1; 
    int length = (rand()%4 + 2);
    int a[5];
    char b[5];
    int left[5] = {0,0,0,0,0}; //每個數左邊有幾個左括號 
    int right[5] = {0,0,0,0,0};//每個數右邊有幾個右括號 
    if(flag == 1)
    {
        for(int i = 0 ; i < length - 1; i++) 
        {
            a[i] = rand()%(100 - 1 + 1) + 1;//隨機生成操作數
            n1 = rand()%(4-0)+0;            //隨機生成四則運算符號 
            b[i] = sign1(n1);
        }
        a[length - 1] = rand()%(100 - 1 + 1) + 1;
        b[length - 1] = =;                //最後加上等號 
        int exit[5] ={0,0,0,0,0};
        int count = 0;                        //計數有幾個右括號還需要加 
        for(int i = 0 ; i < length ; i++)
        {
            if(rand()%3 == 2 && exit[i] > 0 && left[i] == 0 && count > 0)//一個數右邊加括號的條件 
            {
                right[i]++;
                exit[i]--;
                count--; 
            }
            if(rand()%3 == 1 && i != length - 1 && right[i] == 0)//一個數左邊加括號的條件 
            {
                left[i]++;
                count++;
                for(int j = i ; j < length ; j++)
                    exit[j]++;
            }
        }
        while(count != 0) //左右括號不一樣多就需要再次遍歷 
        {
            for(int i = 1; i < length ; i++)
                if(rand()%3 == 2 && exit[i] > 0 && left[i] == 0 && count > 0)
                {
                    right[i]++;
                    exit[i]--;
                    count--;
                }
        }

        for(int i = 0 ; i < length; i++)
        {
            while(left[i] > 0)
            {
                s = s + "(";
                left[i]--;
            }
            s = s + itoa(a[i],str,10);
            while(right[i] > 0)
            {
                s = s + ")";
                right[i]--;
            }
            s = s + b[i];
        }
    } 
    return s;
}

  這套算法比我的投機取巧(直接套娃式生成法,詳見彭依依博客)簡直好了太多,完全實現真隨機,首先生成操作數和數字,對一個已經生成好的,對可以加括號的5個位置隨機插空,之後再對應生成右括號。隊友調試該模塊也算是費勁了心思(別問我怎麽知道,我看著一個BUG一個BUG改過來的,最後成功一刻差點跪下來謝天謝地),這個代碼優點也非常的明顯,比我的代碼隨機性更大,之後的初中高中也直接加上去就好。但是建議寫成類,做繼承或者多態,會更顯得牛*。

  當然代碼也有缺點的地方,查重部分比較拖沓,查重代碼如下:

infile.open(distAll.data());
                    str = question2();
                    notok = 0;
                    p = 0;
                    while(getline(infile,s1))
                    {
                          mypath[p] = s1;
                        p++; 
                    }
                    infile.close();
                    for(int m = 0 ; m < p ; m++)
                    {
                        infile.open(mypath[m].data());
                        while(getline(infile,s2))
                        {
                            string tem = "";                 
                            tem = s2.substr(4) ;                //去掉題號,留下題目進行比對 
                            if(strcmp(str.c_str() , tem.c_str()) == 0)
                                notok = 1;
                        }
                        infile.close();
                    }
                    if(notok == 0)
                    {
                        outfile << k + 1 ;
                        if((k + 1) < 10)
                            outfile << " ";
                        outfile << "" << str << endl;
                        outfile << "      " << endl; 
                    } 
                    else
                        k--;
                    Sleep(1000);

  三次出題三次查重,自己都承認自己多寫了200多行。

  最後有一個BUG當事人和我全都一臉懵逼,摸不著頭腦,就是產生隨機數時,用的種子,結果每個隨機數產生前不加sleep就不會有變化???請往上看這個代碼,最後一個Sleep(1000),雖然解決了BUG,但是程序生成每個題目要等待1s,太慢了爸爸!真香...

  執筆至此,不再多言,隊友已經柳眉倒豎,怒目圓睜看著我,就差擼袖子上了,為了求生欲,下次再聊。

結對編程-人和代碼都長得好看系列