前言
不足之处,请多指教。
该程序不涉及文件读写,没有用链表,主要运用以下知识点:
- 结构体
- 函数封装
一、程序介绍
设计一款基础的学生成绩管理系统,实现包括以下功能:
- 显示帮助菜单
- 成绩录入
- 计算学生平均分
- 列出成绩表
- 按平均成绩由高到低排序
- 清屏
- 退出系统
二、面向结果
在具体实现之前,先思考程序整个的执行流程是怎样的,首先是弹出帮助菜单,菜单中包含需求功能,菜单前面有唯一的编号,提示用户选择,用户通过输入编号进行相应的操作;操作结束后,继续提示用户选择,从而进行不同的操作,循环这一过程,直到用户选择退出操作,整个程序停止。
三、程序实现
1. 搭建框架
1.1 思路
根据面向结果,在用户选择退出之前,规范输入时,需要一直进行选择提示->键入指令->用户操作
这一循环,所以用while(1)
搭配switch case
来实现这一循环,当用户输入选择后,scanf
接收这一选择,程序根据不同的选择来进行相应的case
下的功能,选择什么指令,就让它走对应的功能。在程序刚开始运行的时候,要让菜单显示出来。
- 打印菜单
- 提示输入
- 用户键入
- switch case匹配
1.2 实现顺序
#include <stdio.h> //1
void Init_Menu() //10
{
printf("*************************************\n");
printf(" * 学生成绩管理系统————帮助菜单 *\n");
printf("*************************************\n");
printf(" * H = 显示帮助菜单 *\n");
printf(" * T = 成绩录入 *\n");
printf(" * A = 计算学生平均学分 *\n");
printf(" * L = 列出成绩表 *\n");
printf(" * P = 成绩排序(高->低) *\n");
printf(" * S = 学号查询学生成绩 *\n");
printf(" * C = 清屏 *\n");
printf(" * Q = 退出系统 *\n");
printf("*************************************\n");
}
int main(int argc, char const *argv[]) //2
{
char input;//接受输入的菜单具体命令 //8
Init_Menu();//初始化菜单 //9
while (1) //3
{
printf("请输入指令= ");//提醒用户输入 //4
scanf("%c", &input);//接收输入传给input //5
getchar();//吸收掉换行符 //6
//当输入Q指令,跳出循环,程序结束
if (input == 'Q') //11
{
printf("已退出\n");
break;
}
switch (input) //7
{
case 'H':
printf("执行H功能");//以后替换为相应功能函数
break;
case 'T':
printf("执行T功能");//以后替换为相应功能函数
break;
case 'A':
printf("");
break;
case 'L':
printf("");
break;
case 'P':
printf("");
break;
case 'S':
printf("");
break;
case 'C':
printf("");
break;
default:
printf("输出格式错误,请重新输入!\n");
break;
}
}
return 0;
}
1.3 测试
测试结束,到这里我们就实现了代码的基本雏形。
2. 类型定义
2.1 思路
首先,系统是用来存放,显示,处理学生信息的,而学生的信息包括学号 语文成绩 数学成绩 英语成绩 平均分
这四个部分,所以要用到结构体数组
来定义学生信息,每一个结构体数组成员存放一个学生信息。num会在后面说明。
2.2 实现
typedef struct Student //12
{
int xuehao;//学生学号
float chinese;//语文成绩
float math;//数学成绩
float english;//英语成绩
float avg;//平均分
}Student;
int num; //全局变量,用来接收用户输入的人数
int main(int argc, char const *argv[])
{
char input;//接受输入的菜单具体命令
Student stu[4]; //13
Init_Menu();//初始化菜单
3. 函数实现
首先,先实现添加学生信息功能
,然后通过查看学生信息功能
,测试添加功能是否正确
3.1 添加学生信息——Add_Score()
3.1.1 思路
首先,请用户输入学生人数,通过人数将决定后面你输入多少个学生信息,所以这里想到用for
循环实现,人数是几就让用户循环输入几次。然后在每次循环的过程中,用户每次输入信息时,都能够自动生成学号(1,2,3…),这里想到通过对循环变量加1实现这一操作。在传参时,要改变结构体成员的内容,所以是地址传递
, 而数组名即首地址
,所以实参传入数组名
,形参用同类型的数组
接收即可。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上形参和实参为同一数组,因此当形参数组发生变化时,实参数组也随之变化
。
3.1.2 实现
case 'T':
Add_Score(stu); //14
break;
void Add_Score(Student stu[]) //15
{
//16 好吧,这里没有东西
printf("请输入学生人数:");//17
scanf("%d", &num); //18
printf("请输入%d名学生的三门课成绩(成绩用\\t符间隔):\n", num); //19
printf("%s\t%s\t%s\t%s\n", "学号", "语文", "数学", "外语"); //20
for (int i = 0; i < num; i++) //21
{
//学号从1开始生成,所以i+1
stu[i].xuehao = i+1; //22
//每次输入信息前,显示学号
printf("%d", stu[i].xuehao); //23
//接收用户输入
scanf("%f %f %f", &stu[i].chinese, //24
&stu[i].math,
&stu[i].english);
//吸收换行符
getchar(); //25
}
}
3.1.3 测试
3.2 查看学生信息——Print_Score()
3.2.1 思路
首先,我们需要判断系统里是否有学生信息,如果没有,则提示用户成绩为空,请先使用命令T录入学生成绩
,如果有则输出学生成绩,num
设为全局变量后,默认值为0,当用户进行添加操作后,num值发生改变,可通过num是否为0
判断系统里有无信息。
输出信息时,通过循环,将成员信息输出。
3.2.2 实现
case 'L':
Print_Score(stu); //查看 26
break;
void Print_Score(Student stu[]) //27
{
// 先判断系统是否为空,如果人数为0,则代表一个信息都没有 28
if (num == 0)
{
printf("成绩为空,请先使用命令T录入学生成绩。\n");
return;
}
printf("学生成绩如下:\n"); //29
printf("%s\t%s\t%s\t%s\t%s\n", "学号", "语文", "数学", "外语", "平均分");//30
//当学号不为0时,一直输出学生信息
for (int i = 0;i < num; i++) //31
{
printf("%d\t%.1f\t%.1f\t%.1f\t%.1f\n", stu[i].xuehao,
stu[i].chinese,
stu[i].math,
stu[i].english,
stu[i].avg);
}
}
3.2.3 测试
3.3 计算平均分——Average_Score()
3.3.1 思路
首先,在计算之前,依然要判断结构体数组中是否存有信息,操作同上。
然后遍历学生信息,将每一个数组成员的成绩相加,然后除3得到平均数,就可以计算出每个学生的平均数。
3.3.2 实现
case 'A':
Average_Score(stu);//计算平均分 32
break;
// 计算平均数
void Average_Score(Student stu[]) //33
{
// 先判断系统是否为空,如果学号为0,则代表一个信息都没有
if (num == 0) //34
{
printf("成绩为空,请先使用命令T录入学生成绩。\n");
return;
}
// 计算平均分
for (int i = 0; i < num; i++) //35
{
stu[i].avg = (stu[i].chinese + stu[i].math + stu[i].english) / 3;
}
printf("平均分已计算,请使用命令L查看.\n"); //36
}
3.3.3 测试
3.4 根据平均分排序——Sort_Score()
3.4.1 思路
首先,依旧是判断系统信息是否为空,操作同上。
在进行排序时,如果需要互换位置,不需要挨个互换变结构体组成员的属性,而只需将数组成员的首地址进行互换
,就可以达到内容互换的效果,进而实现互换位置
。结构体数组成员名即首地址
。在进行交换时,通过选择排序
思路来实现交换。
3.4.2 实现
case 'A':
Average_Score(stu);//计算平均分 37
break;
// 根据平均分进行排序
void Sort_Score(Student stu[]) //38
{
// 先判断系统是否为空,如果学号为0,则代表一个信息都没有 39
if (num == 0)
{
printf("成绩为空,请先使用命令T录入学生成绩。\n");
return;
}
// 排序
Student temp_stu; //临时变量 40
// 外层for循环控制循环轮数
for (int i = 0; i < num - 1; i++) //41
{
// 内层for循环控制每一轮的数还要与后面几个数比较
for (int j = i + 1; j < num; j++) //42
{
if (stu[i].avg < stu[j].avg) //43
{
// 结构体数组成员名即收地址,
temp_stu = stu[i]; //44
stu[i] = stu[j]; //45
stu[j] = temp_stu; //46
}
}
}
printf("完成排序,请使用命令L查看\n"); //47
}
3.4.3 测试
3.5 学号查询——Search_Number()
3.5.1 思路
- 判断系统信息是否为空
- 提示用户输入查询学号
- 根据学号遍历整个信息
- 输出查找到的信息
- 没有找到提示用户
3.5.2 实现
case 'S':
Search_Number(stu); // 通过学号查询 48
break;
// 根据学号查询
void Search_Number(Student stu[]) //49
{
// 先判断系统是否为空,如果学号为0,则代表一个信息都没有 50
if (num == 0)
{
printf("成绩为空,请先使用命令T录入学生成绩。\n");
return;
}
int temp; //接收查询的学号 51
printf("请输入要查询的学生学号:\n"); //52
scanf("%d", &temp); //53
getchar();//吸收换行
// 遍历学生信息,找到和学号匹配的信息
for (int i = 0; i < num; i++) //54
{
if (temp == stu[i].xuehao) //55
{
printf("%s\t%s\t%s\t%s\t%s\n", "学号", "语文", "数学", "外语", "平均分"); //56
printf("%d\t%.1f\t%.1f\t%.1f\t%.1f\n", stu[i].xuehao, //57
stu[i].chinese,
stu[i].math,
stu[i].english,
stu[i].avg);
}
else //58
{
printf("没有此人!\n");
}
}
}
3.5.3 测试
3.6 清屏
引入头文件#include <stdlib.h>
case 'C':
system("clear"); // 清屏 //59
break;
到此,所有功能都已实现。
四、全部代码
#include <stdio.h>
#include <stdlib.h>
// 学生信息结构体
typedef struct Student
{
int xuehao;//学生学号
float chinese;//语文成绩
float math;//数学成绩
float english;//英语成绩
float avg;//平均分
}Student;
int num;//全局变量num,用来接收用户输入的学生个数
// 提示菜单
void Init_Menu()
{
printf("*************************************\n");
printf(" * 学生成绩管理系统————帮助菜单 *\n");
printf("*************************************\n");
printf(" * H = 显示帮助菜单 *\n");
printf(" * T = 成绩录入 *\n");
printf(" * A = 计算学生平均学分 *\n");
printf(" * L = 列出成绩表 *\n");
printf(" * P = 成绩排序(高->低) *\n");
printf(" * S = 学号查询学生成绩 *\n");
printf(" * C = 清屏 *\n");
printf(" * Q = 退出系统 *\n");
printf("*************************************\n");
}
// 添加
void Add_Score(Student stu[])
{
printf("请输入学生人数:");
scanf("%d", &num);
printf("请输入%d名学生的三门课成绩(成绩用\\t符间隔):\n", num);
printf("%s\t%s\t%s\t%s\n", "学号", "语文", "数学", "外语");
for (int i = 0; i < num; i++)
{
//学号从1开始生成,所以i+1
stu[i].xuehao = i+1;
//每次输入信息前,显示学号
printf("%d", stu[i].xuehao);
//接收用户输入
scanf("%f %f %f", &stu[i].chinese,
&stu[i].math,
&stu[i].english);
//吸收换行符
getchar();
}
}
// 查看
void Print_Score(Student stu[])
{
// 先判断系统是否为空,如果学号为0,则代表一个信息都没有
if (num == 0)
{
printf("成绩为空,请先使用命令T录入学生成绩。\n");
return;
}
printf("学生成绩如下:\n");
printf("%s\t%s\t%s\t%s\t%s\n", "学号", "语文", "数学", "外语", "平均分");
//当学号不为0时,一直输出学生信息
for (int i = 0; i < num; i++)
{
printf("%d\t%.1f\t%.1f\t%.1f\t%.1f\n", stu[i].xuehao,
stu[i].chinese,
stu[i].math,
stu[i].english,
stu[i].avg);
}
}
// 计算平均数
void Average_Score(Student stu[])
{
// 先判断系统是否为空,如果学号为0,则代表一个信息都没有
if (num == 0)
{
printf("成绩为空,请先使用命令T录入学生成绩。\n");
return;
}
// 计算平均分
for (int i = 0; i < num; i++)
{
stu[i].avg = (stu[i].chinese + stu[i].math + stu[i].english) / 3;
}
printf("平均分已计算,请使用命令L查看.\n");
}
// 根据平均分进行排序
void Sort_Score(Student stu[])
{
// 先判断系统是否为空,如果学号为0,则代表一个信息都没有
if (num == 0)
{
printf("成绩为空,请先使用命令T录入学生成绩。\n");
return;
}
// 排序
Student temp_stu;
// 外层for循环控制循环轮数
for (int i = 0; i < num - 1; i++)
{
// 内层for循环控制每一轮的数还要与后面几个数比较
for (int j = i + 1; j < num; j++)
{
if (stu[i].avg < stu[j].avg)
{
// 结构体数组成员名即收地址,
temp_stu = stu[i];
stu[i] = stu[j];
stu[j] = temp_stu;
}
}
}
printf("完成排序,请使用命令L查看\n");
}
// 根据学号查询
void Search_Number(Student stu[])
{
// 先判断系统是否为空,如果学号为0,则代表一个信息都没有
if (num == 0)
{
printf("成绩为空,请先使用命令T录入学生成绩。\n");
return;
}
int temp; //接收查询的学号
printf("请输入要查询的学生学号:\n");
scanf("%d", &temp);
getchar();//吸收换行
// 遍历学生信息,找到和学号匹配的信息
for (int i = 0; i < num; i++)
{
if (temp == stu[i].xuehao)
{
printf("%s\t%s\t%s\t%s\t%s\n", "学号", "语文", "数学", "外语", "平均分");
printf("%d\t%.1f\t%.1f\t%.1f\t%.1f\n", stu[i].xuehao,
stu[i].chinese,
stu[i].math,
stu[i].english,
stu[i].avg);
}
else
{
printf("没有此人!\n");
}
}
}
int main(int argc, char const *argv[])
{
char input;//接受输入的菜单具体命令
// 定义结构体数组
Student stu[4];
Init_Menu();//初始化菜单
while (1)
{
printf("请输入指令= ");//提醒用户输入
scanf("%c", &input);//接收输入传给input
getchar();//吸收掉换行符
// 退出
if (input == 'Q')
{
printf("已退出\n");
break;
}
switch (input)
{
case 'H':
Init_Menu();;
break;
case 'T':
Add_Score(stu); //添加
break;
case 'A':
Average_Score(stu);//计算平均分
break;
case 'L':
Print_Score(stu); //查看
break;
case 'P':
Sort_Score(stu); //根据平均分排序
break;
case 'S':
Search_Number(stu); // 通过学号查询
break;
case 'C':
system("clear"); //清屏
break;
default:
printf("输出格式错误,请重新输入!\n");
break;
}
}
return 0;
}