|
|
|
|
@ -12,6 +12,7 @@
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#include <direct.h>
|
|
|
|
|
@ -20,21 +21,289 @@
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
// 账户结构体
|
|
|
|
|
// 账户结构体:存储用户账户信息
|
|
|
|
|
struct Account {
|
|
|
|
|
string username;
|
|
|
|
|
string password;
|
|
|
|
|
string type; // 用户类型:小学、初中、高中
|
|
|
|
|
string username; // 用户名
|
|
|
|
|
string password; // 密码
|
|
|
|
|
string type; // 用户类型:小学、初中、高中
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 数学卷子生成主类
|
|
|
|
|
// 抽象题目生成器:定义题目生成器的统一接口
|
|
|
|
|
class MathQuestionGenerator {
|
|
|
|
|
public:
|
|
|
|
|
virtual ~MathQuestionGenerator() {}
|
|
|
|
|
virtual std::string generateQuestion() = 0; // 生成题目的纯虚函数
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 小学题目生成器:生成小学级别的数学题目
|
|
|
|
|
class PrimaryQuestionGenerator : public MathQuestionGenerator {
|
|
|
|
|
public:
|
|
|
|
|
PrimaryQuestionGenerator() {}
|
|
|
|
|
|
|
|
|
|
// 生成指定范围内的随机数
|
|
|
|
|
int randomNumber(int min, int max) {
|
|
|
|
|
return rand() % (max - min + 1) + min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建数学表达式字符串
|
|
|
|
|
std::string buildExpression(const std::vector<int>& operands, const std::vector<char>& operators) {
|
|
|
|
|
size_t n = operands.size();
|
|
|
|
|
// 简单情况:只有两个操作数
|
|
|
|
|
if (n == 2) {
|
|
|
|
|
return std::to_string(operands[0]) + " " + std::string(1, operators[0]) + " " + std::to_string(operands[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 随机选择括号位置
|
|
|
|
|
size_t l = 1, r = n - 2;
|
|
|
|
|
if (r > l) {
|
|
|
|
|
l = 1 + rand() % (n - 2);
|
|
|
|
|
size_t max_r = n - 2;
|
|
|
|
|
size_t range = max_r - l;
|
|
|
|
|
if (range == 0) {
|
|
|
|
|
r = l + 1;
|
|
|
|
|
} else {
|
|
|
|
|
r = l + 1 + rand() % range;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
l = 1;
|
|
|
|
|
r = 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建带括号的表达式
|
|
|
|
|
std::string expression;
|
|
|
|
|
for (size_t i = 0; i < n; i++) {
|
|
|
|
|
if (i == l) expression += "(";
|
|
|
|
|
expression += std::to_string(operands[i]);
|
|
|
|
|
if (i < operators.size()) {
|
|
|
|
|
expression += " " + std::string(1, operators[i]) + " ";
|
|
|
|
|
}
|
|
|
|
|
if (i == r) expression += ")";
|
|
|
|
|
}
|
|
|
|
|
return expression;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成小学题目:包含加减乘除运算,支持括号
|
|
|
|
|
std::string generateQuestion() override {
|
|
|
|
|
int operandCount = randomNumber(2, 5); // 操作数数量:2-5个
|
|
|
|
|
std::vector<int> operands;
|
|
|
|
|
std::vector<char> operators;
|
|
|
|
|
|
|
|
|
|
// 生成第一个操作数
|
|
|
|
|
operands.push_back(randomNumber(1, 100));
|
|
|
|
|
|
|
|
|
|
// 生成后续操作数和运算符
|
|
|
|
|
for (int i = 0; i < operandCount - 1; i++) {
|
|
|
|
|
int opType = randomNumber(0, 3); // 随机选择运算符类型
|
|
|
|
|
int prev = operands.back();
|
|
|
|
|
int next;
|
|
|
|
|
|
|
|
|
|
switch (opType) {
|
|
|
|
|
case 0: // 加法
|
|
|
|
|
next = randomNumber(1, 100);
|
|
|
|
|
operators.push_back('+');
|
|
|
|
|
operands.push_back(next);
|
|
|
|
|
break;
|
|
|
|
|
case 1: // 减法(确保结果非负)
|
|
|
|
|
next = randomNumber(1, prev);
|
|
|
|
|
operators.push_back('-');
|
|
|
|
|
operands.push_back(next);
|
|
|
|
|
break;
|
|
|
|
|
case 2: // 乘法
|
|
|
|
|
next = randomNumber(1, 100);
|
|
|
|
|
operators.push_back('*');
|
|
|
|
|
operands.push_back(next);
|
|
|
|
|
break;
|
|
|
|
|
case 3: // 除法(确保能整除)
|
|
|
|
|
next = randomNumber(1, 10);
|
|
|
|
|
int result = randomNumber(1, 10);
|
|
|
|
|
int dividend = next * result;
|
|
|
|
|
operands.back() = dividend; // 修改被除数以确保整除
|
|
|
|
|
operators.push_back('/');
|
|
|
|
|
operands.push_back(next);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return buildExpression(operands, operators);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 初中题目生成器:生成初中级别的数学题目(包含平方和开方)
|
|
|
|
|
class MiddleQuestionGenerator : public MathQuestionGenerator {
|
|
|
|
|
public:
|
|
|
|
|
MiddleQuestionGenerator() {}
|
|
|
|
|
|
|
|
|
|
// 生成指定范围内的随机数
|
|
|
|
|
int randomNumber(int min, int max) {
|
|
|
|
|
return rand() % (max - min + 1) + min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成初中题目:包含平方和开方运算
|
|
|
|
|
std::string generateQuestion() override {
|
|
|
|
|
int operandCount = randomNumber(2, 5);
|
|
|
|
|
std::vector<std::string> items;
|
|
|
|
|
bool hasSquareOrRoot = false; // 标记是否已包含平方或开方
|
|
|
|
|
|
|
|
|
|
// 生成操作数项
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
int opType = randomNumber(0, 2);
|
|
|
|
|
// 确保至少有一个平方或开方运算
|
|
|
|
|
if ((!hasSquareOrRoot && i == operandCount - 1) || (opType > 0 && !hasSquareOrRoot)) {
|
|
|
|
|
if (opType == 1) {
|
|
|
|
|
items.push_back(std::to_string(randomNumber(1, 100)) + "²"); // 平方
|
|
|
|
|
} else {
|
|
|
|
|
items.push_back("√" + std::to_string(randomNumber(1, 100))); // 开方
|
|
|
|
|
}
|
|
|
|
|
hasSquareOrRoot = true;
|
|
|
|
|
} else {
|
|
|
|
|
items.push_back(std::to_string(randomNumber(1, 100))); // 普通数字
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成运算符
|
|
|
|
|
std::vector<std::string> ops;
|
|
|
|
|
for (int i = 1; i < operandCount; i++) {
|
|
|
|
|
int opType = randomNumber(0, 3);
|
|
|
|
|
switch (opType) {
|
|
|
|
|
case 0: ops.push_back("+"); break;
|
|
|
|
|
case 1: ops.push_back("-"); break;
|
|
|
|
|
case 2: ops.push_back("*"); break;
|
|
|
|
|
case 3: ops.push_back("/"); break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 找到可以加括号的位置(普通数字位置)
|
|
|
|
|
std::vector<int> validIdx;
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
if (items[i].find("²") == std::string::npos && items[i].find("√") == std::string::npos) {
|
|
|
|
|
validIdx.push_back(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 随机选择括号位置
|
|
|
|
|
int l = 0, r = 0;
|
|
|
|
|
if (validIdx.size() > 1) {
|
|
|
|
|
l = validIdx[rand() % (validIdx.size() - 1)];
|
|
|
|
|
int range = validIdx.size() - (l + 1);
|
|
|
|
|
if (range == 0) {
|
|
|
|
|
r = l + 1;
|
|
|
|
|
} else {
|
|
|
|
|
r = l + 1 + rand() % range;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建表达式
|
|
|
|
|
std::string expr;
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
if (i == l && validIdx.size() > 1) expr += "(";
|
|
|
|
|
expr += items[i];
|
|
|
|
|
if (i == r && validIdx.size() > 1) expr += ")";
|
|
|
|
|
if (i < ops.size()) expr += " " + ops[i] + " ";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果没有括号,给整个表达式加括号
|
|
|
|
|
if (expr.find('(') == std::string::npos && validIdx.size() > 1) expr = "(" + expr + ")";
|
|
|
|
|
return expr;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 高中题目生成器:生成高中级别的数学题目(包含三角函数)
|
|
|
|
|
class HighQuestionGenerator : public MathQuestionGenerator {
|
|
|
|
|
public:
|
|
|
|
|
HighQuestionGenerator() {}
|
|
|
|
|
|
|
|
|
|
// 生成指定范围内的随机数
|
|
|
|
|
int randomNumber(int min, int max) {
|
|
|
|
|
return rand() % (max - min + 1) + min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成高中题目:包含三角函数、平方和开方运算
|
|
|
|
|
std::string generateQuestion() override {
|
|
|
|
|
int operandCount = randomNumber(2, 5);
|
|
|
|
|
std::vector<std::string> items;
|
|
|
|
|
bool hasTrigonometry = false; // 标记是否已包含三角函数
|
|
|
|
|
|
|
|
|
|
// 生成操作数项
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
int opType = randomNumber(0, 5);
|
|
|
|
|
// 确保至少有一个三角函数
|
|
|
|
|
if ((!hasTrigonometry && i == operandCount - 1) || (opType >= 3 && !hasTrigonometry)) {
|
|
|
|
|
int trigType = randomNumber(0, 2);
|
|
|
|
|
switch (trigType) {
|
|
|
|
|
case 0: items.push_back("sin(" + std::to_string(randomNumber(1, 100)) + ")"); break;
|
|
|
|
|
case 1: items.push_back("cos(" + std::to_string(randomNumber(1, 100)) + ")"); break;
|
|
|
|
|
case 2: items.push_back("tan(" + std::to_string(randomNumber(1, 100)) + ")"); break;
|
|
|
|
|
}
|
|
|
|
|
hasTrigonometry = true;
|
|
|
|
|
} else if (opType == 1) {
|
|
|
|
|
items.push_back(std::to_string(randomNumber(1, 100)) + "²"); // 平方
|
|
|
|
|
} else if (opType == 2) {
|
|
|
|
|
items.push_back("√" + std::to_string(randomNumber(1, 100))); // 开方
|
|
|
|
|
} else {
|
|
|
|
|
items.push_back(std::to_string(randomNumber(1, 100))); // 普通数字
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成运算符
|
|
|
|
|
std::vector<std::string> ops;
|
|
|
|
|
for (int i = 1; i < operandCount; i++) {
|
|
|
|
|
int opType = randomNumber(0, 3);
|
|
|
|
|
switch (opType) {
|
|
|
|
|
case 0: ops.push_back("+"); break;
|
|
|
|
|
case 1: ops.push_back("-"); break;
|
|
|
|
|
case 2: ops.push_back("*"); break;
|
|
|
|
|
case 3: ops.push_back("/"); break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 找到可以加括号的位置(非三角函数位置)
|
|
|
|
|
std::vector<int> validIdx;
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
if (items[i].find("sin(") == std::string::npos &&
|
|
|
|
|
items[i].find("cos(") == std::string::npos &&
|
|
|
|
|
items[i].find("tan(") == std::string::npos) {
|
|
|
|
|
validIdx.push_back(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 随机选择括号位置
|
|
|
|
|
int l = -1, r = -1;
|
|
|
|
|
if (validIdx.size() > 1) {
|
|
|
|
|
int idx1 = rand() % validIdx.size();
|
|
|
|
|
int idx2;
|
|
|
|
|
do {
|
|
|
|
|
idx2 = rand() % validIdx.size();
|
|
|
|
|
} while (idx1 == idx2);
|
|
|
|
|
|
|
|
|
|
if (validIdx[idx1] < validIdx[idx2]) {
|
|
|
|
|
l = validIdx[idx1];
|
|
|
|
|
r = validIdx[idx2];
|
|
|
|
|
} else {
|
|
|
|
|
l = validIdx[idx2];
|
|
|
|
|
r = validIdx[idx1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建表达式
|
|
|
|
|
std::string expr;
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
if (i == l) expr += "(";
|
|
|
|
|
expr += items[i];
|
|
|
|
|
if (i == r) expr += ")";
|
|
|
|
|
if (i < ops.size()) expr += " " + ops[i] + " ";
|
|
|
|
|
}
|
|
|
|
|
return expr;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 数学卷子生成主类:管理用户登录、题目生成、文件保存等核心功能
|
|
|
|
|
class MathPaperGenerator {
|
|
|
|
|
private:
|
|
|
|
|
vector<Account> accounts; // 所有账户信息
|
|
|
|
|
string currentUser; // 当前登录用户
|
|
|
|
|
string currentType; // 当前题目类型
|
|
|
|
|
bool isLoggedIn; // 登录状态
|
|
|
|
|
map<string, set<string>> userQuestions; // 用户已生成题目集合(防止重复)
|
|
|
|
|
vector<Account> accounts; // 存储所有账户信息
|
|
|
|
|
string currentUser; // 当前登录用户
|
|
|
|
|
string currentType; // 当前题目类型
|
|
|
|
|
bool isLoggedIn; // 登录状态标记
|
|
|
|
|
map<string, set<string>> userQuestions; // 用户已生成题目记录(用于查重)
|
|
|
|
|
MathQuestionGenerator* questionGenerator; // 题目生成器指针
|
|
|
|
|
|
|
|
|
|
// 创建目录
|
|
|
|
|
bool createDirectory(const string& path) {
|
|
|
|
|
@ -68,7 +337,7 @@ private:
|
|
|
|
|
return files;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 去除字符串首尾空白
|
|
|
|
|
// 去除字符串首尾空白字符
|
|
|
|
|
string trim(const string& str) {
|
|
|
|
|
size_t start = str.find_first_not_of(" \t\n\r");
|
|
|
|
|
size_t end = str.find_last_not_of(" \t\n\r");
|
|
|
|
|
@ -78,44 +347,10 @@ private:
|
|
|
|
|
return str.substr(start, end - start + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成[min, max]范围的随机数
|
|
|
|
|
int randomNumber(int min, int max) {
|
|
|
|
|
return rand() % (max - min + 1) + min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// 构造函数,初始化账户并创建用户文件夹
|
|
|
|
|
MathPaperGenerator() {
|
|
|
|
|
isLoggedIn = false;
|
|
|
|
|
currentUser = "";
|
|
|
|
|
currentType = "";
|
|
|
|
|
|
|
|
|
|
accounts = {
|
|
|
|
|
{"张三1", "123", "小学"},
|
|
|
|
|
{"张三2", "123", "小学"},
|
|
|
|
|
{"张三3", "123", "小学"},
|
|
|
|
|
{"李四1", "123", "初中"},
|
|
|
|
|
{"李四2", "123", "初中"},
|
|
|
|
|
{"李四3", "123", "初中"},
|
|
|
|
|
{"王五1", "123", "高中"},
|
|
|
|
|
{"王五2", "123", "高中"},
|
|
|
|
|
{"王五3", "123", "高中"}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const auto& account : accounts) {
|
|
|
|
|
string folderPath = account.username;
|
|
|
|
|
if (!directoryExists(folderPath)) {
|
|
|
|
|
createDirectory(folderPath);
|
|
|
|
|
}
|
|
|
|
|
loadUserQuestions(account.username);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载用户已生成题目(防止重复)
|
|
|
|
|
void loadUserQuestions(const string& username) {
|
|
|
|
|
userQuestions[username].clear();
|
|
|
|
|
string folderPath = username;
|
|
|
|
|
|
|
|
|
|
if (!directoryExists(folderPath)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
@ -139,307 +374,114 @@ public:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用户登录
|
|
|
|
|
bool login(const string& username, const string& password) {
|
|
|
|
|
for (const auto& account : accounts) {
|
|
|
|
|
if (account.username == username && account.password == password) {
|
|
|
|
|
currentUser = username;
|
|
|
|
|
currentType = account.type;
|
|
|
|
|
isLoggedIn = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 注销
|
|
|
|
|
void logout() {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// 构造函数:初始化账户、创建用户目录、加载历史题目
|
|
|
|
|
MathPaperGenerator() {
|
|
|
|
|
isLoggedIn = false;
|
|
|
|
|
currentUser = "";
|
|
|
|
|
currentType = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 切换题目类型
|
|
|
|
|
bool switchType(const string& type) {
|
|
|
|
|
string trimmedType = trim(type);
|
|
|
|
|
if (trimmedType == "小学" || trimmedType == "初中" || trimmedType == "高中") {
|
|
|
|
|
currentType = trimmedType;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成小学题目(仅加减乘除)
|
|
|
|
|
string generatePrimaryQuestion() {
|
|
|
|
|
int operandCount = randomNumber(2, 5);
|
|
|
|
|
vector<int> operands;
|
|
|
|
|
vector<char> operators;
|
|
|
|
|
|
|
|
|
|
// 先生成第一个操作数
|
|
|
|
|
operands.push_back(randomNumber(1, 100));
|
|
|
|
|
// 初始化预设账户
|
|
|
|
|
accounts = {
|
|
|
|
|
{"张三1", "123", "小学"},
|
|
|
|
|
{"张三2", "123", "小学"},
|
|
|
|
|
{"张三3", "123", "小学"},
|
|
|
|
|
{"李四1", "123", "初中"},
|
|
|
|
|
{"李四2", "123", "初中"},
|
|
|
|
|
{"李四3", "123", "初中"},
|
|
|
|
|
{"王五1", "123", "高中"},
|
|
|
|
|
{"王五2", "123", "高中"},
|
|
|
|
|
{"王五3", "123", "高中"}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount - 1; i++) {
|
|
|
|
|
int opType = randomNumber(0, 3);
|
|
|
|
|
int prev = operands.back();
|
|
|
|
|
int next;
|
|
|
|
|
switch (opType) {
|
|
|
|
|
case 0: // 加法
|
|
|
|
|
next = randomNumber(1, 100);
|
|
|
|
|
operators.push_back('+');
|
|
|
|
|
operands.push_back(next);
|
|
|
|
|
break;
|
|
|
|
|
case 1: // 减法,保证前一个数大于等于后一个数
|
|
|
|
|
next = randomNumber(1, prev);
|
|
|
|
|
operators.push_back('-');
|
|
|
|
|
operands.push_back(next);
|
|
|
|
|
break;
|
|
|
|
|
case 2: // 乘法
|
|
|
|
|
next = randomNumber(1, 100);
|
|
|
|
|
operators.push_back('*');
|
|
|
|
|
operands.push_back(next);
|
|
|
|
|
break;
|
|
|
|
|
case 3: // 除法,保证能整除且结果为正整数
|
|
|
|
|
{
|
|
|
|
|
// 先随机一个除数,不能为0
|
|
|
|
|
next = randomNumber(1, 10);
|
|
|
|
|
int result = randomNumber(1, 10);
|
|
|
|
|
int dividend = next * result;
|
|
|
|
|
// dividend 作为前一个数,next 作为后一个数
|
|
|
|
|
operands.back() = dividend;
|
|
|
|
|
operators.push_back('/');
|
|
|
|
|
operands.push_back(next);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
// 创建用户目录并加载历史题目
|
|
|
|
|
for (const auto& account : accounts) {
|
|
|
|
|
string folderPath = account.username;
|
|
|
|
|
if (!directoryExists(folderPath)) {
|
|
|
|
|
createDirectory(folderPath);
|
|
|
|
|
}
|
|
|
|
|
loadUserQuestions(account.username);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return buildExpression(operands, operators);
|
|
|
|
|
questionGenerator = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成初中题目(加减乘除+平方/根号)
|
|
|
|
|
string generateMiddleQuestion() {
|
|
|
|
|
int operandCount = randomNumber(2, 5);
|
|
|
|
|
vector<int> operands;
|
|
|
|
|
vector<string> operators; // 使用string以支持平方和根号
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
operands.push_back(randomNumber(1, 100));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 确保至少有一个平方或根号
|
|
|
|
|
bool hasSquareOrRoot = false;
|
|
|
|
|
|
|
|
|
|
// 切换题目类型:小学/初中/高中
|
|
|
|
|
bool switchType(const string& type) {
|
|
|
|
|
string trimmedType = trim(type);
|
|
|
|
|
|
|
|
|
|
// 构建表达式
|
|
|
|
|
string expression = "";
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
int opType = randomNumber(0, 3);
|
|
|
|
|
switch (opType) {
|
|
|
|
|
case 0: expression += " + "; break;
|
|
|
|
|
case 1: expression += " - "; break;
|
|
|
|
|
case 2: expression += " * "; break;
|
|
|
|
|
case 3: expression += " / "; break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 随机决定是否添加平方或根号(确保至少有一个)
|
|
|
|
|
int specialOp = randomNumber(0, 3);
|
|
|
|
|
if ((!hasSquareOrRoot && i == operandCount - 1) || (specialOp == 0 && i < operandCount - 1)) {
|
|
|
|
|
// 添加平方或根号
|
|
|
|
|
if (randomNumber(0, 1) == 0) {
|
|
|
|
|
expression += to_string(operands[i]) + "²"; // 平方
|
|
|
|
|
} else {
|
|
|
|
|
expression += "√" + to_string(operands[i]); // 根号
|
|
|
|
|
}
|
|
|
|
|
hasSquareOrRoot = true;
|
|
|
|
|
} else {
|
|
|
|
|
expression += to_string(operands[i]);
|
|
|
|
|
}
|
|
|
|
|
// 清理旧的生成器
|
|
|
|
|
if (questionGenerator) {
|
|
|
|
|
delete questionGenerator;
|
|
|
|
|
questionGenerator = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果还没有平方或根号,强制添加一个
|
|
|
|
|
if (!hasSquareOrRoot) {
|
|
|
|
|
int pos = randomNumber(0, operandCount - 1);
|
|
|
|
|
size_t numStart = 0;
|
|
|
|
|
for (int i = 0; i < pos; i++) {
|
|
|
|
|
size_t opPos = expression.find_first_of("+-*/", numStart);
|
|
|
|
|
if (opPos != string::npos) {
|
|
|
|
|
numStart = opPos + 3; // 跳过运算符和空格
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在指定位置插入平方或根号
|
|
|
|
|
if (randomNumber(0, 1) == 0) {
|
|
|
|
|
expression.insert(numStart, "(");
|
|
|
|
|
size_t insertPos = expression.find(' ', numStart);
|
|
|
|
|
if (insertPos == string::npos) {
|
|
|
|
|
insertPos = expression.size();
|
|
|
|
|
}
|
|
|
|
|
expression.insert(insertPos, ")²");
|
|
|
|
|
} else {
|
|
|
|
|
expression.insert(numStart, "√(");
|
|
|
|
|
size_t insertPos = expression.find(' ', numStart);
|
|
|
|
|
if (insertPos == string::npos) {
|
|
|
|
|
insertPos = expression.size();
|
|
|
|
|
}
|
|
|
|
|
expression.insert(insertPos, ")");
|
|
|
|
|
}
|
|
|
|
|
// 根据类型创建相应的题目生成器
|
|
|
|
|
if (trimmedType == "小学") {
|
|
|
|
|
currentType = trimmedType;
|
|
|
|
|
questionGenerator = new PrimaryQuestionGenerator();
|
|
|
|
|
return true;
|
|
|
|
|
} else if (trimmedType == "初中") {
|
|
|
|
|
currentType = trimmedType;
|
|
|
|
|
questionGenerator = new MiddleQuestionGenerator();
|
|
|
|
|
return true;
|
|
|
|
|
} else if (trimmedType == "高中") {
|
|
|
|
|
currentType = trimmedType;
|
|
|
|
|
questionGenerator = new HighQuestionGenerator();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return expression;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成高中题目(加减乘除+平方/根号+三角函数)
|
|
|
|
|
string generateHighQuestion() {
|
|
|
|
|
int operandCount = randomNumber(2, 5);
|
|
|
|
|
vector<int> operands;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
operands.push_back(randomNumber(1, 100));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 确保至少有一个三角函数
|
|
|
|
|
bool hasTrigonometry = false;
|
|
|
|
|
|
|
|
|
|
// 构建表达式
|
|
|
|
|
string expression = "";
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
int opType = randomNumber(0, 3);
|
|
|
|
|
switch (opType) {
|
|
|
|
|
case 0: expression += " + "; break;
|
|
|
|
|
case 1: expression += " - "; break;
|
|
|
|
|
case 2: expression += " * "; break;
|
|
|
|
|
case 3: expression += " / "; break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 随机决定是否添加平方、根号或三角函数
|
|
|
|
|
int specialOp = randomNumber(0, 5);
|
|
|
|
|
if ((!hasTrigonometry && i == operandCount - 1) || specialOp >= 2) {
|
|
|
|
|
// 添加特殊运算
|
|
|
|
|
int opChoice = randomNumber(0, 4);
|
|
|
|
|
switch (opChoice) {
|
|
|
|
|
case 0: // 平方
|
|
|
|
|
expression += to_string(operands[i]) + "²";
|
|
|
|
|
break;
|
|
|
|
|
case 1: // 根号
|
|
|
|
|
expression += "√" + to_string(operands[i]);
|
|
|
|
|
break;
|
|
|
|
|
case 2: // sin
|
|
|
|
|
expression += "sin(" + to_string(operands[i]) + ")";
|
|
|
|
|
hasTrigonometry = true;
|
|
|
|
|
break;
|
|
|
|
|
case 3: // cos
|
|
|
|
|
expression += "cos(" + to_string(operands[i]) + ")";
|
|
|
|
|
hasTrigonometry = true;
|
|
|
|
|
break;
|
|
|
|
|
case 4: // tan
|
|
|
|
|
expression += "tan(" + to_string(operands[i]) + ")";
|
|
|
|
|
hasTrigonometry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
expression += to_string(operands[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果还没有三角函数,强制添加一个
|
|
|
|
|
if (!hasTrigonometry) {
|
|
|
|
|
int pos = randomNumber(0, operandCount - 1);
|
|
|
|
|
size_t numStart = 0;
|
|
|
|
|
for (int i = 0; i < pos; i++) {
|
|
|
|
|
size_t opPos = expression.find_first_of("+-*/", numStart);
|
|
|
|
|
if (opPos != string::npos) {
|
|
|
|
|
numStart = opPos + 3; // 跳过运算符和空格
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在指定位置插入三角函数
|
|
|
|
|
int trigChoice = randomNumber(0, 2);
|
|
|
|
|
size_t insertPos;
|
|
|
|
|
switch (trigChoice) {
|
|
|
|
|
case 0:
|
|
|
|
|
expression.insert(numStart, "sin(");
|
|
|
|
|
insertPos = expression.find(' ', numStart);
|
|
|
|
|
if (insertPos == string::npos) {
|
|
|
|
|
insertPos = expression.size();
|
|
|
|
|
}
|
|
|
|
|
expression.insert(insertPos, ")");
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
expression.insert(numStart, "cos(");
|
|
|
|
|
insertPos = expression.find(' ', numStart);
|
|
|
|
|
if (insertPos == string::npos) {
|
|
|
|
|
insertPos = expression.size();
|
|
|
|
|
}
|
|
|
|
|
expression.insert(insertPos, ")");
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
expression.insert(numStart, "tan(");
|
|
|
|
|
insertPos = expression.find(' ', numStart);
|
|
|
|
|
if (insertPos == string::npos) {
|
|
|
|
|
insertPos = expression.size();
|
|
|
|
|
}
|
|
|
|
|
expression.insert(insertPos, ")");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// 用户登录验证
|
|
|
|
|
bool login(const string& username, const string& password) {
|
|
|
|
|
for (const auto& account : accounts) {
|
|
|
|
|
if (account.username == username && account.password == password) {
|
|
|
|
|
currentUser = username;
|
|
|
|
|
currentType = account.type;
|
|
|
|
|
isLoggedIn = true;
|
|
|
|
|
switchType(currentType); // 根据用户类型初始化题目生成器
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return expression;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建表达式
|
|
|
|
|
string buildExpression(const vector<int>& operands, const vector<char>& operators) {
|
|
|
|
|
// 构建表达式,保证顺序与生成一致
|
|
|
|
|
string expression = to_string(operands[0]);
|
|
|
|
|
for (size_t i = 0; i < operators.size(); i++) {
|
|
|
|
|
expression += " " + string(1, operators[i]) + " " + to_string(operands[i + 1]);
|
|
|
|
|
}
|
|
|
|
|
return expression;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 判断题目是否重复
|
|
|
|
|
bool isQuestionDuplicate(const string& question) {
|
|
|
|
|
return userQuestions[currentUser].find(question) != userQuestions[currentUser].end();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成指定数量题目
|
|
|
|
|
|
|
|
|
|
// 生成指定数量的题目
|
|
|
|
|
vector<string> generateQuestions(int count) {
|
|
|
|
|
vector<string> questions;
|
|
|
|
|
set<string> generatedSet;
|
|
|
|
|
set<string> generatedSet; // 本次生成题目的临时集合
|
|
|
|
|
int attempts = 0;
|
|
|
|
|
const int MAX_ATTEMPTS = count * 10;
|
|
|
|
|
const int MAX_ATTEMPTS = count * 10; // 最大尝试次数防止无限循环
|
|
|
|
|
|
|
|
|
|
// 生成不重复的题目
|
|
|
|
|
while (questions.size() < count && attempts < MAX_ATTEMPTS) {
|
|
|
|
|
string question;
|
|
|
|
|
|
|
|
|
|
if (currentType == "小学") {
|
|
|
|
|
question = generatePrimaryQuestion();
|
|
|
|
|
} else if (currentType == "初中") {
|
|
|
|
|
question = generateMiddleQuestion();
|
|
|
|
|
} else if (currentType == "高中") {
|
|
|
|
|
question = generateHighQuestion();
|
|
|
|
|
if (questionGenerator) {
|
|
|
|
|
question = questionGenerator->generateQuestion();
|
|
|
|
|
} else {
|
|
|
|
|
question = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查题目是否重复
|
|
|
|
|
if (!isQuestionDuplicate(question) && generatedSet.find(question) == generatedSet.end()) {
|
|
|
|
|
questions.push_back(question);
|
|
|
|
|
generatedSet.insert(question);
|
|
|
|
|
userQuestions[currentUser].insert(question);
|
|
|
|
|
userQuestions[currentUser].insert(question); // 添加到用户历史记录
|
|
|
|
|
}
|
|
|
|
|
attempts++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果无法生成足够的不重复题目,用简单题目填充
|
|
|
|
|
// 如果无法生成足够的不重复题目,使用备用方案
|
|
|
|
|
while (questions.size() < count) {
|
|
|
|
|
string question;
|
|
|
|
|
if (currentType == "小学") {
|
|
|
|
|
question = to_string(randomNumber(1, 100)) + " + " + to_string(randomNumber(1, 100));
|
|
|
|
|
question = to_string(rand() % 100 + 1) + " + " + to_string(rand() % 100 + 1);
|
|
|
|
|
} else if (currentType == "初中") {
|
|
|
|
|
question = to_string(randomNumber(1, 100)) + "² + " + to_string(randomNumber(1, 100));
|
|
|
|
|
question = to_string(rand() % 100 + 1) + "² + " + to_string(rand() % 100 + 1);
|
|
|
|
|
} else {
|
|
|
|
|
question = "sin(" + to_string(randomNumber(1, 100)) + ") + " + to_string(randomNumber(1, 100));
|
|
|
|
|
question = "sin(" + to_string(rand() % 100 + 1) + ") + " + to_string(rand() % 100 + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isQuestionDuplicate(question)) {
|
|
|
|
|
@ -450,102 +492,76 @@ public:
|
|
|
|
|
|
|
|
|
|
return questions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存题目到文件
|
|
|
|
|
void saveQuestions(const vector<string>& questions) {
|
|
|
|
|
time_t now = time(nullptr);
|
|
|
|
|
tm* localTime = localtime(&now);
|
|
|
|
|
|
|
|
|
|
stringstream filename;
|
|
|
|
|
filename << setfill('0')
|
|
|
|
|
<< localTime->tm_year + 1900 << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_mon + 1 << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_mday << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_hour << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_min << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_sec << ".txt";
|
|
|
|
|
|
|
|
|
|
string filepath = currentUser + "/" + filename.str();
|
|
|
|
|
ofstream file(filepath, ios::binary);
|
|
|
|
|
|
|
|
|
|
if (file.is_open()) {
|
|
|
|
|
unsigned char bom[] = {0xEF, 0xBB, 0xBF};
|
|
|
|
|
file.write((char*)bom, 3);
|
|
|
|
|
for (size_t i = 0; i < questions.size(); i++) {
|
|
|
|
|
string line = to_string(i + 1) + ". " + questions[i] + "\n";
|
|
|
|
|
file.write(line.c_str(), line.size());
|
|
|
|
|
if (i < questions.size() - 1) {
|
|
|
|
|
file.write("\n", 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
file.close();
|
|
|
|
|
cout << "题目已保存到: " << filepath << endl;
|
|
|
|
|
} else {
|
|
|
|
|
cout << "文件保存失败!" << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查题目是否重复
|
|
|
|
|
bool isQuestionDuplicate(const string& question) {
|
|
|
|
|
return userQuestions[currentUser].find(question) != userQuestions[currentUser].end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// 提示用户输入题目数量或切换类型
|
|
|
|
|
void promptTypeAndCount() {
|
|
|
|
|
cout << endl << "准备生成" << currentType << "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录)" << endl;
|
|
|
|
|
cout << "或者输入\"切换为小学/初中/高中\"来切换题目类型: ";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理用户输入
|
|
|
|
|
void processInput() {
|
|
|
|
|
string input;
|
|
|
|
|
getline(cin, input);
|
|
|
|
|
|
|
|
|
|
input = trim(input);
|
|
|
|
|
|
|
|
|
|
if (input == "-1") {
|
|
|
|
|
logout();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input.find("切换为") == 0) {
|
|
|
|
|
string type = input.substr(9);
|
|
|
|
|
type = trim(type);
|
|
|
|
|
|
|
|
|
|
if (switchType(type)) {
|
|
|
|
|
cout << "切换成功!当前类型为:" << currentType << endl;
|
|
|
|
|
cout << "准备生成" << currentType << "数学题目,请输入生成题目数量: ";
|
|
|
|
|
getline(cin, input);
|
|
|
|
|
processCountInput(input);
|
|
|
|
|
} else {
|
|
|
|
|
cout << "请输入小学、初中和高中三个选项中的一个" << endl;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
// 处理类型切换命令
|
|
|
|
|
void handleSwitchType(const string& type) {
|
|
|
|
|
if (switchType(type)) {
|
|
|
|
|
cout << "切换成功!当前类型为:" << currentType << endl;
|
|
|
|
|
promptTypeAndCount();
|
|
|
|
|
string input;
|
|
|
|
|
getline(cin, input);
|
|
|
|
|
processCountInput(input);
|
|
|
|
|
} else {
|
|
|
|
|
cout << "请输入小学、初中和高中三个选项中的一个" << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
processCountInput(input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理题目数量输入
|
|
|
|
|
void processCountInput(const string& input) {
|
|
|
|
|
//*
|
|
|
|
|
// 处理数量输入
|
|
|
|
|
void handleCountInput(const string& trimmedInput) {
|
|
|
|
|
try {
|
|
|
|
|
//*/
|
|
|
|
|
int count = stoi(input);
|
|
|
|
|
int count = stoi(trimmedInput);
|
|
|
|
|
if (count >= 10 && count <= 30) {
|
|
|
|
|
vector<string> questions = generateQuestions(count);
|
|
|
|
|
saveQuestions(questions);
|
|
|
|
|
} else {
|
|
|
|
|
cout << "题目数量应在10-30之间" << endl;
|
|
|
|
|
}
|
|
|
|
|
//*
|
|
|
|
|
} catch (const exception& e) {
|
|
|
|
|
cout << "请输入有效的数字" << endl;
|
|
|
|
|
}
|
|
|
|
|
//*/
|
|
|
|
|
|
|
|
|
|
cout << "请输入有效的数字或切换命令" << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 主运行入口
|
|
|
|
|
// 保存题目到文件
|
|
|
|
|
void saveQuestionsToFile(const string& filepath, const vector<string>& questions) {
|
|
|
|
|
ofstream file(filepath);
|
|
|
|
|
if (file.is_open()) {
|
|
|
|
|
for (size_t i = 0; i < questions.size(); i++) {
|
|
|
|
|
file << (i + 1) << ". " << questions[i];
|
|
|
|
|
if (i < questions.size() - 1) file << "\n\n"; // 题目之间空一行
|
|
|
|
|
}
|
|
|
|
|
file.close();
|
|
|
|
|
cout << "题目已保存到: " << filepath << endl;
|
|
|
|
|
} else {
|
|
|
|
|
cout << "文件保存失败! 请检查目录权限。" << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// 主运行循环:程序入口点
|
|
|
|
|
void run() {
|
|
|
|
|
srand(time(nullptr));
|
|
|
|
|
srand(time(nullptr)); // 初始化随机数种子
|
|
|
|
|
|
|
|
|
|
cout << "=== 中小学数学卷子自动生成程序 ===" << endl;
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
if (!isLoggedIn) {
|
|
|
|
|
// 登录流程
|
|
|
|
|
cout << "请输入用户名和密码(用空格隔开): ";
|
|
|
|
|
string username, password;
|
|
|
|
|
cin >> username >> password;
|
|
|
|
|
cin.ignore();
|
|
|
|
|
cin.ignore(); // 清除输入缓冲区
|
|
|
|
|
|
|
|
|
|
if (login(username, password)) {
|
|
|
|
|
cout << "登录成功!当前选择为" << currentType << "出题" << endl;
|
|
|
|
|
@ -555,18 +571,78 @@ public:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 登录后的主循环
|
|
|
|
|
while (isLoggedIn) {
|
|
|
|
|
cout << endl << "准备生成" << currentType << "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录)" << endl;
|
|
|
|
|
cout << "或者输入\"切换为小学/初中/高中\"来切换题目类型: ";
|
|
|
|
|
promptTypeAndCount();
|
|
|
|
|
processInput();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理用户输入
|
|
|
|
|
void processInput() {
|
|
|
|
|
string input;
|
|
|
|
|
getline(cin, input);
|
|
|
|
|
input = trim(input);
|
|
|
|
|
|
|
|
|
|
if (input == "-1") {
|
|
|
|
|
logout(); // 退出当前用户
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input.find("切换为") == 0) {
|
|
|
|
|
string type = input.substr(9);
|
|
|
|
|
type = trim(type);
|
|
|
|
|
handleSwitchType(type);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
processCountInput(input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理数量输入或切换命令
|
|
|
|
|
void processCountInput(const string& input) {
|
|
|
|
|
string trimmedInput = trim(input);
|
|
|
|
|
|
|
|
|
|
if (trimmedInput.find("切换为") == 0) {
|
|
|
|
|
string type = trimmedInput.substr(9);
|
|
|
|
|
type = trim(type);
|
|
|
|
|
handleSwitchType(type);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleCountInput(trimmedInput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存题目到文件(带时间戳的文件名)
|
|
|
|
|
void saveQuestions(const vector<string>& questions) {
|
|
|
|
|
time_t now = time(nullptr);
|
|
|
|
|
tm* localTime = localtime(&now);
|
|
|
|
|
|
|
|
|
|
stringstream filename;
|
|
|
|
|
filename << setfill('0')
|
|
|
|
|
<< localTime->tm_year + 1900 << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_mon + 1 << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_mday << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_hour << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_min << "-"
|
|
|
|
|
<< setw(2) << localTime->tm_sec << ".txt";
|
|
|
|
|
|
|
|
|
|
string filepath = currentUser + "/" + filename.str();
|
|
|
|
|
saveQuestionsToFile(filepath, questions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 注销当前用户
|
|
|
|
|
void logout() {
|
|
|
|
|
isLoggedIn = false;
|
|
|
|
|
currentUser = "";
|
|
|
|
|
currentType = "";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 程序主函数:创建生成器实例并启动程序
|
|
|
|
|
int main() {
|
|
|
|
|
|
|
|
|
|
MathPaperGenerator generator;
|
|
|
|
|
generator.run();
|
|
|
|
|
generator.run(); // 启动主循环
|
|
|
|
|
return 0;
|
|
|
|
|
}
|