[C语言]基于链表的学生管理系统(大一第一学期的课设报告及代码)
实验题目: 课程设计报告设计与撰写
课程名称: 程序设计基础课程设计
实验类型:□演示性 □验证性 □操作性 ■设计性 □综合性
实验日期: 2021年 3月19日
目录
1.问题描述
1.1题目内容与要求
学生成绩管理程序
要求:本程序用于教学单位(院/系)的学生成绩管理。要求程序能够实现学生信息录入(可以实现增加、删除、修改学生的基本信息)、单科学习成绩的录入;班级内单科成绩排名;成绩查询:查询某个学生的各科成绩、统计所有不及格科目超过2科的学生名单;
1.2需求分析
1.本次设计面向软件工程专业(SE)的各个班级
2.通过输入相关功能对应的代号进行操作(如图)
3.各个功能再进行细分,如修改或者删除学生信息时,用户可能只知道同学的名字或者学号;
查询排名时可能只想查某个班级或者整个专业,不同的选择又可分为对应团体的不同科目或总分排名.
4.学生的数量是未知的,信息也会不断增加,这就要求该系统需要较好的持久性,适当利用文件操作和链表可以很好地满足这一点.
2.1模块划分
序号 | 模块名称 | 模块作用 | 包含函数名 | 函数所在文件名称 | ||
0 | 主菜单 | 加载数据, 显示菜单, 提供选项输入接口,以显示子菜单 | 0-2 | Home_page | fuctionState.h | |
0-1 | Load_data | dealInfor.cpp | ||||
0-3 | Select_fuction | |||||
1 | 录入 信息 | 依次录入任意个学生基本信息,同时判断该同学分数是否合格 | 1-1 | Input_new_student | ||
1-2 | Tail_add_node | |||||
1-3 | Judge_score | |||||
2 | 修改 信息 | 根据学号/名字 查找某学生并选择性修改各项信息 | 2-1 | Search_student_toChange | ||
2-2 | Change_information_selection | |||||
2-3 | Change_score | |||||
3 | 删除 学生 | 根据学号/名字 找到任意数量学生并删除 | 3 | Delete_student | ||
4 | 查询 个人信息 | 根据学号/名字 查找某学生并显示其所有信息 | 4-1 | Search_student | searchInfor.cpp | |
4-2 | Show_studentInformation |
5 | 查询排名 | 选择排名需要按照的团体[班级/全系].两种各自又分为不同科目的排名,最终显示出来想查看的排名表 | 5-1 | Rank_kindSelect | searchInfor.cpp |
5-2 | Build_rankClass | ||||
5-3 | Rank_subjectSelect | ||||
5-4 | Rank_byScore | ||||
6 | 显示所有信息 | 可选择查看所有不合格的学生[不及格科目超过两门]或全体学生(无序)的信息 | 6-1 | Show_all_selection | |
6-2 | Show_all_unqualified_student | ||||
6-3 | Show_all_student | ||||
7 | 存档 | 退出前将数据存档于源码所在目录的”student.txt”中 | 7 | Save_data | dealInfor.cpp |
2.2文件结构
本系统包括:
①主程序文件main.cpp : 启动程序;
②fuctionState.h : 进行函数原型和结构体的声明。
③dealInfor.cpp : 定义与数据处理有关的函数.
④searchInfor.cpp : 定义与数据查找有关的函数.
⑤(可能有)student.txt,用来储存学生信息.
2.3系统主要执行逻辑设计
(图2.1)
2.4函数原型及关系
2.4.1函数调用关系
本系统函数调用关系如图2.2所示:
图2.2 函数调用关系图
2.4.2函数原型设计
0.主菜单模块函数
(1)函数0-1 Load_data
void Load_data(Stu* pHead);
函数作用:将同文件目录下可能存在的student.txt中的数据录入程序
参数解释:主函数将链表头的地址通过pHead传入该函数,将文件中的数据录入新节点并插到链表尾部
(2)函数0-2 Home_page
void Home_page();
函数作用:显示菜单
- 函数0-3 Select_fuction
void Select_fuction(Stu* pHead);
函数作用:选择功能,调用其他分功能函数
参数解释:主函数将链表头的地址通过pHead传入该函数,当调用其他功能函数时,同样需要链表头的地址.
1.录入信息模块函数
(1)函数1-1 Input_new_student
void Input_new_student(Stu* pHead);
函数作用:新建节点,录入若干个新同学的信息
参数解释:同0-3
- 函数1-2 Judge_score
void Judge_score(Stu* student);
函数作用:判断录入的新同学成绩是否合格
参数解释:函数1-1通过student将录入的新同学的节点地址传入该函数,以此来获取其各项成绩;函数 2-3 通过student将修改了成绩的同学的节点地址传入该函数,以此来获取其各项成绩
- 函数void Tail_add_node
void Tail_add_node(Stu* pHead, Stu* new1);
函数作用:将新建的同学节点连到链表尾部
参数解释:函数1-1分别通过pHead,new1将链表头的地址和新建的同学的地址传入该函数
2.修改信息模块函数
- 函数2-1 Search_student_toChange
void Search_student_toChange(Stu* pHead);
函数作用:通过名字或学号找需要修改信息的同学
参数解释:同0-3
- 函数2-2 Change_information_selection
void Change_information_selection(Stu* student);
函数作用:选择需要修改的信息
参数解释:函数2-1通过student将需要修改信息的同学的节点地址传入该函数
- 函数2-3 Change_score
void Change_score(Stu* student);
函数作用:修改该同学成绩
参数解释:函数2-2通过student将需要修改成绩的同学的节点地址传入该函数
3.删除学生模块函数Delete_student
void Delete_student(Stu* pHead);
函数作用:通过名字/学号找到要删除的
参数解释:主函数将链表头的地址通过pHead传入该函数,以此来遍历链表,找到需要删除的同学.
4.查询个人信息模块函数
(1)函数4-1 Search_student
void Search_student(Stu* pHead);
函数作用:找到想查看的同学
参数解释:主函数将链表头的地址通过pHead传入该函数,以此来遍历链表,找到想查看的同学.
(2)函数4-2 Show_studentInformation
void Show_studentInformation(Stu* student);
函数作用:显示该同学信息
参数解释:函数4-1通过student将想查看的同学的节点地址传入该函数
5.查询排名模块函数
(1)函数5-1 Rank_kindSelect
void Rank_kindSelect(Stu* pHead);
函数作用:选择要查看班级排名或是全系排名,若是班级,判断想查看的班级是否存在
参数说明:主函数将链表头的地址通过pHead传入该函数,
(2)函数5-2 Build_rankClass
Stu* Build_rankClass(Stu* pHead, int rankClass);
函数作用:临时组建好要排名的班级
参数说明:若是函数5-2中找到了要查看排名的班级,则通过pHead将链表头的地址传入,通过rankClass传入要查看的班级,以此来遍历链表,将符合条件的同学至于新建的链表中,并返回此班级的链表头的地址
(3)函数5-3 Rank_subjectSelect
void Rank_subjectSelect(Stu* pHead);
函数作用:选择要查看的具体科目排名
参数说明:函数5-1 通过pHead将链表头的地址传入该函数
- 函数5-4 Rank_byScore
void Rank_byScore(Stu* pHead, int subject);
函数作用:排名
参数说明:pHead为链表头的地址,函数5-3函数将要查看的排名种类通过subject传入该函数,若1≤subject≤4,则按单科排名的数据格式输出,若subject=5,则按总分排名的数据格式输出.
6显示所有信息模块函数
(1)函数6-1 Show_all_selection
void Show_all_selection(Stu* pHead);
函数作用:选择要查看所有不合格的学生还是全系学生的信息
参数说明:函数2-1,函数3,或是主函数通过pHead将链表头的地址传入该函数
(2)函数6-2 Show_all_unqualified_student
void Show_all_unqualified_student(Stu* pHead);
函数作用:显示所有不合格的学生
参数说明:函数6-1通过pHead将链表头的地址传入该函数
(3)函数6-3 Show_all_student
void Show_all_student(Stu* pHead);
函数作用:显示全系学生
参数说明:同上
7.存档模块函数 Save_data
void Save_data(Stu* pHead);
函数作用:将数据存入同一目录下的student.txt中
参数说明:主函数通过pHead将链表头的地址传入该函数,以此来遍历整条链表,将数据依次录入文件
3.详细设计
3.1用户交互界面设计
开启程序有三秒的加载效果,一列ooo ooo ooo依次减少;
若加载数据后发现录入了学生,则有图3.1.1,否则为图3.1.2
(图3.1.1)
(图3.1.2)
无论哪个类型选择,如果输入了不符合选项的数字或是字母,会有提示要求重新输入,如图3.1.3
(图3.1.3)
如果要修改/删除的同学并未被录入,则会有提示,如图3.1.4
(图3.1.4)
如果要查看排名的班级未被录入,则会有提示,如图3.1.5
(图3.1.5)
另外,排名列表做的较为简洁,如图3.1.6
(图3.1.6)
3.2核心数据结构设计
单向链表的增,删,改,查以及直插法排序。
3.3核心算法设计
1.成绩排序算法
(1)算法功能描述:将链表按照要排名的分数成绩从大到小排序
(2)输入数据:链表中的m_rankScore(3)输出数据:链表中m_rankScore从大到小排列
(4)算法流程图:如图3.3.1
图3.3.1
2.增加新同学算法
(1)算法功能描述:将新同学的节点连接到链表尾部
(2)输入数据:链表头和新同学所在节点的地址(3)输出数据:新同学的节点连接到了链表尾部
(4)算法流程图:如图3.3.2
(图3.3.2)
- 删除同学算法
(1)算法功能描述:将指定的同学节点从链表中删除
(2)输入数据:链表头的地址(3)输出数据:链表中无该同学
(4)算法流程图:如图3.3.3
(图3.3.3)
4.测试
在学生信息的录入及修改中,均加入了分数的合理性判断(不得超过100)如图4.1,学号不得超过十位(如图4.2)
(图4.1)
(图4.2)
录入完后,在查询信息功能和student.txt文件中均找到了该同学(如图4.3,4.4)
(图4.3)
(图4.4)
还有部分测试已在3.1用户交互界面设计说明,在此不再赘述
5.总结
5.1遇到的问题及解决方法
a.[Error] jump to case label [-fpermissive]
问题:C语言编程时,在switch case 结构中, 如果在case里定义变量就会出现这种编译错误:jump to case label [-fpermissive]
原因:编译器认为这种写法会错过变量的定义,因些报这个错。
解决方法:将变量的定义移到switch case结构之上;
总结:尽量不要在case语句下定义变量!
查询一番发现:
高版的VS默认不让使用scanf,fopen等函数,说是scanf,fopen等函数不安全,而代替其函数的是scanf_s,fopen_s等函数,后边有个"_s"的形式
想要继续使用scanf,可以在源文件
开头加个:#define_CRT_SECURE_NO_WARNINGS
或者
效果都一样,就是预编时处理一下,加个宏而已,让其忽略安全检测
那么,C语言中的printf,scanf为什么不安全呢?主要区别就在于printf只会检查格式字符串是否为空(null),而printf_s还会检查格式字符串是否合法。
5.2感言
经过本次课设,体验到了根据用户需求独自设计框架、功能的全过程,在开发的过程中也碰到了一些疑惑,如学生的信息块的连接方式,若是仅用传统的数组进行操作,逻辑上可能会好理解一些,但其中的诟病也是很显然,由于开始申请的空间是固定的,而数组一个基本的性质便是在内存空间中是连续的,然而熟悉了指针的优势后,可以在每一个有限的数组中增加指针来实现其连接性,从而某种意义上实现了数组的延长……那么为什么不一开始就把每一个结构体“分而治之”,实现一条可以自由操作、“柔顺”的链呢?是的,数据结构中的链表此时派上了用场,因为本次设计框架较为简单,没有用双向链表的必要,就采用了单向。
最后感谢同学在文件操作上的帮助,以及网上大佬对bug的解答.
附代码
//转载须经同意,不得商业用途,后果自负
//main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <windows.h>
#include"fuctionState.h"
#include"dealInfor.cpp"
#include"searchInfor.cpp"
int main()
{
system("color F0");
Stu* pHead = (Stu*)malloc(sizeof(Stu));
memset(pHead, 0, sizeof(Stu));
pHead->next = NULL;
Load_data(pHead);//加载数据
Select_fuction(pHead);
free(pHead);
return 0;
}
//转载须经同意,不得商业用途,后果自负
//functon.h
typedef struct Student {
char m_name[20]; //姓名
char m_number[20]; //学号
int m_class; //班级
int m_ChineseScore; //语文成绩
int m_MathScore; //数学成绩
int m_EnglishScore; //英语成绩
int m_programScore; //程序设计成绩
int m_totalScore; //总分
int m_rankScore; //按种类排名时的中间变量
bool m_qualifiedScore; //分数合格(不及格科目超过2科即为不合格)
struct Student* next; //指针域
}Stu;
//0-1加载数据
void Load_data(Stu* pHead);
//0-2.主页
void Home_page()
{
system("cls");
printf(" ___________________________\n");
printf(" | |\n");
printf(" | SE成绩管理系统4.0 |\n");
printf(" |___________________________|\n");
printf(" | 1.录入信息 |\n");
printf(" | 2.修改信息 |\n");
printf(" | 3.删除学生 |\n");
printf(" | 4.查询个人信息 |\n");
printf(" | 5.查询排名 |\n");
printf(" | 6.显示所有信息 |\n");
printf(" | 7.存档 |\n");
printf(" | 8.退出 |\n");
printf(" |___________________________|\n");
printf(" ------ Made By:泥烟 ------\n");
printf("| |\n");
printf("| 注意: |\n");
printf("| 1.成绩均为整数,且满分为100 |\n");
printf("| 2.学号不超过十位 |\n");
printf("| 3.若有重复名字, |\n");
printf("| 请在其后加上\"(班级)\", |\n");
printf("| 例如:张三(2),张三(3)... |\n");
printf("| 4.非正常退出会造成新数据存档失败 |\n");
printf("|___________________________________|\n");
}
//0-3选择功能
void Select_fuction(Stu* pHead);
//1-1.录入信息
void Input_new_student(Stu* pHead);
//1-2.判断分数是否合格
void Judge_score(Stu* student);
//1-3.节点连接(尾插)
void Tail_add_node(Stu* pHead, Stu* new1);
//2-1.找到要修改的学生[通过名字/学号找学生]
void Search_student_toChange(Stu* pHead);
//2-2.修改信息选项
void Change_information_selection(Stu* student);
//2-3.改成绩
void Change_score(Stu* student);
//3.删除学生
void Delete_student(Stu* pHead);
//4-1.查询个人信息[通过名字/学号找学生]
void Search_student(Stu* pHead);
//4-2.个人信息
void Show_studentInformation(Stu* student);
//5-1.排名种类选择[班级/全系]
void Rank_kindSelect(Stu* pHead);
//5-2.创建需要排名的班级
Stu* Build_rankClass(Stu* pHead, int rankClass);
//5-3.按科目排名
void Rank_subjectSelect(Stu* pHead);
//5-4.排名
void Rank_byScore(Stu* pHead, int subject);
//6-1.显示所有信息(不合格学生or全体学生)
void Show_all_selection(Stu* pHead);
//6-2.所有不合格的学生
void Show_all_unqualified_student(Stu* pHead);
//6-3.全体学生
void Show_all_student(Stu* pHead);
//7.存档
void Save_data(Stu* pHead);
具体代码参见:基于c语言和链表学生管理系统-CSDN泥烟.zip
转载须经同意,不得商业用途,后果自负
本文来自博客园,作者:泥烟,CSDN同名, 转载请注明原文链接:https://www.cnblogs.com/Knight02/p/15799170.html