test #1

Merged
hnu202326010101 merged 2 commits from develop into main 4 months ago

28
.gitignore vendored

@ -0,0 +1,28 @@
# 编译生成的可执行文件
*.exe
*.out
*.o
*.obj
# 临时文件
*.tmp
*.temp
*~
# 系统文件
.DS_Store
Thumbs.db
# IDE文件
.vscode/
.idea/
*.swp
*.swo
# 生成的题目文件夹(用户数据)
xiaoxue*/
chuzhong*/
gaozhong*/
# 日志文件
*.log

@ -0,0 +1,172 @@
# Git版本控制使用说明
## 项目Git结构
根据头歌平台要求,本项目采用以下分支结构:
- **master分支**:稳定版本,用于发布
- **develop分支**:开发版本,用于日常开发
## 快速设置(推荐)
### 方法一:使用自动化脚本
1. 双击项目根目录下的 `git_setup.bat` 文件
2. 按照提示输入Git用户名和邮箱
3. 脚本会自动完成仓库初始化和分支创建
### 方法二:手动设置
如果您熟悉Git命令可以按照以下步骤手动设置
## 详细设置步骤
### 1. 检查Git安装
```bash
git --version
```
如果提示"git不是内部或外部命令"请先安装Git
- 访问https://git-scm.com/download/win
- 下载并安装Git for Windows
### 2. 初始化仓库
```bash
# 进入项目目录
cd "e:\学习通\download\软件项目管理\软件2301班_沈永佳_个人项目"
# 初始化Git仓库
git init
# 配置用户信息
git config user.name "您的姓名"
git config user.email "您的邮箱"
```
### 3. 创建分支结构
```bash
# 创建并切换到develop分支
git checkout -b develop
# 添加所有文件
git add .
# 提交初始版本
git commit -m "初始提交:中小学数学卷子自动生成程序"
# 创建master分支
git checkout -b master
# 合并develop分支到master
git merge develop --no-ff -m "合并develop分支到master稳定版本"
# 切换回develop分支进行日常开发
git checkout develop
```
## 连接头歌平台
### 1. 在头歌平台创建项目
1. 登录头歌平台
2. 创建新项目:`软件2301班_沈永佳_个人项目`
3. 复制项目的Git仓库地址
### 2. 添加远程仓库
```bash
# 添加远程仓库(替换为实际的仓库地址)
git remote add origin https://git.educoder.net/your-username/软件2301班_沈永佳_个人项目.git
# 推送master分支
git push -u origin master
# 推送develop分支
git push -u origin develop
```
## 日常开发流程
### 开发新功能
```bash
# 确保在develop分支
git checkout develop
# 拉取最新代码
git pull origin develop
# 修改代码后提交
git add .
git commit -m "描述您的修改内容"
# 推送到远程develop分支
git push origin develop
```
### 发布稳定版本
```bash
# 切换到master分支
git checkout master
# 合并develop分支的稳定功能
git merge develop --no-ff -m "发布版本v1.x"
# 推送到远程master分支
git push origin master
# 切换回develop分支继续开发
git checkout develop
```
## 常用Git命令
| 命令 | 说明 |
|------|------|
| `git status` | 查看文件状态 |
| `git log --oneline` | 查看提交历史 |
| `git branch` | 查看分支列表 |
| `git checkout [分支名]` | 切换分支 |
| `git add .` | 添加所有修改的文件 |
| `git commit -m "消息"` | 提交修改 |
| `git push origin [分支名]` | 推送到远程分支 |
| `git pull origin [分支名]` | 拉取远程分支 |
## 文件结构说明
```
项目根目录/
├── .git/ # Git版本控制目录
├── .gitignore # Git忽略文件配置
├── src/ # 源代码目录
│ ├── main.cpp # 主程序文件
│ ├── Makefile # 编译配置
│ ├── run.bat # 运行脚本
│ └── run_utf8.bat # UTF-8编码运行脚本
├── doc/ # 文档目录
│ ├── README.md # 项目说明
│ └── Git使用说明.md # 本文档
└── git_setup.bat # Git自动设置脚本
```
## 注意事项
1. **编码问题**确保使用UTF-8编码避免中文乱码
2. **分支管理**
- develop分支用于日常开发
- master分支只用于稳定版本发布
3. **提交信息**:使用清晰的中文描述提交内容
4. **文件忽略**`.gitignore`已配置忽略编译文件和用户数据
## 故障排除
### 问题1Git命令不识别
**解决方案**安装Git for Windows并重启命令行
### 问题2中文文件名乱码
**解决方案**
```bash
git config --global core.quotepath false
```
### 问题3推送失败
**解决方案**:检查网络连接和仓库地址是否正确
## 联系方式
如有问题,请联系:
- 姓名:沈永佳
- 班级软件2301班

