0%

C语言学生成绩管理系统

C语言 学生成绩管理系统

简述:该学生管理系统数据结构采用结构体

1、系统需求分析

1.1系统介绍

本学生管理系统是为教师人员提供管理班级成绩的工具,该系统可以实现的对学生的成绩进行增、删、改、查、信息保存和信息导入等基本功能,以及对学生成绩排序和分段的扩展功能,有利于对学生成绩管理。

1.2功能性需求

(1) 成绩录入

(2) 成绩输出、成绩排序(按平均成绩)

(3) 成绩查找

(4) 成绩修改

(5) 删除成绩

(6) 文件存储、文件导入

1.3非功能性需求

(1) 友好的交互页面

(2) 登陆密码设置

(3) 数据的保护

2、程序结构设计

该该系统总体的流程图框架如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
graph TD
学生成绩管理系统 -->A[登 陆 界 面]
A-->B[菜 单 界 面]
B-->录入成绩
B-->输出成绩
B-->C[成绩排序]
B-->D[成绩查找]
D-->按学号查找
D-->按姓名查找
B-->成绩修改
B-->F[成绩删除]
F-->按学号删除
F-->按姓名删除
B-->E[文件管理]
E-->文件导入
E-->文件保存

3、用户界面设计

登陆界面

登陆界面根据自己的需要进行设计,尽量设计的和谐美观。
如我的登陆界面额外添加了获取时间和登陆密码功能!
以下展示主要代码和效果展示。

获取时间代码

1
2
3
4
5
6
   time_t timep;    //系统时间 
struct tm *p_1;
time (&timep);
p_1=gmtime(&timep);
printf("\t\t\t\t\t\t 当前时间%02d时%02d分%\n",8+p_1->tm_hour,p_1->tm_min);
printf("\t\t\t\t\t\t %d年%02d月%02d日\n",1900+p_1->tm_year,1+p_1->tm_mon,p_1->tm_mday);
1
2
3
4
5
6
7
8
printf("\t★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n\n");
printf("\t★\t\t\t\t\t有朋自远方来,不亦乐乎! \t\t\t\t\t★\n\n");
printf("\t★\t\t\t*****************************************************\t\t\t\t★\n\n");
printf("\t★\t\t\t\t\t 学 生 管 理 系 统\t\t\t\t\t\t★\n\n");
printf("\t★\t\t\t 制作者:Mr.Wang 专业:软件工程1801 学号:************\t\t\t\t★\n\n");
printf("\t★\t\t\t*****************************************************\t\t\t\t★\n\n");
printf("\t★\t\t\t 欢迎使用软件工程18-01的学生管理系统,祝您使用愉快! \t\t\t\t★\n\n");
printf("\t★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n\n");

如图:登陆界面

菜单界面

进入页面后设计一个菜单界面,也就是功能界面,在该界面上进行操作

1
2
3
4
5
printf("\t\t★————————————————————————————————————————★\n\n");
printf("\t\t\t | 1. 成绩录入\t\t2. 成绩显示\t\t3. 各科均分 |\n\n");
printf("\t\t\t | 4. 成绩排序\t\t5. 成绩查找\t\t6. 信息修改 |\n\n");
printf("\t\t\t | 7. 删除成绩\t\t8. 成绩分段\t\t0. 退出系统 |\n\n");
printf("\t\t★————————————————————————————————————————★\n");

展示如下:

登陆界面

4、功能设计

在该模块中,将会介绍程序的主要功能实现的设计思想和代码

4.1成绩录入

设计思想

成绩录入是对结构体中班级、姓名、学号和五门成绩的录入,同时加上对五门成绩平均成绩的计算。按照基本的录入,只需用scanf函数对数据输入,用printf函数进行汉字的打印即可。然后进行文件保存该组数据,最后判断是否继续录入。

流程图如下

