结对编程-人和代码都长得好看系列

  说实话,看本人队友的代码已有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,太慢了爸爸!真香...

  执笔至此,不再多言,队友已经柳眉倒竖,怒目圆睁看着我,就差撸袖子上了,为了求生欲,下次再聊。

原文地址:https://www.cnblogs.com/tursa/p/9715326.html

时间: 2024-10-09 15:16:51

结对编程-人和代码都长得好看系列的相关文章

结对编程队友代码分析

这次结对编程的队友是可熊,感谢可熊不嫌弃我这个鶸,,和我组队 通过分析可熊的代码,深刻体会到了自己代码的不规范以及代码可延展性的缺失 比如using namespace std; ,这一行代码虽然自己写的时候很方便,但没有考虑到别人的编程习惯,某些工程代码里会出现以关键字做变量名的情况,这样写会不兼容 所以要用cin,cout作为标准输入输出应该如下面代码: int x; std::cin >> x ; std::cout << x << std::endl; 或者像这

#个人作业Week2——结对编程对象代码复审

General 代码能够正确运行,能够正确生成指定数量的题目和答案,并且能够对给出的题目和答案文件进行比对,输出结果. 代码没有非常复杂的逻辑,比较容易理解,但是在缺少注释的情况下有部分代码需要较长时间的分析才能理解. 建议将Program类中的方法改为非static类型的,有利于提高程序的封装性. Security 对于控制台输入的格式检查不到位,例如:如果参数-n中出现字母,或者答案文件中出现字母,在调用int.Parse()时会出现程序崩溃的错误. 很多函数都没有对输入的参数进行格式检查,

结对编程——队友代码的优缺点分析

一·项目的需求分析 需求文档中给出5个需求,第一个是用户的登录要求用户名和密码相匹配,并且有着初始的出题类型:需求二则限制题目的操作数和取值范围: 需求三要求我们输入题目数量,这里给出限定条件10-30个题目并且要求同一位老师的题目不能一样:需求四则要我们满足切换出题类型:需求五则 是对题目保存路径和文件的要求. 二·代码优缺点分析 main函数大体框架为:一个循环加一个if的判断语句来确定登陆对象,并且每一个登录对象都有一个唯一的标识,eg:张三1的标识为(0,1),再将其标 识传递给user

软件工程导论 结对编程 队友代码分析

这次的个人项目是中小学数学卷子自动生成程序,每个人都自己动手编写了自己的代码.今天的任务是看队友的代码,并指出他代码中的优点和缺点. 以下是对队友代码的个人评价. 优点: ①代码结构组织有序. 代码非常的模块化,每一个函数的功能清晰明了,框架结构清晰.而我是一个main()函数写到底,这一点我应该以后注意. 他的框架 我的框架 ②交互友好 经过对程序的实际测试,发现交互是非常友好的,我每一步都知道我应该输入什么内容,他做的比项目原本需求的交互更好. 比需求更加人性化. ③程序严谨,测试未发现明显

#个人博客作业week2——结对编程伙伴代码复审

General 1.程序能够顺利地运行.程序通过命令行输入,能够向对应的文件中输出符合要求的题目和答案.程序能够根据用户的不同选择,进行题目的生产或答案的校验,生成出的题目符合参数要求和项目的查重等各种要求,答案校验准确迅速. 2.代码逻辑清晰,没有令人难以理解的部分. 3.他的编码风格与我相似,大括号的使用让我能很清楚地划分模块.变量名很函数名的命名做到了”望文生义“. 4.阅读过程中没有发现冗余重复多余的代码,项目中没有任何一个部分注释掉代码. 5.代码模块化十分清晰,主要分为了表达式,分数

结对编程-队友代码欣赏

运行结果: 优点: 1.注释恰当,符合命名规范 2.添加了新增用户的功能 3.将不选用初中/高中的操作符视为正常情况而不是特殊情况,使代码的分支减少,逻辑清晰 缺点: 1.user.java下的三个类都存储了用户名与密码,而没有特别的区别与彼此的函数,显得有点多余,个人认为可以用一个类表示,减少代码量以及数据的传递次数 2.题目之间没有空行,没有检查题目是否重复 原文地址:https://www.cnblogs.com/marinmoring/p/9710751.html

中小学数学卷子自动生成程序: 结对编程对方代码分析

需求分析: 1.命令行输入用户名和密码,两者之间用空格隔开(程序预设小学.初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学.初中和高中三个选项中的一个.否则提示“请输入正确的用户名.密码”,重新输入用户名.密码: 2.登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学.初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题.每道题目的操作

结对编程——队友代码分析

队友使用的是c++语言,IDE用得是VS2015.下面开始进行优缺点的分析. 优点:①严格按照代码规范,分文件进行模块的分类.整个工程一共有8个文件,Login.h,Login.cpp,Subject.h,Subject.cpp,User.h,User.cpp,UsersTable.h,main.cpp,类的声明在几个头文件中,然后再在另一个文件中对类中的方法进行具体实现.比如login类: #pragma once #include"User.h" using namespace s

结对编程-队友代码分析

按照老师的要求,对队友的代码进行解析,先说缺点在看优点,改正缺点学习优点,一起进步! 1.首先打开代码的时候,关于账号密码的存储,将账号和密码直接存储在了一个数组中.按照"用户名 密码"的格式,这在之后的登陆检测中确实可以方便检测,但是个人感觉将账号密码直接存储在一起会造成一些安全问题. string allUser[]={"张三1 123","张三2 123","张三3 123","李四1 123",&q