前言
大家好吖,欢迎来到 YY 滴项目系列 ,热烈欢迎! 本章主要内容面向接触过C语言的老铁
主要内容含:
欢迎订阅 YY滴C++专栏!更多干货持续更新!以下是传送门!
- PS:以下内容是部分展示,完整可以下载该博客相关资料,里面有所有资料,包括完整代码和项目要求
1 1 实践内容 【小项目】学生成绩管理系统 学生 2 人到 3 人一组,按组完成《学生成绩管理系统》,具体要求是: 1)
已知存放学生信息的有三个 ASCII 文件,分别是: Stu_Info.txt 中有学生信息,包括学号、姓名、学院代码、性别代码、 10
门成绩 S_Code.txt 中有性别代码及其所对应的性别名称 C_Code.txt 中有学院代码及其所对应的学院名称 2)
设计至少三个结构体,分别包含上述三个文件中包含的内容 3) 《学生成绩管理系统》的框架(至少 4 个函数,至少 3 个源代码文件)
学生成绩系统菜单*
- 读取数据
- 按姓名排序,输出
- 按平均成绩排序,输出
- 输出给定学院学生
- 修改给定学生成绩信息(修改后的信息,需输出到文件)
- 按姓名查询学生,输出
- 修改系统密码*
- 返回上一级菜单
***************************** 设计要求为交互式,程序执行后,显示上述菜单;比如输入 2 后,执行按姓 名排序;进入 2 后,也可以再设计子菜单,从大到小?还是从小到大?还是返 回上一级菜单?可由用户输入,比如:- 从大到小排序
- 从小到大排序
- 返回上一级菜单 菜单中的修改密码为提高模块*,即程序执行需有密码(密码可以存放在一个 3 文件中,但是不得以明文出现);密码修改模块。 可增加模块,但是不能减少模块。
目 录
2021—_2022_学年第_1_学期 1 1 实践内容 1 2 小组成员分工及任务分配 2 3 系统分析及设计 3
3.1 数a据结构设计 3
3.2 模块划分 3 4 系统实现 4
4.1 各模块程序流程图 4
4.2 各模块程序程序实现 5 5 系统测试 17
6. 总结和展望 23 参考文献 24
已经给出三个ASCII文件,分别是:
Employee_Info.txt中有职工工资信息,包括职工号、所属部门编号、姓名、性别代码、基本工资、津贴、个人所得税、其他扣款
S_Code.txt中有性别代码及其所对应的性别名称 D_ Code.txt中有部门编号及其名称 要求如下:
1)设计三个结构体,至少能够描述上述三个文件中包含的内容;
2)进入系统前要求用户首先登陆,密码正确方可进入(要求建立一个保存密码密文的文件,如果文件不存在,首先创建文件并设置密码)
void passage() 1) 设计《职工工资管理系统》的框架(要求至少4个函数,至少3个源文件):
职工工资系统菜单* Void menu()
- 按职工姓名排序,输出
void Sortname(struct Contact* ps)
void SortRollname(struct Contact* ps, int flag)
void ShowRollname(const struct Contact* ps)- 计算职工的应发工资(基本工资+津贴),实发工资(应发工资-个人所得税-其他扣款);
void Countpay(struct Contact* ps)- 按应发工资排序,输出
void Sortpayp(struct Contact* ps)
void Sortpay(struct Contact* ps, int flag)
void pSortpay(const struct Contact* ps)- 添加职工及其工资信息
void AddStaff(struct Contact* ps)- 修改给定职工的工资信息(修改后的信息,需输出到文件)
void ModifyStaff(struct Contact* ps)- 按姓名查询职工,输出
void Sortname(struct Contact* ps)
void SortRollname(struct Contact* ps, int flag)
void ShowRollname(const struct Contact* ps)- 删除职工
void DeletePayroll(struct Contact* ps)- 修改系统密码
void Moditywordl(struct Contact* ps)- 返回上一级菜单//ps修改为退出程序
EXIT
添加:保存写入文件板块:
void Savepayroll(struct Contact* ps)
查找重复职工,id板块:
int FindByName(const struct Contact* ps, char name[MAX_NAME])
int Checkrepeat(const struct Contact* ps, int id)
按照职工代码排序板块:
void sortid(struct Contact* ps)
【提示1】开始进入菜单前,除了登陆外,还需要进行系统初始化:即读取原始文件数据,并以链表或数组保存。
void InitContact(struct Contact* ps)
void LoadRoll(struct Contact* ps)
【提示2】设计为交互式,程序执行后,显示上述菜单;比如输入2后,执行按姓名排序;进入2后,也可以再设计子菜单,从大到小?还是从小到大?还是返回上一级菜单?可由用户输入,比如:- 从大到小排序
- 从小到大排序
- 返回上一级菜单 //设置在修改模块中 【提示3】可增加模块,但是不能减少模块,即0-8是必须的
马佳彬:全包
(根据要求,划分为几个独立的模块-函数)
个人全包
Ps:本项目划分为三大实现区域
- pay.h:实现结构体的声明,和若干.c文件的声明
- main.c:实现项目的主干功能,包含菜单和密码,以及枚举。
- 若干.c模块(ps:各.c文件均声明pay.h)
Ps:本项目的核心,是初始化模块以及保存模块
Ps:由于使用了枚举,所以先行展示
(ps:二级菜单没有使用枚举,怕冲突)
Ps:使用了清屏函数(避免报告冗余,略去插入思路)
Ps:头文件中声明的结构体以及定义
- 进入密码模块(密码模块在main函数前,省去声明,menu()同理)
- 初始化iuput为后续do while嵌套switch case的分类标识
- 创建Contact结构体(可见上图声明的结构体)
- 用memset函数开辟对ps指向的成员data开辟一块空间,由max来控制开辟空间
- 注意sizeof(结构体),要注意内存对齐的问题
- Ps:内存对齐的本质是牺牲空间来换取时间,也许会多开辟空间无伤大雅
- Ps:要做到既节省空间又节省时间,可以在设置结构体成员的时候,尽量把小的结构成员放在一起。
- 接下来采取同样的方式,将剩下两个转化“代码-部门/性别”的文件内容读取到对应的结构体中
原理:设置两个参数,一个是输入的数组,一个是职工册结构体的地址。
- Ps:strcmp的两个参数都是指针
- 不同点/设计重点:返回参数
- FindByName,返回要找到的名字的序号i(非职工代码)
- Checkrepeat,只需要标识找到与否的状态
- 原理:冒泡排序后,用序号打印结构体PeoInform中对应的name成员
- 二级菜单原理:用goto语句自由穿梭
原理:用for运行实现每个对应序号的PeoInform结构体成员的对应成员计算;
用for运行打印结构体中存储的数据;
- 原理:添加到PeoInfrom结构体中;由保存函数导入文件
原理:
- 创建一个数组,填入待查找的名字
- 通过FindByname函数填入,在之中用strcmp比较
- 利用结构体打印
- Tran函数实现的功能是在展示的时候,将性别代码和部门代码转化成对应的性别和部门。x,y是全局变量,分别储存了性别代码和部门代码的种类。在遍历的时候以它为终止条件。可以实现精确的查找。
原理:
- 创建一个数组,填入要删除的名字
- 通过FindByname函数填入,在之中用strcmp比较
- 用下一位PeoInform的内容填入
- Size–(比如删除最后一位,虽然填入没有内容,后通过保存函数保存也能实现删除)
实验完成情况。还有那些不足,会如何改进
- 低级错误:
- 把结构体指针当作文件指针,导致程序运行起来自动崩溃
- 规划函数名字时没有清晰规划,调用时出现不知名bug
- 由于思路不够清晰,初始化阶段出现bug;创建多余结构体成员num承担size功能
- 重点错误:
- 在读取数据,实现读取注释功能时。忽略了读取到总数100时,下一个读取的num跳过1直接到0;
- 解决方法:用fseek函数,将指针向前偏移一个字节
- 一些思路上的反思:
- 在面对添加板块时:一开始想直接在文件中进行添加,采用了w/w+的方式,发现文档直接只剩下添加的成员;后明白w/w+都会直接创建新文件,若存在同名文件则覆盖。
- 后采取追加的方式a。发现添加数据直接添加到最后的数据后面,没有换行;后加入“写入换行”方式。
- 此时并没有设计保存方式,还面临排序问题;(好比1 3 序号,缺少2;在尾部填入2,需要其回嵌入到13中间);此时发现直接在文件中修改不是很可靠。
- 最后决定,采取一并把数据导入到结构体con中,再对con的成员结构体PeoInform进行排序,最后再直接覆盖旧文件的方案;这种思路具有统一性,且十分清晰,具备很高的调整属性(按职工序号或其余方式)
- 在面对保存板块时:想过直接用二进制方式,直接把PeoInform成员全部导入到文件中。为保证文档中的代码可读(非二进制形式),遂放弃。
- 个人总结
- 本次项目(含报告)大概耗时30小时左右,其中大量的时间在程序的调试和bug的查找中。由于调试经验不足以及对调试功能的陌生,以至于造成许多细小的错误浪费了大量的时间的结果。
- 在不断的调试过程中,一步一步深化了对指针和结构体的理解。[在结构体中嵌套次级结构体成员,并通过一级结构体成员的部分成员(size)来调控结构体成员的方式。]
- 对程序与文件的交互有了更进一步的了解。[程序和文件之间可以通过结构体成员来搭建联系(上文中思路的反思),具备更多的可调节性]
- 补全了对(w/w+/a/fseek)的认识和实际应用经验