Compare commits

...

1 Commits

Author SHA1 Message Date
Your Name c8a41c3a01 中小学生试卷自动生成程序
4 months ago

@ -0,0 +1,3 @@
# self-project
Windows shell可正常运行

@ -0,0 +1,514 @@
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <ctime>
#include <fstream>
//第五版问题:?未知
#include <set>
#include <dirent.h>
#ifdef _WIN32
#include <direct.h>
#include <windows.h>
#else
#include <sys/stat.h>
#include <sys/types.h>
#endif
using namespace std;
// 用户类型枚举
enum UserType {
PRIMARY, // 小学
JUNIOR, // 初中
SENIOR, // 高中
UNKNOWN //未知
};
// 用户结构体
struct User {
string username;
string password;
UserType type;
};
//加载所有历史题目,便于查重
set<string> loadExistingQuestions(const string& userDir) {
set<string> existingQuestions;//使用集合避免重复
#ifdef _WIN32
// Windows版本的目录遍历
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile((userDir + "\\*.txt").c_str(), &findFileData);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
string filename = userDir + "\\" + findFileData.cFileName;
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) {
string question = line.substr(dotPos + 2); // 跳过". "
existingQuestions.insert(question);
}
}
}
file.close();
}
} while (FindNextFile(hFind, &findFileData));
FindClose(hFind);
}
#endif
return existingQuestions;
}
//检查题目是否唯一
bool isQuestionUnique(const string& question, const set<string>& existingQuestions) {
return existingQuestions.find(question) == existingQuestions.end();
}
//字符串分割函数
vector<string> split(const string& str, char delimiter) {
vector<string> tokens;
string token;
istringstream tokenStream(str);
while (getline(tokenStream, token, delimiter)) {
if (!token.empty()) {
tokens.push_back(token);
}
}
return tokens;
}
// 字符串修剪函数 - 去除字符串首尾的空白字符
string trim(const string& str) {
size_t start = str.find_first_not_of(" \t\n\r");
if (start == string::npos) return "";
size_t end = str.find_last_not_of(" \t\n\r");
return str.substr(start, end - start + 1);
}
// 字符串转小写函数 - 将字符串转换为小写形式
string toLower(const string& str) {
string result = str;
transform(result.begin(), result.end(), result.begin(), ::tolower);
return result;
}
//数字验证函数
bool isNumber(const string& str) {
if (str.empty()) return false;
if (str == "-1") return true;
for (size_t i = 0; i < str.length(); i++) {
if (!isdigit(str[i])) return false;
}
return true;
}
// 获取当前时间字符串 - 生成格式为"年-月-日-时-分-秒"的时间字符串
string getCurrentTimeString() {
time_t now = time(0);
struct tm* localTime = localtime(&now);
char buffer[20];
strftime(buffer, sizeof(buffer), "%Y-%m-%d-%H-%M-%S", localTime);
return string(buffer);
}
//创建目录函数
bool createDirectory(const string& path) {
#ifdef _WIN32
return _mkdir(path.c_str()) == 0;
#else
return mkdir(path.c_str(), 0755) == 0;
#endif
}
//用户类型转中文字符串
string getUserTypeString(UserType type) {
switch (type) {
case PRIMARY: return "小学";
case JUNIOR: return "初中";
case SENIOR: return "高中";
default: return "未知";
}
}
//将中文字符串转换为对应枚举
UserType parseUserType(const string& typeStr) {
string lowerType = toLower(typeStr);
if (lowerType == "小学") return PRIMARY;
if (lowerType == "初中") return JUNIOR;
if (lowerType == "高中") return SENIOR;
return UNKNOWN;
}
// 用户管理类
class UserManager {
private:
vector<User> users;
void initializeUsers() {
// 小学账号
users.push_back((User){"张三1", "123", PRIMARY});
users.push_back((User){"张三2", "123", PRIMARY});
users.push_back((User){"张三3", "123", PRIMARY});
// 初中账号
users.push_back((User){"李四1", "123", JUNIOR});
users.push_back((User){"李四2", "123", JUNIOR});
users.push_back((User){"李四3", "123", JUNIOR});
// 高中账号
users.push_back((User){"王五1", "123", SENIOR});
users.push_back((User){"王五2", "123", SENIOR});
users.push_back((User){"王五3", "123", SENIOR});
}
public:
//构造函数初始化
UserManager() {
initializeUsers();
}
//验证用户名密码是否正确
User* authenticate(const string& username, const string& password) {
for (size_t i = 0; i < users.size(); i++) {
if (users[i].username == username && users[i].password == password) {
return &users[i];
}
}
return NULL;
}
};
//抽象题目生成器接口类,定义基本操作
class IQuestionGenerator {
public:
virtual ~IQuestionGenerator() {}
virtual void setUserType(UserType type) = 0;
virtual string generateQuestion() = 0;
virtual vector<string> generatePaper(int questionCount, const string& username) = 0;
};
// 具体题目生成器实现类,继承接口
class QuestionGenerator : public IQuestionGenerator {
private:
UserType currentType;
set<string> existingQuestions;//历史题目集合用于查重
int generateOperand() {
return rand() % 100 + 1;//操作数范围1-100
}
//生成表达式
string generateExpression(int operandCount) {
string operators[] = {"+", "-", "*", "/"};
vector<int> operands;//存放操作数
for (int i = 0; i < operandCount; i++) {
operands.push_back(generateOperand());
}
stringstream ss;
ss << operands[0];
for (int i = 1; i < operandCount; i++) {
string op = operators[rand() % 4];//随机运算符
ss << " " << op << " " << operands[i];
}
return ss.str();
}
//生成小学题目
string generatePrimaryQuestion() {
int operandCount = rand() % 4 + 2; // 小学要求2-5个操作数
return generateExpression(operandCount);
}
//生成初中题目
string generateJuniorQuestion() {
int operandCount = rand() % 5 + 1;
string expression = generateExpression(operandCount);
// 确保至少有一个平方或开根号
if (rand() % 2 == 0) {
return expression +"^2"; // 平方
} else {
return "" + expression; // 开根号
}
}
//生成高中题目
string generateSeniorQuestion() {
int operandCount = rand() % 5 + 1;
string expression = generateExpression(operandCount);
// 确保至少有一个三角函数
string trigFunctions[] = {"sin", "cos", "tan"};
string trigFunc = trigFunctions[rand() % 3];
return trigFunc + "(" + expression + ")";
}
public:
//构造函数,初始化随机种子
QuestionGenerator() : currentType(PRIMARY) {
srand(time(0));
}
//设置用户类型
void setUserType(UserType type) override {//重载
currentType = type;
}
// 设置历史题目,便于查重
void setExistingQuestions(const set<string>& questions) {
existingQuestions = questions;
}
//生成单个题目
string generateQuestion() override {
string question;
int attempts = 0;
const int MAX_ATTEMPTS = 100; // 防止无限循环
// 循环生成题目直到生成不重复的题目或达到最大尝试次数
do {
switch (currentType) {
case PRIMARY:
question = generatePrimaryQuestion();
break;
case JUNIOR:
question = generateJuniorQuestion();
break;
case SENIOR:
question = generateSeniorQuestion();
break;
default:
question = generatePrimaryQuestion();
}
attempts++;
} while (!isQuestionUnique(question, existingQuestions) && attempts < MAX_ATTEMPTS);
// 将新题目添加到历史记录中
existingQuestions.insert(question);
return question;
}
//生成整张试卷(指定数量题目)
vector<string> generatePaper(int questionCount, const string& username) override {//重载
vector<string> paper;
for (int i = 1; i <= questionCount; i++) {
string question = generateQuestion();
stringstream ss;
ss << i << ". " << question;//题号
paper.push_back(ss.str());
}
return paper;
}
};
// 试卷系统主类
class PaperSystem {
private:
UserManager userManager;
QuestionGenerator questionGenerator;
User* currentUser;
string currentDirectory;
set<string> existingQuestions;//登录时加载历史题目
//用户登录函数
bool login() {
cout << "请输入用户名和密码(用空格隔开):";
string input;
getline(cin, input);
vector<string> tokens = split(input, ' ');
if (tokens.size() != 2) {
cout << "请输入正确的用户名、密码" << endl;
return false;
}
string username = trim(tokens[0]);
string password = trim(tokens[1]);
currentUser = userManager.authenticate(username, password);
if (currentUser == NULL) {
cout << "请输入正确的用户名、密码" << endl;
return false;
}
questionGenerator.setUserType(currentUser->type);
// 加载历史题目用于查重
string userDir = currentDirectory + "/" + currentUser->username;
createDirectory(userDir);
existingQuestions = loadExistingQuestions(userDir);
questionGenerator.setExistingQuestions(existingQuestions);
cout << "当前选择为" << getUserTypeString(currentUser->type) << "出题" << endl;
return true;
}
//处理命令行的"切换为xx"命令
bool processSwitchCommand(const string& input) {
if (input.length() < 7) return false; // "切换为XX" 至少7个字符
string prefix = input.substr(0, 6);
if (toLower(prefix) != "切换为") return false;
string typeStr = trim(input.substr(6));
UserType newType = parseUserType(typeStr);
//切换类型不合法
if (newType == UNKNOWN) {
cout << "请输入小学、初中和高中三个选项中的一个" << endl;
return true; // 命令格式正确但内容错误
}
// 永久切换用户类型
currentUser->type = newType;
questionGenerator.setUserType(newType);
cout << "准备生成" << getUserTypeString(newType) << "数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录";
return true;
}
// 处理输入并验证题目数量
int getValidQuestionCount() {
string input;
getline(cin, input);
input = trim(input);
if (processSwitchCommand(input)) {
return -3; // 特殊代码表示切换类型
}
if (input == "-1") {
return -1; // 退出代码
}
if (!isNumber(input)) {
cout << "请输入有效的数字!" << endl;
return -2;
}
int questionCount = atoi(input.c_str());
if (questionCount < 10 || questionCount > 30) {
cout << "题目数量范围是10-30请重新输入。" << endl;
return -2;
}
return questionCount;
}
// 生成并保存试卷,更新历史题目,便于查重
void generateAndSavePaper(int questionCount) {
vector<string> paper = questionGenerator.generatePaper(questionCount, currentUser->username);
string filename = getCurrentTimeString() + ".txt";
string userDir = currentDirectory + "/" + currentUser->username;
createDirectory(userDir);
string fullPath = userDir + "/" + filename;
savePaperToFile(paper, fullPath);
cout << "试卷已生成并保存到: " << fullPath << endl;
// 更新历史题目记录(从文件中重新加载,确保包含最新题目)
existingQuestions = loadExistingQuestions(userDir);
questionGenerator.setExistingQuestions(existingQuestions);
}
//
void generatePaper() {
cout << "准备生成" << getUserTypeString(currentUser->type)
<< "数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录";
while (true) {
int questionCount = getValidQuestionCount();
if (questionCount == -3) { // 切换类型
continue;
}
if (questionCount == -2) { // 需要重新输入
cout << "准备生成" << getUserTypeString(currentUser->type)
<< "数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录";
continue;
}
if (questionCount == -1) { // 退出
currentUser = NULL;
return;
}
// 有效的题目数量
generateAndSavePaper(questionCount);
break;
}
}
//保存试卷到文件 - 将题目列表写入文件
void savePaperToFile(const vector<string>& paper, const string& filename) {
ofstream file(filename.c_str());
if (file.is_open()) {
for (size_t i = 0; i < paper.size(); i++) {
file << paper[i] << endl;
if (i < paper.size() - 1) {
file << endl; // 题目之间空一行
}
}
file.close();
}
}
void userSession() {
while (currentUser != NULL) {
generatePaper();
}
}
public:
PaperSystem() : currentUser(NULL) {
currentDirectory = "papers";
createDirectory(currentDirectory);
}
//系统主循环-程序入口
void run() {
cout << "=== 中小学数学卷子自动生成程序 ===" << endl;
while (true) {
if (currentUser == NULL) {
if (!login()) {
continue;
}
}
userSession();
}
}
};
int main() {
PaperSystem system;
system.run();
return 0;
}
Loading…
Cancel
Save