G
N
I
D
A
O
L

学生选课系统(C语言课程设计)


学生选课系统(C语言课程设计)

摘要

学生选课系统可以读取本地文本文件中的用户(学校、教师、学生)信息和课程信息,并能校验当前使用用户的信息进行登录操作。在用户登陆后,该系统可以匹配读取文件后的缓存信息中的用户的权限:学校用户可以自由修改/增添任意用户和课程信息,教师可以查询课程和修改自己所在课程的学生选课信息,学生可以查询课程和进行自己的选课操作。在用户操作后,系统会自动更新信息入文本文件中保存。

该系统可以在本地有效处理关于教师上课、学生选课的问题,并且大大方便了学校对全体师生选课数据的处理操作。本系统使用Visual Studio 2019编写,采用代码为C语言,使用了较为简单且基础的函数和代码。

关键词:本地文件,用户登录,选课,管理系统,修改信息

题目要求

  1. 查阅文献资料,一般在5篇以上;
  2. 以学校学生选课管理业务为背景,通过调研、分析现有的管理模式和已有的管理软件,建立系统模型;
  3. 完成软件结构设计和算法设计;
  4. 完成系统的软件开发和测试工作;
  5. 撰写设计说明书;
  6. 做好答辩工作。

需求分析

产品需求概述

功能简介

学生选课系统,针对学校进行自主选课/查课的系统,分别面向学校、教师、学生,提供带筛选功能的查询、编辑、导入/导出等学生选课相关功能,如图所示。

功能简介

限制条件

  • 软件同目录下必须包括两份数据文件:

    一份名为用户数据.txt,其内容必须包含首行内容权限类型 账号 密码 姓名 课程代码和末行内容0

    另一份名为课程数据.txt,其内容必须包含首行内容课程代码 教师代码学分 选课性质 选课类型 学期 上课时间 课程名字 上课地点学生上限和末行内容0

    限制原因:该数据文件模拟正常网络选课时用户共用的数据文件,其地址必须固定且文件必须唯一存在。

  • 使用本系统应避免多用户同时操作。

    限制原因:由于该系统为本地读取文件并载入缓存,而非实时更新本地数据,导致多用户同时对同一数据或不同数据进行操作时只有其中一条有效或导致数据信息不匹配。

  • 手动修改数据文件应避免格式错误或内容不匹配。

    限制原因:该系统能在一定程度上对内容格式错误或不匹配信息进行报错或忽略,但限于数据量庞大和系统功能复杂,不正确的读取仍然可能出现无法估量的严重后果。

功能需求

学校对课程和用户管理功能

实现功能:对所有课程和用户进行筛选查看所有信息,筛选包括选课类型、选课性质、上课时间、上课地点、学期,能够实现对所有信息的新建,删除,修改,查看等基本功能。

教师对课程和学生查询功能

实现功能:对所有课程进行筛选查看所有信息,对该教师相关学生进行查询和退课操作。

学生对课程和个人查询功能

实现功能:对所有课程进行筛选查看所有信息并可执行选课操作,对个人选课进行查看和退课。

用户登陆

实现功能:用户输入账号和密码进行登陆操作,其密码具有一定加密功能。登陆后可修改密码,并按用户类型提供不同服务。

文件载入/保存

实现功能:用户操作的所有数据近乎实时地保存在本地文件中。

不支持的功能

  • 系统日志:实时记录用户操作,供学校管理员进行分析或问题查询。

    不支持原因:待开发中

  • 系统设置:包括记住账号,配置访问地址,读取自定义数据类型等等。

    不支持原因:待开发中

  • 互联网多用户实时操作:全网多个用户同时对该系统进行使用操作

    不支持原因:网络及数据库部分技术缺失,已有功能所使用技术框架地局限性。

数据描述

数据描述

数据名 数据类型 说明
文本长度 const int 50 限制大部分字符串的长度
选课上限 const int 30 限制学生选课数量
选课类型_数量 const int 4 定义数量
选课性质_数量 const int 4 定义数量
上课时间_数量 const int 5 定义数量
上课地点_数量 const int 2 定义数量
学期_数量 const int 10 定义数量
选课类型 const char [][] 见附录 课程元素
选课性质 const char [][]
上课时间 const char [][]
上课星期 const char [7][10]
上课地点 const char [][]
学期 const char [][]
用户数据 FILE* 处理用户数据文件
课程数据 FILE* 处理课程数据文件
系统日志 FILE* 处理系统日志文件
用户数量 int 0 记录用户数据条数
课程数量 int 0 记录课程数据条数
登录用户ID int 0 记录目前登陆用户的内部ID
筛选条件 int [10][10] 0 用于记录课程筛选 0-显示,1-隐藏
*课_程 struct 课程 NULL 记录每一条课程数据
*用_户 struct 用户 NULL 记录每一条用户数据
其他 union 临时数据 用于其他大部分临时数据
struct 课程 int 课程代码 int 学分 int 选课性质 int 选课类型 int 学期 int 上课时间 int 上课星期 char 教师代码[] char 课程名字[] int 上课地点 int 学生上限 int 用户数量 int* 用户ID 课程代码:-1表示待删除
struct 用户 char 账号[] char 密码[] char 姓名[] int 权限类型 int 课程数量 int* 课程代码 账号:同时表示学号或工号 权限类型:1表示学校,2表示教师,3表示学生,-1表示待删除
union 临时数据 char 文本型[1000] char 字符型 int 整数型 double 小数型 FILE* 文件型 用于其他大部分临时数据 如:处理循环,计数,测试值,输入……
  1. 性能需求

    数据精确度:该系统针对学生选课,其数据十分重要且要求精准。软件设置多处输入提示和使用菜单的方式,并编写了输入检测函数和数据校验,极大程度避免了用户数据出现问题。

    时间特性:该系统要求实时更新数据文件。软件通过操作触发性更新数据文件,极大程度降低了多用户同时操作的数据更新风险。

    相互合作的用户数或者所支持的操作:多用户同时多地操作。软件通过模拟固定地址的数据文件进行读写,理论上可上传至网络进行近乎同时的多地操作。

    容量需求:该系统要求储存处理学校庞大的师生用户数据和课程数据。软件通过动态分配内存的方法临时储存数据,其上限根据载入的数据自动调整,理论上限仅由软件运行的硬件配置决定。

概要设计

软件概要设计是从总体上把握系统设计框架,他包括模块划分、处理流程和接口设计,概要设计说明书对上述内容作了总体描述,体现了用户需求与应用系统实现之间的关系,在设计过程中起到了提纲挈领的作用。

系统体系结构图

系统体系结构图

系统流程图

系统流程图

详细设计

系统主要函数说明

函数名称 函数功能
数据校验 用于转换学生课程代码为外部或内部ID
带检测输入 用于带检测非法输入的输入操作
字符串加解密 用于处理密码加解密
筛选判断 用于筛选浏览课程的各项属性进行判断
用户_ID查询 用于查找账号对应内部ID
课程_ID查询 用于查找课程对应内部ID
课程操作 选中课程后用于读取或编辑课程信息
用户操作 选中用户后用于读取或编辑用户信息
添加课程 根据用户ID添加相应课程ID的选课
退课 根据用户ID删除相应课程ID的选课
搜索用户 用户信息中选择搜索用户后对相应用户进行编辑
搜索课程 课程信息中选择搜索课程后对相应课程进行编辑
浏览用户 用户信息中选择浏览用户后显示所有用户信息
浏览课程 课程信息中选择浏览课程后有筛选地显示所有课程信息
我的课程 根据用户ID可编辑地显示学生课程
我的学生 根据教师ID可编辑地显示学生信息
修改密码 根据用户ID无需知道原密码修改密码
导入课程 根据操作类型在自定义位置或默认位置导入课程文件信息
导出课程 根据操作类型在自定义位置或默认位置导出课程文件信息
导入用户 根据操作类型在自定义位置或默认位置导入用户文件信息
导出用户 根据操作类型在自定义位置或默认位置导出用户文件信息
载入文件 打开软件时载入数据文件
登陆 载入数据文件后用户登陆
菜单 用户登陆后显示菜单
用户信息 菜单选择显示用户信息

数据校验

[功能] 用于转换学生课程代码为外部或内部ID

[参数] int 转换类型,临时数据 循环[3],课程ID

[返回值] return 0:正常返回

[算法描述]

![数据校验][数据校验]

带检测输入

[功能] 用于带检测非法输入的输入操作

[参数] void* 待存入变量,int 输入类型,int 判断次数,临时数据 判断

[返回值] return 判断次数

[算法描述]

带检测输入

字符串加解密

[功能] 用于处理密码加解密

[参数] void* 待存入变量,int 输入类型,int 判断次数,临时数据 判断

[返回值] return 判断次数

[算法描述]

字符串加解密

筛选判断

[功能] 用于筛选浏览课程的各项属性进行判断

[参数] int 课程ID,临时数据 循环[2],临时数据 判断内容

