v4.1.0: 目录结构标准化 - 创建include/src目录分离头文件和源文件

This commit is contained in:
2025-10-07 23:27:53 +08:00
parent 53964df405
commit 0894171ae0
39 changed files with 176 additions and 107 deletions
+113
View File
@@ -0,0 +1,113 @@
/**
* @file config.h
* @brief 学生成绩管理系统参数配置头文件
* @note 本文件集中定义了学生成绩管理系统的所有参数配置,便于统一管理和修改
*/
#ifndef CONFIG_H
#define CONFIG_H
// 系统配置参数
// 定义系统中各种实体的数量限制,确保内存使用可控
#define MAX_STUDENTS 1000 // 最大学生数量 - 系统可以存储的学生记录上限
#define MAX_COURSES 10 // 每个学生最多课程数 - 限制单个学生可选修的课程数量
#define MAX_USERS 50 // 最大用户数量 - 系统支持的用户账户上限
#define MAX_LOGIN_ATTEMPTS 3 // 最大登录尝试次数 - 防止暴力破解,超过次数将锁定账户
// 字符串长度限制
// 定义各种字符串字段的最大长度,防止缓冲区溢出并优化内存分配
#define MAX_ID_LENGTH 20 // 学号最大长度 - 包含终止符,实际可用19个字符
#define MAX_NAME_LENGTH 50 // 姓名最大长度 - 支持中文姓名,包含终止符
#define MAX_COURSE_NAME_LENGTH 50 // 课程名称最大长度 - 支持完整的课程名称描述
#define MAX_USERNAME_LENGTH 30 // 用户名最大长度 - 登录系统使用的用户名
#define MAX_PASSWORD_LENGTH 30 // 密码最大长度 - 用户密码的字符数限制
// 分数相关配置
// 定义成绩评价体系的分数范围和等级标准
#define MIN_SCORE 0.0 // 最低分数 - 成绩的下限值
#define MAX_SCORE 100.0 // 最高分数 - 成绩的上限值,采用百分制
#define PASS_SCORE 60.0 // 及格分数 - 判断学生是否通过课程的分数线
#define EXCELLENT_SCORE 90.0 // 优秀分数 - 判断学生成绩是否优秀的分数线
// 年龄相关配置
// 定义学生年龄的合理范围,用于数据验证
#define MIN_AGE 10 // 最小年龄 - 考虑到最年轻的学生可能年龄
#define MAX_AGE 100 // 最大年龄 - 考虑到继续教育等特殊情况的年龄上限
// 文件路径配置
// 定义系统使用的数据文件和目录路径
#define STUDENTS_FILE "data/students.csv" // 学生数据文件 - 存储所有学生信息的CSV格式文件
#define USERS_FILE "data/users.txt" // 用户数据文件 - 存储系统用户账户信息
#define BACKUP_DIR "backup/" // 备份目录 - 数据备份文件的存储位置
// 菜单选项定义
// 主菜单的选项编号,用于用户界面导航
#define MENU_EXIT 0 // 退出系统
#define MENU_BASIC_FUNCTIONS 1 // 基本功能菜单 - 学生信息的增删改查
#define MENU_STATISTICS 2 // 统计分析菜单 - 成绩统计和数据分析
#define MENU_ADMIN 3 // 管理功能菜单 - 用户管理和系统设置
// 基本功能菜单选项
// 学生信息管理的具体操作选项
#define BASIC_BACK 0 // 返回主菜单
#define BASIC_ADD_STUDENT 1 // 添加学生信息
#define BASIC_DELETE_STUDENT 2 // 删除学生记录
#define BASIC_MODIFY_STUDENT 3 // 修改学生信息
#define BASIC_SEARCH_BY_ID 4 // 按学号查找学生
#define BASIC_SEARCH_BY_NAME 5 // 按姓名查找学生
#define BASIC_DISPLAY_ALL 6 // 显示所有学生信息
#define BASIC_SORT_STUDENTS 7 // 学生信息排序功能
// 统计功能菜单选项
// 成绩统计和数据分析的功能选项
#define STATS_BACK 0 // 返回主菜单
#define STATS_COURSE_ANALYSIS 1 // 课程成绩分析 - 分析各门课程的成绩情况
#define STATS_SCORE_DISTRIBUTION 2 // 成绩分布统计 - 显示成绩的分布情况
#define STATS_SCORE_RANGES 3 // 成绩区间统计 - 按分数段统计学生人数
#define STATS_OVERALL_ANALYSIS 4 // 综合分析 - 整体成绩趋势和统计信息
// 管理功能菜单选项
// 系统管理员专用的用户管理功能
#define ADMIN_BACK 0 // 返回主菜单
#define ADMIN_ADD_USER 1 // 添加新用户账户
#define ADMIN_DELETE_USER 2 // 删除用户账户
#define ADMIN_MODIFY_PASSWORD 3 // 修改用户密码
#define ADMIN_VIEW_USERS 4 // 查看所有用户信息
// 排序选项
// 定义学生信息的排序依据
#define SORT_BY_ID 1 // 按学号排序
#define SORT_BY_NAME 2 // 按姓名排序
#define SORT_BY_TOTAL_SCORE 3 // 按总分排序
#define SORT_BY_AVERAGE_SCORE 4 // 按平均分排序
// 排序顺序
// 定义排序的方向
#define SORT_ASCENDING 1 // 升序排列 - 从小到大
#define SORT_DESCENDING 2 // 降序排列 - 从大到小
// 性别定义
// 使用字符常量表示学生性别,便于数据存储和处理
#define GENDER_MALE 'M' // 男性标识
#define GENDER_FEMALE 'F' // 女性标识
// 颜色代码(用于美化输出)
// ANSI转义序列,用于在终端中显示彩色文本,提升用户体验
#define COLOR_RESET "\033[0m" // 重置颜色 - 恢复默认颜色
#define COLOR_RED "\033[31m" // 红色 - 通常用于错误信息
#define COLOR_GREEN "\033[32m" // 绿色 - 通常用于成功信息
#define COLOR_YELLOW "\033[33m" // 黄色 - 通常用于警告信息
#define COLOR_BLUE "\033[34m" // 蓝色 - 通常用于信息提示
#define COLOR_MAGENTA "\033[35m" // 洋红色 - 用于特殊标记
#define COLOR_CYAN "\033[36m" // 青色 - 用于标题或重要信息
#define COLOR_WHITE "\033[37m" // 白色 - 用于普通文本
// 系统消息
// 预定义的系统提示信息,保证消息的一致性和易于维护
#define MSG_SUCCESS "操作成功!" // 操作成功时的提示信息
#define MSG_FAILURE "操作失败!" // 操作失败时的通用错误信息
#define MSG_NOT_FOUND "未找到相关记录!" // 查询无结果时的提示信息
#define MSG_INVALID_INPUT "输入无效,请重新输入!" // 用户输入格式错误时的提示
#define MSG_FILE_ERROR "文件操作错误!" // 文件读写操作失败时的错误信息
#endif // CONFIG_H
+73
View File
@@ -0,0 +1,73 @@
/**
* @file core_handlers.h
* @brief 核心处理函数头文件
* @note 包含主要的功能处理函数声明
*/
#ifndef CORE_HANDLERS_H
#define CORE_HANDLERS_H
#include "config.h"
// 核心处理函数声明
/**
* @brief 处理基本功能菜单
* @details 显示并处理学生信息管理的基本功能菜单循环
* 提供学生信息的增删改查、排序等核心功能
* 循环显示菜单直到用户选择返回主菜单
* @note 包含的功能:
* - 添加学生信息
* - 删除学生信息
* - 修改学生信息
* - 按学号查找学生
* - 按姓名查找学生
* - 显示所有学生
* - 学生信息排序
*/
void handleBasicFunctions();
/**
* @brief 处理统计功能菜单
* @details 显示并处理统计分析功能菜单循环
* 提供各种学生成绩的统计分析功能
* 循环显示菜单直到用户选择返回主菜单
* @note 包含的功能:
* - 课程统计分析
* - 成绩分布统计
* - 学生排名统计
* - 综合统计分析
*/
void handleStatistics();
/**
* @brief 处理管理功能菜单
* @details 显示并处理系统管理功能菜单循环,仅限管理员用户访问
* 提供用户账户管理的各项功能
* 循环显示菜单直到用户选择返回主菜单
* @note 包含的功能:
* - 添加用户账户
* - 删除用户账户
* - 修改用户密码
* - 查看所有用户
* @warning 此函数仅应在验证用户为管理员后调用
*/
void handleAdminFunctions();
/**
* @brief 处理学生排序功能
* @details 提供交互式的学生信息排序功能
* 用户可选择排序依据(学号、姓名、总分、平均分)和排序顺序(升序、降序)
* 排序完成后自动显示排序结果
* @note 排序依据选项:
* 1. 按学号排序
* 2. 按姓名排序
* 3. 按总分排序
* 4. 按平均分排序
* @note 排序顺序选项:
* 1. 升序
* 2. 降序
*/
void handleSortStudents();
#endif // CORE_HANDLERS_H
+36
View File
@@ -0,0 +1,36 @@
/**
* @file file_utils.h
* @brief 文件操作工具函数头文件
* @note 包含文件和目录操作相关函数声明
*/
#ifndef FILE_UTILS_H
#define FILE_UTILS_H
#include <stdbool.h>
// 文件操作函数
/**
* @brief 检查文件是否存在
* @details 使用access函数(Unix/Linux)或_access函数(Windows)检查文件是否存在且可读
* @param filename 要检查的文件路径
* @return 如果文件存在且可读返回true,否则返回false
* @note 函数只检查文件是否存在,不检查文件内容
* @warning 如果filename为NULL,返回false
*/
bool fileExists(const char* filename);
/**
* @brief 创建目录
* @details 使用mkdir函数创建指定路径的目录
* 在Windows下使用_mkdir,在Unix/Linux下使用mkdir
* @param path 要创建的目录路径
* @return 如果目录创建成功或已存在返回true,否则返回false
* @note 如果目录已存在,函数返回true
* @note 函数不会递归创建父目录
* @warning 如果path为NULL,返回false
*/
bool createDirectory(const char* path);
#endif // FILE_UTILS_H
+38
View File
@@ -0,0 +1,38 @@
/**
* @file globals.h
* @brief 全局变量声明头文件
* @note 集中管理所有全局变量的声明,提高代码可维护性
*/
#ifndef GLOBALS_H
#define GLOBALS_H
#include <stdbool.h>
#include "types.h"
// 全局变量声明
extern Student students[MAX_STUDENTS]; // 学生数组
extern User users[MAX_USERS]; // 用户数组
extern int studentCount; // 当前学生数量
extern int userCount; // 当前用户数量
extern char currentUser[MAX_USERNAME_LENGTH]; // 当前登录用户
extern bool isCurrentUserAdmin; // 当前用户是否为管理员
// 系统状态变量
extern bool systemInitialized; // 系统是否已初始化
extern bool dataModified; // 数据是否已修改(用于判断是否需要保存)
// 统计信息缓存(可选,用于提高性能)
extern float overallAverageScore; // 全体学生平均分
extern float highestScore; // 最高分
extern float lowestScore; // 最低分
extern bool statsNeedUpdate; // 统计信息是否需要更新
// 排序参数
extern int currentSortCriteria; // 当前排序依据
extern int currentSortOrder; // 当前排序顺序
// 统计缓存
extern StatisticsCache statsCache; // 统计分析缓存
#endif // GLOBALS_H
+153
View File
@@ -0,0 +1,153 @@
/**
* @file io_utils.h
* @brief 输入输出工具函数头文件
* @note 包含界面显示、用户输入等相关函数声明
*/
#ifndef IO_UTILS_H
#define IO_UTILS_H
#include <stdbool.h>
// 界面显示函数
/**
* @brief 清理输入缓冲区
* @details 清除标准输入流中的所有剩余字符,直到遇到换行符或文件结束符
* 主要用于防止输入缓冲区中的残留字符影响后续输入操作
* @note 在使用scanf等函数后调用此函数可以避免输入问题
*/
void clearInputBuffer();
/**
* @brief 暂停系统,等待用户按键
* @details 显示提示信息并等待用户按下任意键后继续执行
* 在Windows系统下使用_getch()函数,在其他系统下使用getchar()函数
* @note 用于在菜单操作完成后暂停,让用户有时间查看结果
* @warning 在非Windows系统下需要按回车键才能继续
*/
void pauseSystem();
/**
* @brief 清屏
* @details 根据操作系统类型调用相应的清屏命令
* Windows系统使用"cls"命令,其他系统使用"clear"命令
* @note 用于清除终端屏幕内容,提供更好的用户界面体验
* @warning 依赖于系统命令,在某些受限环境下可能无法正常工作
*/
void clearScreen();
/**
* @brief 打印分隔线
* @details 输出一行由等号组成的分隔线,用于美化界面显示
* @note 分隔线长度为40个字符,用于分隔不同的界面区域
*/
void printSeparator();
/**
* @brief 打印标题头
* @details 以美观的格式显示标题,标题上下各有一条分隔线
* @param title 要显示的标题文本,不能为NULL
* @note 标题会居中显示,前面有10个空格的缩进
* @warning 如果title为NULL,可能导致程序崩溃
*/
void printHeader(const char* title);
// 安全输入函数
/**
* @brief 安全输入整数
* @details 提供安全的整数输入功能,包含范围验证和错误处理
* 使用fgets和sscanf组合避免缓冲区溢出,循环直到获得有效输入
* @param prompt 显示给用户的提示信息
* @param min 允许输入的最小值(包含)
* @param max 允许输入的最大值(包含)
* @return 返回用户输入的有效整数
* @note 函数会一直循环直到用户输入有效的整数
* @note 自动显示输入范围提示
* @warning 如果prompt为NULLprintf可能出现问题
*/
int safeInputInt(const char* prompt, int min, int max);
/**
* @brief 安全输入浮点数
* @details 提供安全的浮点数输入功能,包含范围验证和错误处理
* 使用fgets和sscanf组合避免缓冲区溢出,循环直到获得有效输入
* @param prompt 显示给用户的提示信息
* @param min 允许输入的最小值(包含)
* @param max 允许输入的最大值(包含)
* @return 返回用户输入的有效浮点数
* @note 函数会一直循环直到用户输入有效的浮点数
* @note 自动显示输入范围提示,精度为小数点后1位
* @warning 如果prompt为NULLprintf可能出现问题
*/
float safeInputFloat(const char* prompt, float min, float max);
/**
* @brief 安全输入字符串
* @details 提供安全的字符串输入功能,包含空值检查和自动去除首尾空格
* 使用fgets避免缓冲区溢出,自动移除换行符并处理空白字符
* @param prompt 显示给用户的提示信息
* @param buffer 存储输入字符串的缓冲区
* @param maxLen 缓冲区的最大长度(包含终止符)
* @note 函数会一直循环直到用户输入非空字符串
* @note 自动移除输入字符串的首尾空白字符
* @warning 如果buffer为NULL或maxLen<=0,可能导致程序崩溃
*/
void safeInputString(const char* prompt, char* buffer, int maxLen);
// 颜色输出函数
/**
* @brief 彩色输出
* @details 使用ANSI转义序列在终端中输出彩色文本
* 输出格式为:颜色代码 + 文本 + 重置代码
* @param text 要输出的文本内容
* @param color ANSI颜色代码字符串(如COLOR_RED、COLOR_GREEN等)
* @note 输出后会自动重置颜色为默认值
* @warning 如果终端不支持ANSI转义序列,可能显示乱码
*/
void printColored(const char* text, const char* color);
/**
* @brief 成功消息
* @details 以绿色显示成功消息,用于提示操作成功完成
* @param message 要显示的成功消息文本
* @note 消息会以绿色显示,并在末尾自动添加换行符
*/
void printSuccess(const char* message);
/**
* @brief 错误消息
* @details 以红色显示错误消息,用于提示操作失败或出现错误
* @param message 要显示的错误消息文本
* @note 消息会以红色显示,并在末尾自动添加换行符
*/
void printError(const char* message);
/**
* @brief 警告消息
* @details 以黄色显示警告消息,用于提示需要注意的情况
* @param message 要显示的警告消息文本
* @note 消息会以黄色显示,并在末尾自动添加换行符
*/
void printWarning(const char* message);
/**
* @brief 信息消息
* @details 以青色显示信息消息,用于提示一般性信息
* @param message 要显示的信息消息文本
* @note 消息会以青色显示,并在末尾自动添加换行符
*/
void printInfo(const char *message);
/**
* @brief 安全输入单个字符
* @details 提供安全的字符输入功能,避免缓冲区溢出
* @param prompt 显示给用户的提示信息
* @return 返回用户输入的字符
* @note 自动清理输入缓冲区
*/
char safeInputChar(const char *prompt);
#endif // IO_UTILS_H
+69
View File
@@ -0,0 +1,69 @@
/**
* @file main_menu.h
* @brief 主菜单实现文件
* @note 实现各种菜单显示功能函数声明
*/
#ifndef MAIN_MENU_H
#define MAIN_MENU_H
#include "config.h"
// 主菜单和子菜单显示函数
/**
* @brief 显示主菜单
* @details 显示学生成绩管理系统的主菜单界面,包括当前用户信息和可用功能选项
* 根据用户权限动态显示菜单项(管理员可看到系统管理功能)
* @note 菜单选项:
* 1. 基本功能管理(所有用户)
* 2. 统计分析功能(所有用户)
* 3. 系统管理功能(仅管理员)
* 0. 退出系统
*/
void displayMainMenu();
/**
* @brief 显示基本功能菜单
* @details 显示学生信息管理的基本功能菜单,包括增删改查和排序功能
* 同时显示当前系统中的学生总数
* @note 菜单功能:
* 1. 添加学生信息
* 2. 删除学生信息
* 3. 修改学生信息
* 4. 按学号查找学生
* 5. 按姓名查找学生
* 6. 显示所有学生
* 7. 学生信息排序
* 0. 返回主菜单
*/
void displayBasicFunctionsMenu();
/**
* @brief 显示统计功能菜单
* @details 显示统计分析功能菜单,提供各种数据统计和分析选项
* 显示当前学生总数和系统平均分(如果有学生数据)
* @note 菜单功能:
* 1. 课程统计分析
* 2. 成绩分布统计
* 3. 分数段统计
* 4. 综合统计分析
* 0. 返回主菜单
*/
void displayStatisticsMenu();
/**
* @brief 显示管理功能菜单
* @details 显示系统管理功能菜单,仅管理员可访问
* 提供用户账户管理功能,显示当前用户总数
* @note 菜单功能:
* 1. 添加用户账户
* 2. 删除用户账户
* 3. 修改用户密码
* 4. 查看所有用户
* 0. 返回主菜单
* @warning 此菜单仅限管理员用户访问
*/
void displayAdminMenu();
#endif // MAIN_MENU_H
+22
View File
@@ -0,0 +1,22 @@
/**
* @file math_utils.h
* @brief 数学计算工具函数头文件
* @note 包含数学计算相关函数声明
*/
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
/**
* @brief 计算平均值
* @details 计算浮点数数组的算术平均值
* 遍历数组求和,然后除以元素个数
* @param scores 浮点数数组
* @param count 数组元素个数
* @return 返回数组的平均值,如果count为0返回0.0
* @note 如果count为0,函数返回0.0避免除零错误
* @warning 如果scores为NULL且count>0,可能导致程序崩溃
*/
float calculateAverage(float scores[], int count);
#endif // MATH_UTILS_H
+47
View File
@@ -0,0 +1,47 @@
/**
* @file security_utils.h
* @brief 安全工具函数头文件
* @note 提供密码哈希、验证等安全相关功能
*/
#ifndef SECURITY_UTILS_H
#define SECURITY_UTILS_H
#include <stdint.h>
#include "config.h"
// SHA-256哈希长度定义
#define SHA256_DIGEST_LENGTH 32
#define SHA256_HEX_LENGTH 65 // 64字符 + 1个终止符
/**
* @brief 计算字符串的SHA-256哈希值
* @param input 输入字符串
* @param output 输出缓冲区,至少需要SHA256_HEX_LENGTH字节
* @note 输出为64位十六进制字符串
*/
void sha256_hash(const char *input, char *output);
/**
* @brief 验证密码是否匹配哈希值
* @param password 明文密码
* @param hash 存储的哈希值
* @return 匹配返回1,不匹配返回0
*/
int verify_password(const char *password, const char *hash);
/**
* @brief 生成密码哈希值
* @param password 明文密码
* @param hash_output 输出缓冲区,至少需要SHA256_HEX_LENGTH字节
*/
void hash_password(const char *password, char *hash_output);
/**
* @brief 安全地清除内存中的敏感数据
* @param ptr 指向敏感数据的指针
* @param size 数据大小
*/
void secure_memset(void *ptr, size_t size);
#endif // SECURITY_UTILS_H
+250
View File
@@ -0,0 +1,250 @@
/**
* @file statistical_analysis.h
* @brief 统计分析功能头文件
* @note 包含各种统计分析功能的函数声明
*/
#ifndef STATISTICAL_ANALYSIS_H
#define STATISTICAL_ANALYSIS_H
#include "types.h"
// 主要统计分析函数
/**
* @brief 显示课程统计信息
* @details 统计并显示所有课程的详细信息,包括每门课程的人数、最高分、最低分、平均分和及格率
* 自动收集系统中所有不重复的课程名称,并为每门课程计算统计数据
* @note 显示内容包括:
* - 课程名称
* - 选课人数
* - 最高分、最低分、平均分
* - 及格率(基于PASS_SCORE阈值)
* @warning 如果没有学生数据或课程数据,将显示相应警告信息
*/
void displayCourseStatistics();
/**
* @brief 显示分数分布
* @details 统计并显示学生平均分的分布情况,按分数段进行分类统计
* 显示各分数段的人数和百分比,以及总体及格情况
* @note 分数段划分:
* - 90-100分:优秀
* - 80-89分:良好
* - 70-79分:中等
* - 60-69分:及格
* - 0-59分:不及格
* @warning 如果没有学生数据,将显示警告信息
*/
void displayScoreDistribution();
/**
* @brief 显示学生排名
* @details 按学生平均分进行降序排序,显示学生排名列表
* 包括排名、学号、姓名、总分和平均分信息
* @note 排序规则:按平均分从高到低排序
* @note 显示格式:排名 | 学号 | 姓名 | 总分 | 平均分
* @warning 如果没有学生数据,将显示警告信息
*/
void displayStudentRanking();
/**
* @brief 显示系统总体统计
* @details 显示系统的综合统计信息,包括学生信息统计、成绩统计和课程统计
* 提供系统整体数据的全面概览
* @note 统计内容包括:
* - 学生信息:总数、性别分布、平均年龄
* - 成绩统计:最高/最低/平均分、标准差
* - 课程统计:总课程数、平均课程数
* @warning 如果没有学生数据,将显示警告信息
*/
void displayOverallStatistics();
// 查找功能
/**
* @brief 查找最高分学生
* @details 查找并显示平均分最高的学生信息
* 遍历所有学生,找出平均分最高者并显示其详细信息
* @note 比较依据:学生的平均分(averageScore
* @warning 如果没有学生数据,将显示警告信息
*/
void findTopStudent();
/**
* @brief 查找最低分学生
* @details 查找并显示平均分最低的学生信息
* 遍历所有学生,找出平均分最低者并显示其详细信息
* @note 比较依据:学生的平均分(averageScore
* @warning 如果没有学生数据,将显示警告信息
*/
void findBottomStudent();
/**
* @brief 按课程查找最高分
* @details 在指定课程中查找并显示最高分学生的信息
* 用户输入课程名称,系统查找该课程的最高分获得者
* @note 查找过程:
* 1. 用户输入课程名称
* 2. 遍历所有学生的该课程成绩
* 3. 找出最高分及对应学生
* 4. 显示学生信息和分数
* @warning 如果课程不存在,将显示错误信息
*/
void findTopScoreInCourse();
// 计算函数
/**
* @brief 计算课程统计信息
* @details 计算指定课程的详细统计数据,包括选课人数、分数统计和及格率
* @param courseName 要统计的课程名称
* @return CourseStats 包含课程统计信息的结构体
* @note 统计内容包括:
* - studentCount: 选课学生数量
* - maxScore, minScore: 最高分和最低分
* - totalScore, averageScore: 总分和平均分
* - passRate: 及格率(百分比)
* @warning 如果课程不存在,返回全零的统计结构体
*/
CourseStats calculateCourseStats(const char* courseName);
/**
* @brief 计算分数分布
* @details 根据学生的平均分计算各分数段的人数分布
* @return ScoreDistribution 包含各分数段人数的结构体
* @note 分数段定义:
* - excellent: 90-100分
* - good: 80-89分
* - medium: 70-79分
* - pass: 60-69分
* - fail: 0-59分
*/
ScoreDistribution calculateScoreDistribution();
/**
* @brief 计算系统总体统计
* @details 计算系统的综合统计数据,包括学生、成绩和课程的各项统计指标
* @return OverallStats 包含系统总体统计信息的结构体
* @note 计算内容包括:
* - 学生统计:总数、性别分布、平均年龄
* - 成绩统计:最高/最低/平均分、标准差
* - 课程统计:总课程数、人均课程数
* @note 标准差计算使用总体标准差公式
*/
OverallStats calculateOverallStats();
/**
* @brief 计算学生统计信息
* @details 计算指定学生的总分和平均分
* 根据学生的所有课程成绩计算统计数据
* @param student 指向要计算统计信息的学生结构体的指针
* @note 计算内容:
* - totalScore: 所有课程成绩的总和
* - averageScore: 平均成绩(总分/课程数)
* @note 如果学生没有课程,总分和平均分都设为0
* @warning 传入的student指针不能为NULL
*/
void calculateStudentStats(Student* student);
/**
* @brief 更新全局统计缓存
* @details 更新系统的全局统计缓存变量,包括全体平均分、最高分和最低分
* 当学生数据发生变化时调用此函数更新缓存
* @note 更新的全局变量:
* - overallAverageScore: 全体学生平均分
* - highestScore: 最高平均分
* - lowestScore: 最低平均分
* - statsNeedUpdate: 统计更新标志(设为false
* @note 如果没有学生数据,所有统计值都设为0
* @see overallAverageScore, highestScore, lowestScore, statsNeedUpdate
*/
void updateGlobalStats();
// 缓存管理函数
/**
* @brief 初始化统计缓存
* @details 初始化统计缓存系统,清空所有缓存数据
* @note 在系统启动时调用,确保缓存处于干净状态
*/
void initStatisticsCache();
/**
* @brief 检查缓存是否有效
* @details 检查统计缓存是否仍然有效,通过比较学生数量和数据哈希值
* @return bool 如果缓存有效返回true,否则返回false
* @note 当学生数据发生变化时,缓存会被标记为无效
*/
bool isCacheValid();
/**
* @brief 更新统计缓存
* @details 重新计算并更新所有统计缓存数据
* @note 当缓存无效时调用,重新计算所有统计信息并更新缓存
* @note 包括总体统计、分数分布和学生排名的缓存更新
*/
void updateStatisticsCache();
/**
* @brief 使缓存无效
* @details 将统计缓存标记为无效,强制下次访问时重新计算
* @note 当学生数据被修改时调用,确保统计数据的准确性
*/
void invalidateCache();
/**
* @brief 计算数据哈希值
* @details 计算当前学生数据的哈希值,用于检测数据变化
* @return unsigned long 当前数据的哈希值
* @note 基于学生数量、学号、成绩等关键数据计算哈希值
*/
unsigned long calculateDataHash();
/**
* @brief 获取缓存的总体统计
* @details 获取缓存的总体统计数据,如果缓存无效则先更新缓存
* @return OverallStats 总体统计数据
* @note 优先使用缓存数据,提高查询效率
*/
OverallStats getCachedOverallStats();
/**
* @brief 获取缓存的分数分布
* @details 获取缓存的分数分布数据,如果缓存无效则先更新缓存
* @return ScoreDistribution 分数分布数据
* @note 优先使用缓存数据,避免重复计算
*/
ScoreDistribution getCachedScoreDistribution();
/**
* @brief 获取缓存的学生排名
* @details 获取缓存的学生排名数据,如果缓存无效则先更新缓存
* @param rankings 输出参数,存储排名数据的数组
* @return int 返回排名数据的数量
* @note 排名按平均分降序排列,优先使用缓存数据
*/
int getCachedStudentRankings(StudentRank* rankings);
// 排序优化函数
/**
* @brief 快速排序分区函数
* @details 对学生排名数组进行分区操作,用于快速排序
* @param arr 要分区的学生排名数组
* @param low 分区的起始索引
* @param high 分区的结束索引
* @return int 分区点的索引
*/
int partitionRankings(StudentRank arr[], int low, int high);
/**
* @brief 快速排序函数
* @details 对学生排名数组按平均分进行快速排序(降序)
* @param arr 要排序的学生排名数组
* @param low 排序的起始索引
* @param high 排序的结束索引
*/
void quickSortRankings(StudentRank arr[], int low, int high);
#endif // STATISTICAL_ANALYSIS_H
+34
View File
@@ -0,0 +1,34 @@
/**
* @file string_utils.h
* @brief 字符串处理工具函数头文件
* @note 包含字符串操作相关函数声明
*/
#ifndef STRING_UTILS_H
#define STRING_UTILS_H
#include <stdbool.h>
/**
* @brief 去除字符串首尾空白字符
* @details 移除字符串开头和结尾的空格、制表符、换行符等空白字符
* 使用双指针技术,从两端向中间处理,原地修改字符串
* @param str 要处理的字符串,函数会直接修改此字符串
* @note 函数会直接修改传入的字符串,不会分配新内存
* @note 如果整个字符串都是空白字符,结果将是空字符串
* @warning 如果str为NULL,可能导致程序崩溃
*/
void trimString(char* str);
/**
* @brief 检查字符串是否为空
* @details 检查字符串是否为NULL、空字符串或只包含空白字符
* 使用isspace函数检查每个字符是否为空白字符
* @param str 要检查的字符串
* @return 如果字符串为空或只包含空白字符返回true,否则返回false
* @note 空白字符包括空格、制表符、换行符等
* @note 如果str为NULL,返回true
*/
bool isEmptyString(const char* str);
#endif // STRING_UTILS_H
+56
View File
@@ -0,0 +1,56 @@
/**
* @file student_crud.h
* @brief 学生数据增删改操作头文件
* @note 声明学生数据的创建、删除、修改等CRUD功能
*/
#ifndef STUDENT_CRUD_H
#define STUDENT_CRUD_H
#include "config.h"
/**
* @brief 添加新学生
* @details 交互式地添加新学生信息,包括基本信息和课程成绩
* 验证学号唯一性、姓名格式、年龄范围等
* 自动计算总分和平均分
* @note 会检查学生数量是否已达上限MAX_STUDENTS
* @note 学号必须唯一,不能与现有学生重复
* @warning 如果学生数量已满,会显示错误信息并返回
* @see MAX_STUDENTS, isValidStudentId(), isValidName()
*/
void addStudent();
/**
* @brief 删除学生
* @details 提供交互式界面删除指定学号的学生信息
* 包含确认机制,防止误删除操作
* @note 删除流程:
* 1. 输入要删除的学生学号
* 2. 查找并显示学生信息
* 3. 用户确认删除操作
* 4. 删除学生并重新排列数组
* 5. 更新数据修改和统计更新标志
* @warning 删除操作不可逆,请谨慎操作
* @warning 如果没有学生数据,将显示警告信息
*/
void deleteStudent();
/**
* @brief 修改学生信息
* @details 提供交互式界面修改指定学生的各项信息
* 支持修改姓名、年龄、性别和课程成绩等信息
* @note 修改选项:
* 1. 修改姓名
* 2. 修改年龄
* 3. 修改性别
* 4. 修改课程成绩(包括修改现有成绩、添加新课程、删除课程)
* @note 课程成绩修改包含:
* - 修改现有课程成绩
* - 添加新课程
* - 删除课程
* @warning 修改课程信息后会自动重新计算总分和平均分
*/
void modifyStudent();
#endif // STUDENT_CRUD_H
+36
View File
@@ -0,0 +1,36 @@
/**
* @file student_io.h
* @brief 学生数据文件输入输出操作头文件
* @note 声明学生数据的文件读写、CSV解析等功能
*/
#ifndef STUDENT_IO_H
#define STUDENT_IO_H
#include "config.h"
/**
* @brief 从CSV文件加载学生数据
* @details 从STUDENTS_FILE指定的CSV文件中读取学生信息并加载到内存中
* 解析CSV格式数据,包括学号、姓名、年龄、性别、课程信息等
* 如果文件不存在,会初始化为空的学生列表
* @note 会跳过CSV文件的头部行,最多加载MAX_STUDENTS个学生
* @note 加载完成后会设置statsNeedUpdate标志为true
* @warning 如果CSV格式不正确,可能导致数据解析错误
* @see STUDENTS_FILE, MAX_STUDENTS, Student结构体
*/
void loadStudentsFromFile();
/**
* @brief 将学生数据保存到CSV文件
* @details 将内存中的所有学生数据以CSV格式保存到STUDENTS_FILE文件中
* 包含完整的CSV头部和所有学生的详细信息
* 保存成功后会重置dataModified标志
* @note CSV格式包括:学号、姓名、年龄、性别、课程数量、各课程名称和成绩、总分、平均分
* @note 对于课程数量不足MAX_COURSES的学生,会用空值填充
* @warning 如果文件无法创建或写入,会显示错误信息
* @see STUDENTS_FILE, MAX_COURSES, dataModified
*/
void saveStudentsToFile();
#endif // STUDENT_IO_H
+54
View File
@@ -0,0 +1,54 @@
/**
* @file student_search.h
* @brief 学生数据搜索和显示操作头文件
* @note 声明学生数据的查找、显示等功能
*/
#ifndef STUDENT_SEARCH_H
#define STUDENT_SEARCH_H
#include "config.h"
/**
* @brief 按学号查找学生
* @details 根据用户输入的学号精确查找学生信息
* 找到后显示该学生的详细信息
* @note 查找方式:精确匹配学号
* @warning 如果没有学生数据或未找到匹配学生,将显示相应提示信息
*/
void searchStudentByID();
/**
* @brief 按姓名查找学生
* @details 根据用户输入的姓名进行模糊查找学生信息
* 支持部分姓名匹配,显示所有匹配的学生详细信息
* @note 查找方式:模糊匹配(包含子字符串)
* @note 如果找到多个匹配学生,将全部显示
* @warning 如果没有学生数据或未找到匹配学生,将显示相应提示信息
*/
void searchStudentByName();
/**
* @brief 显示所有学生信息
* @details 以表格形式显示系统中所有学生的基本信息
* 包括学号、姓名、年龄、性别、总分和平均分
* @note 显示格式:表格形式,便于查看和比较
* @note 显示内容:学号、姓名、年龄、性别、总分、平均分
* @note 同时显示总学生数统计
* @warning 如果没有学生数据,将显示警告信息
*/
void displayAllStudents();
/**
* @brief 显示单个学生详细信息
* @details 显示指定学生的完整详细信息,包括基本信息和所有课程成绩
* @param student 指向要显示信息的学生结构体的常量指针
* @note 显示内容:
* - 基本信息:学号、姓名、年龄、性别、课程数量
* - 课程成绩:每门课程的名称和分数
* - 统计信息:总分和平均分
* @warning 传入的student指针不能为NULL
*/
void displayStudentInfo(const Student *student);
#endif // STUDENT_SEARCH_H
+28
View File
@@ -0,0 +1,28 @@
/**
* @file student_sort.h
* @brief 学生数据排序操作头文件
* @note 声明学生数据的排序功能
*/
#ifndef STUDENT_SORT_H
#define STUDENT_SORT_H
#include "config.h"
/**
* @brief 排序学生信息
* @details 根据指定的排序依据和顺序对学生数组进行排序
* 使用冒泡排序算法实现
* @param criteria 排序依据(SORT_BY_ID, SORT_BY_NAME, SORT_BY_TOTAL_SCORE, SORT_BY_AVERAGE_SCORE
* @param order 排序顺序(SORT_ASCENDING升序, SORT_DESCENDING降序)
* @note 排序依据选项:
* - SORT_BY_ID: 按学号排序
* - SORT_BY_NAME: 按姓名排序
* - SORT_BY_TOTAL_SCORE: 按总分排序
* - SORT_BY_AVERAGE_SCORE: 按平均分排序
* @note 排序算法:冒泡排序(适合小规模数据)
* @note 排序完成后会设置dataModified标志
*/
void sortStudents(int criteria, int order);
#endif // STUDENT_SORT_H
+43
View File
@@ -0,0 +1,43 @@
/**
* @file system_utils.h
* @brief 系统工具函数头文件
* @note 包含系统初始化和清理相关函数声明
*/
#ifndef SYSTEM_UTILS_H
#define SYSTEM_UTILS_H
#include <stdbool.h>
// 系统初始化和清理函数
/**
* @brief 初始化系统
* @details 执行系统启动时的初始化操作,包括创建必要的数据目录
* 调用createDataDirectories函数创建数据存储目录
* @return 如果初始化成功返回true,否则返回false
* @note 此函数应在程序启动时调用
* @note 如果初始化失败,会输出错误信息
*/
bool initializeSystem();
/**
* @brief 创建数据目录
* @details 创建程序运行所需的数据存储目录
* 目前创建"data"目录用于存储学生数据文件
* @return 如果目录创建成功或已存在返回true,否则返回false
* @note 如果目录已存在,函数仍返回true
* @note 可以根据需要扩展创建更多目录
*/
bool createDataDirectories();
/**
* @brief 清理系统资源
* @details 执行程序退出前的清理操作
* 目前主要输出清理完成的提示信息
* @note 此函数应在程序退出前调用
* @note 可以根据需要添加更多清理操作,如关闭文件、释放内存等
*/
void cleanupSystem();
#endif // SYSTEM_UTILS_H
+109
View File
@@ -0,0 +1,109 @@
/**
* @file types.h
* @brief 统一的数据类型定义文件
* @note 集中管理所有结构体定义,提高代码可维护性和一致性
*/
#ifndef TYPES_H
#define TYPES_H
#include <stdbool.h>
#include "config.h"
#include "security_utils.h"
// 核心数据结构
/**
* @brief 学生信息结构体
* @note 包含学生的基本信息、课程和成绩数据
*/
typedef struct {
char studentID[MAX_ID_LENGTH]; // 学号
char name[MAX_NAME_LENGTH]; // 姓名
int age; // 年龄
char gender; // 性别 ('M'/'F')
char courses[MAX_COURSES][MAX_COURSE_NAME_LENGTH]; // 课程名称
float scores[MAX_COURSES]; // 各科成绩
int courseCount; // 课程数量
float totalScore; // 总分
float averageScore; // 平均分
} Student;
/**
* @brief 用户信息结构体
* @note 包含用户登录信息和权限设置
*/
typedef struct {
char username[MAX_USERNAME_LENGTH];
char passwordHash[SHA256_HEX_LENGTH]; // 存储SHA-256哈希值
bool isAdmin; // 是否为管理员
} User;
// 统计分析相关结构体
/**
* @brief 课程统计结构体
* @note 包含单门课程的统计信息
*/
typedef struct {
int studentCount;
float maxScore;
float minScore;
float totalScore;
float averageScore;
float passRate;
} CourseStats;
/**
* @brief 分数分布结构体
* @note 按分数段统计学生人数分布
*/
typedef struct {
int excellent; // 90-100分
int good; // 80-89分
int medium; // 70-79分
int pass; // 60-69分
int fail; // 0-59分
} ScoreDistribution;
/**
* @brief 学生排名结构体
* @note 用于学生排名功能
*/
typedef struct {
int studentIndex;
float averageScore;
float totalScore;
} StudentRank;
/**
* @brief 总体统计结构体
* @note 包含系统整体的统计信息
*/
typedef struct {
int totalStudents;
int maleCount;
int femaleCount;
float averageAge;
float highestAverage;
float lowestAverage;
float overallAverageScore;
float standardDeviation;
int totalCourses;
float averageCoursesPerStudent;
} OverallStats;
/**
* @brief 统计缓存结构体
* @note 用于缓存统计计算结果,提高性能
*/
typedef struct {
bool isValid; // 缓存是否有效
OverallStats overallStats; // 总体统计缓存
ScoreDistribution scoreDistribution; // 分数分布缓存
StudentRank rankings[MAX_STUDENTS]; // 排名缓存
int lastStudentCount; // 上次缓存时的学生数量
unsigned long lastDataHash; // 数据哈希值,用于检测数据变化
} StatisticsCache;
#endif // TYPES_H
+110
View File
@@ -0,0 +1,110 @@
/**
* @file user_manage.h
* @brief 用户管理实现文件
* @note 实现用户认证和管理功能函数声明
*/
#ifndef USER_MANAGE_H
#define USER_MANAGE_H
#include "config.h"
/**
* @brief 处理用户登录
* @details 提供用户登录验证功能,验证用户名和密码的正确性
* 登录成功后设置当前用户信息和管理员权限
* @return int 登录成功返回1,失败返回0
* @note 登录过程:
* 1. 获取用户输入的用户名和密码
* 2. 遍历用户数组进行验证
* 3. 验证成功则设置currentUser和isCurrentUserAdmin
* @note 设置的全局变量:
* - currentUser: 当前登录用户名
* - isCurrentUserAdmin: 当前用户是否为管理员
*/
int loginSystem();
/**
* @brief 从文件加载用户数据
* @details 从USERS_FILE文件中读取用户数据到内存
* 如果文件不存在,则创建默认的管理员和普通用户账户
* @note 文件格式:每行格式为 "username:password:isAdmin"
* 其中isAdmin为1表示管理员,0表示普通用户
* @note 默认账户:
* - 管理员:用户名admin,密码123456
* - 普通用户:用户名teacher,密码password
* @warning 如果文件格式错误,可能导致数据加载不完整
*/
void loadUsersFromFile();
/**
* @brief 将用户数据保存到文件
* @details 将内存中的用户数据写入到USERS_FILE文件中
* 采用文本格式存储,每个用户占一行
* @note 文件格式:每行格式为 "username:password:isAdmin"
* 其中isAdmin为1表示管理员,0表示普通用户
* @warning 如果文件无法打开,将显示错误信息
*/
void saveUsersToFile();
/**
* @brief 增加用户账户
* @details 提供交互式界面添加新的用户账户
* 包括用户名唯一性检查、密码设置和用户类型选择
* @note 添加流程:
* 1. 检查用户数量是否达到上限
* 2. 输入新用户名并检查唯一性
* 3. 设置密码
* 4. 选择用户类型(普通用户/管理员)
* 5. 保存到文件并更新数据修改标志
* @warning 如果用户数量已达MAX_USERS上限,将拒绝添加
* @warning 如果用户名已存在,将拒绝添加
*/
void addUserAccount();
/**
* @brief 删除用户账户
* @details 提供交互式界面删除指定的用户账户
* 包含安全检查,防止删除当前登录用户和最后一个用户
* @note 删除限制:
* - 不能删除当前登录的用户
* - 系统至少需要保留一个用户账户
* @note 删除过程:
* 1. 输入要删除的用户名
* 2. 进行安全检查
* 3. 查找用户并删除
* 4. 重新排列用户数组
* 5. 保存到文件并更新数据修改标志
* @warning 删除操作不可逆,请谨慎操作
*/
void deleteUserAccount();
/**
* @brief 修改用户密码
* @details 提供交互式界面修改指定用户的密码
* 管理员可以修改任何用户的密码
* @note 修改流程:
* 1. 输入要修改密码的用户名
* 2. 查找用户是否存在
* 3. 输入新密码
* 4. 更新用户密码
* 5. 保存到文件并更新数据修改标志
* @warning 密码修改后立即生效,用户需要使用新密码登录
*/
void modifyUserPassword();
/**
* @brief 查看所有用户
* @details 显示系统中所有用户的信息列表
* 包括用户名、用户类型和当前登录状态
* @note 显示内容:
* - 用户名
* - 用户类型(管理员/普通用户)
* - 状态(标识当前登录用户)
* - 总用户数统计
* @note 表格格式显示,便于查看和管理
* @warning 如果没有用户数据,将显示警告信息
*/
void viewAllUsers();
#endif // USER_MANAGE_H
+101
View File
@@ -0,0 +1,101 @@
/**
* @file validation.h
* @brief 数据验证函数头文件
* @note 包含学生信息各字段的验证函数声明
*/
#ifndef VALIDATION_H
#define VALIDATION_H
#include <stdbool.h>
// 数据验证函数
/**
* @brief 验证成绩是否有效
* @details 检查成绩是否在有效范围内(0-100分)
* @param score 要验证的成绩值
* @return 如果成绩有效返回true,否则返回false
* @note 有效成绩范围为0.0到100.0(包含边界值)
*/
bool isValidScore(float score);
/**
* @brief 验证学号是否有效
* @details 检查学号格式是否符合要求:非空且长度在合理范围内
* @param id 要验证的学号字符串
* @return 如果学号有效返回true,否则返回false
* @note 学号不能为空,长度必须在1到MAX_ID_LENGTH之间
* @warning 如果id为NULL,返回false
*/
bool isValidStudentId(const char* id);
/**
* @brief 验证姓名是否有效
* @details 检查姓名格式是否符合要求:非空且长度在合理范围内
* @param name 要验证的姓名字符串
* @return 如果姓名有效返回true,否则返回false
* @note 姓名不能为空,长度必须在1到MAX_NAME_LENGTH之间
* @warning 如果name为NULL,返回false
*/
bool isValidName(const char* name);
/**
* @brief 验证性别是否有效
* @details 检查性别是否为'M'(男)或'F'(女)
* @param gender 要验证的性别字符
* @return 如果性别有效返回true,否则返回false
* @note 只接受'M'或'F'两个值
*/
bool isValidGender(char gender);
/**
* @brief 验证年龄是否有效
* @details 检查年龄是否在合理范围内
* @param age 要验证的年龄值
* @return 如果年龄有效返回true,否则返回false
* @note 有效年龄范围为MIN_AGE到MAX_AGE(包含边界值)
*/
bool isValidAge(int age);
/**
* @brief 验证课程名称是否有效
* @details 检查课程名称格式是否符合要求:非空且长度在合理范围内
* @param courseName 要验证的课程名称字符串
* @return 如果课程名称有效返回true,否则返回false
* @note 课程名称不能为空,长度必须在1到MAX_COURSE_NAME_LENGTH之间
* @warning 如果courseName为NULL,返回false
*/
bool isValidCourseName(const char* courseName);
/**
* @brief 验证用户名是否有效
* @details 检查用户名格式是否符合要求:非空、长度合理且只包含字母数字
* @param username 要验证的用户名字符串
* @return 如果用户名有效返回true,否则返回false
* @note 用户名不能为空,长度必须在3到MAX_USERNAME_LENGTH之间,只能包含字母和数字
* @warning 如果username为NULL,返回false
*/
bool isValidUsername(const char* username);
/**
* @brief 验证密码强度是否符合要求
* @details 检查密码是否满足最低安全要求
* @param password 要验证的密码字符串
* @return 如果密码有效返回true,否则返回false
* @note 密码长度必须在6到MAX_PASSWORD_LENGTH之间
* @warning 如果password为NULL,返回false
*/
bool isValidPassword(const char* password);
/**
* @brief 验证数组索引是否在有效范围内
* @details 检查索引是否在指定范围内,防止数组越界
* @param index 要验证的索引值
* @param maxIndex 最大有效索引值(不包含)
* @return 如果索引有效返回true,否则返回false
* @note 有效索引范围为0到maxIndex-1
*/
bool isValidIndex(int index, int maxIndex);
#endif // VALIDATION_H