@ -0,0 +1,154 @@
# 中小学数学卷子自动生成程序
## 项目概述
本项目是一个基于C++开发的中小学数学卷子自动生成程序,面向小学、初中和高中数学老师,能够根据不同学段的难度要求自动生成数学题目并保存为试卷文件。
## 功能特性
### 1. 用户登录系统
- 预设小学、初中、高中各3个教师账号
- 用户名密码验证机制
- 根据账户类型自动识别出题难度
### 2. 智能题目生成
- **小学题目**2-3个操作数数值范围1-50支持加减法
- **初中题目**3-4个操作数数值范围1-100支持加减乘法
- **高中题目**4-5个操作数数值范围1-100支持加减乘除法
### 3. 题目管理
- 自动避免同一教师生成重复题目
- 按教师账号创建独立文件夹
- 以时间戳命名保存试卷文件(年-月-日-时-分-秒.txt
### 4. 灵活的类型切换
- 登录后可切换不同学段出题类型
- 支持命令行快速切换
## 预设账号信息
| 学段 | 用户名 | 密码 |
|------|--------|------|
| 小学 | xiaoxue1 | 123456 |
| 小学 | xiaoxue2 | 123456 |
| 小学 | xiaoxue3 | 123456 |
| 初中 | chuzhong1 | 123456 |
| 初中 | chuzhong2 | 123456 |
| 初中 | chuzhong3 | 123456 |
| 高中 | gaozhong1 | 123456 |
| 高中 | gaozhong2 | 123456 |
| 高中 | gaozhong3 | 123456 |
## 编译和运行
### 编译要求
- C++17 或更高版本
- 支持 `<filesystem>` 库的编译器(如 GCC 8+ 或 Clang 7+
### 编译方法
#### 使用 Makefile推荐
```bash
cd src
make
```
#### 手动编译
```bash
cd src
g++ -std=c++17 -Wall -Wextra -O2 -o math_exam_generator main.cpp
```
### 运行程序
#### 方法一使用UTF-8编码脚本推荐解决乱码问题
```bash
cd src
run_utf8.bat
```
#### 方法二:手动设置编码后运行
```bash
cd src
chcp 65001
math_exam_generator.exe
```
#### 方法三:直接运行(可能出现中文乱码)
```bash
cd src
math_exam_generator.exe
```
## 使用说明
### 1. 登录
启动程序后,输入用户名和密码,用空格隔开:
```
请输入用户名和密码(用空格隔开): xiaoxue1 123456
```
### 2. 生成试卷
登录成功后输入要生成的题目数量10-30题
```
准备生成小学数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录20
```
### 3. 切换类型
在登录状态下,可以切换出题类型:
```
切换为初中
```
### 4. 退出登录
输入 -1 可退出当前用户,重新登录:
```
准备生成小学数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录-1
```
## 文件结构
```
项目根目录/
├── src/ # 源代码目录
│ ├── main.cpp # 主程序文件
│ └── Makefile # 编译配置文件
├── doc/ # 文档目录
│ └── README.md # 项目说明文档
└── [用户名]/ # 自动生成的用户文件夹
└── 年-月-日-时-分-秒.txt # 生成的试卷文件
```
## 试卷格式示例
```
1. 25 + 18 - 7 = ?
2. 42 - 15 + 23 = ?
3. 8 + 17 - 9 + 14 = ?
```
## 技术特点
- **面向对象设计**:使用类封装功能模块
- **STL容器**:使用 vector、map、set 等容器管理数据
- **文件系统操作**:使用 C++17 filesystem 库进行文件管理
- **随机数生成**使用现代C++随机数生成器
- **异常处理**:对用户输入进行验证和异常处理
## 开发环境
- 编程语言C++17
- 编译器GCC 8+ / Clang 7+ / MSVC 2019+
- 操作系统Windows / Linux / macOS
## 版本控制
本项目使用Git进行版本控制
- `master` 分支:稳定版本
- `develop` 分支:开发版本
## 作者
软件2301班 - 沈永佳

@ -0,0 +1,63 @@
@echo off
chcp 65001 >nul
echo ========================================
echo 中小学数学卷子生成程序 Git 设置
echo ========================================
echo.
echo 正在检查Git是否已安装...
git --version >nul 2>&1
if %errorlevel% neq 0 (
echo [错误] 未检测到Git请先安装Git
echo 1. 访问 https://git-scm.com/download/win
echo 2. 下载并安装Git for Windows
echo 3. 重新运行此脚本
pause
exit /b 1
)
echo [成功] Git已安装
echo.
echo 正在初始化Git仓库...
git init
if %errorlevel% neq 0 (
echo [错误] Git初始化失败
pause
exit /b 1
)
echo 正在配置Git用户信息...
set /p username="请输入您的Git用户名: "
set /p email="请输入您的Git邮箱: "
git config user.name "%username%"
git config user.email "%email%"
echo.
echo 正在创建分支结构...
git checkout -b develop
git add .
git commit -m "初始提交:中小学数学卷子自动生成程序"
echo 正在创建master分支...
git checkout -b master
git merge develop --no-ff -m "合并develop分支到master稳定版本"
echo.
echo ========================================
echo Git仓库设置完成
echo.
echo 分支结构:
echo - master: 稳定版本
echo - develop: 开发版本(当前分支)
echo.
echo 下一步:
echo 1. 在头歌平台创建项目仓库
echo 2. 复制仓库地址
echo 3. 运行以下命令添加远程仓库:
echo git remote add origin [仓库地址]
echo git push -u origin master
echo git push -u origin develop
echo ========================================
pause

@ -0,0 +1,22 @@
# Makefile for Math Exam Generator
CXX = g++
CXXFLAGS = -std=c++17 -Wall -Wextra -O2
TARGET = math_exam_generator
SOURCE = main.cpp
# Default target
all: $(TARGET)
# Build target
$(TARGET): $(SOURCE)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(SOURCE)
# Clean target
clean:
rm -f $(TARGET) $(TARGET).exe
# Run target
run: $(TARGET)
./$(TARGET)
.PHONY: all clean run

@ -0,0 +1,410 @@
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <random>
#include <fstream>
#include <sstream>
#include <ctime>
#include <iomanip>
#include <filesystem>
#include <set>
#include <locale>
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#endif
using namespace std;
namespace fs = std::filesystem;
// 用户账号结构
struct User {
string username;
string password;
string type; // "小学", "初中", "高中"
};
// 数学题目结构
struct MathQuestion {
string question;
int answer;
bool operator<(const MathQuestion& other) const {
return question < other.question;
}
};
class MathExamGenerator {
private:
vector<User> users;
User currentUser;
bool isLoggedIn;
string currentType;
random_device rd;
mt19937 gen;
// 存储已生成的题目,避免重复
map<string, set<MathQuestion>> generatedQuestions;
public:
MathExamGenerator() : gen(rd()), isLoggedIn(false) {
initializeUsers();
loadExistingQuestions();
}
// 初始化预设账号
void initializeUsers() {
// 小学账号
users.push_back({"xiaoxue1", "123456", "小学"});
users.push_back({"xiaoxue2", "123456", "小学"});
users.push_back({"xiaoxue3", "123456", "小学"});
// 初中账号
users.push_back({"chuzhong1", "123456", "初中"});
users.push_back({"chuzhong2", "123456", "初中"});
users.push_back({"chuzhong3", "123456", "初中"});
// 高中账号
users.push_back({"gaozhong1", "123456", "高中"});
users.push_back({"gaozhong2", "123456", "高中"});
users.push_back({"gaozhong3", "123456", "高中"});
}
// 加载已存在的题目
void loadExistingQuestions() {
for (const auto& user : users) {
string folderPath = user.username;
if (fs::exists(folderPath)) {
for (const auto& entry : fs::directory_iterator(folderPath)) {
if (entry.is_regular_file() && entry.path().extension() == ".txt") {
loadQuestionsFromFile(entry.path().string(), user.username);
}
}
}
}
}
// 从文件加载题目
void loadQuestionsFromFile(const string& filename, const string& username) {
ifstream file(filename);
string line;
while (getline(file, line)) {
if (!line.empty() && line.find('.') != string::npos) {
// 提取题目部分(去掉题号)
size_t dotPos = line.find('.');
if (dotPos != string::npos && dotPos + 1 < line.length()) {
string question = line.substr(dotPos + 1);
// 去掉前后空格
question.erase(0, question.find_first_not_of(" \t"));
question.erase(question.find_last_not_of(" \t") + 1);
MathQuestion mq;
mq.question = question;
mq.answer = 0; // 这里简化处理
generatedQuestions[username].insert(mq);
}
}
}
file.close();
}
// 用户登录
bool login(const string& username, const string& password) {
for (const auto& user : users) {
if (user.username == username && user.password == password) {
currentUser = user;
currentType = user.type;
isLoggedIn = true;
cout << "当前选择为" << currentType << "出题" << endl;
return true;
}
}
return false;
}
// 生成小学数学题
MathQuestion generatePrimaryQuestion() {
uniform_int_distribution<> opCount(2, 3); // 操作数2-3个
uniform_int_distribution<> numDist(1, 50); // 数值范围1-50
uniform_int_distribution<> opDist(0, 1); // 0:加法, 1:减法
int operandCount = opCount(gen);
vector<int> numbers;
vector<char> operators;
for (int i = 0; i < operandCount; i++) {
numbers.push_back(numDist(gen));
}
for (int i = 0; i < operandCount - 1; i++) {
operators.push_back(opDist(gen) == 0 ? '+' : '-');
}
// 构建题目字符串
stringstream ss;
ss << numbers[0];
int result = numbers[0];
for (int i = 0; i < operators.size(); i++) {
ss << " " << operators[i] << " " << numbers[i + 1];
if (operators[i] == '+') {
result += numbers[i + 1];
} else {
result -= numbers[i + 1];
}
}
// 确保结果为正数
if (result < 0) {
return generatePrimaryQuestion();
}
ss << " = ?";
MathQuestion question;
question.question = ss.str();
question.answer = result;
return question;
}
// 生成初中数学题
MathQuestion generateMiddleQuestion() {
uniform_int_distribution<> opCount(3, 4); // 操作数3-4个
uniform_int_distribution<> numDist(1, 100); // 数值范围1-100
uniform_int_distribution<> opDist(0, 2); // 0:加法, 1:减法, 2:乘法
int operandCount = opCount(gen);
vector<int> numbers;
vector<char> operators;
for (int i = 0; i < operandCount; i++) {
numbers.push_back(numDist(gen));
}
for (int i = 0; i < operandCount - 1; i++) {
int op = opDist(gen);
if (op == 0) operators.push_back('+');
else if (op == 1) operators.push_back('-');
else operators.push_back('*');
}
// 构建题目字符串
stringstream ss;
ss << numbers[0];
int result = numbers[0];
for (int i = 0; i < operators.size(); i++) {
ss << " " << operators[i] << " " << numbers[i + 1];
if (operators[i] == '+') {
result += numbers[i + 1];
} else if (operators[i] == '-') {
result -= numbers[i + 1];
} else {
result *= numbers[i + 1];
}
}
ss << " = ?";
MathQuestion question;
question.question = ss.str();
question.answer = result;
return question;
}
// 生成高中数学题
MathQuestion generateHighQuestion() {
uniform_int_distribution<> opCount(4, 5); // 操作数4-5个
uniform_int_distribution<> numDist(1, 100); // 数值范围1-100
uniform_int_distribution<> opDist(0, 3); // 0:加法, 1:减法, 2:乘法, 3:除法
int operandCount = opCount(gen);
vector<int> numbers;
vector<char> operators;
for (int i = 0; i < operandCount; i++) {
numbers.push_back(numDist(gen));
}
for (int i = 0; i < operandCount - 1; i++) {
int op = opDist(gen);
if (op == 0) operators.push_back('+');
else if (op == 1) operators.push_back('-');
else if (op == 2) operators.push_back('*');
else {
operators.push_back('/');
// 确保除法结果为整数
numbers[i + 1] = numbers[i] % numbers[i + 1] == 0 ? numbers[i + 1] :
(numbers[i] / numbers[i + 1] + 1);
}
}
// 构建题目字符串
stringstream ss;
ss << numbers[0];
double result = numbers[0];
for (int i = 0; i < operators.size(); i++) {
ss << " " << operators[i] << " " << numbers[i + 1];
if (operators[i] == '+') {
result += numbers[i + 1];
} else if (operators[i] == '-') {
result -= numbers[i + 1];
} else if (operators[i] == '*') {
result *= numbers[i + 1];
} else {
if (numbers[i + 1] != 0) {
result /= numbers[i + 1];
}
}
}
ss << " = ?";
MathQuestion question;
question.question = ss.str();
question.answer = (int)result;
return question;
}
// 根据类型生成题目
MathQuestion generateQuestion(const string& type) {
if (type == "小学") {
return generatePrimaryQuestion();
} else if (type == "初中") {
return generateMiddleQuestion();
} else {
return generateHighQuestion();
}
}
// 检查题目是否重复
bool isQuestionDuplicate(const MathQuestion& question) {
return generatedQuestions[currentUser.username].count(question) > 0;
}
// 生成试卷
void generateExam(int questionCount) {
vector<MathQuestion> questions;
// 生成不重复的题目
while (questions.size() < questionCount) {
MathQuestion question = generateQuestion(currentType);
if (!isQuestionDuplicate(question)) {
questions.push_back(question);
generatedQuestions[currentUser.username].insert(question);
}
}
// 创建用户文件夹
string folderPath = currentUser.username;
if (!fs::exists(folderPath)) {
fs::create_directory(folderPath);
}
// 生成文件名(年-月-日-时-分-秒.txt
auto now = chrono::system_clock::now();
auto time_t = chrono::system_clock::to_time_t(now);
auto tm = *localtime(&time_t);
stringstream filename;
filename << folderPath << "/"
<< put_time(&tm, "%Y-%m-%d-%H-%M-%S") << ".txt";
// 写入文件
ofstream file(filename.str());
for (int i = 0; i < questions.size(); i++) {
file << (i + 1) << ". " << questions[i].question << endl;
if (i < questions.size() - 1) {
file << endl; // 题目之间空一行
}
}
file.close();
cout << "试卷已生成并保存到: " << filename.str() << endl;
}
// 切换类型
bool switchType(const string& newType) {
if (newType == "小学" || newType == "初中" || newType == "高中") {
currentType = newType;
return true;
}
return false;
}
// 主运行循环
void run() {
cout << "=== 中小学数学卷子自动生成程序 ===" << endl;
while (true) {
if (!isLoggedIn) {
cout << "请输入用户名和密码(用空格隔开): ";
string username, password;
cin >> username >> password;
if (login(username, password)) {
continue;
} else {
cout << "请输入正确的用户名、密码" << endl;
continue;
}
}
cout << "准备生成" << currentType << "数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录";
string input;
cin >> input;
// 检查是否是切换命令
if (input.find("切换为") == 0) {
string newType = input.substr(3); // 去掉"切换为"
if (switchType(newType)) {
cout << "准备生成" << currentType << "数学题目,请输入生成题目数量:";
continue;
} else {
cout << "请输入小学、初中和高中三个选项中的一个" << endl;
continue;
}
}
try {
int count = stoi(input);
if (count == -1) {
isLoggedIn = false;
cout << "已退出登录" << endl;
continue;
}
if (count >= 10 && count <= 30) {
generateExam(count);
} else {
cout << "题目数量必须在10-30之间" << endl;
}
} catch (const exception& e) {
cout << "请输入有效的数字" << endl;
}
}
}
};
int main() {
#ifdef _WIN32
// 设置控制台编码为UTF-8解决中文乱码问题
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
// 设置locale为中文
setlocale(LC_ALL, "zh_CN.UTF-8");
#endif
MathExamGenerator generator;
generator.run();
return 0;
}

@ -0,0 +1,11 @@
@echo off
echo 正在编译程序...
g++ -std=c++17 -Wall -Wextra -O2 -o math_exam_generator.exe main.cpp
if %errorlevel% equ 0 (
echo 编译成功!正在启动程序...
echo.
math_exam_generator.exe
) else (
echo 编译失败!
pause
)

@ -0,0 +1,12 @@
@echo off
chcp 65001 >nul
echo 正在编译程序...
g++ -std=c++17 -Wall -Wextra -O2 -o math_exam_generator.exe main.cpp
if %errorlevel% equ 0 (
echo 编译成功!正在启动程序...
echo.
math_exam_generator.exe
) else (
echo 编译失败!
pause
)
Loading…
Cancel
Save