input
代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//*************************************
//*************************************
//学生成绩录入
void input(struct Student stu[])
{
void save(struct Student stu[]);//声明保存文件函数
int choose;
int i;
char tempcla[10]={"-1"}; //定义临时姓名字符串,用于按(-1)返回菜单
a:
system("cls"); //清屏
fflush(stdin); //清空缓存区
printf("成 绩 录 入\n");
printf("************************************************************************************************************\n");
printf("请依次输入\t\t班级、姓名、 学号、 五门课成绩(高数 英语 C语言 计算机基础 软件工程导论)\n");
printf("班级(按-1返回菜单):"); //输入班级
while(scanf("%s",stu[count].cla)==0) //判断返回值,除去类型错误bug
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
if(strcmp(stu[count].cla,tempcla)==0) //按-1返回菜单
{
printf("\n按任意键返回菜单!\n\n");
system("pause");
return;
}
while(strlen(stu[count].cla)>10) //判断字符长度
{
fflush(stdin);
printf("班级输入不合理,请重新录入:");
scanf("%s",stu[count].cla);
}
printf("\n姓名:"); //输入姓名
fflush(stdin);
while(scanf("%s",stu[count].name)==0)
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
while(strlen(stu[count].name)>7)
{
fflush(stdin);
printf("姓名不合理,请重新录入:");
scanf("%s",stu[count].name);
}
printf("\n学号:"); //输入姓名
w:
fflush(stdin);
while(scanf("%lld",&stu[count].num)==0)
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
for(i=0;i<count;i++) //判断重复学号
{
if(stu[count].num==stu[i].num)
{
printf("已有该学号,请重新输入:\n");
goto w;
}
}
printf("\n高数(0~100):"); //输入高数
fflush(stdin);
while(scanf("%f",&stu[count].score[0])==0)
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
while(stu[count].score[0]<0||stu[count].score[0]>100)
{
fflush(stdin);
printf("数据超出,请重新输入:");
scanf("%f",&stu[count].score[0]);
}
printf("\n英语(0~100):"); //输入英语
fflush(stdin);
while(scanf("%f",&stu[count].score[1])==0)
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
while(stu[count].score[1]<0||stu[count].score[1]>100)
{
fflush(stdin);
printf("数据超出,请重新输入:");
scanf("%f",&stu[count].score[1]);
}
printf("\nC语言(0~100):"); //输入C语言
fflush(stdin);
while(scanf("%f",&stu[count].score[2])==0)
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
while(stu[count].score[2]<0||stu[count].score[2]>100)
{
fflush(stdin);
printf("数据超出,请重新输入:");
scanf("%f",&stu[count].score[2]);
}
printf("\n计算机基础(0~100):"); //输入计算机基础
fflush(stdin);
while(scanf("%f",&stu[count].score[3])==0)
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
while(stu[count].score[3]<0||stu[count].score[3]>100)
{
fflush(stdin);
printf("数据超出,请重新输入:");
scanf("%f",&stu[count].score[3]);
}
printf("\n软件工程导论(0~100):"); //输入软件工程导论
fflush(stdin);
while(scanf("%f",&stu[count].score[4])==0)
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
while(stu[count].score[4]<0||stu[count].score[4]>100)
{
fflush(stdin);
printf("数据超出,请重新输入:");
scanf("%f",&stu[count].score[4]);
}
stu[count].aver=(stu[count].score[0]+stu[count].score[1]+stu[count].score[2]+stu[count].score[3]+stu[count].score[4])/5.0;//计算平均成绩
count++; //结构体数据数+1
save(p); //保存文件
fflush(stdin);
printf("是否继续录入:\n\n");
printf("1.是 2.否\n");
fflush(stdin);
printf("\n请选择:");
b:
while(scanf("%d",&choose)==0)
{
printf("您输入的格式错误,请重新输入:\n");
fflush(stdin);
goto b;
}
switch(choose)
{
case 1:goto a;break;
case 2:return;break;
default:printf("没有该序号,请重新输入:");goto b;
}
}

部分代码说明

1
2
3
4
5
6
7
8
9
while(scanf("%s",stu[count].cla)==0)   //判断返回值,除去类型错误bug 
{
fflush(stdin);
printf("格式有误,请重新输入:");
}

//在输入成绩时通常直接使用scanf,但当我们做项目时,为了具有一定的容错性,需要判断输入数据的类型和
//判断scanf的返回值,如果直接使用scanf,输入其它类型的数据,程序将会炸掉,因此我们需要用这种形式
//保证系统正常运行

