# 数学考试系统 - 项目说明文档 ## 项目概述 这是一个基于C++实现的智能数学题目生成系统,支持小学、初中、高中三个不同难度级别的题目自动生成。系统具有用户管理、题目查重、文件保存和日志记录等完整功能。 ## 项目结构 ### 核心模块 | 模块 | 文件 | 功能描述 | | -------- | ------------------------- | ---------------------------- | | 主程序 | `main.cc` | 程序入口,系统配置和启动 | | 系统核心 | `exam_system.h/.cc` | 系统主流程控制,用户会话管理 | | 题目生成 | `problem_generator.h/.cc` | 不同难度题目生成器实现 | | 文件管理 | `file_manager.h/.cc` | 用户目录和题目文件管理 | | 查重服务 | `duplicate_checker.h` | 题目重复性检查 | | 输入验证 | `input_validator.h/.cc` | 各类输入数据验证 | | 日志系统 | `logger.h/.cc` | 分级日志记录 | ## 详细设计说明 ### 1. 系统架构 ```Mermaid graph TD A[ExamSystem
系统控制中心] --> B[ProblemGenerator
题目生成器] A --> C[FileManager
文件管理器] A --> D[DuplicateChecker
查重服务] B --> B1[小学生成器] B --> B2[初中生成器] B --> B3[高中生成器] C --> C1[目录操作] C --> C2[文件操作] D --> D1[历史题目管理] D --> D2[重复检查] ``` ### 架构分层说明 | 层次 | 组件 | 职责 | 设计模式 | | :--------- | :----------------- | :------------ | :----------------- | | 用户交互层 | 用户界面 | 控制台I/O处理 | - | | 核心控制层 | ExamSystem | 系统流程控制 | 状态模式 | | 业务逻辑层 | ProblemGenerator等 | 核心业务处理 | 工厂模式、策略模式 | | 数据访问层 | FileManager | 数据持久化 | - | | 基础设施层 | Logger等 | 支撑服务 | 单例模式 | | 数据存储层 | 文件系统 | 数据存储 | - | ### 2. 用户管理 **预置用户账户**: - 小学组:张三1、张三2、张三3 - 初中组:李四1、李四2、李四3 - 高中组:王五1、王五2、王五3 - 密码:均为"123" ### 3. 题目生成器设计 #### 3.1 小学题目生成器 (`PrimarySchoolGenerator`) - **运算符**:+、-、×、÷ - **特点**:确保计算结果不为负数 - **操作数**:2-5个 - **数值范围**:1-100 **示例题目**:15 + 23 - 7 × 3 #### 3.2 初中题目生成器 (`MiddleSchoolGenerator`) - **新增运算符**:平方(²)、开根号(√) - **特点**:至少包含一个特殊运算符 - **操作数**:1-5个 **示例题目**:(5)² + √16 × 3 #### 3.3 高中题目生成器 (`HighSchoolGenerator`) - **新增运算符**:sin、cos、tan - **特点**:包含三角函数计算 - **角度范围**:0-360度 **示例题目**:sin(45°) + cos(90°) × 2 ### 4. 核心算法实现 #### 4.1 表达式求值算法 ```cpp // 处理运算符优先级:先乘除,后加减 int EvaluateExpression(const std::string& expression) { // 1. 分词处理 // 2. 第一遍:处理乘除法 // 3. 第二遍:处理加减法 // 4. 返回最终结果 } ``` #### 4.2 题目查重机制 - 基于用户名的题目历史记录 - 实时检查新生成题目是否重复 - 支持历史题目加载 #### 4.3 文件命名策略 ```cpp // 格式:YYYY-MM-DD-HH-MM-SS.txt std::string GenerateFilename() { //1.获取当前时间 //2.生成格式字符串 //3.返回文件名 } ``` ### 5. 系统配置参数 | 参数 | 值 | 说明 | | :------------- | :--- | :------------------------- | | 最小题目数量 | 10 | 单次生成最少题目数 | | 最大题目数量 | 30 | 单次生成最多题目数 | | 操作数最小值 | 1 | 题目中数字的最小值 | | 操作数最大值 | 100 | 题目中数字的最大值 | | 最大操作数个数 | 5 | 单个题目最多包含的数字个数 | ### 6. 使用流程 1. **启动系统** ```bash ./exam_system ``` 2. **用户登录** ```bash 请输入用户名和密码(用空格隔开): 张三1 123 ``` 3. **题目生成** ```BASH 当前选择为小学出题 准备生成小学数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录): 15 ``` 4. **类型切换** ```bash 切换为初中 准备生成初中数学题目,请输入生成题目数量... ``` 5. **退出登录** ```bash 准备生成小学数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录): -1 ``` ### 7. 文件存储结构 ```text 项目根目录/ ├── 张三1/ │ ├── 2025-01-15-10-30-45.txt │ └── 2025-01-15-11-15-20.txt ├── 李四1/ │ └── 2025-01-15-09-45-10.txt └── 王五1/ └── 2025-01-15-14-20-35.txt ``` ### 8. 设计模式应用 #### 8.1 工厂模式 ```cpp std::unique_ptr factory = ProblemGeneratorFactory::CreateGenerator("小学"); ``` #### 8.2 策略模式 不同难度的题目生成器实现统一的`ProblemGenerator`接口 #### 8.3 单例模式 日志系统和文件管理器使用静态方法提供全局访问 ### 9.系统要求 **操作系统** - **仅支持 Windows 系统** - 不支持 Linux、macOS 等其他操作系统 **编译器要求** - **支持 C++17 标准的编译器** - 推荐使用: - Microsoft Visual Studio 2017 或更高版本 - MinGW-w64 (GCC 8.0 或更高版本) - Clang with MSVC backend ### 10.编译和运行 **先到src目录下** ```bash cd src ``` **编译命令**: ```bash g++ -std=c++17 -Wall -Wextra -I. -Iexam_system -Ifile_manager -Ilogger -o exam_system main/main.cc exam_system/exam_system.cc exam_system/problem_generator.cc exam_system/duplicate_checker.cc exam_system/input_validator.cc file_manager/file_manager.cc logger/logger.cc ``` **或者** ```bash cd ../build --config Debug --target all -j 12 -- ``` **运行**: ```bash .\exam_system.exe ``` ## 核心类详细说明 ### 1 ExamSystem 类 - 系统主控制器 #### 类定义位置 - **头文件**:`exam_system.h` - **实现文件**:`exam_system.cc` #### 职责说明 作为系统的核心控制器,负责协调所有模块的工作,管理用户会话状态,处理用户交互流程。 #### 核心成员变量 ```cpp private: SystemConfig config_; // 系统配置信息 std::unique_ptr generator_; // 题目生成器实例 const UserInfo* current_user_; // 当前登录用户指针 DuplicateChecker duplicate_checker_; // 查重服务实例 ``` #### 主要方法详解 ##### 构造函数 ```cpp ExamSystem(const SystemConfig& config); ``` **功能**:初始化系统配置,设置初始状态 **参数**: - `config`:包含用户列表等系统配置信息 **调用时机**:系统启动时 ##### Run() 方法 ```cpp void Run(); ``` **功能**:系统主循环,处理用户交互流程 **流程**: 1. 显示登录提示 2. 处理用户登录 3. 进入命令循环等待用户输入 4. 处理题目生成、类型切换、退出等命令 ##### Login() 方法 ```cpp bool Login(const std::string& username, const std::string& password); ``` **功能**:用户身份验证 **参数**: - `username`:用户名 - `password`:密码 **返回值**:登录成功返回true,失败返回false **处理逻辑**: 1. 验证用户名密码格式 2. 在配置的用户列表中查找匹配用户 3. 设置当前用户和对应的题目生成器 4. 加载用户历史题目 ##### GenerateExam() 方法 ```cpp std::vector GenerateExam(int count); ``` **功能**:生成指定数量的题目 **参数**: - `count`:需要生成的题目数量 **返回值**:生成的题目列表 **关键逻辑**: - 使用当前题目生成器生成题目 - 验证题目有效性 - 检查题目重复性 - 格式化题目(添加题号) ##### SwitchType() 方法 ```cpp void SwitchType(const std::string& type); ``` **功能**:切换题目生成类型 **参数**: - `type`:目标类型("小学"/"初中"/"高中") **处理逻辑**: 1. 验证类型有效性 2. 创建新的题目生成器 3. 更新用户界面提示 ### 2 ProblemGenerator 类体系 - 题目生成器 #### 类层次结构 ``` ProblemGenerator (抽象基类) ├── BaseProblemGenerator (基础实现) ├── PrimarySchoolGenerator (小学题目生成器) ├── MiddleSchoolGenerator (初中题目生成器) └── HighSchoolGenerator (高中题目生成器) ``` #### ProblemGenerator 抽象基类 ##### 核心接口 ```cpp virtual std::string GenerateProblem() = 0; virtual std::string GetCurrentType() const = 0; virtual void SetCurrentType(const std::string& type) = 0; virtual bool ValidateProblem(const std::string& problem) const = 0; virtual int GetMinOperandCount() const = 0; ``` #### PrimarySchoolGenerator 类 ##### 特点 - 生成小学难度数学题目 - 确保计算结果不为负数 - 支持加减乘除四则运算 ##### 核心方法 ```cpp std::string GenerateProblem() override; ``` **生成逻辑**: 1. 随机确定操作数数量(2-5个) 2. 生成确保非负的表达式 3. 验证表达式有效性 4. 返回格式化后的题目 ##### 关键算法 ```cpp std::string GenerateNonNegativeExpression(int operand_count); ``` **特殊处理**: - 对减法运算进行特殊处理,确保被减数大于减数 - 多次尝试生成有效表达式 #### MiddleSchoolGenerator 类 ##### 特点 - 生成初中难度数学题目 - 包含平方和开根号运算 - 确保至少包含一个特殊运算符 ##### 新增功能 ```cpp std::string GenerateSquareOrRoot(); ``` **平方运算**:生成 `(数字)²` 格式 **开根号运算**:生成 `√完全平方数` 格式 #### HighSchoolGenerator 类 ##### 特点 - 生成高中难度数学题目 - 包含三角函数运算 - 角度范围为0-360度 ##### 新增功能 ```cpp std::string GenerateTrigonometricFunction(); ``` **支持的函数**:sin、cos、tan **格式**:`函数名(角度°)` ### 3 FileManager 类 - 文件管理器 #### 类特性 - 全部方法为静态方法 - 提供跨平台文件操作支持 #### 核心方法详解 ##### CreateUserDirectory() 方法 ```cpp static bool CreateUserDirectory(const std::string& username); ``` **功能**:创建用户专属目录 **实现**: - 使用 `_mkdir()`(Windows)或 `mkdir()`(Linux)创建目录 - 检查目录是否已存在 - 记录创建结果日志 ##### SaveProblemsToFile() 方法 ```cpp static bool SaveProblemsToFile(const std::string& username, const std::vector& problems); ``` **功能**:保存题目列表到文件 **文件命名**:使用时间戳格式 `YYYY-MM-DD-HH-MM-SS.txt` **文件格式**:每道题目用空行分隔 ##### LoadUserHistoryProblems() 方法 ```cpp static std::vector LoadUserHistoryProblems(const std::string& username); ``` **功能**:加载用户所有历史题目 **流程**: 1. 检查用户目录是否存在 2. 获取目录下所有txt文件 3. 从每个文件中提取题目 4. 返回合并的题目列表 ##### ExtractProblemsFromFile() 方法 ```cpp static std::vector ExtractProblemsFromFile(const std::string& filepath); ``` **功能**:从单个文件解析题目 **解析逻辑**: - 使用正则表达式识别题号行 - 按空行分割不同题目 - 提取题目内容(去除题号) ### 4 DuplicateChecker 类 - 查重服务 #### 核心数据结构 ```cpp private: std::map> user_problems_; std::set loaded_users_; ``` #### 主要方法详解 ##### AddProblem() 方法 ```cpp void AddProblem(const std::string& username, const std::string& problem); ``` **功能**:添加题目到用户题目记录 **用途**:记录新生成的题目,用于后续查重 ##### CheckDuplicate() 方法 ```cpp bool CheckDuplicate(const std::string& username, const std::string& problem) const; ``` **功能**:检查题目是否重复 **检查范围**: - 当前会话生成的题目 - 已加载的历史题目 **返回值**:重复返回true,否则返回false ##### LoadUserHistory() 方法 ```cpp void LoadUserHistory(const std::string& username); ``` **功能**:加载用户历史题目到查重系统 **特性**:每个用户只加载一次,避免重复加载 ##### HasLoadedHistory() 方法 ```cpp bool HasLoadedHistory(const std::string& username) const; ``` **功能**:检查用户历史题目是否已加载 **用途**:防止重复加载历史题目 ### 5 InputValidator 类 - 输入验证器 #### 验证功能列表 ##### ValidateUsername() ```cpp static bool ValidateUsername(const std::string& username); ``` **验证规则**: - 非空 - 长度不超过50字符 ##### ValidatePassword() ```cpp static bool ValidatePassword(const std::string& password); ``` **验证规则**: - 非空 - 长度不超过50字符 ##### ValidateUserType() ```cpp static bool ValidateUserType(const std::string& user_type); ``` **有效值**:"小学"、"初中"、"高中" ##### ValidateQuestionCount() ```cpp static bool ValidateQuestionCount(int count); ``` **有效范围**:10-30 或 -1(退出代码) ##### ValidateSwitchCommand() ```cpp static bool ValidateSwitchCommand(const std::string& command); ``` **有效格式**:以"切换为"开头的字符串 ### 6 Logger 类 - 日志系统 #### 日志级别 ```cpp enum class Level { INFO, // 普通信息 WARNING, // 警告信息 ERROR // 错误信息 }; ``` #### 核心方法 ##### Log() 方法 ```cpp static void Log(Level level, const std::string& message); ``` **输出格式**:`[时间戳] 级别: 消息内容` **特性**:根据设置的日志级别过滤输出 ##### SetLogLevel() 方法 ```cpp static void SetLogLevel(Level level); ``` **功能**:设置全局日志级别,低于该级别的日志不会输出