一、开发任务
开发任务的具体要求
实现平台是VisualStudio2022,大多数同学用的应该是devc++,区别主要体现在VisualStudio中scanf需要用scanf_s替代,gets需要用gets_s替代,还有等等之类的安全性替代。在搬运代码的时候要注意这一点。
第22题学生基本信息管理(难度系数:5级)——C语言编程模拟实现一个学生基本信息管理系统。
本来想淘宝买,要价400还不如自己写一个。还没看着免费发布的,可能是别人写的质量比较高。我的这个系统里边还有些问题,分数打个勉强及格吧。
文章同步在博客园:https://www.cnblogs.com/kenneth2012/p/15989902.html[计算机实习项目:学生基本信息管理系统]
二、需求分析
某学校学生管理部门在新生入学时,会登记每个学生的个人基本信息,以便今后提供给教务处、学生所在系部、毕业工作指导委员会等部门使用。学生信息管理系统的基本功能是实现学生信息的录入、修改、删除、查询、统计。
*录入功能:*
能够录入八位学号(4位入学年份+1位系别+1位班级+2位班级学号)、姓名、性别、籍贯(精确到市)、高考各科成绩(有新高考和旧高考两种模式)、民族、专业、家庭收入
*修改功能:*
能够实现对文件中任一数据的修改,并且修改需符合和录入一样的格式
*删除功能:*
能够实现对文件中任一行数据的删除。
*查询功能:*
1、按学号查询某个学生的基本信息;
2、按班级号查询该班全体学生的基本信息;
3、按年级查询该年级全体学生基本信息;
4、按专业查询全体学生基本信息;
*统计功能:*
1、按班级统计高考课程各科最高、最低、平均入学成绩,以及每个人的总分;
2、按入校时间统计每个专业入学人数;
3、按给定班级号统计该班生源所属省市人数;
4、按给定年级统计不同少数民族学生人数;
5、按所学专业统计不同年级男女生人数;
6、按给定年级统计各个班级中家庭收入低于该班级全体同学家庭平均收入的学生人数。
*程序中有如下性能:*
(1)学号不能不能超过位数,入学年份也不能在在校学生入学学年范围之外,性别只能输入两种,高考模式也只有两种,高考各科成绩不能超过满分也不能负数。
(2)为了防止管理系统被破坏,编辑操作必须是有特定口令的人才可以完成。查询和浏览则不用口令。
三、程序设计
针对需求做如下设计:
(1)数据结构设计
学生信息管理系统中的信息结构是:姓名、八位学号(4位入学年份+1位系别+1位班级+2位班级学号)、性别(W、M)、系别、籍贯、高考模式、高考成绩、民族、专业、家庭人数、家庭收入
typedef struct INFO
{
char name[N]; //姓名
char num[N]; //学号
char sex[N]; //性别
char dep[N]; //系别
char province[N];//籍贯
char mode[N];//高考模式
char score[N][N]; //高考成绩
char ethnic[N];//民族
char pro[N];//专业
int familyNum; //家庭人数
int fincome; //家庭收入
float t;
} Info;
//为编辑操作设计的口令是一个长度为6的字符串。其中取值假设是”12356”
char e[6] = ”123456”;
(2)模块设计
本任务主要算法是实现对于文件信息的查找、修改、删除、统计。
增加一行新数据
将信息读入结构体数组中,遍历结构体写入文件。
修改某个数据
以姓名为标识符读取对应行的数据,确认需要修改的内容及其结果,重新将读取指针指向该行开头,将更改内容后的数据行写入文件。
删除一个已有数据
以姓名为标识符读取对应行的数据,将数据全部存到结构体数组中,并确认需要删除的行。
将删除行对应的结构体数组位置之后的数据向前移动一个单位长度,覆盖删除行的数据,重置文件读取指针到文件头,重新遍历写入结构体数组。
以上三个操作是编辑学生基本信息,对此每次选择该功能时,则要求“输入密码”,如果正确,则允许编辑,否则,则不允许。
查询学生基本信息
允许用学号、姓名、专业、班级查询学生信息管理系统中的学生信息。
统计数据公开
1.按学号查询某个学生的基本信息
2.按班级号查询该班全体学生的基本信息
3.按年级查询该年级全体学生基本信息
4.按专业查询全体学生基本信息
5.按班级查询高考成绩相关信息
6.按班级统计该班生源所属省市人数
7.按年级统计不同少数民族学生人数
8.按专业统计不同年级男女生人数
9.按年级统计各班低于平均收入的同学
10.按年级统计专业人数
(1)void Check_Information() //查看学生基本信息
/*从文件读取输出,不作赘述。
贴代码如下:*/
void Check_Information()
{
FILE* fp;
int i = 0;
if ((fopen_s(&fp,"C:\\Users\\80958\\Desktop\\test00.txt", "r")) == NULL)
printf("打开失败!");
system("cls");
printf("\t\t********************************************\n");
printf("\t\t* *\n");
printf("\t\t* 学 生 信 息 管 理 系 统 *\n");
printf("\t\t* 查看学生基本信息 *\n");
printf("\t\t* *\n");
printf("\t\t********************************************\n");
printf("-------------------------------------------------------------------------------\n");
printf("\t姓名\t学号\t性别\t系别\t籍贯\t高考模式\t高考成绩\t 民族\t专业\t家庭人数\t家庭收入\n");
printf("-------------------------------------------------------------------------------\n");
while (!feof(fp))
{
fscanf_s(fp, "%10s %10s %s %10s %10s %s ", stu[i].name,10, stu[i].num,10, stu[i].sex,3, stu[i].dep,10, stu[i].province,10, stu[i].mode,3);
if (!atoi(stu[i].mode)) {
for (int t = 0; t < 4; t++)
fscanf_s(fp, "%s", stu[i].score[t],5);
}
else for (int t = 0; t < 9; t++)fscanf_s(fp, "%s", stu[i].score[t],5);
fscanf_s(fp, "%10s %10s %d %d", stu[i].ethnic,10, stu[i].pro,10, &stu[i].familyNum, &stu[i].fincome);
printf("%10s %10s %s %10s %10s %s ", stu[i].name, stu[i].num, stu[i].sex, stu[i].dep, stu[i].province, stu[i].mode);
if (!atoi(stu[i].mode)) {
for (int t = 0; t < 4; t++)printf("%s ", stu[i].score[t]);
}
else for (int t = 0; t < 9; t++)printf("%s ", stu[i].score[t]);
printf("%10s %10s %d %d", stu[i].ethnic, stu[i].pro, stu[i].familyNum, stu[i].fincome);
printf("\n-------------------------------------------------------------------------------\n");
i++;
}
printf("按任意键返回主菜单!");
_getch();
fclose(fp);
}
(2)void Menu_Information_Handing(); //学生基本信息处理
其中有4个case,分别为录入、修改、删除和返回菜单功能,具体操作在函数中详细介绍
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gbzVRqa-1646899480094)(file:///C:\Users\80958\AppData\Local\Temp\ksohtml\wpsEBCB.tmp.jpg)]
(3)void Input_Information(); //录入学生信息
1、将用户输入读入结构体数组中,具有较严格边界检查;
2、遍历结构体数组将数据写入文件。
贴代码如下:
void Input_Information()
{
FILE* fp;
char t;
int i, n, m, z; int r;
char s[N];
time_t now;
struct tm e;
time(&now);
localtime_s(&e, &now);
fopen_s(&fp,"C:\\Users\\80958\\Desktop\\test00.txt", "a+");
do
{
printf("\n********************************************\n");
printf("请输入要录入的人数:");
scanf_s("%s", s,5);
getchar();
n = atoi(s);
while (n <= 0)
{
fflush(stdin);
printf("输入有误,请再次输入正确人数,或输入-1直接停止:");
scanf_s("%s", s,5);
n = atoi(s);
if (n == -1)break;
}
printf("\n 请按以下对应信息正确录入!\n");
for (i = 0; i < n; i++)
{
system("cls");
//清空输入缓冲区
printf("-------------------------------------------------------------------------------\n");
printf("请输入第%d 名学生姓名:", i + 1);
fflush(stdin);
gets_s(stu[i].name);
fflush(stdin);
printf("请输入第%d 名学生学号(8 位):", i + 1);
gets_s(stu[i].num);
while ((strlen(stu[i].num) != 8) || ((atoi(stu[i].num) / 10000) > e.tm_year + 1900)|| ((atoi(stu[i].num) / 10000) < e.tm_year + 1896))
{
printf("输入有误,请输入 8 位学号数:");
gets_s(stu[i].num);
}
fflush(stdin);
printf("请输入第%d 名学生性别([男].M/[女].W):", i + 1);
scanf_s("%s",stu[i].sex,5);
while (strcmp(stu[i].sex, "M") && strcmp(stu[i].sex, "W"))
{
fflush(stdin);
printf("输入有误,请按要求正确输入([男].M/[女].W):");
scanf_s("%s", stu[i].sex,5);
}
getchar();
printf("请输入第%d 名学生系别(1~4):", i + 1);
gets_s(stu[i].dep);
m = atoi(stu[i].dep);
while ((m == 0 || m > 4) || strlen(stu[i].dep) != 1)
{
fflush(stdin);
printf("输入有误,请按要求正确输入系别(1~4):");
gets_s(stu[i].dep);
m = atoi(stu[i].dep);
}
fflush(stdin);
printf("请输入第%d 名学生籍贯(精确到市):", i + 1);
gets_s(stu[i].province);
fflush(stdin);
printf("请输入第%d 名学生的高考模式(0_旧高考,1_新高考):", i + 1);
gets_s(stu[i].mode);
while (strcmp(stu[i].mode, "0") && strcmp(stu[i].mode, "1"))
{
fflush(stdin);
printf("输入有误,请按要求正确输入高考模式(0_旧高考,1_新高考):");
gets_s(stu[i].mode);
}
fflush(stdin);
if (!atoi(stu[i].mode)) {
printf("请输入第%d 名学生高考成绩:\n语文\t数学\t英语\t综合\n", i + 1);
for (int t = 0; t < 4; t++) {
do
{
scanf_s("%s", stu[i].score[t],20);
if((atoi(stu[i].score[t]) > 150 && t < 3) || (atoi(stu[i].score[t]) > 300 && t == 3) || (atoi(stu[i].score[t]) < 0))
printf("输入有误,请按要求正确输入第%d科成绩", t + 1);
}while((atoi(stu[i].score[t]) > 150 && t < 3) || (atoi(stu[i].score[t]) > 300 && t == 3) || (atoi(stu[i].score[t]) < 0));
}
}
else {
printf("请输入第%d 名学生高考成绩,没考的科目写零分:\n语文\t数学\t英语\t政治\t历史\t地理\t生物\t物理\t化学\n", i + 1);
do {
for (int t = 0; t < 9; t++) {
do
{
scanf_s("%s", stu[i].score[t], 20);
if ((atoi(stu[i].score[t]) > 150) || (atoi(stu[i].score[t]) < 0))
printf("输入有误,请按要求正确输入第%d科成绩", t + 1);
} while ((atoi(stu[i].score[t]) > 150) || (atoi(stu[i].score[t]) < 0));
}
z = 0;
for (int t = 0; t < 9; t++) {
z += atoi(stu[i].score[t]);
}
} while (z > 750);
}
fflush(stdin);
printf("请输入第%d 名学生民族(要写族):", i + 1);
scanf_s("%s",stu[i].ethnic,20);
fflush(stdin);
printf("请输入第%d 名学生专业(写全称):", i + 1);
scanf_s("%s", stu[i].pro,20);
fflush(stdin);
printf("请输入第%d 名学生家庭人数:", i + 1);
scanf_s("%d",&stu[i].familyNum);
fflush(stdin);
printf("请输入第%d 名学生家庭收入:", i + 1);
scanf_s("%d", &stu[i].fincome);
getchar();
fprintf(fp, "%10s %10s %s %10s %10s %s ", stu[i].name, stu[i].num, stu[i].sex, stu[i].dep,stu[i].province, stu[i].mode);
if (!atoi(stu[i].mode)) {
for (int t = 0; t < 4; t++)
fprintf(fp, "%s ", stu[i].score[t]);
}
else for (int t = 0; t < 9; t++)fprintf(fp, "%s ", stu[i].score[t]);
fprintf(fp, "%10s %10s %d %d\n", stu[i].ethnic, stu[i].pro,stu[i].familyNum, stu[i].fincome);
}
printf("-------------------------------------------------------------------------------\n");
printf("是否继续输入?([Y].是/[任意键].否)\n");
t = _getch();
} while (t == 'Y' || t == 'y');
printf("-------------------------------------------------------------------------------\n");
printf("信息已保存,按任意键返回主菜单!");
_getch();
fclose(fp);
}
(4)void Modify_Information(); //修改学生基本信息
1、以姓名为标识符遍历文件,找到对应学生
2、将对应学生的数据读入结构体,输入修改内容对待修改数据进行覆盖
3、通过fseek将文件读取指针返回本行开头
4、重新写入数据
贴代码如下:
void Modify_Information()
{
FILE* fp;
char str[N];
char t;
int i = -1, x = 0;
int j, m;
time_t now;
struct tm e;
time(&now);
localtime_s(&e, &now);
fopen_s(&fp,"C:\\Users\\80958\\Desktop\\test00.txt", "r+");
printf("-------------------------------------------------------------------------------\n");
printf("\t姓名\t学号\t性别\t系别\t籍贯\t高考模式\t高考成绩\t\t\t民族\t专业\t家庭人数\t家庭收入\n");
printf("-------------------------------------------------------------------------------\n");
while (!feof(fp))
{
i++;
fscanf_s(fp, "%10s %10s %s %10s %10s %s ", stu[i].name, 10, stu[i].num, 10, stu[i].sex, 3, stu[i].dep, 10, stu[i].province, 10, stu[i].mode, 3);
if (!atoi(stu[i].mode)) {
for (int t = 0; t < 4; t++)
fscanf_s(fp, "%s", stu[i].score[t], 5);
}
else for (int t = 0; t < 9; t++)fscanf_s(fp, "%s", stu[i].score[t], 5);
fscanf_s(fp, "%10s %10s %d %d", stu[i].ethnic, 10, stu[i].pro, 10, &stu[i].familyNum, &stu[i].fincome);
printf("%10s %10s %s %10s %10s %s ", stu[i].name, stu[i].num, stu[i].sex, stu[i].dep, stu[i].province, stu[i].mode);
if (!atoi(stu[i].mode)) {
for (int t = 0; t < 4; t++)
printf("%s", stu[i].score[t]);
}
else for (int t = 0; t < 9; t++)
printf("%s", stu[i].score[t]);
printf("%10s %10s %d %d", stu[i].ethnic, stu[i].pro, stu[i].familyNum, stu[i].fincome);
printf("\n-------------------------------------------------------------------------------\n");
}
do
{
printf("-------------------------------------------------------------------------------\n");
printf("请输入要修改信息的学生姓名:");
fflush(stdin);
scanf_s("%s",str,10);
getchar();
for (j = 0; j < (i + 1); j++)
{
if (strcmp(str, stu[j].name) == 0)
{
printf("----------------------------------------------------------------------------------------\n");
printf("\t姓名\t学号\t性别\t系别\t籍贯\t高考模式\t高考成绩\t\t\t民族\t专业\t家庭人数\t家庭收入\n");
printf("----------------------------------------------------------------------------------------\n");
printf("%10s %10s %s %10s %10s %s ", stu[j].name, stu[j].num, stu[j].sex, stu[j].dep, stu[j].province, stu[j].mode);
if (!atoi(stu[j].mode)) {
for (int t = 0; t < 4; t++)printf("%s", stu[j].score[t]);
}
else for (int t = 0; t < 9; t++)printf("%s", stu[j].score[t]);
printf("%10s %10s %d %d", stu[j].ethnic, stu[j].pro, stu[j].familyNum, stu[j].fincome);
printf("\n-------------------------------------------------------------------------------\n");
printf("1.姓名2.学号3.性别4.系别5.籍贯6.高考模式7.高考成绩8.民族9.专业10.家庭人数11.家庭收入\n输入要修改的信息:");
scanf_s("%d", &x);
printf("-------------------------------------------------------------------------------\n");
system("cls");
switch (x)
{
case 1:
fflush(stdin);
printf("修改该学生姓名:");
scanf_s("%10s",stu[j].name,10);
getchar();
printf("-------------------------------------------------------------------------------\n");
fseek(fp, j * 96, 0);
fprintf(fp, "%10s %10s %s %10s %10s %s ", stu[j].name, stu[j].num, stu[j].sex, stu[j].dep, stu[j].province, stu[j].mode);
if (!atoi(stu[j].mode)) {
for (int t = 0; t < 4; t++)fprintf(fp, "%s ", stu[j].score[t]);
}
else for (int t = 0; t < 9; t++)fprintf(fp, "%s ", stu[j].score[t]);
fprintf(fp, "%10s %10s %d %d\n", stu[j].ethnic, stu[j].pro, stu[j].familyNum, stu[j].fincome);
break;
case 2:
fflush(stdin);
printf("修改该学生学号:");
scanf_s("%10s",stu[j].num,10);
getchar();
while ((strlen(stu[j].num) != 8)