[返回值] return 1,return 0

[算法描述]

筛选判断

用户_ID查询

[功能] 用于查找账号对应内部ID

[参数] char 账号,临时数据 循环,临时数据 目标ID,临时数据 个数

[返回值] return 目标ID,return -(个数+1)

[算法描述]

用户_ID查询

课程_ID查询

[功能] 用于查找课程对应内部ID

[参数] int 课程代码,临时数据 循环,临时数据 目标ID,临时数据 个数

[返回值] return 目标ID,return -(个数+1)

[算法描述]

课程_ID查询

课程操作

[功能] 选中课程后用于读取或编辑课程信息

[参数] int 课程ID,课程 临时课程,临时数据 操作,临时数据 循环

[返回值] return -1,return 0,return 1

[算法描述]

课程操作

用户操作

[功能] 选中用户后用于读取或编辑用户信息

[参数] int 用户ID,用户 临时用户,临时数据 操作,临时数据 循环

[返回值] return -1,return 0,return 1

[算法描述]

用户操作

添加课程

[功能] 根据用户ID添加相应课程ID的选课

[参数] int 用户ID,int 课程ID,临时数据 循环

[返回值] return 0,return -1

[算法描述]

添加课程

退课

[功能] 根据用户ID删除相应课程ID的选课

[参数] int 用户ID,int 课程ID,临时数据 循环

[返回值] return 0

[算法描述]

退课

搜索用户

[功能] 用户信息中选择搜索用户后对相应用户进行编辑

[参数] 临时数据 账号,临时数据 循环,临时数据 计数,临时数据 操作

[返回值] return 0,return 1

[算法描述]

搜索用户

搜索课程

[功能] 课程信息中选择搜索课程后对相应课程进行编辑

[参数] 临时数据 课程,临时数据 循环,临时数据 操作

[返回值] return 0,return 1

[算法描述]

搜索课程

浏览用户

[功能] 用户信息中选择浏览用户后显示所有用户信息

[参数] 临时数据 循环[2],临时数据 操作

[返回值] return 0

[算法描述]

浏览用户

浏览课程

[功能] 课程信息中选择浏览课程后有筛选地显示所有课程信息

[参数] 临时数据 循环,临时数据 操作

[返回值] return 0

[算法描述]

浏览课程

我的课程

[功能] 根据用户ID可编辑地显示学生课程

[参数] int 用户ID,临时数据 循环,临时数据 操作

[返回值] return 0

[算法描述]

我的课程

我的学生

[功能] 根据教师ID可编辑地显示学生信息

[参数] 临时数据 循环[2],操作[3],临时数据 用户ID

[返回值] return 0

[算法描述]

我的学生

修改密码

[功能] 根据用户ID无需知道原密码修改密码

[参数] 临时数据 密码_第一遍, 临时数据 密码_第二遍

[返回值] return -1,return 0

[算法描述]

![修改密码][修改密码]

导入课程

[功能] 根据操作类型在自定义位置或默认位置导入课程文件信息

[参数] int 操作类型,临时数据 位置信息, 临时数据 载入, 临时数据 文件位置_下一行, 临时数据 文件位置_当前行, 临时数据 账号

[返回值] return -1,return 0

[算法描述]

导入课程

导出课程

[功能] 根据操作类型在自定义位置或默认位置导出课程文件信息

[参数] int 操作类型,临时数据 位置信息,临时数据 循环

[返回值] return -1,return 0

[算法描述]

导出课程

导入用户

[功能] 根据操作类型在自定义位置或默认位置导入用户文件信息

[参数] int 操作类型,临时数据 位置信息, 临时数据 载入, 临时数据 文件位置_下一行, 临时数据 文件位置_当前行, 临时数据 账号

[返回值] return -1,return 0

[算法描述]

导入用户

导出用户

[功能] 根据操作类型在自定义位置或默认位置导出用户文件信息

[参数] int 操作类型,临时数据 位置信息,临时数据 循环[2]

[返回值] return -1,return 0

[算法描述]

导出用户

载入文件

[功能] 打开软件时载入数据文件

[参数] 无

[返回值] return 0,exit(-1)

[算法描述]

载入文件

登陆

[功能] 载入数据文件后用户登陆

[参数] 临时数据 账号,临时数据 密码,char[] 储存的密码

[返回值] return 0,return -1

[算法描述]

登陆

菜单

[功能] 用户登陆后显示菜单

[参数] 临时数据 操作

[返回值] return 0

[算法描述]

菜单

用户信息

[功能] 菜单选择显示用户信息

[参数] 临时数据 操作

[返回值] return 0,return 1,return -1

[算法描述]

用户信息

总结

本次课程设计历时10天,其中设计阶段2天,接着2天时间同时进行整体框架的编程实现和部分细节的设计,剩余6天时间分别对文件进行了整理工作,对程序进行BUG检测和分析,完成设计说明书和总结反思。

通过本次,也是首次课程设计,我亲身体验到了大型系统制作的流程和遇到的困难和成就感。在这次体验让我更加熟悉对庞大、复杂系统的框架设计分析,对各项数据处理和代码格式以及注释的细节要求处理。

本系统设计之初参考了本校的教务管理系统,并结合个人过去的使用操作经验,马上形成了功能详尽且贴合实际的系统框架。结合课程设计期间对其他同学的拜访和互相交流,我体会到了使用经验在课程创新设计中的重要性。

在编程实现的过程中,对照框架设计并删改或阉割了许多内容,致使许多细节和功能无法呈现或无法短时间实现,这让我体会到了个人技术能力在统一理想与现实中的重要性。

尽管如此,可实现并最终呈现出的功能,包括检测输入、加解密密码、筛选、多数据相互联动等首次尝试的复杂功能均被攻克,并结合文件存取、用户登陆、数据编辑等基本功能,形成了一个尽可能完善且可投入实际使用的学生选课系统。

除此以外,本次课程设计的代码均设置了测试接口,并搭建了尽可能通用的功能模块。使得本系统在今后具有极大的升级空间,并确实地为今后的升级铺平了道路。

参考文献

  1. 颜晖.C语言程序设计(第3版).北京:高等教育出版社,2015.8
  2. 颜晖,张泳.C语言程序设计实验与习题指导(第3版).北京:高等教育出版社,2015.8
  3. 谭浩强.C语言程序设计.清华大学出版社,2010.6
  4. 谭浩强.C程序设计题解与上机指导.清华大学出版社,2010.6
  5. E.Balagurusamy.标准C程序设计 第7版.清华大学出版社,2017
  6. 李根福.C语言项目开发全程实录.清华大学出版社,2013

致谢

本次课程设计完成共历时10天,在这10中不断有同学向我请教管理系统的有关内容,让我从中获取了许多灵感。感谢同学们提供的建议和灵感。

此外,在本次编程过程中,我在网络社区中搜索到了许多相关的函数以及使用技巧和细枝末节,感谢广大网友在网络上的无私奉献。

感谢指导老师为我分析命题和对系统的点评,指导。

特别感谢朋友在我测试和修改系统的过程中提供的部分测试数据。感谢室友和朋友们协助我进行BUG测试,寻找错误,感谢他们为我提供使用反馈信息。

附录

数据文件

系统日志-未完工

-1    文本长度        50
-1    选课上限        30
-1    选课类型_数量    4
-1    选课性质_数量    4
-1    上课时间_数量    5
-1    上课地点_数量    2
-1    学期_数量        10
-1    选课类型        正选        重修        选修        补修
-1    选课性质        实践教学课    公共基础必修课    创业课程        其他
-1    上课时间        第一节        第二节        第三节        第四节        晚上
-1    上课地点        本部        西校区
-1    学期            2019上半年    2019下半年    2020上半年    2020年下半年                2021年上半年    2021年下半年    2022年上半年    2022年下半年                2023年上半年    2023年下半年
0    账号

用户数据

权限类型    账号    密码    姓名    课程代码
0
//0作为读取数据结尾
//请按格式录入信息

课程数据

课程代码    教师代码    学分    选课性质    选课类型    学期    上课时间    课程名字    上课地点    学生上限
0
//0作为读取数据结尾
//请按格式录入信息

用户数据-测试

权限类型    账号    密码    姓名          课程代码
1            admin    awnrm    
2            TC001    FW00!    测试老师1    
2            TC002    FW00"    测试老师2
2            TC003    FW00#    测试老师3    
2            TC004    FW00$    测试老师4    
3            100001       !0000!    测试学生1     1 2 3 4 5 6 
3           100002    !0000"    测试学生2     1 3 5
3           100003    !0000#    测试学生3     2 4 6 
3           100004    !0000$    测试学生4     3 5 6
3            100005    !0000%    测试学生5     1 2 4 5 
3           100006    !0000&    测试学生6     6
3            100007    !0000'    测试学生7     3 5 
0    
//测试账号密码同账号

课程数据-测试

