9.29 #2

Merged
hnu202326010226 merged 0 commits from develop into main 5 months ago

@ -1,2 +0,0 @@
# louis_program

@ -0,0 +1,10 @@
在登陆系统额外设置了登陆输错三次直接结束程序的功能
首先生成存放账号的文件夹,若账号存在,则输出“用户文件夹已存在”
若不存在,则创建并输出“文件夹创建成功”
每次出题将在生成每一个题目时查重若未重复则显示“成功生成第x道题目”
生成结束后显示“题目已保存到文件xxxxxx”

@ -0,0 +1,127 @@
#include "FileHandler.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
#include <windows.h>
#include <direct.h>
#include <ctime>
#include <cstdio>
using namespace std;
void FileHandler::removeSpaces(string& str) {
str.erase(remove(str.begin(), str.end(), ' '), str.end());
}
string FileHandler::getBaseDirectory() {
return ".\\数学题目库";
}
void FileHandler::initializeBaseDirectory() {
string baseDir = getBaseDirectory();
// 检查基础目录是否存在
if (_access(baseDir.c_str(), 0) != 0) {
cout << "正在创建基础目录:" << baseDir << endl;
if (_mkdir(baseDir.c_str()) == 0) {
cout << "基础目录创建成功" << endl;
} else {
cout << "警告:无法创建基础目录" << endl;
}
}
}
string FileHandler::getCurrentTimeString() {
time_t now = time(nullptr);
tm* t = localtime(&now);
char timeStr[50];
sprintf(timeStr, "%04d-%02d-%02d-%02d-%02d-%02d",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
return string(timeStr);
}
bool FileHandler::createUserDirectory(const string& username) {
initializeBaseDirectory();
string dirPath = getBaseDirectory() + "\\" + username;
// 检查文件夹是否已存在
if (_access(dirPath.c_str(), 0) == 0) {
return false; // 文件夹已存在
}
// 创建新文件夹
if (_mkdir(dirPath.c_str()) == 0) {
return true; // 创建成功
} else {
return false; // 创建失败
}
}
void FileHandler::saveQuestionsToFile(const string& userType, int count,
const string& username, const string& questions) {
string timeStr = getCurrentTimeString();
string filename = timeStr + ".txt";
string filepath = getBaseDirectory() + "\\" + username + "\\" + filename;
// 打开文件进行写入
FILE* file = fopen(filepath.c_str(), "w");
if (file == NULL) {
printf("错误:无法创建文件 %s\n", filepath.c_str());
return;
}
// 写入文件头信息
fprintf(file, "用户:%s\n", username.c_str());
fprintf(file, "题目类型:%s\n", userType.c_str());
fprintf(file, "题目数量:%d\n", count);
fprintf(file, "生成时间:%s\n", timeStr.c_str());
fprintf(file, "============================\n\n");
// 写入题目内容
fprintf(file, "%s", questions.c_str());
fclose(file);
printf("题目已保存到文件:%s\n", filepath.c_str());
}
void FileHandler::clearInputBuffer() {
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
void FileHandler::trimString(string& str) {
// 去除前导空格
size_t start = str.find_first_not_of(" \t\n\r");
if (start != string::npos) {
str = str.substr(start);
}
// 去除尾部空格
size_t end = str.find_last_not_of(" \t\n\r");
if (end != string::npos) {
str = str.substr(0, end + 1);
}
}
bool FileHandler::isNumber(const string& str) {
if (str.empty()) return false;
size_t start = 0;
if (str[0] == '-') {
start = 1;
if (str.length() == 1) return false;
}
for (size_t i = start; i < str.length(); i++) {
if (!isdigit(str[i])) {
return false;
}
}
return true;
}

@ -0,0 +1,22 @@
#ifndef FILEHANDLER_H
#define FILEHANDLER_H
#include <string>
class FileHandler {
public:
void removeSpaces(std::string& str);
void saveQuestionsToFile(const std::string& userType, int count,
const std::string& username, const std::string& questions);
std::string getCurrentTimeString();
bool createUserDirectory(const std::string& username);
void clearInputBuffer();
void trimString(std::string& str);
bool isNumber(const std::string& str);
private:
std::string getBaseDirectory();
void initializeBaseDirectory();
};
#endif

@ -0,0 +1,238 @@
#include "QuestionGenerator.h"
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <algorithm>
#include "FileHandler.h"
using namespace std;
FileHandler handler1;
// QuestionGenerator 基类实现
void QuestionGenerator::generateBaseElements() {
// 随机操作数数量1-5个
operandCount = rand() % 5 + 1;
// 生成操作数
for (int i = 0; i < operandCount; i++) {
operands[i] = rand() % 100 + 1;
}
// 生成运算符
for (int i = 0; i < operandCount - 1; i++) {
char availableOps[] = {'+', '-', '*', '/'};
operators[i] = availableOps[rand() % 4];
// 如果是除法避免除0即可不要求整除
if (operators[i] == '/' && operands[i+1] == 0) {
operands[i+1] = 1;
}
}
}
string QuestionGenerator::buildBaseQuestion() {
string question;
char temp[50];
for (int i = 0; i < operandCount; i++) {
sprintf(temp, "%d", operands[i]);
question += temp;
if (i < operandCount - 1) {
sprintf(temp, " %c ", operators[i]);
question += temp;
}
}
question += " =";
return question;
}
// PrimaryQuestionGenerator 实现
string PrimaryQuestionGenerator::generateQuestion() {
generateBaseElements();
return buildBaseQuestion();
}
// MiddleSchoolQuestionGenerator 实现
string MiddleSchoolQuestionGenerator::generateQuestion() {
generateBaseElements();
// 确保至少有一个平方或开根号
bool hasSpecialOp = false;
int specialOpIndex = rand() % operandCount;
int specialOpType = rand() % 2; // 0:平方, 1:开根号
string question;
char temp[50];
for (int i = 0; i < operandCount; i++) {
if (i == specialOpIndex && !hasSpecialOp) {
if (specialOpType == 0) {
sprintf(temp, "%d²", operands[i]);
} else {
sprintf(temp, "√%d", operands[i]);
}
question += temp;
hasSpecialOp = true;
} else {
sprintf(temp, "%d", operands[i]);
question += temp;
}
if (i < operandCount - 1) {
sprintf(temp, " %c ", operators[i]);
question += temp;
}
}
question += " =";
return question;
}
// HighSchoolQuestionGenerator 实现
string HighSchoolQuestionGenerator::generateQuestion() {
generateBaseElements();
// 确保至少有一个三角函数
bool hasTrigOp = false;
int trigOpIndex = rand() % operandCount;
int trigOpType = rand() % 3; // 0:sin, 1:cos, 2:tan
string question;
char temp[50];
for (int i = 0; i < operandCount; i++) {
if (i == trigOpIndex && !hasTrigOp) {
// 避免tan(90°)的情况
int angle = operands[i];
if (trigOpType == 2 && angle == 90) {
angle = 89; // 将90°改为89°
}
switch (trigOpType) {
case 0:
sprintf(temp, "sin(%d°)", angle);
break;
case 1:
sprintf(temp, "cos(%d°)", angle);
break;
case 2:
sprintf(temp, "tan(%d°)", angle);
break;
}
question += temp;
hasTrigOp = true;
} else {
sprintf(temp, "%d", operands[i]);
question += temp;
}
if (i < operandCount - 1) {
sprintf(temp, " %c ", operators[i]);
question += temp;
}
}
question += " =";
return question;
}
// QuestionFactory 实现
QuestionGenerator* QuestionFactory::createGenerator(const string& userType) {
if (userType == "小学") {
return new PrimaryQuestionGenerator();
} else if (userType == "初中") {
return new MiddleSchoolQuestionGenerator();
} else if (userType == "高中") {
return new HighSchoolQuestionGenerator();
}
return nullptr;
}
// 题目比较函数
bool compareQuestions(const string& question1, const string& question2) {
if (question1.empty() || question2.empty()) {
return false;
}
string q1 = question1;
string q2 = question2;
// 去除所有空格
q1.erase(remove(q1.begin(), q1.end(), ' '), q1.end());
q2.erase(remove(q2.begin(), q2.end(), ' '), q2.end());
// 直接比较字符串
return q1 == q2;
}
// 生成题目主函数
void generateQuestions(const string& userType, int count, const string& username) {
// 创建题目数组
vector<string> questionArray;
int generatedCount = 0;
int attemptCount = 0;
const int MAX_ATTEMPTS = count * 10;
// 设置随机数种子
srand(static_cast<unsigned int>(time(nullptr)));
printf("正在生成 %d 道 %s 数学题目...\n", count, userType.c_str());
// 创建对应的题目生成器
QuestionGenerator* generator = QuestionFactory::createGenerator(userType);
if (!generator) {
printf("错误:不支持的题目类型\n");
return;
}
while (generatedCount < count && attemptCount < MAX_ATTEMPTS) {
attemptCount++;
string newQuestion = generator->generateQuestion();
// 检查在数组中是否重复
bool isDuplicate = false;
for (const auto& existingQuestion : questionArray) {
if (compareQuestions(existingQuestion, newQuestion)) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
questionArray.push_back(newQuestion);
generatedCount++;
printf("成功生成第 %d 道题目\n", generatedCount);
} else {
printf("检测到重复题目,重新生成...\n");
}
}
delete generator;
if (generatedCount < count) {
printf("警告:在 %d 次尝试后只生成了 %d 道不重复的题目\n", MAX_ATTEMPTS, generatedCount);
}
// 构建最终的题目字符串
string questions;
char temp[200];
for (int i = 0; i < generatedCount; i++) {
sprintf(temp, "%d. %s\n", i + 1, questionArray[i].c_str());
questions += temp;
}
// 在控制台显示题目
printf("\n=== 生成的 %s 数学题目 ===\n", userType.c_str());
printf("%s", questions.c_str());
printf("============================\n");
// 保存到文件
handler1.saveQuestionsToFile(userType, generatedCount, username, questions);
}

@ -0,0 +1,52 @@
#ifndef QUESTIONGENERATOR_H
#define QUESTIONGENERATOR_H
#include <string>
#include <vector>
// 题目生成器抽象基类
class QuestionGenerator {
protected:
int operandCount;
int operands[5];
char operators[4];
void generateBaseElements();
std::string buildBaseQuestion();
public:
virtual ~QuestionGenerator() {}
virtual std::string generateQuestion() = 0;
};
// 小学题目生成器
class PrimaryQuestionGenerator : public QuestionGenerator {
public:
std::string generateQuestion() override;
};
// 初中题目生成器
class MiddleSchoolQuestionGenerator : public QuestionGenerator {
public:
std::string generateQuestion() override;
};
// 高中题目生成器
class HighSchoolQuestionGenerator : public QuestionGenerator {
public:
std::string generateQuestion() override;
};
// 题目生成工厂
class QuestionFactory {
public:
static QuestionGenerator* createGenerator(const std::string& userType);
};
// 题目比较函数
bool compareQuestions(const std::string& question1, const std::string& question2);
// 生成题目主函数
void generateQuestions(const std::string& userType, int count, const std::string& username);
#endif

@ -1,88 +1,22 @@
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include "QuestionGenerator.h"
#include "FileHandler.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 定义用户结构
typedef struct {
char username[20];
char password[10];
char userType[10];
} User;
// 用户结构体
struct User {
string username;
string password;
string userType;
};
FileHandler handler;
// 函数声明
void initializeUsers(User users[]);
int loginSystem(char *currentUserType);
void showMainMenu(const char *currentUserType);
int handleCommand(const char *command, char *currentUserType);
int switchUserType(const char *command, char *currentUserType);
void generatePaper(const char *userType);
int getQuestionCount();
void generateQuestions(const char *userType, int count);
void clearInputBuffer();
void trimString(char *str);
int isNumber(const char *str);
int main() {
// 设置控制台为UTF-8编码解决中文乱码
SetConsoleOutputCP(65001);
char currentUserType[10] = "";
// 主程序循环
while (1) {
// 调用登录系统函数
if (!loginSystem(currentUserType)) {
printf("登录失败,程序退出\n");
break;
}
// 登录成功后进入主菜单
showMainMenu(currentUserType);
// 命令处理循环
char command[50];
int shouldLogout = 0;
while (!shouldLogout) {
printf("> ");
// 读取整行输入
if (fgets(command, sizeof(command), stdin) == NULL) {
shouldLogout = 1;
break;
}
// 去除换行符和前后空格
trimString(command);
// 检查是否为空输入
if (strlen(command) == 0) {
continue;
}
// 处理命令
int result = handleCommand(command, currentUserType);
if (result == -1) {
shouldLogout = 1; // 退出当前用户,重新登录
} else if (result == 1) {
// 命令处理成功,继续循环
}
}
printf("退出当前用户,返回登录界面...\n\n");
}
printf("程序结束,按任意键退出...");
getchar();
return 0;
}
// 初始化用户数据
void initializeUsers(User users[]) {
User presetUsers[9] = {
void initializeUsers(vector<User>& users) {
users = {
{"张三1", "123", "小学"},
{"张三2", "123", "小学"},
{"张三3", "123", "小学"},
@ -93,229 +27,159 @@ void initializeUsers(User users[]) {
{"王五2", "123", "高中"},
{"王五3", "123", "高中"}
};
for (int i = 0; i < 9; i++) {
users[i] = presetUsers[i];
}
}
// 登录系统函数
int loginSystem(char *currentUserType) {
User users[9];
bool loginSystem(string& currentUserType, string& currentUsername) {
vector<User> users;
initializeUsers(users);
printf("=== 数学老师出题系统 ===\n");
printf("请输入用户名和密码(用空格隔开):\n");
cout << "=== 数学老师出题系统 ===" << endl;
cout << "请输入用户名和密码(用空格隔开):" << endl;
char username[20], password[10];
int authenticated = 0;
string username, password;
int attempts = 0;
// 登录验证
while (!authenticated && attempts < 3) {
printf("> ");
scanf("%s %s", username, password);
clearInputBuffer();
while (attempts < 3) {
cout << "> ";
cin >> username >> password;
handler.clearInputBuffer();
// 验证用户
for (int i = 0; i < 9; i++) {
if (strcmp(users[i].username, username) == 0 &&
strcmp(users[i].password, password) == 0) {
authenticated = 1;
strcpy(currentUserType, users[i].userType);
break;
for (const auto& user : users) {
if (user.username == username && user.password == password) {
currentUserType = user.userType;
currentUsername = user.username;
cout << "当前选择为 " << currentUserType << " 出题" << endl;
// 创建用户文件夹
if (handler.createUserDirectory(currentUsername)) {
cout << "用户文件夹创建成功" << endl;
} else {
cout << "用户文件夹已存在" << endl;
}
return true;
}
}
if (authenticated) {
printf("当前选择为 %s 出题\n", currentUserType);
return 1;
attempts++;
cout << "请输入正确的用户名、密码" << endl;
if (attempts < 3) {
cout << "请重新输入用户名和密码:" << endl;
} else {
attempts++;
printf("请输入正确的用户名、密码\n");
if (attempts < 3) {
printf("请重新输入用户名和密码:\n");
} else {
printf("登录失败次数过多\n");
}
cout << "登录失败次数过多" << endl;
}
}
return 0;
return false;
}
// 显示主菜单
void showMainMenu(const char *currentUserType) {
printf("\n登录成功!当前选择为 %s 出题\n", currentUserType);
printf("系统提示:准备生成 %s 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n", currentUserType);
printf("\n可用命令:\n");
printf("- 输入数字:生成指定数量的题目\n");
printf("- 切换为 小学/初中/高中:切换出题类型\n");
printf("- -1退出当前用户\n\n");
void showMainMenu(const string& currentUserType) {
cout << "\n登录成功!当前选择为 " << currentUserType << " 出题" << endl;
cout << "系统提示:准备生成 " << currentUserType << " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录" << endl;
cout << "\n可用命令:" << endl;
cout << "- 输入数字:生成指定数量的题目" << endl;
cout << "- 切换为 小学/初中/高中:切换出题类型" << endl;
cout << "- -1退出当前用户" << endl << endl;
}
// 切换用户类型
bool switchUserType(const string& command, string& currentUserType) {
if (command.length() < 9) return false;
string newType = command.substr(9); // 跳过"切换为"的9个字节
if (newType == "小学" || newType == "初中" || newType == "高中") {
currentUserType = newType;
cout << "已切换到 " << currentUserType << " 出题" << endl;
cout << "系统提示:准备生成 " << currentUserType << " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录" << endl;
return true;
} else {
cout << "请输入小学、初中和高中三个选项中的一个" << endl;
cout << "系统提示:准备生成 " << currentUserType << " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录" << endl;
return false;
}
}
// 处理命令
int handleCommand(const char *command, char *currentUserType) {
int handleCommand(const string& command, string& currentUserType, const string& currentUsername) {
// 检查退出命令
if (strcmp(command, "-1") == 0) {
if (command == "-1") {
return -1; // 退出当前用户
}
// 检查切换命令
if (strncmp(command, "切换为", 6) == 0) {
return switchUserType(command, currentUserType);
if (command.find("切换为") == 0) {
switchUserType(command, currentUserType);
return 1;
}
// 检查是否为数字(生成题目)
if (isNumber(command)) {
int count = atoi(command);
if (count > 0 && count <= 100) {
printf("正在生成 %d 道 %s 数学题目...\n", count, currentUserType);
generateQuestions(currentUserType, count);
printf("题目生成完成!\n\n");
printf("系统提示:准备生成 %s 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n", currentUserType);
return 1;
} else if (count == 0) {
printf("题目数量必须大于0\n");
printf("系统提示:准备生成 %s 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n", currentUserType);
if (handler.isNumber(command)) {
int count = stoi(command);
// 题目数量有效范围10-30
if (count >= 10 && count <= 30) {
generateQuestions(currentUserType, count, currentUsername);
cout << "题目生成完成!" << endl << endl;
cout << "系统提示:准备生成 " << currentUserType << " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录" << endl;
return 1;
} else if (count == -1) {
return -1; // 退出当前用户
} else {
printf("题目数量必须在1-100之间\n");
printf("系统提示:准备生成 %s 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n", currentUserType);
cout << "题目数量必须在10-30之间" << endl;
cout << "系统提示:准备生成 " << currentUserType << " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录" << endl;
return 1;
}
}
printf("未知命令!\n");
printf("系统提示:准备生成 %s 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n", currentUserType);
cout << "未知命令!" << endl;
cout << "系统提示:准备生成 " << currentUserType << " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录" << endl;
return 1;
}
// 切换用户类型
// 切换用户类型 - 从"切换为XX"中提取XX部分
int switchUserType(const char *command, char *currentUserType) {
// 命令格式是"切换为XX"我们需要提取XX部分
// "切换为"占6个字节所以从第6个字节开始就是XX部分
char newType[10] = "";
// 复制"切换为"后面的内容
if (strlen(command) >= 8) { // 确保命令长度足够
strcpy(newType, command +9); // 跳过"切换为"的6个字节
printf("%s",newType);
}
// 验证类型是否合法
if (strcmp(newType, "小学") == 0) {
strcpy(currentUserType, "小学");
printf("已切换到 小学 出题\n");
printf("系统提示:准备生成 小学 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n");
return 1;
}
else if (strcmp(newType, "初中") == 0) {
strcpy(currentUserType, "初中");
printf("已切换到 初中 出题\n");
printf("系统提示:准备生成 初中 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n");
return 1;
}
else if (strcmp(newType, "高中") == 0) {
strcpy(currentUserType, "高中");
printf("已切换到 高中 出题\n");
printf("系统提示:准备生成 高中 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n");
return 1;
}
else {
printf("请输入小学、初中和高中三个选项中的一个\n");
printf("系统提示:准备生成 %s 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录\n", currentUserType);
return 1;
}
}
// 生成数学题目
void generateQuestions(const char *userType, int count) {
printf("=== 生成的 %s 数学题目 ===\n", userType);
// 设置随机数种子
srand((unsigned int)time(NULL));
for (int i = 1; i <= count; i++) {
if (strcmp(userType, "小学") == 0) {
// 小学题目:简单的加减法
int a = rand() % 50 + 1;
int b = rand() % 50 + 1;
char op = (rand() % 2 == 0) ? '+' : '-';
printf("%d. %d %c %d = \n", i, a, op, b);
}
else if (strcmp(userType, "初中") == 0) {
// 初中题目:包含乘除法
int a = rand() % 20 + 1;
int b = rand() % 20 + 1;
char ops[] = {'+', '-', '*', '/'};
char op = ops[rand() % 4];
if (op == '/' && b == 0) b = 1;
printf("%d. %d %c %d = \n", i, a, op, b);
int main() {
string currentUserType;
string currentUsername;
// 主程序循环
while (true) {
// 调用登录系统函数
if (!loginSystem(currentUserType, currentUsername)) {
cout << "登录失败,程序退出" << endl;
break;
}
else if (strcmp(userType, "高中") == 0) {
// 高中题目:包含平方、开方等
int a = rand() % 10 + 1;
int type = rand() % 3;
if (type == 0) {
printf("%d. %d² = \n", i, a);
} else if (type == 1) {
printf("%d. √%d = \n", i, a*a);
} else {
printf("%d. log₁₀(%d) = \n", i, a*10);
// 登录成功后进入主菜单
showMainMenu(currentUserType);
// 命令处理循环
string command;
bool shouldLogout = false;
while (!shouldLogout) {
cout << "> ";
getline(cin, command);
handler.trimString(command);
// 检查是否为空输入
if (command.empty()) {
continue;
}
// 处理命令
int result = handleCommand(command, currentUserType, currentUsername);
if (result == -1) {
shouldLogout = true; // 退出当前用户,重新登录
}
}
}
printf("============================\n");
}
// 清除输入缓冲区
void clearInputBuffer() {
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
// 去除字符串前后空格和换行符
void trimString(char *str) {
if (str == NULL) return;
char *start = str;
char *end = str + strlen(str) - 1;
while (*start && isspace((unsigned char)*start)) {
start++;
}
while (end > start && isspace((unsigned char)*end)) {
end--;
}
memmove(str, start, end - start + 1);
str[end - start + 1] = '\0';
char *newline = strchr(str, '\n');
if (newline) *newline = '\0';
newline = strchr(str, '\r');
if (newline) *newline = '\0';
}
// 检查字符串是否为数字
int isNumber(const char *str) {
if (str == NULL || *str == '\0') {
return 0;
cout << "退出当前用户,返回登录界面..." << endl << endl;
}
// 检查是否为-1
if (strcmp(str, "-1") == 0) {
return 1;
}
cout << "程序结束,按任意键退出...";
cin.get();
for (int i = 0; str[i] != '\0'; i++) {
if (!isdigit(str[i])) {
return 0;
}
}
return 1;
return 0;
}

Binary file not shown.
Loading…
Cancel
Save