1、课题内容
本课题的核心是设计一个“小学100以内整数加减运算”系统,该系统需要满足以下主要功能
(1)题目生成:随机生成10道不重复的加减运算题,减法运算确保被减数大于减数。
提供选择题和填空题两种出题方式供用户选择。
(2)答题与评分:用户答题后,系统根据答案计算得分,并累计总分。提供用户查看错题的功能,并在用户答对错题后将其从错题集中删除。
(3)用户交互与反馈:提供菜单选项,包括登录、答题、查阅答题情况、错题再答等。答题结束后,系统给出总用时。
(4)文件导出功能:提供生成题目及对应答案到文本文件的功能,以便线下测试。
2、功能要求
(1)菜单系统:设计清晰易用的菜单界面,提供用户选择不同功能的入口。
(2)答题情况查阅:答题期间不允许查阅答题情况,答题结束后可以查看。
(3)错题再答:提供错题再答功能,答对后从错题集中删除。
(4)文件导出:允许用户选择文件所在地址,生成题目和答案文本文件。
3、选做要求
(1)帮助功能:提供系统使用说明和模拟答题功能,帮助用户了解系统操作。
(2)用户管理:设计完整的登录、注册以及找回密码功能。
(3)题目难度与数量:允许用户自主选择题目难度和数量。
4、其他要求
(1)界面与交互:界面设计应美观,用户交互应方便快捷。
(2)代码注释:代码应包含详细的注释,包括变量、函数以及关键语句段的解释。
(3)程序结构:程序结构应清晰,可读性强,命名规范。
本课题旨在设计一个功能齐全、界面美观、交互便捷的小学100以内整数加减运算系统,旨在帮助小学生提高数学运算能力,并通过各种功能提供个性化的学习体验。
#define _CRT_SECURE_NO_WARNINGS //在VS中使用 避免出现scanf printf不安全警告
/*********头文件************/
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
#include <errno.h>
#include<time.h>
#include<windows.h>
#include<conio.h>
/*********宏定义************/
#define MAX_NUM 99//困难模式出的题目数字范围 x + y = z x - y = z 0<x,y,z <= MAX_NUM
#define MAX_NUM1 9//简单模式出的题目数字范围 x + y = z x - y = z 0<x,y,z <= MAX_NUM
#define MAX_NUM2 19//中等模式出的题目数字范围 x + y = z x - y = z 0<x,y,z <= MAX_NUM
#define MAX_ID 11//ID不超过11位
#define MAX_PWD 20//密码不超过20位
#define MAX_NAME 15//姓名不超过15位
#define MAX_SEX 5//性别不超过5位
#define MAX_PHONE 12//手机号不超过12位
/*********题目结构体************/
typedef struct _Title
{
int opt_num1;//操作数1
int opt_num2;//操作数2
int opt_ch;//操作符0代表+ 1代表-
int style;//0代表选择题 1代表填空题
int correct_ans;//如果是选择保存的是正确选项 如果是填空保存正确答案
int user_ans;//记录用户的答案
int choice[4];//随机生成的4个答案 不重复 其中一个为正确答案
}Title;
/*******用户结构体*******/
typedef struct Users
{
char id[MAX_ID];//用户ID
char pwd[MAX_PWD];//用户密码
char name[MAX_NAME];//用户姓名
char sex[MAX_SEX];//用户性别
char phone[MAX_PHONE];//用户手机号
}Users;
/******全局变量*******/
char ID[MAX_ID];//登陆时所用ID
int TITLE_NUM;//每次测试的出题量
/******自定义字体和背景颜色******/
/* uFore:字体; uBack:背景 */
VOID SetColor(UINT uFore, UINT uBack) {
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, uFore + uBack * 0x10);
}
/********主菜单*********/
/*choice记录用户的选择*/
/*返回值:返回用户的选择*/
int Main_Menu()
{
int choice;//用户选择
system("cls");//清空屏幕输出
printf("1:登录答题\n");
printf("2:查阅答题\n");
printf("3:错题再答\n");
printf("4:打印试卷\n");
printf("5:系统帮助\n");
printf("0:退出系统\n");
printf("请输入选项:");
while (1)
{
SetColor(4, 15);
if (scanf("%d", &choice) == 1)
{
SetColor(0, 15);
if (choice >= 0 && choice <= 5)
{
break;
}
else
{
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
else
{
SetColor(0, 15);
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
return choice;//返回选择
}
/**********生成简单难度选择题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Choice_Title1(Title title[], int n)
{
int i, j;//循环迭代使用
title[n].style = 0;//题目类型为选择题
do
{
title[n].opt_num1 = (rand() % MAX_NUM1) + 1;//随机生成操作数1
title[n].opt_num2 = (rand() % MAX_NUM1) + 1;//随机生成操作数2
title[n].opt_ch = rand() % 2;//随机生成操作符
switch (title[n].opt_ch)//根据操作符 生成正确答案等
{
case 0://加法的情况
if (title[n].opt_num1 + title[n].opt_num2 <= MAX_NUM1)//确保结果在100以内
{
title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2;//得到正确答案
for (i = 0; i < 4; i++)//随机生成4个选项
{
title[n].choice[i] = (rand() % MAX_NUM1) + 1;
while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
{
title[n].choice[i] = (rand() % MAX_NUM1) + 1;//重复就重新生成
}
for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
{
if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
{
i--;
break;
}
}
}
title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
title[n].choice[title[n].correct_ans] = title[n].opt_num1 + title[n].opt_num2;//把答案放在正确选项的位置
return;
}
break;
case 1://减法的情况
if (title[n].opt_num1 - title[n].opt_num2 > 0)//确保答案大于0
{
title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2;//获取正确答案
for (i = 0; i < 4; i++)//随机生成4个选项
{
title[n].choice[i] = (rand() % MAX_NUM1) + 1;
while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
{
title[n].choice[i] = (rand() % MAX_NUM1) + 1;//重复就重新生成
}
for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
{
if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
{
i--;
break;
}
}
}
title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
title[n].choice[title[n].correct_ans] = title[n].opt_num1 - title[n].opt_num2;//把答案放在正确选项的位置
return;
}
break;
}
} while (1);
}
/**********生成中等难度选择题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Choice_Title2(Title title[], int n)
{
int i, j;//循环迭代使用
title[n].style = 0;//题目类型为选择题
do
{
title[n].opt_num1 = (rand() % MAX_NUM2) + 1;//随机生成操作数1
title[n].opt_num2 = (rand() % MAX_NUM2) + 1;//随机生成操作数2
title[n].opt_ch = rand() % 2;//随机生成操作符
switch (title[n].opt_ch)//根据操作符 生成正确答案等
{
case 0://加法的情况
if (title[n].opt_num1 + title[n].opt_num2 <= MAX_NUM2)//确保结果在100以内
{
title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2;//得到正确答案
for (i = 0; i < 4; i++)//随机生成4个选项
{
title[n].choice[i] = (rand() % MAX_NUM2) + 1;
while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
{
title[n].choice[i] = (rand() % MAX_NUM2) + 1;//重复就重新生成
}
for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
{
if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
{
i--;
break;
}
}
}
title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
title[n].choice[title[n].correct_ans] = title[n].opt_num1 + title[n].opt_num2;//把答案放在正确选项的位置
return;
}
break;
case 1://减法的情况
if (title[n].opt_num1 - title[n].opt_num2 > 0)//确保答案大于0
{
title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2;//获取正确答案
for (i = 0; i < 4; i++)//随机生成4个选项
{
title[n].choice[i] = (rand() % MAX_NUM2) + 1;
while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
{
title[n].choice[i] = (rand() % MAX_NUM2) + 1;//重复就重新生成
}
for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
{
if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
{
i--;
break;
}
}
}
title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
title[n].choice[title[n].correct_ans] = title[n].opt_num1 - title[n].opt_num2;//把答案放在正确选项的位置
return;
}
break;
}
} while (1);
}
/**********生成困难难度选择题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Choice_Title3(Title title[], int n)
{
int i, j;//循环迭代使用
title[n].style = 0;//题目类型为选择题
do
{
title[n].opt_num1 = (rand() % MAX_NUM) + 1;//随机生成操作数1
title[n].opt_num2 = (rand() % MAX_NUM) + 1;//随机生成操作数2
title[n].opt_ch = rand() % 2;//随机生成操作符
switch (title[n].opt_ch)//根据操作符 生成正确答案等
{
case 0://加法的情况
if (title[n].opt_num1 + title[n].opt_num2 <= MAX_NUM)//确保结果在100以内
{
title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2;//得到正确答案
for (i = 0; i < 4; i++)//随机生成4个选项
{
title[n].choice[i] = (rand() % MAX_NUM) + 1;
while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
{
title[n].choice[i] = (rand() % MAX_NUM) + 1;//重复就重新生成
}
for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
{
if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
{
i--;
break;
}
}
}
title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
title[n].choice[title[n].correct_ans] = title[n].opt_num1 + title[n].opt_num2;//把答案放在正确选项的位置
return;
}
break;
case 1://减法的情况
if (title[n].opt_num1 - title[n].opt_num2 > 0)//确保答案大于0
{
title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2;//获取正确答案
for (i = 0; i < 4; i++)//随机生成4个选项
{
title[n].choice[i] = (rand() % MAX_NUM) + 1;
while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
{
title[n].choice[i] = (rand() % MAX_NUM) + 1;//重复就重新生成
}
for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
{
if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
{
i--;
break;
}
}
}
title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
title[n].choice[title[n].correct_ans] = title[n].opt_num1 - title[n].opt_num2;//把答案放在正确选项的位置
return;
}
break;
}
} while (1);
}
/**********选择题获取用户的答案*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*参数3 int i: 当前测试的第i+1题*/
/*返回值:0代表该题答错 1代表回答正确*/
int Get_User_Choice(Title title[], int n, int i)
{
int j;//用于迭代
char choice;//获取 用户选择
system("cls");//清屏
printf("第%d题: ", n + i + 1);//输出题号
printf("%d ", title[n + i].opt_num1);//输出操作数1
switch (title[n + i].opt_ch)//输出符号
{
case 0:printf("+ "); break;
case 1:printf("- "); break;
}
printf("%d = \n", title[n + i].opt_num2);//输出操作数2
for (j = 0; j < 4; j++)//打印4个选项
{
printf("%c:%d ", 'A' + j, title[n + i].choice[j]);
}
printf("\n");
printf("请输入选择:");
while (getchar() != '\n');//清空缓冲区
SetColor(4, 15);
scanf("%c", &choice);//获取选择
SetColor(0, 15);
choice = toupper(choice);//转换成大写
while (choice < 'A' || choice > 'D')//判断输入数据的范围 不在A--D则重新输入
{
printf("请重新输入选择:");
fflush(stdin);
SetColor(4, 15);
scanf("%c", &choice);
SetColor(0, 15);
choice = toupper(choice);
}
title[n + i].user_ans = choice - 'A';//记录用户的选择
if (title[n + i].user_ans == title[n + i].correct_ans)//如果答对了
{
printf("恭喜你,答对了!\n");
system("pause");
return 1;
}
printf("答错了,正确答案为:%c!\n", title[n + i].correct_ans + 'A');//如果答错了
system("pause");
return 0;
}
/***错题重答中选择题获取用户的答案***/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int i: 当前测试的第i+1题*/
/*返回值:0代表该题答错 1代表回答正确*/
int Get_User_Choice2(Title title[], int n, int i)
{
int j;//用于迭代
char choice;//获取 用户选择
system("cls");//清屏
printf("第%d题: ", i + 1);//输出题号
printf("%d ", title[i].opt_num1);//输出操作数1
switch (title[i].opt_ch)//输出符号
{
case 0:printf("+ "); break;
case 1:printf("- "); break;
}
printf("%d = \n", title[i].opt_num2);//输出操作数2
for (j = 0; j < 4; j++)//打印4个选项
{
printf("%c:%d ", 'A' + j, title[i].choice[j]);
}
printf("\n");
printf("请输入选择:");
while (getchar() != '\n');//清空缓冲区
SetColor(4, 15);
scanf("%c", &choice);//获取选择
SetColor(0, 15);
choice = toupper(choice);//转换成大写
while (choice < 'A' || choice > 'D')//判断输入数据的范围 不在A--D则重新输入
{
printf("请重新输入选择:");
fflush(stdin);
SetColor(4, 15);
scanf("%c", &choice);
SetColor(0, 15);
choice = toupper(choice);
}
title[i].user_ans = choice - 'A';//记录用户的选择
if (title[i].user_ans == title[i].correct_ans)//如果答对了
{
printf("恭喜你,答对了!\n");
system("pause");
return 1;
}
printf("答错了,正确答案为:%c!\n", title[i].correct_ans + 'A');//如果答错了
system("pause");
return 0;
}
/**********用户开始回答选择题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*返回值:本次答题回答正确的题目数量*/
int Start_Choice(Title title[], int n)
{
while (1)
{
int choice;
int i;
int count = 0;//记录回答正确的数量
printf("1:简单\n");
printf("2:中等\n");
printf("3:困难\n");
printf("请选择难度:");
SetColor(4, 15);
scanf("%d", &choice);
SetColor(0, 15);
if (choice != 1 && choice != 2 && choice != 3)
continue;
Sleep(500);
printf("请输入题数:");
SetColor(4, 15);
scanf("%d", &TITLE_NUM);
SetColor(0, 15);
clock_t start, end;//计时
start = clock();
if (choice == 1)
{
for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Choice_Title1(title, n + i);//生成题目
count += Get_User_Choice(title, n, i);//回答题目
}
end = clock();
printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
system("pause");
return count;//返回回答正确的数量
}
else if (choice == 2)
{
for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Choice_Title2(title, n + i);//生成题目
count += Get_User_Choice(title, n, i);//回答题目
}
end = clock();
printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
system("pause");
return count;//返回回答正确的数量
}
else if (choice == 3)
{
for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Choice_Title3(title, n + i);//生成题目
count += Get_User_Choice(title, n, i);//回答题目
}
end = clock();
printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
system("pause");
return count;//返回回答正确的数量
}
else
continue;
}
}
/**********生成简单难度填空题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Fill_Title1(Title title[], int n)
{
title[n].style = 1;//题目类型为填空题
do
{
title[n].opt_num1 = (rand() % MAX_NUM1) + 1;//随机生成操作数1
title[n].opt_num2 = (rand() % MAX_NUM1) + 1;//随机生成操作数2
title[n].opt_ch = rand() % 2;//随机生成操作符
switch (title[n].opt_ch)//根据操作符 生成正确答案等
{
case 0://加法的情况
if (title[n].opt_num1 + title[n].opt_num2 <= MAX_NUM1)//确保结果在10以内
{
title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2;//得到正确答案
return;
}
break;
case 1://减法的情况
if (title[n].opt_num1 - title[n].opt_num2 > 0)//确保答案大于0
{
title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2;//获取正确答案
return;
}
break;
}
} while (1);
}
/**********生成中等难度填空题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Fill_Title2(Title title[], int n)
{
title[n].style = 1;//题目类型为填空题
do
{
title[n].opt_num1 = (rand() % MAX_NUM2) + 1;//随机生成操作数1
title[n].opt_num2 = (rand() % MAX_NUM2) + 1;//随机生成操作数2
title[n].opt_ch = rand() % 2;//随机生成操作符
switch (title[n].opt_ch)//根据操作符 生成正确答案等
{
case 0://加法的情况
if (title[n].opt_num1 + title[n].opt_num2 <= MAX_NUM2)//确保结果在20以内
{
title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2;//得到正确答案
return;
}
break;
case 1://减法的情况
if (title[n].opt_num1 - title[n].opt_num2 > 0)//确保答案大于0
{
title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2;//获取正确答案
return;
}
break;
}
} while (1);
}
/**********生成困难难度填空题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Fill_Title3(Title title[], int n)
{
title[n].style = 1;//题目类型为填空题
do
{
title[n].opt_num1 = (rand() % MAX_NUM) + 1;//随机生成操作数1
title[n].opt_num2 = (rand() % MAX_NUM) + 1;//随机生成操作数2
title[n].opt_ch = rand() % 2;//随机生成操作符
switch (title[n].opt_ch)//根据操作符 生成正确答案等
{
case 0://加法的情况
if (title[n].opt_num1 + title[n].opt_num2 <= MAX_NUM)//确保结果在100以内
{
title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2;//得到正确答案
return;
}
break;
case 1://减法的情况
if (title[n].opt_num1 - title[n].opt_num2 > 0)//确保答案大于0
{
title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2;//获取正确答案
return;
}
break;
}
} while (1);
}
/**********填空题获取用户的答案*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*参数3 int i: 当前测试的第i+1题*/
/*返回值:0代表该题答错 1代表回答正确*/
int Get_User_Fill(Title title[], int n, int i)
{
system("cls");//清屏
printf("第%d题: ", n + i + 1);//输出题号
printf("%d ", title[n + i].opt_num1);//输出操作数1
switch (title[n + i].opt_ch)//输出符号
{
case 0:printf("+ "); break;
case 1:printf("- "); break;
}
printf("%d = \n", title[n + i].opt_num2);//输出操作数2
printf("请输入答案:");
while (getchar() != '\n');//清空缓冲区
SetColor(4, 15);
scanf("%d", &title[n + i].user_ans);
SetColor(0, 15);
if (title[n + i].user_ans == title[n + i].correct_ans)//如果答对了
{
printf("恭喜你,答对了!\n");
system("pause");
return 1;
}
printf("答错了,正确答案为:%d!\n", title[n + i].correct_ans);//如果答错了
system("pause");
return 0;
}
/****错题重答中填空题获取用户的答案****/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int i: 当前测试的第i+1题*/
/*返回值:0代表该题答错 1代表回答正确*/
int Get_User_Fill2(Title title[], int n, int i)
{
system("cls");//清屏
printf("第%d题: ", i + 1);//输出题号
printf("%d ", title[i].opt_num1);//输出操作数1
switch (title[i].opt_ch)//输出符号
{
case 0:printf("+ "); break;
case 1:printf("- "); break;
}
printf("%d = \n", title[i].opt_num2);//输出操作数2
printf("请输入答案:");
while (getchar() != '\n');//清空缓冲区
SetColor(4, 15);
scanf("%d", &title[i].user_ans);
SetColor(0, 15);
if (title[i].user_ans == title[i].correct_ans)//如果答对了
{
printf("恭喜你,答对了!\n");
system("pause");
return 1;
}
printf("答错了,正确答案为:%d!\n", title[i].correct_ans);//如果答错了
system("pause");
return 0;
}
/**********用户开始回答填空题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*返回值:本次答题回答正确的题目数量*/
int Start_Fill(Title title[], int n)
{
while (1)
{
int i;
int choice;
int count = 0;//记录回答正确的数量
printf("1:简单\n");
printf("2:中等\n");
printf("3:困难\n");
printf("请选择难度:");
SetColor(4, 15);
scanf("%d", &choice);
SetColor(0, 15);
if (choice != 1 && choice != 2 && choice != 3)
continue;
Sleep(500);
printf("请输入题数:");
SetColor(4, 15);
scanf("%d", &TITLE_NUM);
SetColor(0, 15);
clock_t start, end;
start = clock();
if (choice == 1)
{
for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Fill_Title1(title, n + i);//生成题目
count += Get_User_Fill(title, n, i);//回答题目
}
end = clock();
printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
system("pause");
return count;//返回回答正确的数量
}
else if (choice == 2)
{
for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Fill_Title2(title, n + i);//生成题目
count += Get_User_Fill(title, n, i);//回答题目
}
end = clock();
printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
system("pause");
return count;//返回回答正确的数量
}
else if (choice == 3)
{
for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Fill_Title3(title, n + i);//生成题目
count += Get_User_Fill(title, n, i);//回答题目
}
end = clock();
printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
system("pause");
return count;//返回回答正确的数量
}
else
continue;
}
}
/**********选择答题方式的菜单*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int*n : 即数组上次测试答题后的长度*/
/*参数3 int*all : 即数组上次测试答题后回答正确的长度*/
/*参数4 int*last : 本次答题回答正确的题量*/
void Start_Menu(Title title[], int* n, int* all, int* last)
{
int choice;
system("cls");
printf("1:选择题\n");
printf("2:填空题\n");
printf("0:返回\n");
printf("请输入选项:");
while (1)
{
SetColor(4, 15);
if (scanf("%d", &choice) == 1)
{
SetColor(0, 15);
if (choice >= 0 && choice <= 2)
{
break;
}
else
{
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
else
{
SetColor(0, 15);
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
switch (choice)//根据选项 进入选择题或填空题
{
case 1: *last = Start_Choice(title, *n); *all += *last; *n += TITLE_NUM; break;
case 2: *last = Start_Fill(title, *n); *all += *last; *n += TITLE_NUM; break;
}
}
/**********选择答题方式的菜单*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n : 即数组上次测试答题后的长度*/
/*参数3 int all : 即数组上次测试答题后回答正确的长度*/
/*参数4 int last : 本次答题回答正确的题量*/
void Get_State(Title title[], int n, int all, int last)
{
int i;
int count = 0;//记录错题数量
system("cls");
printf("当前总共做:%4d题\n", n);
printf("当前共做对:%4d题\n", all);
printf("上次共做对:%4d题\n", last);
for (i = 0; i < n; i++)
{
if (title[i].user_ans != title[i].correct_ans)
count++;
}
printf("总错题剩余:%4d题\n", count);
system("pause");
}
/**********选择答题方式的菜单*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n : 即数组上次测试答题后的长度*/
void Test_Again(Title title[], int n)
{
int i, flag = 0;
system("cls");
if (n == 0)
{
printf("当前没有错题\n");
system("pause");
return;
}
for (i = 0; i < n; i++)//遍历所有的错题
{
if (title[i].correct_ans != title[i].user_ans)//如果该题是错题
{
flag = 1;
if (title[i].style == 0)//选择题
{
Get_User_Choice2(title, n, i);
}
else//填空题
{
Get_User_Fill2(title, n - TITLE_NUM, i);
}
}
}
if (!flag)
{
printf("当前没有错题\n");
}
system("pause");
}
/******************打印选择题试卷********************/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n : 即数组上次测试答题后的长度*/
/*参数3 FILE*fp1 : 题目所在文件*/
/*参数4 FILE*fp2 : 答案所在文件*/
void Write2Paper_Choice(Title title[], int n, FILE* fp1, FILE* fp2)
{
int i;
char ch;
for (i = 0; i < n; i++)
{
if (title[i].opt_ch == 0) ch = '+';
else ch = '-';
fprintf(fp1, "第%d题: %d %c %d = \n", i + 1, title[i].opt_num1, ch, title[i].opt_num2);
fprintf(fp2, "第%d题: %d %c %d = %c\n", i + 1, title[i].opt_num1, ch, title[i].opt_num2, title[i].correct_ans + 'A');
fprintf(fp1, "A:%d B:%d C:%d D:%d\n\n", title[i].choice[0], title[i].choice[1], title[i].choice[2], title[i].choice[3]);
fprintf(fp2, "A:%d B:%d C:%d D:%d\n\n", title[i].choice[0], title[i].choice[1], title[i].choice[2], title[i].choice[3]);
}
}
/******************打印填空题试卷********************/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n : 即数组上次测试答题后的长度*/
/*参数3 FILE*fp1 : 题目所在文件*/
/*参数4 FILE*fp4 : 答案所在文件*/
void Write2Paper_Fill(Title title[], int n, FILE* fp1, FILE* fp2)
{
int i;
char ch;
for (i = 0; i < n; i++)
{
if (title[i].opt_ch == 0) ch = '+';
else ch = '-';
fprintf(fp1, "第%d题: %d %c %d = \n", i + 1, title[i].opt_num1, ch, title[i].opt_num2);
fprintf(fp2, "第%d题: %d %c %d = %d\n", i + 1, title[i].opt_num1, ch, title[i].opt_num2, title[i].correct_ans);
}
}
/*******系统使用说明********/
void Introduction()
{
system("cls");
printf("欢迎使用小学100以内整数加减运算系统帮助功能!\n");
printf("以下是系统的主要功能和操作说明:\n");
SetColor(4, 15);
printf("1. * * 登录与答题 * *\n");
SetColor(0, 15);
printf("-输入‘1’选择“登录答题”选项,开始答题。\n");
printf("-用户可以输入‘1’选择选择题或输入‘2’选择填空题形式进行答题,也可以输入‘0’返回。\n");
printf("-用户可以输入‘1’选择简单模式,或输入‘2’选择普通模式,或输入‘3’选择困难模式。\n");
printf("-用户可以自主输入生成的题数\n");
printf("-系统将随机生成加减运算题目。\n");
printf("-每道题目答题后,系统将即时反馈是否正确,并计入总分,同时反馈总用时。\n");
SetColor(4, 15);
printf("2. * * 查阅答题情况 * *\n");
SetColor(0, 15);
printf("-输入‘2’选择“查阅答题”选项,查看答题记录和得分。比如:\n");
printf("当前总共做 : 30题\n");
printf("当前共做对 : 25题\n");
printf("上次共做对 : 8题\n");
printf("总错题剩余 : 3题\n");
printf("-注意:在答题期间不能查阅答题情况。\n");
SetColor(4, 15);
printf("3. * * 错题再答 * *\n");
SetColor(0, 15);
printf("-输入‘3’选择“错题再答”选项,重新回答之前答错的题目。\n");
printf("-如果错题答对了,将从错题集中删除。\n");
SetColor(4, 15);
printf("4. * * 生成题目到文件 * *\n");
SetColor(0, 15);
printf("-输入‘4’选择“打印试卷”选项,将题目和答案保存到文本文件中。\n");
printf("-用户可以自主决定文件保存的地址。\n");
printf("-这可以用于线下测试或分享给他人。\n");
SetColor(4, 15);
printf("5. * * 系统帮助 * *\n");
SetColor(0, 15);
printf("-输入‘5’选择系统帮助选项,打开帮助菜单\n");
printf("-输入‘1’打开系统使用说明,或输入‘2’进行模拟答题\n");
SetColor(4, 15);
printf("6. * * 退出系统 * *\n");
SetColor(0, 15);
printf("-输入‘0’选择“退出系统”选项,结束程序运行。\n");
printf("注意事项:\n");
printf("-请确保在答题期间保持专注,不要查阅答题情况。\n");
printf("-如果遇到任何问题或错误,请随时查阅相关文档。\n");
printf("希望以上帮助信息能够助您更好地使用本系统。如果您有任何疑问或建议,请随时与我们联系。\n");
system("pause");
}
/********生成选择题测试*********/
void Start_Choice_Practise()
{
char choice;//获取 用户选择
system("cls");//清屏
clock_t start, end;
start = clock();
printf("第1题: 21 + 55 =\n");
printf("A:6 B:76 C:91 D:49\n");
printf("请输入选择(可无视大小写):\n");
while (getchar() != '\n');//清空缓冲区
while (1)
{
SetColor(4, 15);
if (scanf("%c", &choice) == 1)
{
SetColor(0, 15);
choice = toupper(choice);
if (choice >= 'A' && choice <= 'Z')
{
break;
}
else
{
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
else
{
SetColor(0, 15);
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
if (choice == 'B')
{
printf("恭喜你,答对了!\n");
end = clock();
printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
system("pause");
}
else
{
printf("答错了,正确答案为:B\n");//如果答错了
system("pause");
}
}
/*******生成填空题测试********/
void Start_Fill_Practise()
{
int choice;//获取 用户选择
system("cls");//清屏
clock_t start, end;
start = clock();
printf("第1题: 21 + 55 =\n");
printf("请输入答案:\n");
while (getchar() != '\n');//清空缓冲区
while (1)
{
SetColor(4, 15);
if (scanf("%d", &choice) == 1)
{
SetColor(0, 15);
if (choice >= 1 && choice <= 99)
{
break;
}
else
{
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
else
{
SetColor(0, 15);
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
if (choice == 76)
{
printf("恭喜你,答对了!\n");
end = clock();
printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
system("pause");
}
else
{
printf("答错了,正确答案为:76\n");//如果答错了
system("pause");
}
}
/*******生成测试********/
void Practise_Test()
{
int choice;//系统帮助菜单中用户选择
system("cls");
printf("1:选择题\n");
printf("2:填空题\n");
printf("请输入选项:");
while (1)
{
SetColor(4, 15);
if (scanf("%d", &choice) == 1)
{
SetColor(0, 15);
if (choice >= 1 && choice <= 2)
{
break;
}
else
{
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
else
{
SetColor(0, 15);
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
switch (choice)//根据选项 进入选择题或填空题
{
case 1: Start_Choice_Practise(); break;
case 2: Start_Fill_Practise(); break;
}
}
/*******选择系统帮助的菜单******/
void Help_Menu()
{
int choice;//系统帮助菜单中用户选择
system("cls");
printf("1:系统使用说明\n");
printf("2:模拟答题\n");
printf("请输入选项:");
while (1)
{
SetColor(4, 15);
if (scanf("%d", &choice) == 1)
{
SetColor(0, 15);
if (choice >= 1 && choice <= 2)
{
break;
}
else
{
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
else
{
SetColor(0, 15);
while (getchar() != '\n');
printf("请重新输入选项:");
}
}
switch (choice)
{
case 1: Introduction(); break;
case 2: Practise_Test(); break;
}
}
/********生成试卷菜单*********/
void Print_Paper_Menu()
{
system("cls");//清空屏幕输出
printf("请选择试卷文件所在地址:\n");
char address[100], address_paper[100], address_ans[100];// 定义字符数组用于存储地址
SetColor(4, 15);
scanf("%s", address);
SetColor(0, 15);
address[strcspn(address, "\n")] = 0;// 移除地址字符串末尾的换行符
// 根据用户输入的地址拼接试卷和答案文件的路径
snprintf(address_paper, sizeof(address_paper), "%s\\paper.txt", address);
snprintf(address_ans, sizeof(address_ans), "%s\\ans.txt", address);
int choice;//生成试卷菜单中用户选择
int i, j;//用于迭代
printf("请选择试卷文件中的题数:");
SetColor(4, 15);
scanf("%d", &TITLE_NUM);
SetColor(0, 15);
FILE* fp1, * fp2;// 定义文件指针,用于写入试卷和答案
fp1 = fopen(address_paper, "w+");//保存试卷
fp2 = fopen(address_ans, "w+");//保存答案
Title title[1024];
printf("1:生成选择题\n");
printf("2:生成填空题\n");
printf("3:混合生成\n");
printf("0:返回\n");
printf("请输入选项:");
SetColor(4, 15);
scanf("%d", &choice);//获取选择
SetColor(0, 15);
while (choice < 0 || choice>3)//判断输入的选择是否在0--4之间 不是的话重新输入
{
printf("请重新输入选项:");
SetColor(4, 15);
scanf("%d", &choice);
SetColor(0, 15);
}
switch (choice)
{
case 1:
for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Choice_Title3(title, i);//生成题目
}
Write2Paper_Choice(title, TITLE_NUM, fp1, fp2);
break;
case 2:
for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Fill_Title3(title, i);//生成题目
}
Write2Paper_Fill(title, TITLE_NUM, fp1, fp2);
break;
case 3:
for (i = 0; i < TITLE_NUM / 2; i++)//循环生成题目 回答题目
{
Creat_Choice_Title3(title, i);//生成题目
}
Write2Paper_Choice(title, TITLE_NUM / 2, fp1, fp2);
j = i;
for (; i < TITLE_NUM; i++)//循环生成题目 回答题目
{
Creat_Fill_Title3(title, i);//生成题目
}
Write2Paper_Fill(title + j, TITLE_NUM - TITLE_NUM / 2, fp1, fp2);
break;
}
if (choice != 0)
{
printf("试卷及答案打印成功!请打开文件查看!\n");
system("pause");
}
// 刷新文件缓冲区,确保所有数据都写入文件
fflush(fp1);
fflush(fp2);
fclose(fp1);
fclose(fp2);
}
/*****将所有数据写入到文件*****/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int title_count:答题总数 */
/*参数3 int correct_count_all:正确答题总数 */
/*参数4 int correct_count_last:上一次正确答题数 */
void Save_File(Title title[], int title_count, int correct_count_all, int correct_count_last)
{
FILE* fp = fopen(ID, "wb+ ");
if (fp == NULL) return;
fprintf(fp, "%d %d %d\n", title_count, correct_count_all, correct_count_last);
fwrite(title, sizeof(Title), title_count, fp);
fclose(fp);
}
/*****将所有数据从文件读取*****/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int title_count:答题总数 */
/*参数3 int correct_count_all:正确答题总数 */
/*参数4 int correct_count_last:上一次正确答题数 */
void Load_File(Title title[], int* title_count, int* correct_count_all, int* correct_count_last)
{
FILE* fp = fopen(ID, "rb+");
if (fp == NULL) return;
if (fscanf(fp, "%d %d %d\n", title_count, correct_count_all, correct_count_last) != 3)
{
*title_count = 0;
*correct_count_all = 0;
*correct_count_last = 0;
fclose(fp);
}
fread(title, sizeof(Title), *title_count, fp);
fclose(fp);
}
/*打印菜单*/
void menu()
{
printf("1.注册\n");
printf("2.登录\n");
printf("3.找回密码\n");
printf("请选择:");
}
/*获取光标x坐标*/
/*返回值:返回光标的x坐标*/
int posx()
{
// 定义一个CONSOLE_SCREEN_BUFFER_INFO结构体变量ptr,用于存储控制台屏幕缓冲区的信息
CONSOLE_SCREEN_BUFFER_INFO ptr;
// 调用GetConsoleScreenBufferInfo函数,获取标准输出句柄对应的控制台屏幕缓冲区的信息,并存储到ptr中
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ptr);
return (ptr.dwCursorPosition.X);// 返回ptr中存储的光标位置的x坐标
}
/*获取光标y坐标*/
/*返回值:返回光标的y坐标*/
int posy()
{
CONSOLE_SCREEN_BUFFER_INFO ptr;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ptr);
return (ptr.dwCursorPosition.Y);// 返回ptr中存储的光标位置的y坐标
}
/********定位光标********/
void gotoxy(int x, int y)
{
//更新光标位置
COORD pos;// 定义一个COORD结构体变量pos,用于存储新的光标位置
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle是一个Windows API函数。
// 设置pos结构体的X和Y成员变量,即光标的横纵坐标
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOutput, pos);// 调用SetConsoleCursorPosition函数,将光标移动到指定的位置(pos)
}
/*****输入密码*****/
/**参数1:用户密码**/
void Getpwd(char* pwd)
{
SetColor(4, 15);
int i = 0;// 记录密码长度
int x, y;// 记录光标位置
while (1)
{
pwd[i] = _getch();//获取单个密码(字符)
if (pwd[i] == VK_BACK && i >= 0)//如果输入的是回退键,VK_BACK是键盘的键值,ASCII码值为8
{
if (i > 0)//i>0说明有输入东西了,则回退前一格
{
i--;
x = posx() - 1;//定位x并回退一格
y = posy();//定位y
gotoxy(x, y);//定位光标
printf(" ");//将*用空格掩盖
x = posx() - 1;//再次回退,下次输入时光标才会显示在正确的位置
y = posy();//定位y
gotoxy(x, y);
continue;//然后跳过此次循环
}
else if (i == 0)//i==0说明未输入,直接跳过此次循环
{
continue;
}
}
if (i >= 0 && pwd[i] != VK_RETURN && pwd[i] != VK_BACK)//存在输入
{
x = posx();
y = posy();
gotoxy(x, y);
printf("*");
}
if (i == 0 && pwd[i] == VK_RETURN)//如果未输入直接回车,直接跳过此次循环,避免程序把回车当密码
{
continue;
}
if (pwd[i] == VK_RETURN || i == MAX_PWD - 2)//输入回车了或者到上限
{
i++;
pwd[i] = '\0';//结尾放'\0'
break;
}
i++;
}
SetColor(0, 15);
}
/***注册系统***/
void Register()
{
Users a, b;//创建用户结构体临时变量,a是用来接收用户输入的,b是用来从文件中读取的,来和a作比较
char tmp[20] = "";//用着下面判断的
printf("欢迎来到注册界面!\n");
FILE* pf = fopen("users.dat", "rb+");//"rb+"是以二进制只读方式打开文件的意思
if (!pf)//如果打开失败
{
FILE* pf = fopen("users.dat", "wb+");
Sleep(800);
printf("请输入您的账号>>");
SetColor(4, 15);
scanf("%s", a.id);
SetColor(0, 15);
printf("请输入您的姓名>>");
SetColor(4, 15);
scanf("%s", a.name);
SetColor(0, 15);
printf("请输入您的性别>>");
SetColor(4, 15);
scanf("%s", a.sex);
SetColor(0, 15);
printf("请输入您的电话号码>>");
SetColor(4, 15);
scanf("%s", a.phone);
SetColor(0, 15);
printf("请输入您的密码>>");
Getpwd(a.pwd);//输入密码的函数,有掩盖功能
printf("\n请再次确认您的密码>>");
Getpwd(tmp);
do
{
if (!strcmp(a.pwd, tmp))//两次密码相等
{
pf = fopen("users.dat", "ab");
fwrite(&a, sizeof(Users), 1, pf);
printf("\n账号注册成功,请登录!\n");
Sleep(500);
fclose(pf);
pf = NULL;
return;
}
else
{
printf("\n两次密码不匹配!请重新输入>>");
Getpwd(a.pwd);
printf("\n请再次确认>>");
Getpwd(tmp);
}
} while (1);
}
else
{
fread(&b, sizeof(Users), 1, pf);//将数据读入b中
Sleep(800);
printf("请输入您的账号>>");
SetColor(4, 15);
scanf("%s", a.id);
SetColor(0, 15);
while (1)
{
if (strcmp(a.id, b.id))//两个用户名不相等
{
if (!feof(pf))//未读到文件末尾
{
fread(&b, sizeof(Users), 1, pf);//继续读取文件中的用户到b中
}
else//读到文件末尾了,确认没有重复的id
{
break;
}
}
else//有两个用户名相等
{
printf("此用户名已存在在,请重试!\n");
Sleep(1000);
fclose(pf);//关闭文件
pf = NULL;//pf置空,避免野指针
return;
}
}
printf("请输入您的姓名>>");
SetColor(4, 15);
scanf("%s", a.name);
SetColor(0, 15);
printf("请输入您的性别>>");
SetColor(4, 15);
scanf("%s", a.sex);
SetColor(0, 15);
printf("请输入您的电话号码>>");
SetColor(4, 15);
scanf("%s", a.phone);
SetColor(0, 15);
printf("请输入您的密码>>");
Getpwd(a.pwd);//输入密码的函数,有掩盖功能
printf("\n请再次确认您的密码>>");
Getpwd(tmp);
do
{
if (!strcmp(a.pwd, tmp))//两次密码相等
{
pf = fopen("users.dat", "ab");
fwrite(&a, sizeof(Users), 1, pf);
printf("\n账号注册成功,请登录!\n");
Sleep(500);
fclose(pf);
pf = NULL;
return;
}
else
{
printf("\n两次密码不匹配!请重新输入>>");
Getpwd(a.pwd);
printf("\n请再次确认>>");
Getpwd(tmp);
}
} while (1);
}
}
/**登录系统**/
/*返回值:1代表登录成功 0代表登录失败*/
int Login()
{
Users a, b;//a是用来给用户输入,从文件中读取到b中,用b和a匹配比较
FILE* pf = fopen("users.dat", "rb");//以只读的方式打开文件
if (!pf)//如果读取失败
{
printf("%s\n", strerror(errno));
return 0;
}
printf("欢迎来到登录界面!\n");
Sleep(900);
fread(&b, sizeof(Users), 1, pf);//先从文件中读取一个用户
printf("请输入账号>>");
SetColor(4, 15);
scanf("%s", a.id);
SetColor(0, 15);
while (1)
{
if (!strcmp(a.id, b.id))//在文件中找到了与用户输入相同的id
{
break;
}
else
{
if (!feof(pf))//未读到文件末尾,继续读取文件中的id到b中
{
fread(&b, sizeof(Users), 1, pf);//继续从文件中读取用户信息进b,直到在文件中找到一个和a的信息相同的
}
else//读到文件末尾,没有找到与用户输入相同的账号
{
printf("此账号不存在!请重试!\n");
Sleep(500);
if (Login() == 1)
{
return 1;
}
}
}
}
strcpy(ID, b.id);
strcat(ID, ".dat");
do
{
printf("请输入密码>>");
Getpwd(a.pwd);//获取密码
if (!strcmp(a.pwd, b.pwd))//输入的密码与文件中的相同
{
printf("\n登录成功!欢迎使用!\n");
Sleep(500);
fclose(pf);
pf = NULL;//置空,避免野指针
return 1;
}
else
{
printf("\n密码输入错误,请重新输入\n");
}
} while (strcmp(a.pwd, b.pwd));
}
/*找回密码*/
void Reback()
{
char tmp[20] = "";//密码匹配用的
Users a, b;
FILE* pf = fopen("users.dat", "rb+");//"rb+"是为了读和写以二进制打开文件
if (!pf)//判断能否顺利打开
{
printf("%s", strerror(errno));
return;
}
fread(&b, sizeof(Users), 1, pf);
printf("请输入您的账号>>");
Sleep(800);
SetColor(4, 15);
scanf("%s", a.id);
SetColor(0, 15);
while (1)//在文件中找到与用户输入相同的id
{
if (!strcmp(a.id, b.id))//如果读取到了相同的id(在文件中找到了和用户输入一样的)
{
break;
}
else
{
if (!feof(pf))//未读到文件尾,继续读
{
fread(&b, sizeof(Users), 1, pf);
}
else
{
printf("您输入的账号不存在!请重新输入!\n");
Sleep(500);
fclose(pf);
pf = NULL;
Reback();
return;
}
}
}
//下面是信息匹配验证
do//匹配姓名
{
printf("请输入您的姓名>>");
SetColor(4, 15);
scanf("%s", a.name);
SetColor(0, 15);
if (!strcmp(a.name, b.name))
{
break;
}
else
{
printf("输入错误,请重新输入!\n");
}
} while (strcmp(a.name, b.name));
do//匹配性别
{
printf("请输入您的性别>>");
SetColor(4, 15);
scanf("%s", a.sex);
SetColor(0, 15);
if (!strcmp(a.sex, b.sex))
{
break;
}
else
{
printf("输入错误,请重新输入!\n");
}
} while (strcmp(a.sex, b.sex));
do//匹配电话号码
{
printf("请输入您的电话号码>>");
SetColor(4, 15);
scanf("%s", a.phone);
SetColor(0, 15);
if (!strcmp(a.phone, b.phone))
{
break;
}
else
{
printf("输入错误,请重新输入!\n");
}
} while (strcmp(a.phone, b.phone));
//更改密码
printf("验证成功!请修改您的密码!\n");
printf("请输入您的密码>>");
Getpwd(a.pwd);
printf("请再次确认您的密码>>");
Getpwd(tmp);
if (!pf)
{
printf("%s", strerror(errno));
return;
}
//将原来的密码覆盖掉
do
{
if (!strcmp(a.pwd, tmp))//两次密码相等
{
fseek(pf, -((int)(sizeof(Users) - MAX_ID)), SEEK_CUR);//将文件流调回到要修改的密码的位置
fprintf(pf, "%s", a.pwd);//覆盖原来的密码
printf("密码修改成功,请登录!\n");
Sleep(500);
fclose(pf);
pf = NULL;
return;
}
else
{
printf("两次密码不匹配!请重新输入>>");
SetColor(4, 15);
Getpwd(a.pwd);
SetColor(0, 15);
printf("请再次确认>>");
SetColor(4, 15);
Getpwd(tmp);
SetColor(0, 15);
}
} while (1);
}
/*********界面登录*********/
/*返回值:1代表登录成功 0代表登录失败*/
int Sign_In()
{
char choice;//用户选择
do
{
menu();
setbuf(stdin, NULL);
SetColor(4, 15);
choice = getchar();
SetColor(0, 15);
switch (choice)
{
case '1':
Register();
break;
case '2':
if (Login() == 1)
{
return 1;
}
case '3':
Reback();
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (choice != '0');
}
/*********主函数***********/
int main()
{
system("color F0");//白底黑字
if (!Sign_In()) return 0;//登录界面
int choice;//主菜单用户选择
Title title[1000];//题目数组
int title_count = 0;//总题目长度
int correct_count_all = 0;//总正确
int correct_count_last = 0;//上一次正确
Load_File(title, &title_count, &correct_count_all, &correct_count_last);
srand(time(NULL));//初始化随机数种子
do
{
choice = Main_Menu();
switch (choice)
{
case 1:Start_Menu(title, &title_count, &correct_count_all, &correct_count_last); break;
case 2:Get_State(title, title_count, correct_count_all, correct_count_last); break;
case 3:Test_Again(title, title_count); break;
case 4:Print_Paper_Menu(); break;
case 5:Help_Menu(); break;
}
} while (choice != 0);
Save_File(title, title_count, correct_count_all, correct_count_last);
return 0;
}
5、PS
(1)额外增加了用户自定义题目数量的功能,可以将全局变量中TITLE_NUM改为宏定义从而固定题数为10
(2)在登录答题中增加了用户选择难度的功能,但打印试卷时默认困难难度(因为代码重复率太高,会显得臃肿,虽然已经很臃肿了)
(3)部分功能在用户输入时做了较严格的输入限制,部分功能未完缮(因为懒,而且没必要把用户当傻子),但欢迎大家自行完缮
(4)增加了打印试卷时用户自定义文件路径功能,请使用绝对路径,如:C:\Users\user\source\repos
(5)打印试卷时,也可以自定义题目数量,但如果选择混合输出并且题目数量为奇数时,比如选择题数为9,则只会生成4道选择与4道填空(虽然该功能修复较为简易,但还是懒得改,欢迎大家自行尝试)
(6)教学要求中要求图形界面(GUI),但未能完成,请大家自行探索
(7)本文中代码依旧存在一些bug,但不影响使用,欢迎大家指正
(8)本文使用Visual Studio 2022,控制台为Windows的cmd,请确保编译环境一致
6、参考资料
程序设计题:小学 100 以内正整数加减运算_请针对100以内正整数加法运算的计算器设计2条测试用例-CSDN博客
感谢作者提供的框架代码,虽然存在数组溢出的bug,但结构十分清晰精美
【C语言】简易登录注册系统(登录、注册、改密、文件操作)_c语言设计注册登录-CSDN博客
感谢作者的登录系统,虽然有一些逻辑上的小bug,在修改之后十分实用(ps:使用本文代码中不需要如此文章中所说自行创建users.txt,已添加函数自行创建)