一.简介
本博客是对伍淇铨同学的个人项目代码的评价与分析,此项目是为中小学生自动生成数学试卷,代码思路清晰,结构严谨,功能实现完整。
二.需求分析
1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;
2、登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;
3、题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);
4、在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;
5、生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;
三.代码结构
代码中定义了三个类,分别是system,teacher,generator。
1.system类,主要实现用户的登录与退出和等级转换。
2.teacher类,主要获取老师的用户名,密码以及等级。
3.generator类,主要实现自动生成题目并查重。
四.代码运行结果
1.登录功能
2.功能选择
3.生成题目
五.代码亮点
1.代码风格基本符合Google编码规范,所有头文件使用#define进行保护,函数参数顺序符合标准且函数和变量的命名具有描述性,增加代码的可读性,此外,对系统登陆设置了初始化函数。
2.代码设计了三个类,且对每个类功能进行模块化编程,结构清晰规整。
3.出题代码总体采用 分操作数前后符号的情况 的思路,想法新颖,实现结构清晰易懂,值得借鉴学习。
void generator::generateMath(int num, teacher &teacher) { string name = teacher.getUsername(); int difficulty = teacher.getLevel(); int option = 0; list<string> problems; srand((unsigned) time(nullptr)); for (int i = 0; i < num;) { string problem; int operate_num = rand() % 5 + 1; // 操作数 if (operate_num == 1) { problem = generateOprator(difficulty, &option); problem += to_string(rand() % 100 + 1); if (difficulty == 2 && rand() % 2 == 1 && option == 0) { problem += "^2"; option = 0; } } else { string operations[operate_num]; for (int j = 0; j < operate_num; j++) { operations[j] = to_string(rand() % 100 + 1); } char operators[operate_num - 1]; for (int j = 0; j < operate_num - 1; j++) { operators[j] = baseOperator[rand() % 4]; } int bracket_num = rand() % (operate_num - 1); int bracket_position = 0; int bracket_exist = 0; for (int j = 0; j < operate_num - 1; j++) { problem += generateOprator(difficulty, &option); // √, sin, cos, tan if (bracket_num > 0 && rand() % 2 == 1 && j <= operate_num - 2) { problem += "("; bracket_position = j; bracket_num--; problem += generateOprator(difficulty, &option); problem += operations[j]; bracket_exist++; } else if (j - bracket_position >= 2 && rand() % 2 == 1 && bracket_exist > 0) { problem += operations[j]; if (difficulty == 2 && rand() % 2 == 1 && option == 0) { problem += "^2"; } problem += ")"; bracket_exist--; } else { problem += operations[j]; } option--; if (difficulty == 2 && rand() % 2 == 1 && option == 0) { problem += "^2"; } problem += operators[j]; } problem += generateOprator(difficulty, &option); problem += operations[operate_num - 1]; if (difficulty == 2 && rand() % 2 == 1 && option == 0) { problem += "^2"; option = 0; } while (bracket_exist--) { problem += ")"; if (difficulty == 2 && rand() % 2 == 1 && option == 0) { problem += "^2"; option = 0; } } } problem += " = ?"; if (problem.length() < 9) continue; if (!exist(problem, name)) { // 判断是否重复 cout << problem << endl; i++; problems.push_back(problem); } } saveProblems(problems, name, difficulty); cout << "生成成功!" << endl;View Code
六.存在不足
在小学题目中有单个操作数的情况,在循环语句中使用goto跳转语句,过多使用会造成一定的风险,降低代码的健壮性。