结对编程代码分析
结对编程代码分析
博客简介
本博客是基于颉菁同学的项目代码进行分析与评价
项目简介
个人项目:中小学数学卷子自动生成程序
用户:小学、初中和高中数学老师。
功能:
-
命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;
-
登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;
-
题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);
-
在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;
-
生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;
-
个人项目9月11日晚上10点以前提交至创新课程管理系统。提交方式:工程文件打包,压缩包名为“几班+姓名.rar”。迟交2天及以内者扣分,每天扣20%。迟交2天及以上者0分。
附表-1:账户、密码
账户类型 | 账户 | 密码 | 备注 |
---|---|---|---|
小学 | 张三1 | 123 | |
张三2 | 123 | ||
张三3 | 123 | ||
初中 | 李四1 | 123 | |
李四2 | 123 | ||
李四3 | 123 | ||
高中 | 王五1 | 123 | |
王五2 | 123 | ||
王五3 | 123 |
附表-2:小学、初中、高中题目难度要求
小学 | 初中 | 高中 | |
---|---|---|---|
难度要求 | +,-,*./ | 平方,开根号 | sin,cos,tan |
备注 | 只能有+,-,*./和() | 题目中至少有一个平方或开根号的运算符 | 题目中至少有一个sin,cos或tan的运算符 |
运行结果
![image-20220914204309408](/Users/wuqiquan/Library/Application Support/typora-user-images/image-20220914204309408.png)
![image-20220914204332885](/Users/wuqiquan/Library/Application Support/typora-user-images/image-20220914204332885.png)
总结:登陆功能实现,生成题目功能实现,切换类型功能实现,文件保存功能实现
核心代码分析:
本项目的核心功能在于文件读取以及生成,所以简要分析以下代码
首先是创建文件的对应代码:
首先获取系统时间作为文件名
//创建文件夹
void Get_nowtime() { //调用系统时间
char *fileTime = (char *)malloc(sizeof(char) * 20);
memset(fileTime, 0, sizeof(char) * 20);
time_t n;
time(&n);
strftime(fileTime, 20, "%Y-%m-%d-%H-%M-%S", localtime(&n));
timepath = fileTime;
timepath += ".txt";
}
随后依据文件名生成创建路径,调用Create Directory函数生成文件
void Creat_Doc() {
getcwd(buffer, 100);
path = buffer;
path += "\\";
path += t.name;
const char *docpath;
docpath = path.data();
bool bCreate = CreateDirectory(docpath, NULL);
Get_nowtime();
tempath = path + "\\" + "temp.txt";
timepath = path + "\\" + timepath;
cout << "===========================================================================" << endl;
cout << "文件建立成功,地址为:";
cout << timepath << endl << endl;
}
最后是整个项目的核心内容:出题功能
首先键入生成题目的数目
然后根据用户类型生成不同级别的题目
将已生成的题目用文件流输出到目标文件中
//出题并查重
void Paper_Product() {
cout << "请输入生成题目的数量(10-30),输入-1则退出程序,重新登录" << endl;
cin >> queNum;
while (queNum > 30 || queNum < 10) {
if (queNum == -1) {
cout << "您已退出当前程序,请重新登录" << endl;
User_Login();
Switch_Type();
break;
} else {
cout << "请确认正确的的出题数量(10-30)" << endl;
cin >> queNum;
}
}
Creat_Doc();
question.open(tempath.c_str()); //出题
instrFile.open(tempath.c_str());//将文件中的题以字符串存储到set中,去重
routFile.open(timepath.c_str());//存到正式文件中
quesSet.clear();
char Question[100];
int n = queNum;
int i = 1;
while (n != 0) {
n--;
question << i << "." << " ";
opNum = rand() % 4 + 2;
// if (opNum == 1 && t.type == "小学"){
//
// opNum = rand() % 4 + 2;
// }
int onum = opNum;
if (opNum > 2 && rand() % 2 == 1) { //生成的题目有括号
int a = opNum - 1;
left_pos = rand() % a + 1;
if (left_pos == opNum - 1)
gap = 2;
else if (left_pos == 1 || left_pos == 2)
gap = rand() % (opNum - 2) + 2;
else
gap = rand() % (opNum - left_pos) + 2;
}
bool flag = false; //确保是否有特殊符号标志
while (onum != 0) {
onum--;
if (onum == opNum - left_pos)
question << "(";
int num = rand() % 100 + 1;
int option; //操作数是否做处理
if (t.type == "小学")
option = 0; //0不做处理
else if (t.type == "初中") {
option = rand() % 3;
if (option != 0)
flag = true; //满足至少有一个平方或根号
if (onum == 0 && flag == false)
option = rand() % 2 + 1; //保证最后一个操作数做处理
} else if (t.type == "高中") {
option = rand() % 6;
if (option > 2)
flag = true;
if (onum == 0 && flag == false)
option = rand() % 5 + 1;
}
switch (option) {
case 0:
question << num;
break;
case 1:
question << "√" << num;
break;
case 2:
question << num << "^2";
break;
case 3:
question << "sin" << num << "°";
break;
case 4:
question << "cos" << num << "°";
break;
case 5:
question << "tan" << num << "°";
break;
}
if (onum == opNum - left_pos - gap + 1)
question << ")";
if (onum != 0) {
int opt = rand() % 4;
switch (opt) {
case 0:
question << "+";
break;
case 1:
question << "-";
break;
case 2:
question << "*";
break;
case 3:
question << "/";
break;
}
} else
question << "=";
}
question << endl;
//查重
instrFile.getline(Question, 100);
if (quesSet.find(Question) == quesSet.end()) {
quesSet.insert(Question);
routFile << Question << endl << endl;
i++;
} else
n++;
}
question.close();
routFile.close();
instrFile.close();
remove(tempath.c_str());
核心功能实现逻辑清晰,代码风格规范
优缺点分析:
优点:功能实现完整且代码运行无报错,具有一定的可视化输出形式
缺点:项目在尝试定义与声明分离的过程不符合C++项目规范