scanf的返回值具体解释见他人解释,地址如下:
(https://blog.csdn.net/zhl254467014/article/details/44183567)

为了方便其它功能的实现,在这里需要判断学号是否重复,保证学号的唯一性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
w:
fflush(stdin);
while(scanf("%lld",&stu[count].num)==0)
{
fflush(stdin);
printf("格式有误,请重新输入:");
}
for(i=0;i<count;i++) //判断重复学号
{
if(stu[count].num==stu[i].num)
{
printf("已有该学号,请重新输入:\n");
goto w;
}
}

4.2成绩显示

由于我想按照平均成绩排序的方式输出,因此直接调用该函数

1
2
3
4
5
6
7
8
9
10
11
//*************************************
//*************************************
//学生成绩显示
void print(struct Student stu[])
{
void sort(struct Student stu[]);//声明平均成绩排序函数
system("cls");//清屏函数
if(count==0) printf("\n您尚未录入学生信息,请返回菜单进行录入!\n");
sort(p); //排序函数
return;
}

4.3成绩排序

排序思想:
成绩排序是将结构体中的数据按平均成绩进行排序,在本系统中,我将成绩排序非为按五门成绩排序和平均成绩排序,排序的思想是运用冒泡排序。在此功能中需注意的是排序时要将整组数据随着平均成绩一起改变,最后不能出现平均成绩与信息对应不上。其次在进行字符串互换的时候不能直接赋值号进行互换,要用strcpy函数进行复制,在这里只展示按平均成绩排序的代码,其它成绩排序与之相似

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//*************************************
//*************************************
//平均成绩排序
void sort(struct Student stu[])
{
void save(struct Student stu[]);
system("cls");
fflush(stdin);
char tempname[20]; //临时变量
char tempcla[20];
int i,j;
long long int t1;
float t;
if(count==0) printf("\n\n您尚未录入学生信息,请返回菜单进行录入!\n\n");
else
{
printf("\n成绩显示(按平均成绩排序)\n"); //冒泡排序
for(i=0;i<count-1;i++)
{
for(j=0;j<count-i-1;j++)
{
if(stu[j].aver<stu[j+1].aver) //注意字符串的复制
{
strcpy(tempcla,stu[j].cla);strcpy(stu[j].cla,stu[j+1].cla);strcpy(stu[j+1].cla,tempcla);
strcpy(tempname,stu[j].name);strcpy(stu[j].name,stu[j+1].name);strcpy(stu[j+1].name,tempname);
t1=stu[j].num;stu[j].num=stu[j+1].num;stu[j+1].num=t1;
t=stu[j].score[0];stu[j].score[0]=stu[j+1].score[0];stu[j+1].score[0]=t;
t=stu[j].score[1];stu[j].score[1]=stu[j+1].score[1];stu[j+1].score[1]=t;
t=stu[j].score[2];stu[j].score[2]=stu[j+1].score[2];stu[j+1].score[2]=t;
t=stu[j].score[3];stu[j].score[3]=stu[j+1].score[3];stu[j+1].score[3]=t;
t=stu[j].score[4];stu[j].score[4]=stu[j+1].score[4];stu[j+1].score[4]=t;
t=stu[j].aver;stu[j].aver=stu[j+1].aver;stu[j+1].aver=t;

}
}

}
printf("************************************************************************************************************\n");
printf("\t班级\t姓名\t学号\t\t高数\t英语\tC语言\t计算机基础\t软件工程导论\t平均成绩\t\n");
printf("************************************************************************************************************\n");
for(i=0;i<count;i++)
printf("\t%-8s%-8s%-16lld%-8.2lf%-8.2lf%-8.2lf%-16.2lf%-16.2lf%-12.2lf\n",stu[i].cla,stu[i].name,stu[i].num,
stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
save(p); //保存文件
}
system("pause");
return;
}

4.4成绩查找

设计思想:
成绩查找需要实现的是按学号和姓名查找到学生的所有信息,然后打印出来。该功能的思想是输入学号或姓名,然后在循环体中对结构体进行遍历,找到所查到的结构体的下标值,然后将该下标值对应学生的信息打印出来。按照姓名查询时,判断字符串是否相等需要用strcmp函数。在循环体中对结构体进行遍历的时候,找到的时候,可以用break跳出循环,提高效率。

流程图如下:

search

代码展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//*************************************
//*************************************
//按学号查询
void findnum(struct Student stu[])
{
int i;
int searchindex=-1; //定义下表值
long long int searchnum;
fflush(stdin);
printf("\n请输入查询成绩的学生学号:");
scanf("%lld",&searchnum);
for(i=0;i<count;i++)
{
if(searchnum==stu[i].num)
{
system("cls");
searchindex=i;
printf("************************************************************************************************************\n");
printf("\t班级\t姓名\t学号\t\t高数\t英语\tC语言\t计算机基础\t软件工程导论\t平均成绩\t\n");
printf("************************************************************************************************************\n");
printf("\t%-8s%-8s%-16lld%-8.2lf%-8.2lf%-8.2lf%-16.2lf%-16.2lf%-12.2lf\n\n",stu[i].cla,stu[i].name,stu[i].num,
stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
break; //找到后跳出
}
}
if(searchindex==-1)
printf("\n很抱歉,没有找到该学生的学号!\n\n");
printf("\n按任意键返回成绩查询\n\n");
system("pause");
return;
}
//*************************************
//*************************************
//按姓名查询
void findname(struct Student stu[])
{
int i;
char searchname[20];
int searchindex=-1;
fflush(stdin);
printf("\n请输入查询成绩学生的姓名:\n");
scanf("%s",searchname);
for(i=0;i<count;i++) //循环寻找姓名
{
if(strcmp(searchname,stu[i].name)==0)
{
system("cls");
searchindex=i;
printf("************************************************************************************************************\n");
printf("\t班级\t姓名\t学号\t\t高数\t英语\tC语言\t计算机基础\t软件工程导论\t平均成绩\t\n");
printf("************************************************************************************************************\n");
printf("\t%-8s%-8s%-16lld%-8.2lf%-8.2lf%-8.2lf%-16.2lf%-16.2lf%-12.2lf\n\n",stu[i].cla,stu[i].name,stu[i].num,
stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
break;//找到跳出
}
}
if(searchindex==-1)
printf("\n很抱歉,没有找到该学生的姓名!\n\n");
printf("\n按任意键返回成绩查询\n\n");
system("pause");
return;
}
//*************************************
//*************************************
//成绩查询
void find(struct Student stu[])
{
if(count==0)
{
printf("\n\n您尚未录入学生信息,请返回菜单进行录入!\n\n");
system("pause");
return;
}
int choose;
system("cls");
fflush(stdin);
choose: //成绩查询页面菜单
printf("\n\t\t\t\t\t\t 成绩查询\n\n");
printf("\t\t\t\t\t*****************************\n\n");
printf("\t\t\t\t\t |1.按学号查找 2.按姓名查找|\n\n");
printf("\t\t\t\t\t |3.全部显示 4.返回菜单 |\n\n");
printf("\t\t\t\t\t*****************************\n");
printf("\t\t\t\t\t\n请输入查询方式:");
a:
while(scanf("%d",&choose)==0)
{
printf("输入格式有误,请您重新输入:");
fflush(stdin);
}
switch(choose)
{
case 1:
findnum(p);
system("cls");
goto choose;
break;
case 2:
findname(p);
system("cls");
goto choose;
break;
case 3:
print(p);
system("cls");
goto choose;
break;
case 4:
printf("\n按任意键返回菜单!\n\n");
system("pause");
return;
default:
printf("没有该序号,请您重新输入:");goto a;
}
}

4.5成绩修改

该功能与录入成绩功能相似,成绩修改是对结构体中的信息进行修改,首先找到需要修改同学结构体的下标值,然后对该下标值对应的信息进行覆盖修改,该信息修改的录入与成绩录入功能的录入相同,同样需要注意与成绩录入时的漏洞。过多的不说了,直接上代码,依据我的需求,代码较多,仅供参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
******************************
//修改成绩
void change(struct Student stu[])
{
void save(struct Student stu[]);
int i,j;
int choose;
long long int searchnum,tempnum;
int searchindex=-1;
if(count==0)
{
printf("\n\n您尚未录入学生信息,请返回菜单进行录入!\n\n");
system("pause");
return;
}
a:
system("cls");
printf("\n修改成绩!\n\n");
fflush(stdin);
printf("************************************************\n");
printf("\n请输入修改学生的学号:(按-1返回菜单)");
scanf("%lld",&searchnum);
fflush(stdin);
if(searchnum==-1)
{
printf("\n按任意键返回菜单!\n\n");
system("pause");
return;
}
system("cls");
for(i=0;i<count;i++)
{
if(searchnum==stu[i].num)
{
searchindex=i;
printf("\n该学生信息:\n"); //修改成绩页面菜单
printf("************************************************************************************************************\n");
printf("\t班级\t姓名\t学号\t\t高数\t英语\tC语言\t计算机基础\t软件工程导论\t平均成绩\t\n");
printf("************************************************************************************************************\n");
printf("\t%-8s%-8s%-16lld%-8.2lf%-8.2lf%-8.2lf%-16.2lf%-16.2lf%-12.2lf\n\n",stu[i].cla,stu[i].name,stu[i].num,
stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
printf("************************************************\n");
printf("|1.修改班级\t 2. 修改姓名 |\n");
printf("|3.修改学号\t 4. 修改高数 |\n");
printf("|5.修改英语\t 6. 修改C语言 |\n");
printf("|7.修改计算机基础 8. 修改软件工程导论 |\n");
printf("|9.返回菜单\t |\n");
printf("************************************************\n");
printf("请选择修改的信息:");
choose:
while(scanf("%d",&choose)==0)
{
printf("输入格式有误,请您重新输入:");
fflush(stdin);
}
switch(choose)
{
case 1:
fflush(stdin);
printf("请修改班级:");
while(scanf("%s",stu[i].cla)==0)
{
printf("格式有误,请重新输入:");
fflush(stdin);
}
while(strlen(stu[count].cla)>10) //判断字符长度
{
printf("班级输入不合理,请重新录入:");
fflush(stdin);
scanf("%s",stu[count].cla);
}
break;
case 2:
fflush(stdin);
printf("请修改姓名:");
while(scanf("%s",stu[i].name)==0)
{
printf("格式有误,请重新输入:");
fflush(stdin);
}
while(strlen(stu[count].name)>10) //判断字符长度
{
printf("班级输入不合理,请重新录入:");
fflush(stdin);
scanf("%s",stu[count].name);
}
break;
case 3:
fflush(stdin);
printf("请修改学号:");
w:
while(scanf("%lld",&stu[i].num)==0)
{
printf("格式有误,请重新输入:");
fflush(stdin);
}
tempnum=stu[i].num;
stu[i].num=0;
for(j=0;j<count;j++)
{
if(tempnum==stu[j].num)
{
printf("已有该学号,请重新输入:\n");
goto w;
}
}
stu[i].num=tempnum;
break;
case 4:
fflush(stdin);
printf("请修改高数:");
while(scanf("%f",&stu[i].score[0])==0)
{
printf("格式有误,请重新输入:");
fflush(stdin);
}
while(stu[i].score[0]<0||stu[i].score[0]>100)
{
printf("格式有误,请重新输入:");
fflush(stdin);
scanf("%f",&stu[i].score[0]);
}
break;
case 5:
fflush(stdin);
printf("请修改英语:");
while(scanf("%f",&stu[i].score[1])==0)
{
printf("格式有误,请重新输入:");
fflush(stdin);
}
while(stu[i].score[1]<0||stu[i].score[1]>100)
{
printf("格式有误,请重新输入:");
fflush(stdin);
scanf("%f",&stu[i].score[1]);
}
break;
case 6:
fflush(stdin);
printf("请修改C语言:");
while(scanf("%f",&stu[i].score[2])==0)
{
printf("格式有误,请重新输入:");
fflush(stdin);
}
while(stu[i].score[2]<0||stu[i].score[2]>100)
{
printf("格式有误,请重新输入:");
fflush(stdin);
scanf("%f",&stu[i].score[2]);
}
break;
case 7:
fflush(stdin);
printf("请修改计算机基础:");
while(scanf("%f",&stu[i].score[3])==0)
{
printf("格式有误,请重新输入:");
fflush(stdin);
}
while(stu[i].score[3]<0||stu[i].score[3]>100)
{
printf("格式有误,请重新输入:");
fflush(stdin);
scanf("%f",&stu[i].score[3]);
}
break;
case 8:
fflush(stdin);
printf("请修改软件工程导论:");
while(scanf("%f",&stu[i].score[4])==0)
{
printf("格式有误,请重新输入:");
fflush(stdin);
}
while(stu[i].score[4]<0||stu[i].score[4]>100)
{
printf("格式有误,请重新输入:");
fflush(stdin);
scanf("%f",&stu[i].score[4]);
}
break;
case 9:
printf("\n按任意键返回菜单!\n\n");
save(p);
return;
default:
printf("没有该序号,请您重新输入:");
goto choose;
}//switch结尾处
stu[i].aver=(stu[i].score[0]+stu[i].score[1]+stu[i].score[2]+stu[i].score[3]+stu[i].score[4])/5.0;
printf("\n修改成功:\n");
printf("************************************************************************************************************\n");
printf("\t班级\t姓名\t学号\t\t高数\t英语\tC语言\t计算机基础\t软件工程导论\t平均成绩\t\n");
printf("************************************************************************************************************\n");
printf("\t%-8s%-8s%-16lld%-8.2lf%-8.2lf%-8.2lf%-16.2lf%-16.2lf%-12.2lf\n\n",stu[i].cla,stu[i].name,stu[i].num,
stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
}//if结束处
}//for结束处
if(searchindex==-1)
{
printf("\n很抱歉,未能找到该学生,请重新输入学号!\n\n");
system("pause");
goto a;
}
save(p);
system("pause");
return;
}

4.6成绩删除

设计思想:
删除成绩是对结构体中的信息进行删除,其实对于C语言无法进行删除本身的意义,只是做出了一些假像,其实删除成绩就是覆盖成绩。删除成绩分为按学号删除和按姓名删除。删除成绩的思想为覆盖,首先通过结构体的遍历找到所删学生信息的下标值,然
后从该下标值开始,后面一个学生信息覆盖前面一个学生的信息,最后最关键的一点是将全局变量count即结构体组数-1

流程图如下:

delete
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//*************************************
//*************************************
//删除成绩
void del(struct Student stu[])
{
void delnum(struct Student stu[]);
void delname(struct Student stu[]);
void save(struct Student stu[]);
int choose;
if(count==0)
{
printf("\n\n您尚未录入学生信息,请返回菜单进行录入!\n\n");
system("pause");
return;
}
choose:
fflush(stdin); //删除成绩页面菜单
printf("\n\t\t\t\t\t 删除成绩\n\n");
printf("\t\t\t\t********************************\n\n");
printf(" \t\t\t\t\t 1.按学号删除\n\n\t\t\t\t\t 2.按姓名删除\n\n\t\t\t\t\t 3.返回菜单\n\n");
printf("\t\t\t\t********************************\n\n");
printf("请输入删除方式:");
a:
while(scanf("%d",&choose)==0)
{
printf("输入格式有误,请您重新输入:");
fflush(stdin);
}
switch(choose)
{
case 1:
delnum(p);
save(p);
system("cls");
goto choose;
break;
case 2:
delname(p);
save(p);
system("cls");
goto choose;
break;
case 3:
printf("\n按任意键返回菜单!\n\n");
system("pause");
return;
default:
printf("没有该序号,请您重新输入:");goto a;
}

}
//*************************************
//*************************************
//按学号删除成绩
void delnum(struct Student stu[])
{
void print(struct Student stu[]);
int i,choose;
int searchindex=-1;
long long int deletenum;
fflush(stdin);
printf("请输入要删除学生的学号(按-1返回):");
scanf("%lld",&deletenum);
printf("是否确定删除:\n");
fflush(stdin);
printf("1.是 2.否\n");
fflush(stdin);
printf("请选择:");
b:
while(scanf("%d",&choose)==0)
{
printf("您输入的格式错误,请重新输入:\n");
fflush(stdin);
goto b;
}
switch(choose)
{
case 1:break;
case 2:return;break;
default:printf("没有该序号,请重新输入:");goto b;
}
if(deletenum==-1)
{
printf("\n按任意键返回删除成绩!\n\n");
system("pause");
return;
}
for(i=0;i<count;i++)
{
if(deletenum==stu[i].num)
{
searchindex=i;
break;
}
}
if(searchindex==-1)
{
printf("\n很遗憾,未能找到所要删除学生的学号!\n");
printf("\n按任意键返回菜单\n\n");
system("pause");
return;
}
else //查找信息后,每组数据往前进行覆盖
{
for(i=searchindex;i<count-1;i++)
{
strcpy(stu[i].cla,stu[i+1].cla);
stu[i].num=stu[i+1].num;
strcpy(stu[i].name,stu[i+1].name);
stu[i].score[0]=stu[i+1].score[0];
stu[i].score[1]=stu[i+1].score[1];
stu[i].score[2]=stu[i+1].score[2];
stu[i].score[3]=stu[i+1].score[3];
stu[i].score[4]=stu[i+1].score[4];
stu[i].aver=stu[i+1].aver;
}
count--; //总数据组-1
}
if(count==0)
{
printf("\n目前没有学生信息,请返回菜单录入!\n\n");
system("pause");
return;
}
system("cls"); //删除后进行打印
printf("\n删除成功!\n\n");
printf("************************************************************************************************************\n");
printf("\t班级\t姓名\t学号\t\t高数\t英语\tC语言\t计算机基础\t软件工程导论\t平均成绩\t\n");
printf("************************************************************************************************************\n");
for(i=0;i<count;i++)
printf("\t%-8s%-8s%-16lld%-8.2lf%-8.2lf%-8.2lf%-16.2lf%-16.2lf%-12.2lf\n",stu[i].cla,stu[i].name,stu[i].num,
stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
printf("\n按任意键返回菜单\n\n");
system("pause");
return;
}
//*************************************
//*************************************
//按姓名删除成绩
void delname(struct Student stu[])
{
void print(struct Student stu[]);
int i,choose;
char tempname[10]={"-1"};
int searchindex=-1;
char deletename[20];
fflush(stdin);
printf("请输入要删除学生的姓名(按-1返回):");
scanf("%s",deletename);
printf("是否确定删除:\n");
fflush(stdin);
printf("1.是 2.否\n");
fflush(stdin);
printf("请选择:");
b:
while(scanf("%d",&choose)==0)
{
printf("您输入的格式错误,请重新输入:\n");
fflush(stdin);
goto b;
}
switch(choose)
{
case 1:;break;
case 2:return;break;
default:printf("没有该序号,请重新输入:");goto b;
}
if(strcmp(deletename,tempname)==0)
{
printf("\n按任意键返回删除成绩!\n\n");
system("pause");
return;
}
for(i=0;i<count;i++)
{
if(strcmp(deletename,stu[i].name)==0)
{
searchindex=i;
break;
}
}
if(searchindex==-1)
{
printf("\n很遗憾,未能找到所要删除学生的姓名!\n");
printf("\n按任意键返回菜单\n\n");
system("pause");
return;
}
else
{
for(i=searchindex;i<count-1;i++)
{
strcpy(stu[i].cla,stu[i+1].cla);
stu[i].num=stu[i+1].num;
strcpy(stu[i].name,stu[i+1].name);
stu[i].score[0]=stu[i+1].score[0];
stu[i].score[1]=stu[i+1].score[1];
stu[i].score[2]=stu[i+1].score[2];
stu[i].score[3]=stu[i+1].score[3];
stu[i].score[4]=stu[i+1].score[4];
stu[i].aver=stu[i+1].aver;
}
count--;
}
printf("\n");
printf("\n删除成功!\n\n");
if(count==0)
{
printf("\n目前没有学生信息,请返回菜单录入!\n\n");
system("pause");
return;
}
system("cls");
printf("\n删除成功!\n\n");
printf("************************************************************************************************************\n");
printf("\t班级\t姓名\t学号\t\t高数\t英语\tC语言\t计算机基础\t软件工程导论\t平均成绩\t\n");
printf("************************************************************************************************************\n");
for(i=0;i<count;i++)
printf("\t%-8s%-8s%-16lld%-8.2lf%-8.2lf%-8.2lf%-16.2lf%-16.2lf%-12.2lf\n",stu[i].cla,stu[i].name,stu[i].num,
stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
printf("\n按任意键返回菜单\n\n");
system("pause");
return;
}

核心代码如下,请好好理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
for(i=0;i<count;i++){
if(deletenum==stu[i].num)
{
searchindex=i;
break;
}
}
//查找信息后,每组数据往前进行覆盖
for(i=searchindex;i<count-1;i++)
{
strcpy(stu[i].cla,stu[i+1].cla);
stu[i].num=stu[i+1].num;
strcpy(stu[i].name,stu[i+1].name);
stu[i].score[0]=stu[i+1].score[0];
stu[i].score[1]=stu[i+1].score[1];
stu[i].score[2]=stu[i+1].score[2];
stu[i].score[3]=stu[i+1].score[3];
stu[i].score[4]=stu[i+1].score[4];
stu[i].aver=stu[i+1].aver;
}
count--; //总数据组数-1

4.7文件保存

文件存储简要介绍:

文件存储是将程序中的数据存储如磁盘中,生成文件。在我们没有进行保存之前,我们每次进入系统都要进行录入,如果数据很多,那么操作十分复杂。所有我们需要对数据进行存储。然后进入系统时进行导入,文件的存储分为两种方法,一种是十进制进行存储,另一种是二进制进行存储。这两种方式都可以对数据进行存储,但每种方式都有其的优点和缺点,对于第一种十进制存储,用fprintf函数对磁盘写入,它的优点是格式化输出,在磁盘中可查看数据,也可进行修改使用方便,容易理解,缺点是由于在输入时要将文件中的ASCII码转换为二进制形式在保存在内存变量中,在输出时又要将内存的二进制形式转换成字符,要花费较多时间。并且数据可被其他人查看和修改,在保存数据时需要进行进制转换,可能会造成数据错误。对于二进制存储,用fwrite函数对磁盘文件进行写,优点是fwrite函数可向文件写一个数据块,在读写时以二进制形式进行的。在向磁盘写数据时,直接将内存中一组数据原封不动、不加转换地复制到磁盘文件上,不需要进制转换,运行速度高。其缺点是生成二进制文件,信息是一堆乱码,但是该文件安全系数高,他人无法查看文件内容,对文件数据进行保护。

我的文件是使用二进制存储
具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
void save(struct Student stu[])
{
int i;
FILE*fp;
fp=fopen("student.bat","wb");
for(i = 0; i < count; i++)
{
if(fwrite(&stu[i],sizeof(struct Student),1,fp)!=1)
printf("file write error\n");
}
fclose(fp);
printf("\n已保存至文件中\n\n");
}

鉴于有些人使用十进制文件,我这里也写了,代码如下:

1
2
3
4
5
6
7
8
9
10
11
FILE *fp;
int i;
if((fp=fopen("student.txt","w"))==NULL)
{
printf("error");
exit(0);
}
for(i = 0; i < count; i++)
fprintf(fp,"\t%-8s%-8s%-16lld%-8.2lf%-8.2lf%-8.2lf%-16.2lf%-16.2lf%-12.2lf\n",stu[i].cla,stu[i].name,stu[i].num,stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
printf("save success!\n");
fclose(fp);

4.7文件保存

简要概述
文件导入是对磁盘中的数据导入进学生管理系统的结构体中,对数据进行使用。文件导入是与文件存储相对应,十进制导入对应十进制存储,二进制导入对应二进制存储。因此文件导入也分为两种,十进制导入用fscanf,二进制文件导入用fread

这里同样展示两种方式
首先是二进制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//文件导入
void read(struct Student stu[])
{
int i;
FILE*fp;
if((fp=fopen("student.bat","rb"))==NULL)
return;
for(i=0;i<1000;i++)
{
if(fread(&stu[i],sizeof(struct Student),1,fp)!=1)
{
if(feof(fp))
{
fclose(fp);
goto a;
}
printf("file read error\n");
}
count++; //存入一个,数据组数+1
}
fclose(fp);
a:
printf("\n导入文件已成功,祝您使用愉快!\n\n");
printf("请按任意键进入页面菜单!\n\n");
system("pause");
return;
}

二进制形式

1
2
3
4
5
6
while(num!=EOF){
num=fscanf(fp,"%s %s %lld %f %f %f %f %f %f\n",stu[i].cla,stu[i].name,stu[i].num,
stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3],stu[i].score[4],stu[i].aver);
count++; //存入一个,数据组数+1
}
count--;

4.8主函数代码

主函数代码展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//*************************************
//*************************************
//主函数
int main()
{
system("color 9E"); //设置背景颜色
int i=4;
char code[20]={'1','2','3','4','5','6'},password[20];
int x;
char c;
//初始页面
time_t timep; //系统时间
struct tm *p_1;
time (&timep);
p_1=gmtime(&timep);
printf("\t\t\t\t\t\t 当前时间%02d时%02d分%\n",8+p_1->tm_hour,p_1->tm_min);
printf("\t\t\t\t\t\t %d年%02d月%02d日\n",1900+p_1->tm_year,1+p_1->tm_mon,p_1->tm_mday);
printf("\t★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n\n");
printf("\t★\t\t\t\t\t有朋自远方来,不亦乐乎! \t\t\t\t\t★\n\n");
printf("\t★\t\t\t*****************************************************\t\t\t\t★\n\n");
printf("\t★\t\t\t\t\t 学 生 管 理 系 统\t\t\t\t\t\t★\n\n");
printf("\t★\t\t\t 制作者:Mr.Wang 专业:软件工程1801 学号:************\t\t\t\t★\n\n");
printf("\t★\t\t\t*****************************************************\t\t\t\t★\n\n");
printf("\t★\t\t\t 欢迎使用软件工程18-01的学生管理系统,祝您使用愉快! \t\t\t\t★\n\n");
printf("\t★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n\n");
printf("请输入六位登陆密码!\n");
q:
x=0;
while(x<6 && c!=13)
{
c=getch();
if(c!=13)
putchar('*');
password[x++]=c;
}
password[x]='\0';
if(strcmp(password,code)!=0)
{
fflush(stdin);
printf("\n输入密码有误,您还有%d次机会,请重新输入:",i--);
if(i==-1)
{
exit(0);
}
goto q;
}
read(p); //导入文件
system("cls"); //清屏
//页面菜单
menu:
system("cls");
time (&timep);
p_1=gmtime(&timep);
printf("\t\t\t\t\t\t 当前时间%02d时%02d分%\n",8+p_1->tm_hour,p_1->tm_min);
printf("\t\t\t\t\t\t %d年%02d月%02d日\n",1900+p_1->tm_year,1+p_1->tm_mon,p_1->tm_mday);
printf("\n");
printf("\t\t\t\t\t\t 页 面 菜 单\n");
printf("\n");
printf("\t\t★————————————————————————————————————————★\n\n");
printf("\t\t\t | 1. 成绩录入\t\t2. 成绩显示\t\t3. 各科均分 |\n\n");
printf("\t\t\t | 4. 成绩排序\t\t5. 成绩查找\t\t6. 信息修改 |\n\n");
printf("\t\t\t | 7. 删除成绩\t\t8. 成绩分段\t\t0. 退出系统 |\n\n");
printf("\t\t★————————————————————————————————————————★\n");
printf("\t\t\t\t\t\t * \n");
printf("\t\t\t\t\t\t *** \n");
printf("\t\t\t\t\t\t ***** \n");
printf("\t\t\t\t\t\t *******\n");
printf("\t\t\t\t\t\t *********\n");
printf("\t\t\t\t\t\t *********** \n");
printf("\t\t\t\t\t\t ********************\n");
printf("\t\t\t\t\t\t ******************\n");
printf("\t\t\t\t\t\t ******* ********\n");
printf("\t\t\t\t\t\t ******* ********\n");
printf("\t\t\t\t\t\t ****** *******\n");
printf("\t\t\t\t\t\t****** ******\n");
printf("请选择相应序号:");
int choose;
int a;
w:
while(scanf("%d",&choose)==0)
{
printf("格式错误,请重新输入:");
fflush(stdin);
}
switch(choose)
{
case 1: //成绩录入
system("cls");
printf("学生成绩录入\n");
input(p);
goto menu;
case 2: //成绩显示和排序
system("cls");
printf("学生成绩显示\n");
print(p);
goto menu;
case 3: //均科成绩
system("cls");
average(p);
goto menu;
case 4: //成绩排序
system("cls");
projectsort(p);
goto menu;
case 5: //成绩查找
system("cls");
find(p);
goto menu;
case 6: //成绩修改
system("cls");
change(p);
goto menu;
case 7: //成绩删除
system("cls");
del(p);
goto menu;
case 8: //成绩分段
system("cls");
section(p);
goto menu;
case 0: //退出系统
fflush(stdin);
printf("\n是否继续退出:\n");
printf("\n1. 是 2. 否\n\n");
back:
printf("请选择:");
while(scanf("%d",&a)==0)
{
fflush(stdin);
printf("您输入格式有误,请重新输入:");
}
if(a==1)
{
system("cls");
//心形图案
float y, x, b;
for (y = 1.5f;y > -1.5f;y -= 0.1f)
{
for (x = -1.5f;x < 1.5f;x += 0.05f)
{
b = x*x + y*y - 1;
putchar(b*b*b - x*x*y*y*y <= 0.0f ? '*' : ' ');
}
putchar('\n');
}
Sleep(1000); //休眠
printf("欢迎下次继续使用本产品!\n");
printf("正在退出,请稍后.");
Sleep(500);
printf(".");
Sleep(500);
printf(".");
Sleep(500);
printf(".");
Sleep(500);
printf(".");
Sleep(500);
printf(".");
Sleep(500);
exit(0);
}//if(a==1)结束处
if(a==2)goto menu;
if(a!=1||a!=2)printf("输入有误,重新输入:\n");goto back;
default:
printf("没有该序号!请重新输入:");
goto w;
}//switch结束处
return 0;
}

4、效果展示

login
input)printf)sort)change)exit

退出时的效果可以自行添加,这里我在csdn上找的时一个心型图案,该图案设计者链接如下:

(https://blog.csdn.net/stone15165/article/details/80260580)

源码在github上:(https://github.com/Mr00wang/C-language.git)
以上是该学生管理系统的全部内容,上面没有对各科均分和成绩分段进行展述,如有问题请留言,谢谢!

北以晨光 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
------ 本文结束感谢您的阅读 ------