没有合适的资源?快使用搜索试试~ 我知道了~
李骁睿 课程设计报告1
需积分: 0 0 下载量 90 浏览量
2022-08-03
19:06:02
上传
评论
收藏 561KB PDF 举报
温馨提示
试读
11页
李骁睿 课程设计报告1
资源详情
资源评论
资源推荐
学院
化学学院
辅修专业
计算机科学与技术
学号
16190311
姓名
李骁睿
编译环境:
gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
Linux 5.11.0-27-generic x86_64 GNU/Linux
系统设计:
本系统是一个 Unix Shell 风格的学生选课信息管理程序,使用链表作为记录的基本数据结
构。主要分 3 大模块:指令解析和用户交互模块、账户模块、数据模块。其中,主函数 main()
和主循环 interactiveShell()负责指令解析和用户交互;login.c 包含了所有用户创建、用户登录、
用户身份识别、登录验证、信息保存的功能;lnklist.c 和 curriculum.c 包含了底层数据类型双向
链表的具体实现以及数据的显示、增添、删除等操作。
用户交互模块可以通过 int main(int argc, char** argv)从命令行获取参数从而执行指令或者
进入交互模式。(为了方便命令行执行,本系统从一开始便为命令行模式设计,由于精力关系只
能先实现交互模式。)当执行 eduadmin -i 时便进入交互 shell 模式。-h 或者--help 参数可以
打印帮助信息。以下为程序中的帮助信息。
interactiveShell()函数是主循环。从 stdin 读取用户输入,通过 parser.c 中的 parseArgs(char
*argv[MAX_ARGC], char *str)函数将命令切割为参数并判断命令和子命令,将参数传入对应的模
块函数完成调用。
账户模块的主要函数是 getUserInfo()函数、saveLoginInfo()函数、login()函数和
createAccount(bool admin)函数。
getUserInfo 函数从目录中现有的 user 文件中以二进制形式读取所有用户的用户名、UID 和
哈希值,以链表形式读入内存。saveLoginInfo()则相反。
login()函数是用户登录的关键函数。用户在提示下输入用户名和密码。之后通过用户名和密
码拼接和 MD5 Hash 生成一个 16 位的 Hash 校验值,与文件中读取的用户对应的 Hash 值相比
对。若一致则通过,并将全局变量 USERID 设为文件中读取的 USERID,完成登录。为了保护登
录密码,在登录时会将输入的密码字符以“*”掩盖。
createAccount()函数是用户创建函数。这个函数根据用户输入的用户名和密码,通过拼接
生成 MD5,并将新账户加入到 USERLIST 链表中。USERID 与学号不同。注意到学号最大不会超
过 2^28,可存储在 32bit 的无符号长整型 uint32_t 中。开头 4 位空余可以用来作为区分教师、
学生。也可以设置管理权限位。账户系统拥有两个默认账户 anonymous 和 root。UID 分别为 0
和 1,对应系统的最低权限和最高权限。只有 root 可以创建具有管理权限的账户。anonymous
只允许查看课程和教室信息。saveLoginInfo()可以在退出时或使用 save 命令手动调用。为了避
免直接通过读取密码文件的方式获得他人的登录信息,密码以 MD5 的形式与用户名和 UID 一同
以二进制形式写入 passwd 文件中。当登录信息文件不存在时,程序会提供一个初始化帮助函数
initUserProfile()帮助创建 root 账户和 passwd 文件。
用户数据模块在 curriculum.c 中,底层的数据结构为双向链表,在 lnklist.c 中实现。lnklist.c
中实现了双向链表的初始化、释放和节点的增加、删除、交换、遍历、查询等操作。后面采用的
快速排序算法对链表中的两项直接进行交换操作较为繁琐且容易出错,因此将链表设计为指针的
形式指向数据储存区,交换时只需要交换指针,读取数据时需要指针类型的强制转换。
seekNode()函数设计为传入一个链表信息的结构体、一个返回 bool 值的函数指针用于匹配查询
值、和一个指向被比较数据的 void*指针。qsortcore()是快速排序算法的核心实现。节点的比较
也通过传入函数指针的方式进行,因此可以以平均 O(nlgn)的时间复杂度进行各种排序,也可以
传入一个布尔型的 reverse 参数来指定是否倒序排序。curriculum.c 中包括上述函数所需的各种
比较函数与匹配函数。initData()函数将储存链表用户信息、课程信息、教室信息等的全局变量
结构体初始化。loadData()则从 courses,enrollments,rooms,registries 四个文件中读取信息
并添加在链表中,并处理相互之间指针的链接关系。一系列 userxxxx 函数负责获取并验证用户
输入的合法性,传入 addxxxx 函数中进行真正的添加操作。enroll 和 disenroll 函数负责学生选
课和退选。每一个函数中都会有对当前用户操作权限的检验。且不同权限的账户对用户信息输出
的级别不同。例如只有具有管理权限的账户才能查看具体的选课学生信息。普通账户只能显示选
课人数等。
me()函数是为学生提供的查看并计算当前账户选课情况统计信息的函数。显示学生姓名、学号、
选课列表、总学分、必修学分、选修学分等。一系列 listxxxx 函数用于遍历链表输出信息,便于
用户检索。一系列 showxxxx 函数用于显示给定 USERID/COURSEID/ROOMID 的数据详细信息。
课程 ID 的设计也是与用户 ID 类似,最高位被设计为区分选修与必修的位。这导致必修课的课程
ID 必然大于 2147483647。
关键代码:
常量:
全局变量(globals.h):
一些结构体定义(curriculum.h):
剩余10页未读,继续阅读
顾露
- 粉丝: 15
- 资源: 315
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0