个人编程同伴代码分析

发布时间 2023-09-22 01:46:29作者: 十世镜1
C++ 个人编程:中小学生数学题目生成器

—————结对同伴代码分析



开发环境

  • 开发语言:C++
  • 编辑器:Visual Studio Code
  • 编译器:GCC 8.10 x86-64-w64-mingw32
  • 编译工具:cmake 3.9

问题重述

功能要求

  1. 实现登录功能,需要进行账号密码验证
  2. 实现老师类型切换功能,以及退出登录功能
  3. 每一位老师都有自己的题库文件夹,每一次生成的题目保存在以 "时间.txt" 的格式命名的文件夹中
  4. 实现出题功能,需要分小学、初中、高中三种难度进行出题,每一种难度有对应的要求
  5. 实现题目的查重功能,保证同一个老师的所有题目互不相同

编程要求

  1. 代码格式需要尽量切近 google 编码规范
  2. 实现的程序需要有稳定性,不能出现输入不正常导致程序异常终止的情况
  3. 需要有较好的类封装性,注意应该面对接口编程

代码分析

类定义

抽象类 Teacher

class Teacher {
public:
    std::string GetPassword();
    std::string GetTeachername();
    std::vector<std::string> current_paper_;
    virtual std::string GetType() = 0;
    Teacher(const std::string& username, const std::string& password);
    virtual ~Teacher() ;
    Teacher(const Teacher&)=delete;
    Teacher& operator=(const Teacher&)=delete;
    Teacher(Teacher&&)=delete;
    Teacher& operator=(Teacher&&)=delete;
protected:
    std::string teachername_;
    std::string password_;
};

教师类 (Teacher) 用于表示不同类型教师的基类。

这个类提供了获取教师用户名、密码、以及当前试卷信息的功能。它还定义了一个纯虚函数

GetType(),该函数需要在派生类中实现,用于获取教师的类型(小学、初中、高中等)。


具体类 PrimaryTeacher

class PrimaryTeacher:public Teacher{
public:
    PrimaryTeacher(const std::string& username, const std::string& password);
    virtual std::string GetType() override;
};

具体类 JuniorTeacher

class JuniorTeacher:public Teacher{
public:
    JuniorTeacher(const std::string& username, const std::string& password);
    virtual std::string GetType() override;
};

具体类 SeniorTeacher

class SeniorTeacher:public Teacher{
public:
    SeniorTeacher(const std::string& username, const std::string& password);
    virtual std::string GetType() override;
};

这三个类是 Teacher 的派生类,用于表示各种类型的教师。

他们都继承了 Teacher 类的功能,包括获取教师用户名、密码、以及当前试卷信息的功能。同时,

也实现了纯虚函数 GetType(),以返回对应的教师类型。


重要函数实现分析

这里主要分析试卷生成过程,因为此问题是此题唯一的重难点,也是每位同学几乎都不同的点。

结伴同学使用题库的方法实现该功能。

此功能分为多个步骤,以下使用伪代码说明:

  • 查重函数:
bool DeDuplicate(const std::string &question, Teacher *teacher) :
  if question in question_database_of_this_teacher
    then return true; 
  else
    then return false;

之前向此老师提供的所有题目都在初始化时读入 "current_paper_" 属性中,通过进行遍历查找即可查重

  • 难度测试函数:
bool TestForMiddle(const std::string &question) :
  if "√" or "^" in question
    then return true;
  else
    then return false;
bool TestForHigh(const std::string &question) :
  if "sin" or "cos" or "tan" in question
    then return true;
  else
    then return false;

通过查看对应难度的函数是否有必须具有的计算表达式即可

  • 题目生成函数:
void ProduceProblem(Teacher *teacher) :
  new_question_list is empty
  questions = read_question_from_database;
  if question in questions accord with
  DeDuplicate returns false && test_for_Middle or test_for_High returns true
    then add question to new_question_list

通过以上判断将满足条件的题目加入试卷中即可


运行结果查看

  • 运行结果截图

  • 试卷命名以及内容


总结

功能要求编程要求两个方面来看,结伴同学完成得十分出色,可以对以下几个方面进行肯定

  • 功能要求

    • 使用题库较好地同时解决了题目的合理性以及题目的不重复性两方面
    • 使用难度测试函数结合题库的使用完美地解决了不同难度的问题筛选
  • 编程要求

    • 较好地符合了 google 编码的要求,如取消类默认的拷贝函数、函数以及变量的命名规范等等
    • 使用继承关系大大减少了代码的重复性,具有较好的类封装

但同样地,使用题库本身具有以下问题

  1. 题库需要定时更换,由于所有题目都不可重复,因此题库中的题出一题少一题

  2. 题库的简单读取加遍历去重效率太低,如对于以上方法,完全可以使用不同文件夹分别存放小学、初中、高中三种类型的题目;

    同样的,对于老师的去重也可以将老师之前产生过的文件按照小学、初中、高中类型存放,这样无需读出所有题目,大大提高效率