本文基于刘佳祺同学的个人项目代码进行分析
首先需要完成的功能有:
1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;
此项代码为:
while(1) {
cout<<"请输入用户名和密码:";
cin>>name>>password;
if(name=="张三1"||name=="张三2"||name=="张三3") {
if(password=="123") {
grade="小学";
break;
}
}
else if(name=="李四1"||name=="李四2"||name=="李四3") {
if(password=="123") {
grade="初中";
break;
}
}
else if(name=="王五1"||name=="王五2"||name=="王五3") {
if(password=="123") {
grade="高中";
break;
}
}
else cout<<"请输入正确的用户名、密码"<<endl;
}
cout<<endl<<"准备生成"<<grade<<"数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录;若需要切换年级,请输入\"切换为XX\"):"<<endl;
folder_path=name;
choose_grade();
此部分定义了名为log-on()的函数,通过反复调用ifelse语句完成用户名和密码的正确性判断;
2、登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;
此部分代码为:
string user::left_symbol(string a){
int x=rand()%4;
if(grade=="初中"){
if(x==0||x==2) a="√"+a;
}
if(grade=="高中"){
if(x==0) a="sin"+a;
if(x==1) a="cos"+a;
if(x==2) a="tan"+a;
}
return a;
}
string user::symbol(string a){
int x=rand()%4;
if(x==0) a="+"+a;
if(x==1) a="-"+a;
if(x==2) a="*"+a;
if(x==3) a="/"+a;
return a;
}
string user::figure(string a) {
int x=rand()%100+1;
string y;
y=to_string(x);
a=a+y;
return a;
}
string user::right_symbol(string a){
int x=rand()%3;
if(x==0&&grade=="初中") a=a+"^2";
return a;
}
通过对随机数的调用实现出题功能
3、题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);
此部分代码为:
while(number>30||number<10){
if(number==-1) {
cout<<"您已退出系统,请重新登录"<<endl;
log_on();
break;
}
else{
cout<<"输入生成题目数量无效,请输入10到30间的数";
cin>>number;
}
}
cout<<"生成了一张"<<grade<<"卷子,有"<<number<<"道题目"<<endl;
char file_name[80];
time_t systime;
struct tm *info;
time(&systime);
info = localtime(&systime);
strftime(file_name,80,"%y-%m-%d-%H-%M-%S.txt",info);
file_path=folder_path+"\\"+grade+file_name;
ofstream paper(file_path);
string check_path = folder_path + "\\" + "copy.txt";
ofstream ofs;
ofs.open(check_path.c_str(), ios::app);
for(int i=0;i<number; i++){
string problem;
int number_generated=rand()%5+1;
if(number_generated==1&&grade=="小学") number_generated=rand()%4+2;
int left=0,right=0;
if(number_generated>2&&rand()%2==0){
while(right-left<1||right-left ==number_generated-1){
left= rand() % (number_generated-1);
right=left + rand()%(number_generated-left-1)+1;
}
}
for(int j=0;j<number_generated;j++){
string tmp;
tmp=figure(tmp);
tmp=left_symbol(tmp);
if(j==left&&left!=right) tmp="("+tmp;
if(j!=0) tmp=symbol(tmp);
tmp=right_symbol(tmp);
if(j==right&&right!=left) tmp=tmp+")";
problem+=tmp;
}
problem+="=";
if(!check(problem)){
continue;
}
paper<<i+1<<"."<<problem<<endl<<endl;
ofs<<problem<<endl;
}
paper.close();
ofs.close();
4、在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;
在此部分他定义了一个新的函数choose-grade()来完成切换年级的功能
代码如下:
while(1){
string gradechosen;
cin>>gradechosen;
int k=0;
if(gradechosen=="-1"){
log_on();
break;
}
int flag=1;
for(char x:gradechosen){ //遍历输入字符串,确认是否输入为纯数字
if(x<'0'||x>'9'){
flag=0;
break;
}
k=k*10+x-'0';
}
number=k;
if(flag==1){
set_paper();
}
if(flag==0){
if(gradechosen=="切换为小学"||gradechosen=="切换为初中"||gradechosen=="切换为高中") {
grade=gradechosen.substr(6,4);
cout<<"请输入生成题目数量";
cin>>number;
set_paper();
}
else {
while(1){
cout<<"输入项不符合要求,请输入小学、初中和高中三个选项中的一个";
cin>>gradechosen;
if(gradechosen=="小学"||gradechosen=="初中"||gradechosen=="高中") {
grade=gradechosen;
cout<<"请输入生成题目数量";
cin>>number;
set_paper();
break;
}
}
}
}
}
cout<<"您已退出系统,请重新登录"<<endl;
通过对字符串的判断切换年级,而不仅限于对用户名的识别,功能完善且使用
生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;
优缺点分析:
优点:函数封装完整,代码结构,变量声明都很清晰,使得代码阅读很方便,说明提前设计好了完整框架,对字符串的遍历运用熟练
缺点:用户名密码都是if语句定义实现的,后期添加大量用户时此方法不现实