#include
#include
#include
#include //用于随机数的产生
#include
using namespace std;
int menu(); //菜单
int practise(); //练习
static int g_count = 0; //学生的总数
struct student
{
char name[20];
int num;
float score;
};
student stu[100]; //学生的人数
int exam(student stu[], int length); //考试
int query(student stu[],int length); //查询
int sort(student stu[]); //排序
int del(student stu[],int length); //删除
int main()
{
menu(); //主菜单
return 0;
}
int menu()
{
int length = 20; //学生名字的最大长度
int choose;
printf("小朋友,欢迎你来到小学算术\n");
printf("\t\t\t\t1.计算练习\n");
printf("\t\t\t\t2.计算考试\n");
printf("\t\t\t\t3.成绩查询\n");
printf("\t\t\t\t4.成绩排序\n");
printf("\t\t\t\t5.成绩删除\n");
printf("\t\t\t\t0.退出\n");
printf("请选择:");
scanf("%d", &choose);
system("cls");
switch (choose)
{
case 0:exit(1);
case 1:practise();
case 2:exam(stu, length);
case 3:query(stu,length);
case 4:sort(stu);
case 5:del(stu,length);
default:
cout << "未有该选项,请重新选择 :" << endl
<< "-------------------"
<< "-------------------"
<< endl;
menu(); //调用主菜单
}
return 0;
}
int practise()
{
bool Flag = false; //是否继续答题的控制器
int count_right = 0; //正确数
int count_pro = 0; //总题数
double percen; //正确的百分比
int count = 0; //对一道题的作答次数——计数器
int ret; //学生的答案
//计算过程
do
{
//随机生成一个四则运算符号和两个100以内的整数
char op = "+-*/"[rand() % 4];
int x = rand() % 100;
int y = rand() % 100;
//保证除法能整除
if (op == '/')
{
while (x % y != 0 || y == 0)
{
y = rand() % 100;
}
}
//学生作答
printf("%d %c %d = ", x, op, y);
scanf("%d", &ret);
cout << endl;
//加减乘除的计算
if (op == '+')
{
int k = 0; //switch的控制器(进入主界面 or 退出系统)
int j = 0; //switch的控制器(继续练习 or 退出练习)
for (count = 0; count < 3; count++)
{
if ((x + y) == ret)
{
count_right++; //正确题数加1
cout << "答案正确" << endl;
break;
}
else
{
if (count < 2)
{
cout << "答案错误,请再次作答";
printf("你还有%d次作答机会", 2 - count);
cout << endl;
cout << " = "; //
cin >> ret; //再次作答
continue;
}
cout << "你已错三次,正确答案为:" << (x + y) << endl;
}
}
count_pro++; //总题数加1
//给出选项
printf("\t\t\t\t1.继续练习\n");
printf("\t\t\t\t2.退出练习\n");
printf("请选择:");
cin >> j;
cout << endl;
switch (j)
{
case 1:
Flag = true; //继续练习
break;
case 2:
system("cls");
// 总题数,正确数,正确率
printf("总题数: %d\n", count_pro);
printf("正确数: %d\n", count_right);
percen = ((double)count_right / (double)count_pro) * 100;
printf("正确率: %.1f%%\n", percen);
printf("\t\t\t\t1.进入主界面\n");
printf("\t\t\t\t2.退出系统\n");
printf("请选择:");
cout << endl;
cin >> k;
switch (k)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
}
}
}
if (op == '-')
{
int k = 0; //switch的控制器(进入主界面 or 退出系统)
int j = 0; //switch的控制器(继续练习 or 退出练习)
for (count = 0; count < 3; count++)
{
if ((x - y) == ret)
{
count_right++; //正确题数加1
cout << "答案正确" << endl;
break;
}
else
{
if (count < 2)
{
cout << "答案错误,请再次作答";
printf(",你还有%d次作答机会", 2 - count);
cout << endl;
cout << " = "; //
cin >> ret; //再次作答
continue;
}
cout << "你已错三次,正确答案为:" << (x + y) << endl;
}
}
count_pro++; //总题数加1
//给出选项
printf("\t\t\t\t1.继续练习\n");
printf("\t\t\t\t2.退出练习\n");
printf("请选择:");
cin >> j;
cout << endl;
switch (j)
{
case 1:
Flag = true; //继续练习
break;
case 2:
system("cls");
// 总题数,正确数,正确率
system("cls");
printf("总题数: %d\n", count_pro);
printf("正确数: %d\n", count_right);
percen = ((double)count_right / (double)count_pro) * 100;
printf("正确率: %.1f%%\n", percen);
printf("\t\t\t\t1.进入主界面\n");
printf("\t\t\t\t2.退出系统\n");
printf("请选择:");
cin >> k;
switch (k)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
}
}
}
if (op == '*')
{
int k = 0; //switch的控制器(进入主界面 or 退出系统)
int j = 0; //switch的控制器(继续练习 or 退出练习)
for (count = 0; count < 3; count++)
{
if ((x * y) == ret)
{
count_right++; //正确题数加1
cout << "答案正确" << endl;
break;
}
else
{
if (count < 2)
{
cout << "答案错误,请再次作答";
printf(",你还有%d次作答机会", 2 - count);
cout << endl;
cout << " = "; //
cin >> ret; //再次作答
continue;
}
cout << ",你已错三次,正确答案为:" << (x + y) << endl;
}
}
count_pro++; //总题数加1
//给出选项
printf("\t\t\t\t1.继续练习\n");
printf("\t\t\t\t2.退出练习\n");
printf("请选择:");
cin >> j;
cout << endl;
switch (j)
{
case 1:
Flag = true; //继续练习
break;
case 2:
// 总题数,正确数,正确率
system("cls");
printf("总题数: %d\n", count_pro);
printf("正确数: %d\n", count_right);
percen = ((double)count_right / (double)count_pro) * 100;
printf("正确率: %.1f%%\n", percen);
printf("\t\t\t\t1.进入主界面\n");
printf("\t\t\t\t2.退出系统\n");
printf("请选择:");
cin >> k;
switch (k)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
}
}
}
if (op == '/')
{
int k = 0; //switch的控制器(进入主界面 or 退出系统)
int j = 0; //switch的控制器(继续练习 or 退出练习)
for (count = 0; count < 3; count++)
{
if ((x / y) == ret)
{
count_right++; //正确题数加1
cout << "答案正确" << endl;
break;
}
else
{
if (count < 2)
{
cout << "答案错误,请再次作答";
printf(",你还有%d次作答机会", 2 - count);
cout << endl;
cout << " = "; //
cin >> ret; //再次作答
continue;
}
cout << "你已错三次,正确答案为:" << (x + y) << endl;
}
}
count_pro++; //总题数加1
//给出选项
printf("\t\t\t\t1.继续练习\n");
printf("\t\t\t\t2.退出练习\n");
printf("请选择:");
cin >> j;
cout << endl;
switch (j)
{
case 1:
Flag = true; //继续练习
break;
case 2:
system("cls");
// 总题数,正确数,正确率
printf("总题数: %d\n", count_pro);
printf("正确数: %d\n", count_right);
percen = ((double)count_right / (double)count_pro) * 100;
printf("正确率: %.1f%%\n", percen);
printf("\t\t\t\t1.进入主界面\n");
printf("\t\t\t\t2.退出系统\n");
printf("请选择:");
cin >> k;
switch (k)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
}
}
}
} while (Flag);
return 0;
}
int exam(student* stu, int length)
{
int k = 0; //switch的控制器
int flag = false;
printf("请输入学号: ");
cin >> stu[g_count].num;
printf("请输入姓名: ");
cin.ignore(); // 清除输入缓冲区中的换行符
//保存姓名
cin.getline(stu[g_count].name, length);
cout << endl;
//计算过程
int right[100]; //用来把偶才能正确答案
int ret; //学生答案
int score = 0; //总分数
int count_2 = 0; //作为number_2的下标以及正确答案数组的下标
int count_1 = 0; //作为number_1的下标
int number_1[100]; //保存作答正确的题号
int number_2[200]; //保存作答错误的题号
int count_right = 0; //正确数
int count_pro = 0; //总题数
double percen; //正确的百分比
cout << "请输入题目的数目: ";
do
{
cin >> count_pro;
if (count_pro == 0 || !(count_pro > 0 && count_pro < 10000))
{
cout << "非法操作,请重新输入:";
flag = true;
}
else
flag = false;
} while (flag);
cout << endl;
for (int i = 1; i <= count_pro; i++)
{
//随机生成一个四则运算符号和两个100以内的整数
char op = "+-*/"[rand() % 4];
int x = rand() % 100;
int y = rand() % 100;
//保证除法能整除
if (op == '/')
{
while (x % y != 0 || y == 0)
{
y = rand() % 100;
}
}
//学生作答
printf("第 % d题. %d %c %d = ", i, x, op, y);
scanf("%d", &ret);
cout << endl;
//加减乘除的计算
if (op == '+')
{
if ((x + y) == ret)
{
count_right++; //正确的题数加1
number_1[count_1++] = i; //将题号保存在number_1数组中
}
else
{
right[count_2] = (x + y); //将正确答案保存在right数组中
number_2[count_2++] = i; //将题号保存在number_2数组中
}
}
if (op == '-')
{
if ((x - y) == ret)
{
count_right++; //正确的题数加1
number_1[count_1++] = i; //将题号保存在number_1数组中
}
else
{
right[count_2] = (x - y); //将正确答案保存在right数组中
number_2[count_2++] = i; //将题号保存在number_2数组中
}
}
if (op == '*')
{
if ((x * y) == ret)
{
count_right++; //正确的题数加1
number_1[count_1++] = i; //将题号保存在number_1数组中
}
else
{
right[count_2] = (x * y); //将正确答案保存在right数组中
number_2[count_2++] = i; //将题号保存在number_2数组中
}
}
if (op == '/')
{
if ((x / y) == ret)
{
count_right++; //正确的题数加1
number_1[count_1++] = i; //将题号保存在number_1数组中
}
else
{
right[count_2] = (x / y); //将正确答案保存在right数组中
number_2[count_2++] = i; //将题号保存在number_2数组中
}
}
}
percen = ((double)count_right / (double)count_pro); //计算正确率
score = percen * 100; //计算总分
cout << "你的总分数为: " << score << endl << endl;
printf("正确的题号为: \n");
for (int i = 0; i < count_1; i++) //遍历正确的题号
{
printf(" 第%d题 ", number_1[i]);
if (i % 5 == 0 && i != 0)
cout << endl;
}
cout << endl;
if (count_2 != 0)
{
printf("错误的题号为: \n");
for (int j = 0; j < count_2; j++) //遍历错误的题号
{
printf(" 第%d题, answer: %d ", number_2[j], right[j]);
if (j % 5 == 0 && j != 0)
cout << endl;
}
}
cout << endl;
stu[g_count].score = score; //保存成绩
g_count++;
// 进行保留(更新)最高成绩的操作
if (g_count > 1)
{ // 确保有前一个学生可以比较
if (stu[g_count - 1].num == stu[g_count - 2].num && stu[g_count - 1].score > stu[g_count - 2].score)
{
stu[g_count - 2].score = stu[g_count - 1].score;
g_count--;
}
if (stu[g_count - 1].num == stu[g_count - 2].num && stu[g_count - 1].score < stu[g_count - 2].score)
{
g_count--;
}
}
cout << endl << endl << endl;
printf("\t\t辛苦你了,本次考试结束!\n");
cout << endl;
printf("\t\t\t\t1.进入主界面\n");
printf("\t\t\t\t2.退出系统\n");
printf("请选择: ");
cin >> k;
switch (k)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
}
return 0;
}
int query(student* stu,int length)
{
int k = 0; //switch 的控制器
int i = 0; //switch 的控制器
int num;
char find_name[20];
bool found = false;
do
{
printf("\t请输入学生学号: ");
cin >> num;
cin.ignore(); // 吸收回车键
printf("\t请输入学生姓名: ");
cin.getline(find_name, length);
cout << endl;
for (int i = 0; i < g_count; i++)
{
if (num == stu[i].num && strcmp(find_name, stu[i].name) == 0)
{
cout << "该学生的成绩为: " << stu[i].score << endl;
found = true; // 找到学生
break; // 找到后跳出循环
}
}
if (!found)
{
cout << " 不存在该学生,请做出选择: \n";
printf("\t1.进入主界面\n");
printf("\t2.退出系统\n");
printf("\t3.重新输入\n");
cin >> i;
switch (i)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
case 3:
system("cls");
cout << endl;
}
}
} while (!found);
cout << endl << endl << endl;
printf("\t\t查询结束!\n");
cout << endl;
printf("\t\t\t\t1.进入主界面\n");
printf("\t\t\t\t2.退出系统\n");
printf("请选择: ");
cin >> k;
switch (k)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
}
return 0;
}
int sort(student *stu)
{
int c; //switch控制器
char Temp[20]; //用于名字交换
int temp; //用于交换
//表头
printf("\t%-10s %-20s %-10s\n", "学号", "姓名", "成绩");
// 打印学生排序前的信息
for (int i = 0; i < g_count; i++)
{
printf("\t%-10d %-20s %-10.2f\n", stu[i].num, stu[i].name, stu[i].score);
}
//冒泡排序 大——>小
for (int j = 0; j < g_count - 1; j++) //外循环趟数
{
bool flag = false; //重置标志位
for (int k = 0; k < g_count - 1 - j; k++) //内循环比较
{
if (stu[k].score < stu[k + 1].score)
{ //交换保存成绩
temp = stu[k].score;
stu[k].score = stu[k + 1].score;
stu[k + 1].score = temp;
//交换保存学号
temp = stu[k].num;
stu[k].num = stu[k + 1].num;
stu[k + 1].num = temp;
//交换保存姓名
strcpy(Temp,stu[k].name);
strcpy(stu[k].name, stu[k+1].name);
strcpy(stu[k + 1].name, Temp);
flag = true;
}
}
if (!flag)
break;
}
cout << endl << endl << endl;
//表头
printf("\t%-10s %-20s %-10s\n", "学号", "姓名", "成绩");
// 打印学生排序后的信息
for (int j = 0; j < g_count; j++)
{
printf("\t%-10d %-20s %-10.2f\n", stu[j].num, stu[j].name, stu[j].score);
}
cout << endl;
//排序结束后的选择面板
printf("\t\t排序结束!\n");
cout << endl;
printf("\t\t\t\t1.进入主界面\n");
printf("\t\t\t\t2.退出系统\n");
printf("请选择: ");
cin >> c;
switch (c)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
}
return 0;
}
int del(student *stu,int length)
{
int r; //switch控制器
int temp; //标志删除学生的位置
int k; //switch控制器
int del_num;
char del_name[20];
bool found = false; //是否找到该学生的标志
do
{
printf("\t请输入 要删除学生的学号: ");
cin >> del_num;
cin.ignore(); // 吸收回车键
printf("\t请输入 要删除学生的姓名: ");
cin.getline(del_name, length);
cout << endl;
for (int i = 0; i < g_count; i++)
{
if (del_num == stu[i].num && strcmp(del_name, stu[i].name) == 0)
{
found = true; // 找到学生
temp = i;
break; // 找到后跳出循环
}
}
if (found)
{
for (temp; temp> r;
switch (r)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
}
}
if (!found)
{
cout << "不存在该学生,删除失败,请做出选择: " << endl;
printf("\t1.进入主界面\n");
printf("\t2.退出系统\n");
printf("\t3.重新输入\n");
cin >> k;
switch (k)
{
case 1:
system("cls");
menu(); //主菜单
break;
case 2:
exit(1); //退出系统
break;
case 3:
system("cls");
cout << endl;
}
}
} while (!found);
return 0;
}
在设计程序时,我运用到了本学期学习的:do-while循环,for循环,switch语句,break,continue,结构体(struct)相关知识,数组,if语句,bool变量,冒泡排序,string类的相关函数(比如strcpy、strcmp)等等一系列知识点。
1. 新学习到的知识点:利用Chat Gpt学习static静态变量的使用,再一次复习到了关于变量的生存期以及作用域的相关问题(这帮我解决了 在选择退出系统之前 如何能够反复的录入学生信息以及查询和删除学生信息这一操作)。
2. 利用CSDN(博客网站)学习到了如何生成随机数这一操作,从而进一步学习到了如何生成一道随机的计算题。
3. 无意间摸索到了关于结构体(struct)的一个知识点:当我创造了一个关于学生的结构体,比如struct student{char name[20];};student stu[ 100];当我往一个函数(比如 a(student *stu,int length) ),我将stu传递进去后,在该函数里面进行如:name[20]; strcpy(name,stu[0].name)这样的操作,我发现这个操作是不会报错的,且是可正常运行达到我想要的操作的,因为stu[0].? 这个只是让我们通过结构体变量访问到结构体里面的成员,这个结构体变量就相当于一个入口。这里的本质其实还是“传址”。该发现使得我找到了一种可以交换名字的方法,(无论是char数组还是用string定义的字符串,因为字符数组在长度足够的情况下能够在末尾添加’\0’以此来处理成字符串)即利用string类里的strcpy这个函数,我们可以试着建立一个char Temp[ length ]数组,进行如下操作:
strcpy(Temp,stu[k].name);
strcpy(stu[k].name, stu[k+1].name);
strcpy(stu[k + 1].name, Temp);
如上述所示,类似于普通两个变量之间的交换
4.字符数组与字符串变量判断是否相等的做法不一样,对于string定义的字符串变量而言,我们可以直接用if(? == ?)来进行判断,但是字符数组不可以,所以我们可以利用string类里的strcmp函数来进行判断,比如if(strcmp(a,b)== 0)这样的方式判断,在个程序设计中,我们就是利用这个来遍历查询学生的。