课程代码  教师代码  学分  选课性质  选课类型  学期  上课时间  课程名字  上课地点  学生上限
1    TC001    12    1    3    1    0    测试课程1    0    50
2    TC002    15    2    1    0    2    测试课程2    1    45
3    TC003    11    3    2    3    1    测试课程3    0    60
4    TC004    12    0    3    2    3    测试课程4    1    25
5    TC001    17    3    0    1    4    测试课程5    1    20
6    TC003    19    1    2    2    2    测试课程6    0    20
7    TC001    19    1    3    3    0    测试课程7    1    15
0
//0作为读取数据结尾
//请按格式录入信息

源程序

头文件和函数申明.h

//作者:AnglesD QQ:1005562341 邮箱:dyy3688098qq@163.com
//编译环境:Visual Studio 2019[SDL检查:否]
//调试:Debug x86
//已知问题:上课时间无星期信息,无法为一门课程添加多个上课时间
//待开发模块:打印课表,查看日志,自定义化读取

//更新消息
//1.0.0.1:程序初步完成
//1.0.0.2:纠正了筛选问题
//1.0.0.3:使用更真实的课程信息
//1.0.0.4:纠正了新建课程输入课程名字的问题,纠正了新建课程输入课程7项属性的问题

//头文件
#include
#include
#include
//功能模块
int 数据校验(int 转换类型);//数据匹配:0-转为内部数据;1-转为外部数据
int 带检测输入(void* 待存入变量, int 输入类型);//1-整数,2-小数,3-文本
int 字符串加解密(char* 加密字符串);//用于加解密密码
int 筛选判断(int 课程ID);//用于课程浏览筛选判断
int 用户_ID查询(char* 账号);//账号->ID
int 课程_ID查询(int 课程代码);//课程代码->ID
int 课程操作(int 课程ID);//课程ID为-1则新建
int 用户操作(int 用户ID);//仅权限-1
int 添加课程(int 用户ID, int 课程ID);//学生选课
int 退课(int 用户ID, int 课程ID);//用户中除去课程信息,课程中除去用户信息
int 搜索用户(void);//分权限搜索用户信息
int 搜索课程(void);//不分权限
int 浏览用户(void);//仅权限-1
int 浏览课程(void);//不分权限
int 我的课程(int 用户ID);//课表
int 我的学生(int 教师ID);
int 修改密码(int 用户ID);
int 导入课程(int 操作类型);//0-默认,1-自定义
int 导出课程(int 操作类型);//0-默认,1-自定义
int 导入用户(int 操作类型);//0-默认,1-自定义
int 导出用户(int 操作类型);//0-默认,1-自定义
//界面函数
int 载入文件(void);//读取用户数据和课程数据
int 登陆(void);//登陆界面
int 菜单(void);//首页菜单
int 用户信息(void);//用户菜单界面
int 课程信息(void);//课程菜单界面
int 退出(void);//释放内存并退出

数据类型.cpp

const int 文本长度 = 50, 选课上限 = 30;
const int 选课类型_数量 = 4, 选课性质_数量 = 4, 上课时间_数量 = 5, 上课地点_数量 = 2, 学期_数量 = 10;
//char** 选课类型, ** 选课性质, ** 上课时间, ** 上课地点,**学期,**上课星期;//自定义化读取-未完工
const char 选课类型[选课类型_数量][10] = { "正选","重修","选修","补修" };
const char 选课性质[选课性质_数量][15] = { "实践教学课","公共基础必修课","创业课程","其他" };
const char 上课时间[上课时间_数量][10] = { "第一节","第二节","第三节","第四节","晚上" };
const char 上课星期[7][10] = { "星期一","星期二","星期三","星期四","星期五","星期六", "星期天" };
const char 上课地点[上课地点_数量][10] = { "本部","西校区" };
const char 学期[学期_数量][15] = { "2019上半年","2019下半年","2020上半年" ,"2020年下半年","2021年上半年" ,"2021年下半年" ,"2022年上半年" ,"2022年下半年" ,"2023年上半年","2023年下半年" };
FILE* 用户数据, * 课程数据, * 系统日志;
int 用户数量 = 0, 课程数量 = 0, 登录用户ID = 0, 筛选条件[10][10] = { 0 };//0-显示,1-隐藏
struct 课程 {
    int 课程代码;//-1待删除
    int 学分;
    int 选课性质;
    int 选课类型;
    int 学期;
    int 上课时间;
    int 上课星期;
    char 教师代码[文本长度];
    char 课程名字[文本长度];
    int 上课地点;
    int 学生上限;
    int 用户数量;
    int* 用户ID;
}*课_程 = NULL;
struct 用户 {
    char 账号[文本长度];//学号或工号
    char 密码[文本长度];
    char 姓名[文本长度];
    int 权限类型;//1-学校,2-教师,3-学生,-1-待删除
    int 课程数量;
    int* 课程代码;
}*用_户 = NULL;
union 临时数据
{
    char 文本型[1000];
    char 字符型;
    int 整数型;
    double 小数型;
    FILE* 文件型;
};

界面函数.cpp

int 载入文件(void) {
    if (导入用户(0) == -1) exit(-1);
    if (导入课程(0) == -1) exit(-1);
    数据校验(0);
    system("pause"); system("cls");
    return 0;
}
int 登陆(void) {
    临时数据 账号, 密码;
    printf("登录->请输入账号:");
    带检测输入(账号.文本型, 3);
    账号.整数型 = 用户_ID查询(账号.文本型);//匹配用户数据
    if (账号.整数型 == -1) { printf("该账号不存在,请联系管理员进行纠正!\n"); system("pause"); system("cls"); return -1; }
    printf("登录->请输入密码:");
    带检测输入(密码.文本型, 3);
    if (strcmp(密码.文本型, 用_户[账号.整数型].密码)) { printf("登陆失败,密码错误!\n"); system("pause"); system("cls"); return -1; }
    printf("登陆成功!\n");
    system("pause"); system("cls");
    登录用户ID = 账号.整数型;
    sprintf(账号.文本型, "title %s", 用_户[登录用户ID].账号);
    system(账号.文本型);
    return 0;
}//登陆失败返回-1
int 菜单(void) {
    临时数据 操作;
    printf("菜单\n[1]用户信息\t[2]课程信息\n[3]系统日志\t[0]退出\n请输入数字继续操作:");
    带检测输入(&操作.整数型, 1);
    system("cls");
    switch (操作.整数型) {
    case 1:while (!用户信息()); break;
    case 2:while (!课程信息()); break;
    case 3:while (!查看日志()); break;
    case 0:return 1; break;
    }
    system("cls");
    return 0;
}
int 用户信息(void) {
    临时数据 操作;
    printf("用户信息\n");
    switch (用_户[登录用户ID].权限类型) {
    case 1:
        printf("[1]浏览用户\t[2]搜索用户\n[3]导入用户\t[4]导出用户\n[5]修改密码\t[0]返回\n请输入数字继续操作:");
        带检测输入(&操作.整数型, 1);
        system("cls");
        switch (操作.整数型) {
        case 1:while (!浏览用户()); break;
        case 2:搜索用户(); system("cls");  break;
        case 3:导入用户(1); 数据校验(0); system("pause"); system("cls"); break;
        case 4:导出用户(1); break;
        case 5:while (修改密码(登录用户ID)); break;
        case 0:return 1;
        default:printf("操作非法,请重新输入!"); system("pause");  system("cls"); return -1;
        }
        break;
    case 2:
        printf("工号:%s\t姓名:%s\n[1]我的学生\t[2]搜索学生\n[3]修改密码\t[0]返回\n请输入数字继续操作:", 用_户[登录用户ID].账号, 用_户[登录用户ID].姓名);
        带检测输入(&操作.整数型, 1);
        system("cls");
        switch (操作.整数型) {
        case 1:while (!我的学生(登录用户ID)); break;
        case 2:搜索用户(); system("cls"); break;
        case 3:while (修改密码(登录用户ID)); break;
        case 0:return 1;
        default:printf("操作非法,请重新输入!"); system("pause");  system("cls"); return -1;
        }
        break;
    case 3:
        printf("学号:%s\t姓名:%s\n[1]修改密码\t[0]返回\n请输入数字继续操作:", 用_户[登录用户ID].账号, 用_户[登录用户ID].姓名);
        带检测输入(&操作.整数型, 1);
        system("cls");
        switch (操作.整数型) {
        case 1:while (修改密码(登录用户ID)); break;
        case 0:return 1;
        default:printf("操作非法,请重新输入!"); system("pause"); system("cls"); return -1;
        }
        break;
    }
    return 0;
}
int 课程信息(void) {
    临时数据 操作;
    printf("用户信息\n[1]浏览课程\t[2]搜索课程\n");
    switch (用_户[登录用户ID].权限类型) {
    case 1:
        printf("[3]导入课程\t[4]导出课程\n[0]返回\n请输入数字继续操作:");
        带检测输入(&操作.整数型, 1);
        system("cls");
        switch (操作.整数型) {
        case 1:while (!浏览课程()); break;
        case 2:搜索课程(); system("cls"); break;
        case 3:导入课程(1); 数据校验(0); system("pause"); system("cls");  break;
        case 4:导出课程(1);  break;
        case 0:return 1;
        default:printf("操作非法,请重新输入!\n"); system("pause"); system("cls"); return -1;
        }
        break;
    case 2:case 3:
        printf("[3]我的课程\t[0]返回\n请输入数字继续操作:");
        带检测输入(&操作.整数型, 1);
        system("cls");
        switch (操作.整数型) {
        case 1:while (!浏览课程()); break;
        case 2:搜索课程(); system("cls"); break;
        case 3:while (!我的课程(登录用户ID)); break;
        case 0:return 1;
        default:printf("操作非法,请重新输入!\n"); system("pause"); system("cls"); return -1;
        }
        break;
    }
    return 0;
}
int 退出(void) {
    导出课程(0);
    导出用户(0);
    free(课_程); free(用_户);
    fclose(课程数据); fclose(用户数据);
    printf("感谢使用本软件,欢迎下次再见!\n");
    system("pause");
    system("cls");
    return 0;
}

