# 数学考试系统 - 项目说明文档
## 项目概述
这是一个基于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);
```
**功能**:设置全局日志级别,低于该级别的日志不会输出