Add files via upload

This commit is contained in:
2025-07-17 21:17:50 +08:00
committed by GitHub
parent ecdc668ae3
commit 4e240c6dc9
25 changed files with 1313 additions and 200 deletions
-13
View File
@@ -96,17 +96,4 @@
#define MSG_INVALID_INPUT "输入无效,请重新输入!" #define MSG_INVALID_INPUT "输入无效,请重新输入!"
#define MSG_FILE_ERROR "文件操作错误!" #define MSG_FILE_ERROR "文件操作错误!"
// 数据结构定义
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;
#endif // CONFIG_H #endif // CONFIG_H
+59 -4
View File
@@ -10,9 +10,64 @@
#include "config.h" #include "config.h"
// 核心处理函数声明 // 核心处理函数声明
void handleBasicFunctions(); // 处理基本功能菜单
void handleStatistics(); // 处理统计功能菜单 /**
void handleAdminFunctions(); // 处理管理功能菜单 * @brief 处理基本功能菜单
void handleSortStudents(); // 处理学生排序功能 * @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 #endif // CORE_HANDLERS_H
+22 -2
View File
@@ -10,7 +10,27 @@
#include <stdbool.h> #include <stdbool.h>
// 文件操作函数 // 文件操作函数
bool fileExists(const char* filename); // 检查文件是否存在
bool createDirectory(const char* path); // 创建目录 /**
* @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 #endif // FILE_UTILS_H
+7
View File
@@ -23,3 +23,10 @@ float overallAverageScore = 0.0; // 全体学生平均分
float highestScore = 0.0; // 最高分 float highestScore = 0.0; // 最高分
float lowestScore = 100.0; // 最低分 float lowestScore = 100.0; // 最低分
bool statsNeedUpdate = true; // 统计信息是否需要更新 bool statsNeedUpdate = true; // 统计信息是否需要更新
// 排序参数
int currentSortCriteria = 0; // 当前排序依据
int currentSortOrder = 0; // 当前排序顺序
// 统计缓存
StatisticsCache statsCache = {false, {0}, {0}, {{0}}, 0, 0}; // 统计分析缓存
+8 -8
View File
@@ -8,14 +8,7 @@
#define GLOBALS_H #define GLOBALS_H
#include <stdbool.h> #include <stdbool.h>
#include "config.h" #include "types.h"
// 用户结构体定义
typedef struct {
char username[MAX_USERNAME_LENGTH];
char password[MAX_PASSWORD_LENGTH];
bool isAdmin; // 是否为管理员
} User;
// 全局变量声明 // 全局变量声明
extern Student students[MAX_STUDENTS]; // 学生数组 extern Student students[MAX_STUDENTS]; // 学生数组
@@ -35,4 +28,11 @@ extern float highestScore; // 最高分
extern float lowestScore; // 最低分 extern float lowestScore; // 最低分
extern bool statsNeedUpdate; // 统计信息是否需要更新 extern bool statsNeedUpdate; // 统计信息是否需要更新
// 排序参数
extern int currentSortCriteria; // 当前排序依据
extern int currentSortOrder; // 当前排序顺序
// 统计缓存
extern StatisticsCache statsCache; // 统计分析缓存
#endif // GLOBALS_H #endif // GLOBALS_H
+126 -13
View File
@@ -10,22 +10,135 @@
#include <stdbool.h> #include <stdbool.h>
// 界面显示函数 // 界面显示函数
void clearInputBuffer(); // 清理输入缓冲区
void pauseSystem(); // 暂停系统,等待用户按键 /**
void clearScreen(); // 清屏 * @brief 清理输入缓冲区
void printSeparator(); // 打印分隔线 * @details 清除标准输入流中的所有剩余字符,直到遇到换行符或文件结束符
void printHeader(const char* title); // 打印标题头 * 主要用于防止输入缓冲区中的残留字符影响后续输入操作
* @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);
// 安全输入函数 // 安全输入函数
int safeInputInt(const char* prompt, int min, int max); // 安全输入整数
float safeInputFloat(const char* prompt, float min, float max); // 安全输入浮点数 /**
void safeInputString(const char* prompt, char* buffer, int maxLen); // 安全输入字符串 * @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);
// 颜色输出函数 // 颜色输出函数
void printColored(const char* text, const char* color); // 彩色输出
void printSuccess(const char* message); // 成功消息 /**
void printError(const char* message); // 错误消息 * @brief 彩色输出
void printWarning(const char* message); // 警告消息 * @details 使用ANSI转义序列在终端中输出彩色文本
void printInfo(const char* message); // 信息消息 * 输出格式为:颜色代码 + 文本 + 重置代码
* @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);
#endif // IO_UTILS_H #endif // IO_UTILS_H
+14 -18
View File
@@ -1,7 +1,19 @@
/** /**
* @file main.c * @brief 主程序入口
* @brief 学生成绩管理系统主程序 * @brief 学生成绩管理系统主程序
* @note 系统入口点,包含主要的程序流程控制 * @details 学生成绩管理系统的主入口函数,负责系统初始化、用户登录验证、
* 主菜单循环处理和系统清理等核心流程
* 程序流程:设置编码 -> 系统初始化 -> 用户登录 -> 主菜单循环 -> 数据保存 -> 系统清理
* @param argc 命令行参数个数(当前未使用)
* @param argv 命令行参数数组(当前未使用)
* @return 程序退出状态码:0表示正常退出,-1表示异常退出
* @note 系统预设用户账户:
* 1. admin - 密码:123456(管理员权限)
* 2. teacher - 密码:password(普通用户权限)
* @note 编译运行命令:
* gcc -o student_system.exe *.c -I.
./student_system
* @warning 登录失败超过MAX_LOGIN_ATTEMPTS次会强制退出程序
*/ */
#include <stdio.h> #include <stdio.h>
@@ -25,22 +37,6 @@
#include "core_handlers.h" #include "core_handlers.h"
#include "student_io.h" #include "student_io.h"
/**
* @brief 主程序入口
* @details 学生成绩管理系统的主入口函数,负责系统初始化、用户登录验证、
* 主菜单循环处理和系统清理等核心流程
* 程序流程:设置编码 -> 系统初始化 -> 用户登录 -> 主菜单循环 -> 数据保存 -> 系统清理
* @param argc 命令行参数个数(当前未使用)
* @param argv 命令行参数数组(当前未使用)
* @return 程序退出状态码:0表示正常退出,-1表示异常退出
* @note 系统预设用户账户:
* 1. admin - 密码:123456(管理员权限)
* 2. teacher - 密码:password(普通用户权限)
* @note 编译运行命令:
* gcc -Wall -Wextra -std=c99 -g main.c globals.c main_menu.c user_manage.c core_handlers.c statistical_analysis.c student_io.c student_crud.c student_search.c student_sort.c io_utils.c validation.c string_utils.c file_utils.c math_utils.c system_utils.c -o student_system
./student_system
* @warning 登录失败超过MAX_LOGIN_ATTEMPTS次会强制退出程序
*/
int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
{ {
// 设置控制台编码为UTF-8 // 设置控制台编码为UTF-8
+61 -4
View File
@@ -1,12 +1,69 @@
/**
* @file main_menu.h
* @brief 主菜单实现文件
* @note 实现各种菜单显示功能函数声明
*/
#ifndef MAIN_MENU_H #ifndef MAIN_MENU_H
#define MAIN_MENU_H #define MAIN_MENU_H
#include "config.h" #include "config.h"
// 主菜单和子菜单显示函数 // 主菜单和子菜单显示函数
void displayMainMenu(); // 显示主菜单
void displayBasicFunctionsMenu(); // 显示基本功能菜单 /**
void displayStatisticsMenu(); // 显示统计功能菜单 * @brief 显示主菜单
void displayAdminMenu(); // 显示管理功能菜单 * @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 #endif // MAIN_MENU_H
+11 -2
View File
@@ -7,7 +7,16 @@
#ifndef MATH_UTILS_H #ifndef MATH_UTILS_H
#define MATH_UTILS_H #define MATH_UTILS_H
// 数学计算函数 /**
float calculateAverage(float scores[], int count); // 计算平均值 * @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 #endif // MATH_UTILS_H
+211 -24
View File
@@ -8,6 +8,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <stdbool.h>
#include "statistical_analysis.h" #include "statistical_analysis.h"
#include "config.h" #include "config.h"
#include "globals.h" #include "globals.h"
@@ -173,7 +174,8 @@ void displayScoreDistribution()
return; return;
} }
ScoreDistribution dist = calculateScoreDistribution(); // 使用缓存的分数分布数据
ScoreDistribution dist = getCachedScoreDistribution();
printf("\n分数段分布:\n"); printf("\n分数段分布:\n");
printSeparator(); printSeparator();
@@ -263,28 +265,9 @@ void displayStudentRanking()
return; return;
} }
// 创建排名数 // 使用缓存的排名数
StudentRank rankings[MAX_STUDENTS]; StudentRank rankings[MAX_STUDENTS];
for (int i = 0; i < studentCount; i++) int rankingCount = getCachedStudentRankings(rankings);
{
rankings[i].studentIndex = i;
rankings[i].averageScore = students[i].averageScore;
rankings[i].totalScore = students[i].totalScore;
}
// 按平均分排序(降序)
for (int i = 0; i < studentCount - 1; i++)
{
for (int j = 0; j < studentCount - 1 - i; j++)
{
if (rankings[j].averageScore < rankings[j + 1].averageScore)
{
StudentRank temp = rankings[j];
rankings[j] = rankings[j + 1];
rankings[j + 1] = temp;
}
}
}
printf("\n"); printf("\n");
// 调整中文表头的对齐格式,考虑中文字符的显示宽度 // 调整中文表头的对齐格式,考虑中文字符的显示宽度
@@ -292,7 +275,7 @@ void displayStudentRanking()
"排名", "学号", "姓名", "总分", "平均分"); "排名", "学号", "姓名", "总分", "平均分");
printf("==========================================\n"); printf("==========================================\n");
for (int i = 0; i < studentCount; i++) for (int i = 0; i < rankingCount; i++)
{ {
int idx = rankings[i].studentIndex; int idx = rankings[i].studentIndex;
printf("%-5d %-10s %-12s %-8.2f %-8.2f\n", printf("%-5d %-10s %-12s %-8.2f %-8.2f\n",
@@ -328,7 +311,8 @@ void displayOverallStatistics()
return; return;
} }
OverallStats stats = calculateOverallStats(); // 使用缓存的总体统计数据
OverallStats stats = getCachedOverallStats();
printf("\n学生信息统计:\n"); printf("\n学生信息统计:\n");
printSeparator(); printSeparator();
@@ -651,4 +635,207 @@ void updateGlobalStats()
overallAverageScore = total / studentCount; overallAverageScore = total / studentCount;
statsNeedUpdate = false; statsNeedUpdate = false;
// 使统计缓存无效
invalidateCache();
}
// ==================== 缓存管理函数实现 ====================
/**
* @brief 初始化统计缓存
* @details 初始化统计缓存系统,清空所有缓存数据
* @note 在系统启动时调用,确保缓存处于干净状态
*/
// 快速排序辅助函数:分区
int partitionRankings(StudentRank arr[], int low, int high) {
float pivot = arr[high].averageScore;
int i = (low - 1);
for (int j = low; j <= high - 1; j++) {
// 降序排列:如果当前元素大于等于基准值
if (arr[j].averageScore >= pivot) {
i++;
StudentRank temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
StudentRank temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return (i + 1);
}
// 快速排序主函数
void quickSortRankings(StudentRank arr[], int low, int high) {
if (low < high) {
int pi = partitionRankings(arr, low, high);
quickSortRankings(arr, low, pi - 1);
quickSortRankings(arr, pi + 1, high);
}
}
void initStatisticsCache()
{
statsCache.isValid = false;
statsCache.lastStudentCount = 0;
statsCache.lastDataHash = 0;
memset(&statsCache.overallStats, 0, sizeof(OverallStats));
memset(&statsCache.scoreDistribution, 0, sizeof(ScoreDistribution));
memset(statsCache.rankings, 0, sizeof(statsCache.rankings));
}
/**
* @brief 检查缓存是否有效
* @details 检查统计缓存是否仍然有效,通过比较学生数量和数据哈希值
* @return bool 如果缓存有效返回true,否则返回false
* @note 当学生数据发生变化时,缓存会被标记为无效
*/
bool isCacheValid()
{
if (!statsCache.isValid) {
return false;
}
// 检查学生数量是否变化
if (statsCache.lastStudentCount != studentCount) {
return false;
}
// 检查数据哈希值是否变化
unsigned long currentHash = calculateDataHash();
if (statsCache.lastDataHash != currentHash) {
return false;
}
return true;
}
/**
* @brief 更新统计缓存
* @details 重新计算并更新所有统计缓存数据
* @note 当缓存无效时调用,重新计算所有统计信息并更新缓存
* @note 包括总体统计、分数分布和学生排名的缓存更新
*/
void updateStatisticsCache()
{
if (studentCount == 0) {
initStatisticsCache();
return;
}
// 更新总体统计缓存
statsCache.overallStats = calculateOverallStats();
// 更新分数分布缓存
statsCache.scoreDistribution = calculateScoreDistribution();
// 更新学生排名缓存
for (int i = 0; i < studentCount; i++) {
statsCache.rankings[i].studentIndex = i;
statsCache.rankings[i].averageScore = students[i].averageScore;
statsCache.rankings[i].totalScore = students[i].totalScore;
}
// 使用快速排序按平均分排序(降序)
quickSortRankings(statsCache.rankings, 0, studentCount - 1);
// 更新缓存状态
statsCache.isValid = true;
statsCache.lastStudentCount = studentCount;
statsCache.lastDataHash = calculateDataHash();
}
/**
* @brief 使缓存无效
* @details 将统计缓存标记为无效,强制下次访问时重新计算
* @note 当学生数据被修改时调用,确保统计数据的准确性
*/
void invalidateCache()
{
statsCache.isValid = false;
}
/**
* @brief 计算数据哈希值
* @details 计算当前学生数据的哈希值,用于检测数据变化
* @return unsigned long 当前数据的哈希值
* @note 基于学生数量、学号、成绩等关键数据计算哈希值
*/
unsigned long calculateDataHash()
{
unsigned long hash = 5381; // DJB2 哈希算法初始值
// 包含学生数量
hash = ((hash << 5) + hash) + studentCount;
for (int i = 0; i < studentCount; i++) {
// 包含学号
for (int j = 0; students[i].studentID[j] != '\0'; j++) {
hash = ((hash << 5) + hash) + students[i].studentID[j];
}
// 包含总分和平均分
hash = ((hash << 5) + hash) + (unsigned long)(students[i].totalScore * 100);
hash = ((hash << 5) + hash) + (unsigned long)(students[i].averageScore * 100);
// 包含课程数量
hash = ((hash << 5) + hash) + students[i].courseCount;
// 包含各科成绩
for (int j = 0; j < students[i].courseCount; j++) {
hash = ((hash << 5) + hash) + (unsigned long)(students[i].scores[j] * 100);
}
}
return hash;
}
/**
* @brief 获取缓存的总体统计
* @details 获取缓存的总体统计数据,如果缓存无效则先更新缓存
* @return OverallStats 总体统计数据
* @note 优先使用缓存数据,提高查询效率
*/
OverallStats getCachedOverallStats()
{
if (!isCacheValid()) {
updateStatisticsCache();
}
return statsCache.overallStats;
}
/**
* @brief 获取缓存的分数分布
* @details 获取缓存的分数分布数据,如果缓存无效则先更新缓存
* @return ScoreDistribution 分数分布数据
* @note 优先使用缓存数据,避免重复计算
*/
ScoreDistribution getCachedScoreDistribution()
{
if (!isCacheValid()) {
updateStatisticsCache();
}
return statsCache.scoreDistribution;
}
/**
* @brief 获取缓存的学生排名
* @details 获取缓存的学生排名数据,如果缓存无效则先更新缓存
* @param rankings 输出参数,存储排名数据的数组
* @return int 返回排名数据的数量
* @note 排名按平均分降序排列,优先使用缓存数据
*/
int getCachedStudentRankings(StudentRank* rankings)
{
if (!isCacheValid()) {
updateStatisticsCache();
}
if (rankings != NULL && studentCount > 0) {
memcpy(rankings, statsCache.rankings, studentCount * sizeof(StudentRank));
}
return studentCount;
} }
+228 -48
View File
@@ -7,64 +7,244 @@
#ifndef STATISTICAL_ANALYSIS_H #ifndef STATISTICAL_ANALYSIS_H
#define STATISTICAL_ANALYSIS_H #define STATISTICAL_ANALYSIS_H
#include "config.h" #include "types.h"
// 课程统计结构体
typedef struct {
int studentCount;
float maxScore;
float minScore;
float totalScore;
float averageScore;
float passRate;
} CourseStats;
// 分数分布结构体
typedef struct {
int excellent; // 90-100分
int good; // 80-89分
int medium; // 70-79分
int pass; // 60-69分
int fail; // 0-59分
} ScoreDistribution;
// 学生排名结构体
typedef struct {
int studentIndex;
float averageScore;
float totalScore;
} StudentRank;
// 总体统计结构体
typedef struct {
int totalStudents;
int maleCount;
int femaleCount;
float averageAge;
float highestAverage;
float lowestAverage;
float overallAverageScore;
float standardDeviation;
int totalCourses;
float averageCoursesPerStudent;
} OverallStats;
// 主要统计分析函数 // 主要统计分析函数
void displayCourseStatistics(); // 显示课程统计信息
void displayScoreDistribution(); // 显示分数分布 /**
void displayStudentRanking(); // 显示学生排名 * @brief
void displayOverallStatistics(); // 显示系统总体统计 * @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();
// 查找功能 // 查找功能
void findTopStudent(); // 查找最高分学生
void findBottomStudent(); // 查找最低分学生 /**
void findTopScoreInCourse(); // 按课程查找最高分 * @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); 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(); ScoreDistribution calculateScoreDistribution();
/**
* @brief
* @details
* @return OverallStats
* @note
* -
* - //
* -
* @note 使
*/
OverallStats calculateOverallStats(); OverallStats calculateOverallStats();
/**
* @brief
* @details
*
* @param student
* @note
* - totalScore:
* - averageScore: /
* @note 0
* @warning student指针不能为NULL
*/
void calculateStudentStats(Student* student); void calculateStudentStats(Student* student);
/**
* @brief
* @details
*
* @note
* - overallAverageScore:
* - highestScore:
* - lowestScore:
* - statsNeedUpdate: false
* @note 0
* @see overallAverageScore, highestScore, lowestScore, statsNeedUpdate
*/
void updateGlobalStats(); void updateGlobalStats();
// 缓存管理函数
/**
* @brief
* @details
* @note
*/
void initStatisticsCache();
/**
* @brief
* @details
* @return bool truefalse
* @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 #endif // STATISTICAL_ANALYSIS_H
+21 -3
View File
@@ -9,8 +9,26 @@
#include <stdbool.h> #include <stdbool.h>
// 字符串处理函数 /**
void trimString(char* str); // 去除字符串首尾空白字符 * @brief
bool isEmptyString(const char* str); // 检查字符串是否为空 * @details
* 使
* @param str
* @note
* @note
* @warning str为NULL
*/
void trimString(char* str);
/**
* @brief
* @details NULL
* 使isspace函数检查每个字符是否为空白字符
* @param str
* @return truefalse
* @note
* @note str为NULLtrue
*/
bool isEmptyString(const char* str);
#endif // STRING_UTILS_H #endif // STRING_UTILS_H
+9
View File
@@ -182,6 +182,9 @@ void addStudent()
dataModified = true; dataModified = true;
statsNeedUpdate = true; statsNeedUpdate = true;
// 使统计缓存无效
invalidateCache();
// 显示添加成功信息 // 显示添加成功信息
displayAddedStudentInfo(&newStudent); displayAddedStudentInfo(&newStudent);
@@ -243,6 +246,9 @@ void deleteStudent()
dataModified = true; dataModified = true;
statsNeedUpdate = true; statsNeedUpdate = true;
// 使统计缓存无效
invalidateCache();
printSuccess("学生信息删除成功!"); printSuccess("学生信息删除成功!");
} }
else else
@@ -449,6 +455,9 @@ static void handleStudentModification(Student *student)
dataModified = true; dataModified = true;
statsNeedUpdate = true; statsNeedUpdate = true;
// 使统计缓存无效
invalidateCache();
printSuccess("学生信息修改成功!"); printSuccess("学生信息修改成功!");
} }
+29 -3
View File
@@ -11,19 +11,45 @@
/** /**
* @brief * @brief
* @details * @details
*
*
* @note MAX_STUDENTS
* @note
* @warning
* @see MAX_STUDENTS, isValidStudentId(), isValidName()
*/ */
void addStudent(); void addStudent();
/** /**
* @brief * @brief
* @details * @details
*
* @note
* 1.
* 2.
* 3.
* 4.
* 5.
* @warning
* @warning
*/ */
void deleteStudent(); void deleteStudent();
/** /**
* @brief * @brief
* @details * @details
*
* @note
* 1.
* 2.
* 3.
* 4.
* @note
* -
* -
* -
* @warning
*/ */
void modifyStudent(); void modifyStudent();
+3
View File
@@ -168,6 +168,9 @@ void loadStudentsFromFile()
// 更新统计信息 // 更新统计信息
statsNeedUpdate = true; statsNeedUpdate = true;
// 使统计缓存无效
invalidateCache();
} }
/** /**
+12
View File
@@ -12,12 +12,24 @@
/** /**
* @brief CSV文件加载学生数据 * @brief CSV文件加载学生数据
* @details STUDENTS_FILE指定的CSV文件中读取学生信息并加载到内存中 * @details STUDENTS_FILE指定的CSV文件中读取学生信息并加载到内存中
* CSV格式数据
*
* @note CSV文件的头部行MAX_STUDENTS个学生
* @note statsNeedUpdate标志为true
* @warning CSV格式不正确
* @see STUDENTS_FILE, MAX_STUDENTS, Student结构体
*/ */
void loadStudentsFromFile(); void loadStudentsFromFile();
/** /**
* @brief CSV文件 * @brief CSV文件
* @details CSV格式保存到STUDENTS_FILE文件中 * @details CSV格式保存到STUDENTS_FILE文件中
* CSV头部和所有学生的详细信息
* dataModified标志
* @note CSV格式包括
* @note MAX_COURSES的学生
* @warning
* @see STUDENTS_FILE, MAX_COURSES, dataModified
*/ */
void saveStudentsToFile(); void saveStudentsToFile();
+76 -6
View File
@@ -13,12 +13,16 @@
// 函数前向声明 // 函数前向声明
void displayStudentInfo(const Student *student); void displayStudentInfo(const Student *student);
static int binarySearchByID(const char *studentID);
static void ensureSortedByID();
/** /**
* @brief * @brief
* @details * @details
* 使O(log n)
* *
* @note * @note 使
* @note 线O(n)O(log n)
* @warning * @warning
*/ */
void searchStudentByID() void searchStudentByID()
@@ -37,15 +41,18 @@ void searchStudentByID()
printf("\n"); printf("\n");
safeInputString("请输入学号", studentID, MAX_ID_LENGTH); safeInputString("请输入学号", studentID, MAX_ID_LENGTH);
for (int i = 0; i < studentCount; i++) // 确保数组按学号排序,以支持二分搜索
ensureSortedByID();
// 使用二分搜索查找学生
int index = binarySearchByID(studentID);
if (index != -1)
{ {
if (strcmp(students[i].studentID, studentID) == 0) displayStudentInfo(&students[index]);
{
displayStudentInfo(&students[i]);
pauseSystem(); pauseSystem();
return; return;
} }
}
printError("未找到该学号的学生!"); printError("未找到该学号的学生!");
pauseSystem(); pauseSystem();
@@ -174,3 +181,66 @@ void displayStudentInfo(const Student *student)
printf("平均分: %.2f\n", student->averageScore); printf("平均分: %.2f\n", student->averageScore);
} }
} }
/**
* @brief
* @details
*
* @note
*/
static void ensureSortedByID()
{
// 检查是否已经按学号排序
bool isSorted = true;
for (int i = 0; i < studentCount - 1; i++)
{
if (strcmp(students[i].studentID, students[i + 1].studentID) > 0)
{
isSorted = false;
break;
}
}
// 如果没有排序,则按学号排序
if (!isSorted)
{
// 使用外部排序函数
extern void sortStudents(int criteria, int order);
sortStudents(SORT_BY_ID, SORT_ASCENDING);
}
}
/**
* @brief
* @details 使
* O(log n)线O(n)
* @param studentID
* @return -1
* @note
*/
static int binarySearchByID(const char *studentID)
{
int left = 0;
int right = studentCount - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
int cmp = strcmp(students[mid].studentID, studentID);
if (cmp == 0)
{
return mid; // 找到了
}
else if (cmp < 0)
{
left = mid + 1; // 在右半部分搜索
}
else
{
right = mid - 1; // 在左半部分搜索
}
}
return -1; // 未找到
}
+18
View File
@@ -12,24 +12,42 @@
/** /**
* @brief * @brief
* @details * @details
*
* @note
* @warning
*/ */
void searchStudentByID(); void searchStudentByID();
/** /**
* @brief * @brief
* @details * @details
*
* @note
* @note
* @warning
*/ */
void searchStudentByName(); void searchStudentByName();
/** /**
* @brief * @brief
* @details * @details
*
* @note 便
* @note
* @note
* @warning
*/ */
void displayAllStudents(); void displayAllStudents();
/** /**
* @brief * @brief
* @details
* @param student * @param student
* @note
* -
* -
* -
* @warning student指针不能为NULL
*/ */
void displayStudentInfo(const Student *student); void displayStudentInfo(const Student *student);
+76 -21
View File
@@ -10,10 +10,74 @@
#include "config.h" #include "config.h"
#include "globals.h" #include "globals.h"
/**
* @brief -
* @param a
* @param b
* @return a<b0a=ba>b
*/
static int compareByID(const void *a, const void *b)
{
const Student *studentA = (const Student *)a;
const Student *studentB = (const Student *)b;
int result = strcmp(studentA->studentID, studentB->studentID);
return (currentSortOrder == SORT_ASCENDING) ? result : -result;
}
/**
* @brief -
* @param a
* @param b
* @return a<b0a=ba>b
*/
static int compareByName(const void *a, const void *b)
{
const Student *studentA = (const Student *)a;
const Student *studentB = (const Student *)b;
int result = strcmp(studentA->name, studentB->name);
return (currentSortOrder == SORT_ASCENDING) ? result : -result;
}
/**
* @brief -
* @param a
* @param b
* @return a<b0a=ba>b
*/
static int compareByTotalScore(const void *a, const void *b)
{
const Student *studentA = (const Student *)a;
const Student *studentB = (const Student *)b;
if (studentA->totalScore < studentB->totalScore)
return (currentSortOrder == SORT_ASCENDING) ? -1 : 1;
else if (studentA->totalScore > studentB->totalScore)
return (currentSortOrder == SORT_ASCENDING) ? 1 : -1;
else
return 0;
}
/**
* @brief -
* @param a
* @param b
* @return a<b0a=ba>b
*/
static int compareByAverageScore(const void *a, const void *b)
{
const Student *studentA = (const Student *)a;
const Student *studentB = (const Student *)b;
if (studentA->averageScore < studentB->averageScore)
return (currentSortOrder == SORT_ASCENDING) ? -1 : 1;
else if (studentA->averageScore > studentB->averageScore)
return (currentSortOrder == SORT_ASCENDING) ? 1 : -1;
else
return 0;
}
/** /**
* @brief * @brief
* @details * @details
* 使 * 使qsort标准库函数实现O(n log n)
* @param criteria SORT_BY_ID, SORT_BY_NAME, SORT_BY_TOTAL_SCORE, SORT_BY_AVERAGE_SCORE * @param criteria SORT_BY_ID, SORT_BY_NAME, SORT_BY_TOTAL_SCORE, SORT_BY_AVERAGE_SCORE
* @param order SORT_ASCENDING升序, SORT_DESCENDING降序 * @param order SORT_ASCENDING升序, SORT_DESCENDING降序
* @note * @note
@@ -21,7 +85,7 @@
* - SORT_BY_NAME: * - SORT_BY_NAME:
* - SORT_BY_TOTAL_SCORE: * - SORT_BY_TOTAL_SCORE:
* - SORT_BY_AVERAGE_SCORE: * - SORT_BY_AVERAGE_SCORE:
* @note * @note qsort标准库函数O(n log n)
* @note dataModified标志 * @note dataModified标志
*/ */
void sortStudents(int criteria, int order) void sortStudents(int criteria, int order)
@@ -29,36 +93,27 @@ void sortStudents(int criteria, int order)
if (studentCount <= 1) if (studentCount <= 1)
return; return;
// 使用冒泡排序 // 设置全局排序参数
for (int i = 0; i < studentCount - 1; i++) currentSortCriteria = criteria;
{ currentSortOrder = order;
for (int j = 0; j < studentCount - 1 - i; j++)
{
bool shouldSwap = false;
// 选择对应的比较函数并使用qsort进行排序
switch (criteria) switch (criteria)
{ {
case SORT_BY_ID: case SORT_BY_ID:
shouldSwap = (order == SORT_ASCENDING) ? strcmp(students[j].studentID, students[j + 1].studentID) > 0 : strcmp(students[j].studentID, students[j + 1].studentID) < 0; qsort(students, studentCount, sizeof(Student), compareByID);
break; break;
case SORT_BY_NAME: case SORT_BY_NAME:
shouldSwap = (order == SORT_ASCENDING) ? strcmp(students[j].name, students[j + 1].name) > 0 : strcmp(students[j].name, students[j + 1].name) < 0; qsort(students, studentCount, sizeof(Student), compareByName);
break; break;
case SORT_BY_TOTAL_SCORE: case SORT_BY_TOTAL_SCORE:
shouldSwap = (order == SORT_ASCENDING) ? students[j].totalScore > students[j + 1].totalScore : students[j].totalScore < students[j + 1].totalScore; qsort(students, studentCount, sizeof(Student), compareByTotalScore);
break; break;
case SORT_BY_AVERAGE_SCORE: case SORT_BY_AVERAGE_SCORE:
shouldSwap = (order == SORT_ASCENDING) ? students[j].averageScore > students[j + 1].averageScore : students[j].averageScore < students[j + 1].averageScore; qsort(students, studentCount, sizeof(Student), compareByAverageScore);
break; break;
} default:
return; // 无效的排序依据
if (shouldSwap)
{
Student temp = students[j];
students[j] = students[j + 1];
students[j + 1] = temp;
}
}
} }
dataModified = true; dataModified = true;
+8
View File
@@ -12,8 +12,16 @@
/** /**
* @brief * @brief
* @details * @details
* 使
* @param criteria SORT_BY_ID, SORT_BY_NAME, SORT_BY_TOTAL_SCORE, SORT_BY_AVERAGE_SCORE * @param criteria SORT_BY_ID, SORT_BY_NAME, SORT_BY_TOTAL_SCORE, SORT_BY_AVERAGE_SCORE
* @param order SORT_ASCENDING升序, SORT_DESCENDING降序 * @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); void sortStudents(int criteria, int order);
+12
View File
@@ -10,6 +10,9 @@
#include "file_utils.h" #include "file_utils.h"
#include "io_utils.h" #include "io_utils.h"
#include "config.h" #include "config.h"
#include "user_manage.h"
#include "student_io.h"
#include "statistical_analysis.h"
/** /**
* @brief * @brief
@@ -29,6 +32,15 @@ bool initializeSystem()
return false; return false;
} }
// 加载用户数据
loadUsersFromFile();
// 加载学生数据
loadStudentsFromFile();
// 初始化统计缓存
initStatisticsCache();
printSuccess("系统初始化完成"); printSuccess("系统初始化完成");
return true; return true;
} }
+29 -3
View File
@@ -10,8 +10,34 @@
#include <stdbool.h> #include <stdbool.h>
// 系统初始化和清理函数 // 系统初始化和清理函数
bool initializeSystem(); // 初始化系统
bool createDataDirectories(); // 创建数据目录 /**
void cleanupSystem(); // 清理系统资源 * @brief
* @details
* createDataDirectories函数创建数据存储目录
* @return truefalse
* @note
* @note
*/
bool initializeSystem();
/**
* @brief
* @details
* "data"
* @return truefalse
* @note true
* @note
*/
bool createDataDirectories();
/**
* @brief
* @details 退
*
* @note 退
* @note
*/
void cleanupSystem();
#endif // SYSTEM_UTILS_H #endif // SYSTEM_UTILS_H
+108
View File
@@ -0,0 +1,108 @@
/**
* @file types.h
* @brief
* @note
*/
#ifndef TYPES_H
#define TYPES_H
#include <stdbool.h>
#include "config.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 password[MAX_PASSWORD_LENGTH];
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
+103 -8
View File
@@ -1,15 +1,110 @@
/**
* @file user_manage.h
* @brief
* @note
*/
#ifndef USER_MANAGE_H #ifndef USER_MANAGE_H
#define USER_MANAGE_H #define USER_MANAGE_H
#include "config.h" #include "config.h"
// 用户认证与管理相关函数 /**
int loginSystem(); // 处理用户登录 * @brief
void loadUsersFromFile(); // 从文件加载用户数据 * @details
void saveUsersToFile(); // 将用户数据保存到文件 *
void addUserAccount(); // 增加用户 * @return int 10
void deleteUserAccount(); // 删除用户 * @note
void modifyUserPassword(); // 修改用户密码 * 1.
void viewAllUsers(); // 查看所有用户 * 2.
* 3. currentUser和isCurrentUserAdmin
* @note
* - currentUser:
* - isCurrentUserAdmin:
*/
int loginSystem();
/**
* @brief
* @details USERS_FILE文件中读取用户数据到内存
*
* @note "username:password:isAdmin"
* isAdmin为1表示管理员0
* @note
* - admin123456
* - teacherpassword
* @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 #endif // USER_MANAGE_H
+47 -5
View File
@@ -10,10 +10,52 @@
#include <stdbool.h> #include <stdbool.h>
// 数据验证函数 // 数据验证函数
bool isValidScore(float score); // 验证成绩是否有效
bool isValidStudentId(const char* id); // 验证学号是否有效 /**
bool isValidName(const char* name); // 验证姓名是否有效 * @brief
bool isValidGender(char gender); // 验证性别是否有效 * @details 0-100
bool isValidAge(int age); // 验证年龄是否有效 * @param score
* @return truefalse
* @note 0.0100.0
*/
bool isValidScore(float score);
/**
* @brief
* @details
* @param id
* @return truefalse
* @note 1MAX_ID_LENGTH之间
* @warning id为NULLfalse
*/
bool isValidStudentId(const char* id);
/**
* @brief
* @details
* @param name
* @return truefalse
* @note 1MAX_NAME_LENGTH之间
* @warning name为NULLfalse
*/
bool isValidName(const char* name);
/**
* @brief
* @details 'M''F'
* @param gender
* @return truefalse
* @note 'M''F'
*/
bool isValidGender(char gender);
/**
* @brief
* @details
* @param age
* @return truefalse
* @note MIN_AGE到MAX_AGE
*/
bool isValidAge(int age);
#endif // VALIDATION_H #endif // VALIDATION_H