主函数.cpp

#include"头文件和函数申明.h"
#include"数据类型.cpp"
#include"功能模块.cpp"
#include"界面函数.cpp"
int main(void) {
    system("title 学生选课系统"); 载入文件();
    system("title 登陆"); while (登陆());
    while (!菜单());
    退出();
    return -1;
}

功能模块

int 打印课表(void);//未完工
int 查看日志(void);//未完工

int 数据校验(int 转换类型) {
    临时数据 循环[3], 课程ID;
    printf("数据校验···\n");
    switch (转换类型) {
    case 0:
        for (循环[0].整数型 = 0; 循环[0].整数型 < 用户数量; 循环[0].整数型++) {//将学生选课信息录入到课程数据中
            if (用_户[循环[0].整数型].权限类型 != 3)continue;//跳过学校和教师
            else if (用_户[循环[0].整数型].课程数量 > 选课上限) continue;
            for (循环[1].整数型 = 0; 循环[1].整数型 < 用_户[循环[0].整数型].课程数量; 循环[1].整数型++) {
                课程ID.整数型 = 课程_ID查询(用_户[循环[0].整数型].课程代码[循环[1].整数型]);
                if (课程ID.整数型 < 0) { 用_户[循环[0].整数型].课程代码[循环[1].整数型] *= -1; continue; }
                用_户[循环[0].整数型].课程代码[循环[1].整数型] = 课程ID.整数型;//转换为内部代码
                for (循环[2].整数型 = 0; 循环[2].整数型 < 课_程[课程ID.整数型].用户数量; 循环[2].整数型++)
                    if (课_程[课程ID.整数型].用户ID[循环[2].整数型] == 循环[0].整数型) break;
                if (循环[2].整数型 == 课_程[课程ID.整数型].用户数量) {
                    课_程[课程ID.整数型].用户ID = (int*)realloc(课_程[课程ID.整数型].用户ID, sizeof(int) * ++课_程[课程ID.整数型].用户数量);
                    课_程[课程ID.整数型].用户ID[课_程[课程ID.整数型].用户数量 - 1] = 循环[0].整数型;
                }
            }
        }
        break;
    case 1:
        for (循环[0].整数型 = 0; 循环[0].整数型 < 用户数量; 循环[0].整数型++) {
            if (用_户[循环[0].整数型].权限类型 != 3)continue;
            else if (用_户[循环[0].整数型].课程数量 > 选课上限) continue;
            for (循环[1].整数型 = 0; 循环[1].整数型 < 用_户[循环[0].整数型].课程数量; 循环[1].整数型++)
                if (用_户[循环[0].整数型].课程代码[循环[1].整数型] >= 0)用_户[循环[0].整数型].课程代码[循环[1].整数型] = 课_程[用_户[循环[0].整数型].课程代码[循环[1].整数型]].课程代码;
                else 用_户[循环[0].整数型].课程代码[循环[1].整数型] *= -1;
        }
    }
    printf("数据校验√√√\n");
    return 0;
}
int 带检测输入(void* 待存入变量, int 输入类型) {
    临时数据 判断;
    switch (输入类型) {
    case 1:判断.整数型 = scanf("%d", (int*)待存入变量); break;
    case 2:判断.整数型 = scanf("%lf", (double*)待存入变量); break;
    case 3:判断.整数型 = scanf("%s", (char*)待存入变量); break;
    default:判断.整数型 = 0; break;
    }
    rewind(stdin);//fflush(stdin); 重定义/清空输入缓存区
    return 判断.整数型 == 1 ? 判断.整数型 : (printf("输入非法,请重新输入!\n"), 带检测输入(待存入变量, 输入类型) + 判断.整数型);
}//返回重新输入的次数
int 字符串加解密(char* 加密字符串) {
    临时数据 次数;
    次数.整数型 = 0;
    while (*加密字符串 != '\0') {
        if (*加密字符串 > '0' && *加密字符串 <= '9') *加密字符串 -= 16;
        else if (*加密字符串 >= '!' && *加密字符串 <= ')')*加密字符串 += 16;
        else if (*加密字符串 >= 'A' && *加密字符串 < 'Z')*加密字符串 = 'A' + 'Y' - *加密字符串;
        else if (*加密字符串 > 'a' && *加密字符串 <= 'z')*加密字符串 = 'a' + 'z' - *加密字符串;
        次数.整数型++, 加密字符串++;
    }
    return 次数.整数型;
}//返回字符串加密步骤数
int 筛选判断(int 课程ID) {
    临时数据 循环[2], 判断内容;
    if (课_程[课程ID].学生上限 - 课_程[课程ID].用户数量 < 筛选条件[5][0]) return 1;
    for (循环[0].整数型 = 0; 循环[0].整数型 < 5; 循环[0].整数型++) {
        switch (循环[0].整数型) {
        case 0:判断内容.整数型 = 课_程[课程ID].选课性质; break;
        case 1:判断内容.整数型 = 课_程[课程ID].选课类型; break;
        case 2:判断内容.整数型 = 课_程[课程ID].学期; break;
        case 3:判断内容.整数型 = 课_程[课程ID].上课时间; break;
        case 4:判断内容.整数型 = 课_程[课程ID].上课地点; break;
        }
        for (循环[1].整数型 = 0; 循环[1].整数型 < 10; 循环[1].整数型++)
            if (筛选条件[循环[0].整数型][循环[1].整数型] && 判断内容.整数型 == 循环[1].整数型)
                return 1;
    }
    return 0;
}//判断显示返回0,隐藏返回1
int 用户_ID查询(char* 账号) {
    临时数据 个数, 循环, 目标ID;
    for (目标ID.整数型 = -1, 个数.整数型 = 循环.整数型 = 0; 循环.整数型 < 用户数量; 循环.整数型++)
        if (!strcmp(账号, 用_户[循环.整数型].账号)) 个数.整数型++, 目标ID.整数型 = 循环.整数型;
    if (个数.整数型 == 1) return 目标ID.整数型;
    else return -个数.整数型 - 1;
}//找到一个则返回正确ID,未找到则返回-1,找到多个返回-(1+个数)
int 课程_ID查询(int 课程代码) {
    临时数据 个数, 循环, 目标ID;
    for (目标ID.整数型 = -1, 个数.整数型 = 循环.整数型 = 0; 循环.整数型 < 课程数量; 循环.整数型++)
        if (课程代码 == 课_程[循环.整数型].课程代码) 个数.整数型++, 目标ID.整数型 = 循环.整数型;
    if (个数.整数型 == 1) return 目标ID.整数型;
    else return -个数.整数型 - 1;
}
int 课程操作(int 课程ID) {
    课程 临时课程;
    临时数据 操作, 循环;
    system("cls");
    if (课程ID == -1) {
        printf("新建课程\n请输入新建课程代码:");
        带检测输入(&临时课程.课程代码, 1);
        if (课程_ID查询(临时课程.课程代码) != -1) { printf("该课程已存在!\n"); system("pause"); system("cls"); return -1; }
        printf("请输入新建教师代码:");
        带检测输入(临时课程.教师代码, 3);
        if ((操作.整数型 = 用户_ID查询(临时课程.教师代码)) < 0) { printf("该教师信息有误!\n"); system("pause"); system("cls"); return -1; }
        课_程 = (课程*)realloc(课_程, sizeof(课程) * ++课程数量);
        课_程[课程数量 - 1].课程代码 = 临时课程.课程代码; strcpy(课_程[课程数量 - 1].教师代码, 临时课程.教师代码);
        printf("请输入新建课程名字:");
        带检测输入(课_程[课程数量 - 1].课程名字, 3);
        printf("请依序输入(空格隔开):[学分][选课性质][选课类型][学期][上课时间][上课地点][学生上限]\n->");
        while (scanf("%d%d%d%d%d%d%d", &课_程[课程数量 - 1].学分, &课_程[课程数量 - 1].选课性质, &课_程[课程数量 - 1].选课类型, &课_程[课程数量 - 1].学期, &课_程[课程数量 - 1].上课时间, &课_程[课程数量 - 1].上课地点, &课_程[课程数量 - 1].学生上限) != 7) printf("输入非法,请重新输入:");
        用_户[操作.整数型].课程代码 = (int*)realloc(用_户[操作.整数型].课程代码, sizeof(int) * ++用_户[操作.整数型].课程数量);
        用_户[操作.整数型].课程代码[用_户[操作.整数型].课程数量 - 1] = 课程数量 - 1;
        printf("新建课程√√√");
        导出课程(0);
        return 1;
    }
    else {
        printf("课程信息\n[1]课程代码:%d\t[2]课程名字:%s\t[3]学生上限:%d\n[4]学分:%d\t[5]教师代码:%s\t[6]选课性质:%d\n[7]学期:%d\t[8]上课地点:%d\t\t[9]上课时间:%d\n[10]选课类型:%d\t\t\t\t[0]删除课程\n", 课_程[课程ID].课程代码, 课_程[课程ID].课程名字, 课_程[课程ID].学生上限, 课_程[课程ID].学分, 课_程[课程ID].教师代码, 课_程[课程ID].选课性质, 课_程[课程ID].学期, 课_程[课程ID].上课地点, 课_程[课程ID].上课时间, 课_程[课程ID].选课类型);
        printf("输入序号进行修改,其他数字返回:");
        带检测输入(&操作.整数型, 1);
        switch (操作.整数型) {
        case 0:
            for (循环.整数型 = 0; 循环.整数型 < 课_程[课程ID].用户数量; 循环.整数型++)
                退课(课_程[课程ID].用户ID[循环.整数型], 课程ID);
            课_程[课程ID].课程代码 = -1;
            导出课程(0); 导出用户(0);
            break;
        case 1:
            printf("请输入新课程代码:");
            带检测输入(&临时课程.课程代码, 1);
            if (课程_ID查询(临时课程.课程代码) != -1) { printf("该课程已存在!\n"); system("pause"); system("cls"); return -1; }
            课_程[课程ID].课程代码 = 临时课程.课程代码;
            导出课程(0);
            break;
        case 2:
            printf("请输入新课程名字:");
            带检测输入(课_程[课程ID].课程名字, 3);
            导出课程(0);
            break;
        case 3:
            printf("请输入新学生上限:");
            带检测输入(&课_程[课程ID].学生上限, 1);
            导出课程(0);
            break;
        case 4:
            printf("请输入新学分:");
            带检测输入(&课_程[课程ID].学分, 1);
            导出课程(0);
            break;
        case 5:
            printf("请输入新教师代码:");
            带检测输入(临时课程.教师代码, 3);
            if (用户_ID查询(临时课程.教师代码) < 0) { printf("该教师不存在或存在问题!\n"); system("pause"); system("cls"); return -1; }
            strcpy(课_程[课程ID].教师代码, 临时课程.教师代码);
            导出课程(0);
            break;
        case 6:
            printf("请输入新选课性质:");
            带检测输入(&课_程[课程ID].选课性质, 1);
            导出课程(0);
            break;
        case 7:
            printf("请输入新学期:");
            带检测输入(&课_程[课程ID].学期, 1);
            导出课程(0);
            break;
        case 8:
            printf("请输入新上课地点:");
            带检测输入(&课_程[课程ID].上课地点, 1);
            导出课程(0);
            break;
        case 9:
            printf("请输入新上课时间:");
            带检测输入(&课_程[课程ID].上课时间, 1);
            导出课程(0);
            break;
        case 10:
            printf("请输入新选课类型:");
            带检测输入(&课_程[课程ID].选课类型, 1);
            导出课程(0);
            break;
        default:system("cls"); return 1;
        }
    }
    system("cls");
    return 0;
}
int 用户操作(int 用户ID) {
    用户 临时用户;
    临时数据 操作, 循环;
    system("cls");
    if (用户ID == -1) {
        printf("新建用户\n请输入新建用户权限类型:");
        带检测输入(&临时用户.权限类型, 1);
        if (临时用户.权限类型 > 3 || 临时用户.权限类型 < 0) { printf("错误的权限类型!\n"); system("pause"); system("cls"); return -1; }
        printf("请输入新建用户账号:");
        带检测输入(临时用户.账号, 3);
        if (用户_ID查询(临时用户.账号) != -1) { printf("该账号已存在!\n"); system("pause"); system("cls"); return -1; }
        printf("请输入新建用户密码:");
        带检测输入(临时用户.密码, 3);
        用_户 = (用户*)realloc(用_户, sizeof(用户) * ++用户数量);
        用_户[用户数量 - 1].权限类型 = 临时用户.权限类型; strcpy(用_户[用户数量 - 1].账号, 临时用户.账号); strcpy(用_户[用户数量 - 1].密码, 临时用户.密码);
        if (用_户[用户数量 - 1].权限类型 != 1) {
            printf("请输入新建用户姓名:");
            带检测输入(用_户[用户数量 - 1].姓名, 3);
        }
        if (用_户[用户数量 - 1].权限类型 == 3) {
            用_户[用户数量 - 1].课程数量 = 0;
            用_户[用户数量 - 1].课程代码 = NULL;
            printf("请输入新建用户课程代码(输入课程代码外的数字时中止):");
            while (带检测输入(&操作.整数型, 1), (操作.整数型 = 课程_ID查询(操作.整数型)) >= 0) {
                用_户[用户数量 - 1].课程代码 = (int*)realloc(用_户[用户数量 - 1].课程代码, sizeof(int) * ++用_户[用户数量 - 1].课程数量);
                带检测输入(&用_户[用户数量 - 1].课程代码[用_户[用户数量 - 1].课程数量 - 1], 1);
            }
        }
        printf("新建用户√√√");
        导出用户(0);
    }
    else {
        printf("用户信息\n[1]权限类型:%d\t[2]账号:%s\n[3]修改密码\t[0]删除账号\n", 用_户[用户ID].权限类型, 用_户[用户ID].账号, 用_户[用户ID].密码);
        if (用_户[用户ID].权限类型 != 1) printf("[4]课程信息\n");
        printf("输入序号进行修改,其他数字返回:");
        带检测输入(&操作.整数型, 1);
        switch (操作.整数型) {
        case 0:
            if (用_户[用户ID].权限类型 == 3)
                for (循环.整数型 = 0; 循环.整数型 < 用_户[用户ID].课程数量; 循环.整数型++)
                    退课(用户ID, 用_户[用户ID].课程代码[0]);
            用_户[用户ID].权限类型 = -1;
            导出用户(0);
            break;
        case 1:
            printf("请输入新权限类型:");
            带检测输入(&用_户[用户ID].权限类型, 1);
            导出用户(0);
            break;
        case 2:
            printf("请输入新账号:");
            带检测输入(&临时用户.账号, 3);
            if (用户_ID查询(临时用户.账号) != -1) { printf("该账号已存在!\n"); system("pause"); system("cls"); return -1; }
            strcpy(用_户[用户ID].账号, 临时用户.账号);
            导出用户(0);
            break;
        case 3:while (修改密码(用户ID)); break;
        case 4:
            if (用_户[用户ID].权限类型 == 1) { system("cls"); return 1; }
            else if (用_户[用户ID].权限类型 == 2) while (!我的学生(用户ID));
            else while (!我的课程(用户ID)); break;
            break;
        default:system("cls"); return 1;
        }
    }
    system("cls");
    return 0;
}
int 添加课程(int 用户ID, int 课程ID) {
    临时数据 循环;
    for (循环.整数型 = 0; 循环.整数型 < 用_户[用户ID].课程数量; 循环.整数型++)
        if (用_户[用户ID].课程代码[循环.整数型] == 课程ID) {
            printf("该课程已在选课中!\n");
            return -1;
        }
    用_户[用户ID].课程代码 = (int*)realloc(用_户[用户ID].课程代码, sizeof(int) * ++用_户[用户ID].课程数量);
    用_户[用户ID].课程代码[用_户[用户ID].课程数量 - 1] = 课程ID;
    导出课程(0);
    return 0;
}
int 退课(int 用户ID, int 课程ID) {
    临时数据 循环;
    for (循环.整数型 = 0; 循环.整数型 < 用_户[用户ID].课程数量; 循环.整数型++)
        if (用_户[用户ID].课程代码[循环.整数型] == 课程ID) break;
    用_户[用户ID].课程代码[循环.整数型] = 用_户[用户ID].课程代码[--用_户[用户ID].课程数量];
    for (循环.整数型 = 0; 循环.整数型 < 课_程[课程ID].用户数量; 循环.整数型++)
        if (课_程[课程ID].用户ID[循环.整数型] == 用户ID) break;
    课_程[课程ID].用户ID[循环.整数型] = 课_程[课程ID].用户ID[--课_程[课程ID].用户数量];
    导出课程(0); 导出用户(0);
    return 0;
}
int 搜索用户(void) {
    临时数据 账号, 循环, 计数, 操作;
    switch (用_户[登录用户ID].权限类型) {
    case 1:
        printf("请输入用户账号:");
        带检测输入(账号.文本型, 3);
        账号.整数型 = 用户_ID查询(账号.文本型);
        if (账号.整数型 == -1) { printf("该账号不存在!\n"); system("pause"); system("cls"); return 1; }
        else if (账号.整数型 < 0) { printf("该账号信息错误!\n错误代码:%d", 账号.整数型); system("pause"); system("cls"); return 1; }
        while (!用户操作(账号.整数型));
        break;
    case 2:
        printf("请输入学生学号:");
        带检测输入(账号.文本型, 3);
        账号.整数型 = 用户_ID查询(账号.文本型);
        if (账号.整数型 == -1) { printf("该学生不存在!\n"); system("pause"); system("cls"); return 1; }
        else if (账号.整数型 < 0) { printf("该学生信息错误!请联系管理员纠正", 账号.整数型); system("pause"); system("cls"); return 1; }
        do {
            printf("序号\t课程代码\t课程名字\t选课人数\n");
            for (计数.整数型 = 循环.整数型 = 0; 循环.整数型 < 用_户[账号.整数型].课程数量; 循环.整数型++)
                if (用_户[账号.整数型].课程代码[循环.整数型] >= 0 && 用_户[账号.整数型].课程代码[循环.整数型] < 课程数量 && !strcmp(课_程[用_户[账号.整数型].课程代码[循环.整数型]].教师代码, 用_户[登录用户ID].账号))
                {
                    计数.整数型++;
                    printf("[%d]\t%d\t\t%s\t\t%d/%d\n", 循环.整数型 + 1, 课_程[用_户[账号.整数型].课程代码[循环.整数型]].课程代码, 课_程[用_户[账号.整数型].课程代码[循环.整数型]].课程名字, 课_程[用_户[账号.整数型].课程代码[循环.整数型]].用户数量, 课_程[用_户[账号.整数型].课程代码[循环.整数型]].学生上限);
                }
            printf("学生学号:%s\t学生姓名:%s\t选课数:%d\n", 用_户[账号.整数型].账号, 用_户[账号.整数型].姓名, 计数.整数型);
            printf("请输入序号退课或其他任意键返回:");
            带检测输入(&操作.整数型, 1);
            if (操作.整数型 > 0 && 操作.整数型 < 循环.整数型 + 2) 退课(账号.整数型, 用_户[账号.整数型].课程代码[操作.整数型 - 1]);
            system("cls");
        } while (操作.整数型 > 0 && 操作.整数型 < 循环.整数型 + 2);
        break;
    }
    return 0;
}
int 搜索课程(void) {
    临时数据 课程, 循环, 操作;
    printf("请输入课程代码:");
    带检测输入(&课程.整数型, 1);
    课程.整数型 = 课程_ID查询(课程.整数型);
    switch (用_户[登录用户ID].权限类型) {
    case 1:
        if (课程.整数型 == -1) { printf("该课程不存在!\n"); system("pause"); system("cls"); return 1; }
        else if (课程.整数型 < 0) { printf("该课程信息错误!\n错误代码:%d", 课程.整数型); system("pause"); system("cls"); return 1; }
        while (!课程操作(课程.整数型));
        break;
    case 2:case 3:
        printf("课程代码:%d\t课程名字:%s\t学生上限:%d\n学分:%d\t教师代码:%s\t选课性质:%d\n学期:%d\t上课地点:%d\t\t上课时间:%d\n选课类型:%d\n", 课_程[课程.整数型].课程代码, 课_程[课程.整数型].课程名字, 课_程[课程.整数型].学生上限, 课_程[课程.整数型].学分, 课_程[课程.整数型].教师代码, 课_程[课程.整数型].选课性质, 课_程[课程.整数型].学期, 课_程[课程.整数型].上课地点, 课_程[课程.整数型].上课时间, 课_程[课程.整数型].选课类型);
        if (用_户[登录用户ID].权限类型 == 3) {
            printf("是否选课(1-是,其他键-返回):");
            带检测输入(&操作.整数型, 1);
            if (操作.整数型 == 1) 添加课程(登录用户ID, 1);
        }
        system("pause");
        break;
    }
    return 0;
}
int 浏览用户(void) {
    临时数据 循环[2], 操作;
    printf("浏览用户(共%d条数据)\n序号\t权限类型\t账号\t姓名\t\t课程代码\n", 用户数量);
    for (循环[0].整数型 = 0; 循环[0].整数型 < 用户数量; 循环[0].整数型++, printf("\n")) {
        printf("[%d]\t%d\t\t%s\t", 循环[0].整数型 + 1, 用_户[循环[0].整数型].权限类型, 用_户[循环[0].整数型].账号);
        if (用_户[循环[0].整数型].权限类型 == 1) continue;
        printf("%-10s\t", 用_户[循环[0].整数型].姓名);
        for (循环[1].整数型 = 0; 循环[1].整数型 < 用_户[循环[0].整数型].课程数量; 循环[1].整数型++)
            if (用_户[循环[0].整数型].课程代码[循环[1].整数型] >= 0 && 用_户[循环[0].整数型].课程代码[循环[1].整数型] < 课程数量)
                printf("%d ", 课_程[用_户[循环[0].整数型].课程代码[循环[1].整数型]].课程代码);
    }
    printf("输入序号查看详细信息,输入0新建用户,其他任意键返回:");
    带检测输入(&操作.整数型, 1);
    if (操作.整数型 == 0) while (!用户操作(-1));//新建
    else if (操作.整数型 > 用户数量 || 操作.整数型 < 0) { system("cls"); return 1; }
    else while (!用户操作(操作.整数型 - 1));
    system("cls");
    return 0;
}
int 浏览课程(void) {
    临时数据 循环, 操作;
    printf("浏览课程(共%d条数据)\n%-6s\t\t%-10s\t%-15s\t%-5s\t%-15s\t%-10s\t%-10s\t%-10s\t%-10s\t%-10s\t%s\n", 课程数量, "序号", "课程代码", "教师姓名", "学分", "选课性质[-1]", "选课类型[-2]", "学期[-3]", "上课时间[-4]", "课程名字", "上课地点[-5]", "选课人数[-6]");
    for (循环.整数型 = 0; 循环.整数型 < 课程数量; 循环.整数型++)
        if (!筛选判断(循环.整数型))
            printf("[%06d]\t%-10d\t%-15s\t%-5d\t%-15s\t%-10s\t%-10s\t%-10s\t%-10s\t%-10s\t%d/%d\n", 循环.整数型 + 1, 课_程[循环.整数型].课程代码, 用_户[用户_ID查询(课_程[循环.整数型].教师代码)].姓名, 课_程[循环.整数型].学分, 选课性质[课_程[循环.整数型].选课性质], 选课类型[课_程[循环.整数型].选课类型], 学期[课_程[循环.整数型].学期], 上课时间[课_程[循环.整数型].上课时间], 课_程[循环.整数型].课程名字, 上课地点[课_程[循环.整数型].上课地点], 课_程[循环.整数型].用户数量, 课_程[循环.整数型].学生上限);
    if (用_户[登录用户ID].权限类型 == 1)printf("输入-6到-1进行筛选,输入序号查看详细信息,输入0新建课程,其他任意键返回:");
    else if (用_户[登录用户ID].权限类型 == 2)printf("输入-6到-1进行筛选,其他任意键返回:");
    else if (用_户[登录用户ID].权限类型 == 3)printf("输入-6到-1进行筛选,输入序号选课,其他任意键返回");
    带检测输入(&操作.整数型, 1);
    if (用_户[登录用户ID].权限类型 == 1 && 操作.整数型 == 0) while (!课程操作(-1));
    else if (操作.整数型 >= -6 && 操作.整数型 <= -1) {//筛选
        printf("筛选(0-显示,1-隐藏)\n");
        switch (操作.整数型) {
        case -1:
            printf("选课性质:");
            for (循环.整数型 = 0; 循环.整数型 < 选课性质_数量; 循环.整数型++)
                printf("[%d]%s(%d) ", 循环.整数型 + 1, 选课性质[循环.整数型], 筛选条件[0][循环.整数型]);
            printf("\n输入序列改变显示状态:");
            带检测输入(&操作.整数型, 1);
            筛选条件[0][操作.整数型 - 1] = 1 - 筛选条件[0][操作.整数型 - 1];
            break;
        case -2:
            printf("选课类型:");
            for (循环.整数型 = 0; 循环.整数型 < 选课类型_数量; 循环.整数型++)
                printf("[%d]%s(%d) ", 循环.整数型 + 1, 选课类型[循环.整数型], 筛选条件[1][循环.整数型]);
            printf("\n输入序列改变显示状态:");
            带检测输入(&操作.整数型, 1);
            筛选条件[1][操作.整数型 - 1] = 1 - 筛选条件[1][操作.整数型 - 1];
            break;
        case -3:
            printf("学期:");
            for (循环.整数型 = 0; 循环.整数型 < 学期_数量; 循环.整数型++)
                printf("[%d]%s(%d) ", 循环.整数型 + 1, 学期[循环.整数型], 筛选条件[2][循环.整数型]);
            printf("\n输入序列改变显示状态:");
            带检测输入(&操作.整数型, 1);
            筛选条件[2][操作.整数型 - 1] = 1 - 筛选条件[2][操作.整数型 - 1];
            break;
        case -4:
            printf("上课时间:");
            for (循环.整数型 = 0; 循环.整数型 < 上课时间_数量; 循环.整数型++)
                printf("[%d]%s(%d) ", 循环.整数型 + 1, 上课时间[循环.整数型], 筛选条件[3][循环.整数型]);
            printf("\n输入序列改变显示状态:");
            带检测输入(&操作.整数型, 1);
            筛选条件[3][操作.整数型 - 1] = 1 - 筛选条件[3][操作.整数型 - 1];
            break;
        case -5:
            printf("上课地点:");
            for (循环.整数型 = 0; 循环.整数型 < 上课地点_数量; 循环.整数型++)
                printf("[%d]%s(%d) ", 循环.整数型 + 1, 上课地点[循环.整数型], 筛选条件[4][循环.整数型]);
            printf("\n输入序列改变显示状态:");
            带检测输入(&操作.整数型, 1);
            筛选条件[4][操作.整数型 - 1] = 1 - 筛选条件[4][操作.整数型 - 1];
            break;
        case -6:
            printf("选课数:剩余空间≥%d人,调整人数为:", 筛选条件[5][0]);
            带检测输入(&筛选条件[5][0], 1);
            break;
        }
    }
    else if (操作.整数型 > 课程数量 || 用_户[登录用户ID].权限类型 == 2) { system("cls"); return 1; }
    else
        switch (用_户[登录用户ID].权限类型) {
        case 1:while (!课程操作(操作.整数型 - 1)); break;
        case 3:添加课程(登录用户ID, 操作.整数型 - 1); break;
        }
    system("cls");
    return 0;
}
int 我的课程(int 用户ID) {
    临时数据 循环, 操作;
    system("cls");
    printf("%s的课程信息\n%-6s\t\t%-10s\t%-15s\t%-5s\t%-15s\t%-10s\t%-10s\t%-10s\t%-10s\t%-10s\t%s\n", 用_户[用户ID].账号, "序号", "课程代码", "教师名字", "学分", "选课性质", "选课类型", "学期", "上课时间", "课程名字", "上课地点", "选课数");
    for (循环.整数型 = 0; 循环.整数型 < 用_户[用户ID].课程数量; 循环.整数型++)
        if (用_户[用户ID].课程代码[循环.整数型] >= 0 && 用_户[用户ID].课程代码[循环.整数型] < 课程数量)
            printf("[%06d]\t%-10d\t%-15s\t%-5d\t%-15s\t%-10s\t%-10s\t%-10s\t%-10s\t%-10s\t%d/%d\n", 循环.整数型 + 1, 课_程[用_户[用户ID].课程代码[循环.整数型]].课程代码, 用_户[用户_ID查询(课_程[用_户[用户ID].课程代码[循环.整数型]].教师代码)].姓名, 课_程[用_户[用户ID].课程代码[循环.整数型]].学分, 选课性质[课_程[用_户[用户ID].课程代码[循环.整数型]].选课性质], 选课类型[课_程[用_户[用户ID].课程代码[循环.整数型]].选课类型], 学期[课_程[用_户[用户ID].课程代码[循环.整数型]].学期], 上课时间[课_程[用_户[用户ID].课程代码[循环.整数型]].上课时间], 课_程[用_户[用户ID].课程代码[循环.整数型]].课程名字, 上课地点[课_程[用_户[用户ID].课程代码[循环.整数型]].上课地点], 课_程[用_户[用户ID].课程代码[循环.整数型]].用户数量, 课_程[用_户[用户ID].课程代码[循环.整数型]].学生上限);
    if (用_户[用户ID].权限类型 == 3) {
        printf("输入序号退课,其他任意输入返回:");
        带检测输入(&操作.整数型, 1);
        if (操作.整数型<1 || 操作.整数型>用_户[用户ID].课程数量) { system("cls"); return 1; }
        else 退课(用户ID, 用_户[用户ID].课程代码[操作.整数型]);
    }
    else { system("pause"); system("cls"); return 1; }
    system("cls");
    return 0;
}
int 我的学生(int 教师ID) {
    临时数据 循环[2], 操作[3], 用户ID;
    system("cls");
    printf("%s的学生信息\n课程代码\t课程名字\t序列\t学号\t学生姓名\n", 用_户[教师ID].账号);
    for (循环[0].整数型 = 0; 循环[0].整数型 < 用_户[教师ID].课程数量; 循环[0].整数型++) {
        printf("%05d\t\t%s\t\t[%d]\t共%d/%d位学生\n", 课_程[用_户[教师ID].课程代码[循环[0].整数型]].课程代码, 课_程[用_户[教师ID].课程代码[循环[0].整数型]].课程名字, 循环[0].整数型 + 1, 课_程[用_户[教师ID].课程代码[循环[0].整数型]].用户数量, 课_程[用_户[教师ID].课程代码[循环[0].整数型]].学生上限);
        for (循环[1].整数型 = 0; 循环[1].整数型 < 课_程[用_户[教师ID].课程代码[循环[0].整数型]].用户数量; 循环[1].整数型++)
            if (用_户[课_程[用_户[教师ID].课程代码[循环[0].整数型]].用户ID[循环[1].整数型]].权限类型 != -1)
                printf("\t\t\t\t[%d]\t%s\t%s\n", 循环[1].整数型 + 1, 用_户[课_程[用_户[教师ID].课程代码[循环[0].整数型]].用户ID[循环[1].整数型]].账号, 用_户[课_程[用_户[教师ID].课程代码[循环[0].整数型]].用户ID[循环[1].整数型]].姓名);
    }
    printf("[课程序号_学生序号]退课\n[课程序号_0]添加学生\n[其他输入]返回\n请输入数字继续操作:");
    if (!scanf("%d_%d", &操作[0].整数型, &操作[1].整数型) || 操作[0].整数型<0 || 操作[1].整数型<0 || 操作[0].整数型>用_户[教师ID].课程数量 || 操作[1].整数型>课_程[用_户[教师ID].课程代码[循环[0].整数型]].用户数量) {
        printf("其他输入或下标越界!\n");
        system("pause"); system("cls");
        return -1;
    }
    if (!操作[0].整数型) {
        printf("请输入待添加学生的学号:");
        带检测输入(操作[2].文本型, 3);
        用户ID.整数型 = 用户_ID查询(操作[2].文本型);
        if (用户ID.整数型 < 0) { printf("该学生信息存在问题,请联系管理员纠正!\n"); system("pause"); system("cls"); return -1; }
        else 添加课程(用户ID.整数型, 课_程[用_户[教师ID].课程代码[操作[0].整数型]].课程代码);
    }
    else 退课(用户ID.整数型, 课_程[用_户[教师ID].课程代码[操作[0].整数型]].课程代码);
    return 0;
}//返回查询到的个数
int 修改密码(int 用户ID) {
    临时数据 密码_第一遍, 密码_第二遍;
    printf("请输入修改的密码:");
    带检测输入(密码_第一遍.文本型, 3);
    printf("请再次确认的密码:");
    带检测输入(密码_第二遍.文本型, 3);
    if (strcmp(密码_第一遍.文本型, 密码_第二遍.文本型)) {
        printf("两次密码不相同,请重新输入!\n");
        system("pause"); system("cls");
        return -1;
    }
    else {
        strcpy(用_户[用户ID].密码, 密码_第一遍.文本型);
        printf("密码修改成功!\n");
        system("pause"); system("cls");
        return 0;
    }
}
int 导入课程(int 操作类型) {
    临时数据 位置信息, 载入, 文件位置_下一行, 文件位置_当前行, 账号;
    if (操作类型) {//定位文件位置
        printf("请输入导入文件的详细目录:");
        带检测输入(位置信息.文本型, 3);
    }
    else strcpy(位置信息.文本型, "课程数据.txt");
    printf("加载课程数据···\n");
    课程数据 = fopen(位置信息.文本型, "r");
    if (课程数据 == NULL) {
        printf("课程数据不存在或打开失败,请联系管理员!\n");
        system("pause");//暂停界面
        system("cls");//清空界面
        return -1;
    }//正常运行返回值0
    free(课_程); 课程数量 = 0; 课_程 = NULL;//清空现有数据
    fgets(载入.文本型, 1000, 课程数据);
    while (!feof(课程数据)) {
        文件位置_当前行.整数型 = ftell(课程数据);
        fgets(载入.文本型, 1000, 课程数据);
        文件位置_下一行.整数型 = ftell(课程数据);
        fseek(课程数据, 文件位置_当前行.整数型, SEEK_SET);
        课_程 = (课程*)realloc(课_程, sizeof(课程) * ++课程数量);
        fscanf(课程数据, "%d", &课_程[课程数量 - 1].课程代码);
        if (课_程[课程数量 - 1].课程代码 == 0) {
            课程数量--;
            break;
        }
        课_程[课程数量 - 1].用户数量 = 0;
        课_程[课程数量 - 1].用户ID = NULL;
        fscanf(课程数据, "%s%d%d%d%d%d%s%d%d", 课_程[课程数量 - 1].教师代码, &课_程[课程数量 - 1].学分, &课_程[课程数量 - 1].选课性质, &课_程[课程数量 - 1].选课类型, &课_程[课程数量 - 1].学期, &课_程[课程数量 - 1].上课时间, 课_程[课程数量 - 1].课程名字, &课_程[课程数量 - 1].上课地点, &课_程[课程数量 - 1].学生上限);
        账号.整数型 = 用户_ID查询(课_程[课程数量 - 1].教师代码);
        if (账号.整数型 < 0 || 用_户[账号.整数型].权限类型 != 2) {
            printf("数据文件存在问题,请联系管理员!\n");
            system("pause");
            system("cls");
            return -1;
        }
        else {
            用_户[账号.整数型].课程代码 = (int*)realloc(用_户[账号.整数型].课程代码, sizeof(int) * ++用_户[账号.整数型].课程数量);
            用_户[账号.整数型].课程代码[用_户[账号.整数型].课程数量 - 1] = 课程数量 - 1;
        }
        if (文件位置_下一行.整数型 > ftell(用户数据))fgets(载入.文本型, 1000, 课程数据);//忽略剩余信息
    }
    fclose(课程数据);
    printf("加载课程数据√√√\n");
    return 0;
}
int 导出课程(int 操作类型) {
    临时数据 位置信息, 循环;
    if (操作类型) {
        printf("请输入导出文件的详细目录:");
        带检测输入(位置信息.文本型, 3);
    }
    else strcpy(位置信息.文本型, "课程数据.txt");
    printf("写入课程数据···\n");
    课程数据 = fopen(位置信息.文本型, "w");
    if (课程数据 == NULL) {
        printf("写入文件时出现错误,请联系管理员!\n");
        system("pause");
        system("cls");
        return -1;
    }
    fprintf(课程数据, "课程代码\t教师代码\t学分\t选课性质\t选课类型\t学期\t上课时间\t课程名字\t上课地点\t学生上限\n");
    for (循环.整数型 = 0; 循环.整数型 < 课程数量; 循环.整数型++)
        if (课_程[循环.整数型].课程代码 != -1)
            fprintf(课程数据, "%d\t%s\t%d\t%d\t%d\t%d\t%d\t%s\t%d\t%d\n", 课_程[循环.整数型].课程代码, 课_程[循环.整数型].教师代码, 课_程[循环.整数型].学分, 课_程[循环.整数型].选课性质, 课_程[循环.整数型].选课类型, 课_程[循环.整数型].学期, 课_程[循环.整数型].上课时间, 课_程[循环.整数型].课程名字, 课_程[循环.整数型].上课地点, 课_程[循环.整数型].学生上限);
    fprintf(课程数据, "0");
    fclose(课程数据);
    printf("写入课程数据√√√\n");
    system("pause"); system("cls");
    return 0;
}
int 导入用户(int 操作类型) {
    临时数据 位置信息, 载入, 文件位置_下一行, 文件位置_当前行, 账号;
    if (操作类型) {//定位文件位置
        printf("请输入导入文件的详细目录:");
        带检测输入(位置信息.文本型, 3);
    }
    else strcpy(位置信息.文本型, "用户数据.txt");
    printf("加载用户数据···\n");
    用户数据 = fopen(位置信息.文本型, "r");
    if (用户数据 == NULL) {
        printf("用户数据不存在或打开失败,请联系管理员!\n");
        system("pause");
        system("cls");
        return -1;
    }
    free(用_户); 用户数量 = 0; 用_户 = NULL;//清空现有数据
    fgets(载入.文本型, 1000, 用户数据);//跳过说明行
    while (!feof(用户数据)) {
        文件位置_当前行.整数型 = ftell(用户数据);
        fgets(载入.文本型, 1000, 用户数据);
        文件位置_下一行.整数型 = ftell(用户数据);
        fseek(用户数据, 文件位置_当前行.整数型, SEEK_SET);//复位文件指针位置
        用_户 = (用户*)realloc(用_户, sizeof(用户) * ++用户数量);//动态分配缓存用户数据
        fscanf(用户数据, "%d", &用_户[用户数量 - 1].权限类型);
        switch (用_户[用户数量 - 1].权限类型) {
        case 1:fscanf(用户数据, "%s%s", 用_户[用户数量 - 1].账号, 用_户[用户数量 - 1].密码); break;
        case 2:case 3:
            fscanf(用户数据, "%s%s%s", 用_户[用户数量 - 1].账号, 用_户[用户数量 - 1].密码, 用_户[用户数量 - 1].姓名);
            用_户[用户数量 - 1].课程数量 = 0;
            用_户[用户数量 - 1].课程代码 = NULL;
            while (文件位置_下一行.整数型 - 3 > ftell(用户数据)) {
                用_户[用户数量 - 1].课程代码 = (int*)realloc(用_户[用户数量 - 1].课程代码, sizeof(int) * ++用_户[用户数量 - 1].课程数量);//动态分配缓存课程代码和课程数量
                fscanf(用户数据, "%d", &用_户[用户数量 - 1].课程代码[用_户[用户数量 - 1].课程数量 - 1]);
            }
            break;
        }
        if (用_户[用户数量 - 1].权限类型 == 0) {
            用户数量--;
            break;
        }//判断数据末尾
        字符串加解密(用_户[用户数量 - 1].密码);
        if (文件位置_下一行.整数型 > ftell(用户数据))fgets(载入.文本型, 1000, 用户数据);//忽略剩余信息
    }
    fclose(用户数据);
    printf("加载用户数据√√√\n");
    return 0;
}
int 导出用户(int 操作类型) {
    临时数据 位置信息, 循环[2];
    if (操作类型) {
        printf("请输入导出文件的详细目录:");
        带检测输入(位置信息.文本型, 3);
    }
    else strcpy(位置信息.文本型, "用户数据.txt");
    printf("写入用户数据···\n");
    用户数据 = fopen(位置信息.文本型, "w");
    if (用户数据 == NULL) {
        printf("写入文件时出现错误,请联系管理员!\n");
        system("pause");
        system("cls");
        return -1;
    }
    数据校验(1);
    fprintf(用户数据, "权限类型\t账号\t密码\t姓名\t 课程代码\n");
    for (循环[0].整数型 = 0; 循环[0].整数型 < 用户数量; 循环[0].整数型++) {
        if (用_户[循环[0].整数型].权限类型 == -1) continue;
        字符串加解密(用_户[循环[0].整数型].密码);
        switch (用_户[循环[0].整数型].权限类型) {
        case 1:fprintf(用户数据, "%d\t%s\t%s\t", 用_户[循环[0].整数型].权限类型, 用_户[循环[0].整数型].账号, 用_户[循环[0].整数型].密码); break;
        case 2:fprintf(用户数据, "%d\t%s\t%s\t%s\t", 用_户[循环[0].整数型].权限类型, 用_户[循环[0].整数型].账号, 用_户[循环[0].整数型].密码, 用_户[循环[0].整数型].姓名); break;
        case 3:
            fprintf(用户数据, "%d\t%s\t%s\t%s\t ", 用_户[循环[0].整数型].权限类型, 用_户[循环[0].整数型].账号, 用_户[循环[0].整数型].密码, 用_户[循环[0].整数型].姓名);
            for (循环[1].整数型 = 0; 循环[1].整数型 < 用_户[循环[0].整数型].课程数量; 循环[1].整数型++)
                fprintf(用户数据, "%d ", 用_户[循环[0].整数型].课程代码[循环[1].整数型]);
            break;
        }
        字符串加解密(用_户[循环[0].整数型].密码);
        fprintf(用户数据, "\n");
    }
    fprintf(用户数据, "0");
    fclose(用户数据);
    printf("写入用户数据√√√\n");
    数据校验(0);
    system("pause"); system("cls");
    return 0;
}

//未完工
int 打印课表(void) {
    printf("功能开发中!");
    system("pause"); system("cls");
    return 1;
}
int 查看日志(void) {
    printf("功能开发中!");
    system("pause"); system("cls");
    return 1;
}

文章作者: AnglesD
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AnglesD !
评论
  目录