测试V2 #4

Merged
hnu202326010101 merged 6 commits from develop into develop_v2 4 months ago

@ -56,7 +56,7 @@ make
#### 手动编译
```bash
cd src
g++ -std=c++17 -Wall -Wextra -O2 -o math_exam_generator main.cpp
g++ -std=c++17 -Wall -Wextra -O2 -o math_exam_generator main.cc app.cc auth.cc exam.cc login.cc utils.cc
```
### 运行程序
@ -100,14 +100,14 @@ cd src
│ └── README_root.md # 根目录的README
└── src/ # 源代码目录
├── Makefile # 编译配置文件
├── app.cpp # 应用逻辑
├── auth.cpp # 用户认证模块
├── exam.cpp # 试卷生成模块
├── app.cc # 应用逻辑
├── auth.cc # 用户认证模块
├── exam.cc # 试卷生成模块
├── include/ # 头文件目录
├── login.cpp # 登录逻辑
├── main.cpp # 主程序入口
├── login.cc # 登录逻辑
├── main.cc # 主程序入口
├── math_exam_generator.exe # 编译后的可执行文件
└── utils.cpp # 工具函数
└── utils.cc # 工具函数
```
*注:程序运行时,会在`src`目录下自动生成`paper`文件夹,用于存放用户生成的试卷。*
@ -144,10 +144,12 @@ src/
## 技术特点
- **面向对象设计**:使用类封装功能模块
- **STL容器**:使用 vector、map、set 等容器管理数据
- **文件系统操作**:使用 C++17 filesystem 库进行文件管理
- **随机数生成**使用现代C++随机数生成器
- **异常处理**:对用户输入进行验证和异常处理
- **STL 容器**:使用 vector、map、set 等容器管理数据
- **文件系统操作**:使用 C++17 `<filesystem>` 进行文件管理
- **随机数生成**:使用现代 C++ 随机数生成器
- **显式输入校验**:对用户输入进行验证,避免使用异常进行控制流
- **统一命名与常量**:函数采用 UpperCamelCase常量统一 `k` 前缀
- **头文件守卫**:统一为 `MEG_*_H_` 形式,保持一致性
## 开发环境

@ -11,8 +11,8 @@ else
endif
TARGET := math_exam_generator
SRCS := main.cpp app.cpp auth.cpp exam.cpp login.cpp utils.cpp
OBJS := $(SRCS:.cpp=.o)
SRCS := main.cc app.cc auth.cc exam.cc login.cc utils.cc
OBJS := $(SRCS:.cc=.o)
all: $(TARGET)
@ -20,7 +20,7 @@ $(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $@ $^
-$(RM) $(OBJS)
%.o: %.cpp
%.o: %.cc
$(CXX) $(CXXFLAGS) -c $< -o $@
.PHONY: clean

@ -0,0 +1,103 @@
#include "include/app.h"
#include "include/utils.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <cctype>
#include <algorithm>
namespace fs = std::filesystem;
namespace meg {
// 应用程序构造函数:
// 初始化题目生成器的具体实现(通过抽象接口进行多态管理)
App::App() {
exam_ = std::make_unique<ExamGenerator>();
}
// 处理登录后交互流程:
// - 支持用户通过命令切换题目难度(小学/初中/高中)
// - 显式校验数字输入并生成试卷,避免使用异常进行控制流
void App::handle_logged_in() {
if (!current_user_) return;
current_level_ = current_user_->level;
while (true) {
std::wcout << L"准备生成" << LevelToChinese(current_level_) << L"数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录";
std::wcout.flush();
std::wstring line;
if (!std::getline(std::wcin, line)) return; // EOF
line = Trim(line);
if (line.empty()) continue;
if (line == L"-1") {
std::wcout << L"已退出登录。" << '\n';
current_user_.reset();
return;
}
// 支持命令:切换为小学/初中/高中
if (StartsWith(line, L"切换为")) {
std::wstring t = line.substr(3);
t = Trim(t);
if (t == L"小学") current_level_ = Level::Primary;
else if (t == L"初中") current_level_ = Level::Middle;
else if (t == L"高中") current_level_ = Level::High;
else {
std::wcout << L"不支持的类型:" << t << '\n';
continue;
}
std::wcout << L"已切换为" << LevelToChinese(current_level_) << L"" << '\n';
continue;
}
// 显式校验输入为数字,避免异常
std::string ascii(line.begin(), line.end());
bool all_digits = !ascii.empty() && std::all_of(ascii.begin(), ascii.end(), [](unsigned char c){ return std::isdigit(c); });
if (!all_digits) {
std::wcout << L"请输入正确的数字,或使用指令如:切换为初中。" << '\n';
continue;
}
int n = std::stoi(ascii);
if (n < 10 || n > 30) {
std::wcout << L"请输入 10-30 之间的数字。" << '\n';
continue;
}
fs::path base = fs::path("paper") / current_user_->username;
fs::create_directories(base);
auto history_path = base / ".history.txt";
auto history = exam_->load_history(history_path);
auto questions = exam_->GenerateUnique(current_level_, n, history);
// 保存试卷
std::string ts = NowTimestampStr();
fs::path outfile = base / (ts + ".txt");
std::ofstream fout(outfile);
for (size_t i = 0; i < questions.size(); ++i) {
fout << (i + 1) << ". " << questions[i] << "\n\n";
}
fout.close();
exam_->append_history(history_path, questions);
std::wcout << L"已生成试卷:" << outfile.wstring() << '\n';
}
}
void App::run() {
InitConsoleLocale();
std::wcout << L"中小学数学卷子自动生成程序" << '\n';
while (true) {
if (!current_user_) {
auto u = login_.prompt_login();
if (!u) return; // EOF 退出
current_user_ = u;
current_level_ = current_user_->level;
} else {
handle_logged_in();
}
}
}
} // namespace meg

@ -1,92 +0,0 @@
#include "include/app.hpp"
#include "include/utils.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
namespace fs = std::filesystem;
namespace meg {
App::App() {}
void App::handle_logged_in() {
if (!current_user_) return;
current_level_ = current_user_->level;
while (true) {
std::wcout << L"准备生成" << level_to_chinese(current_level_) << L"数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录";
std::wcout.flush();
std::wstring line;
if (!std::getline(std::wcin, line)) return; // EOF
line = trim(line);
if (line.empty()) continue;
if (line == L"-1") {
std::wcout << L"已退出登录。" << std::endl;
current_user_.reset();
return;
}
// 支持命令:切换为小学/初中/高中
if (starts_with(line, L"切换为")) {
std::wstring t = line.substr(3);
t = trim(t);
if (t == L"小学") current_level_ = Level::Primary;
else if (t == L"初中") current_level_ = Level::Middle;
else if (t == L"高中") current_level_ = Level::High;
else {
std::wcout << L"不支持的类型:" << t << std::endl;
continue;
}
std::wcout << L"已切换为" << level_to_chinese(current_level_) << L"" << std::endl;
continue;
}
// 尝试解析数量
try {
int n = std::stoi(std::string(line.begin(), line.end()));
if (n < 10 || n > 30) {
std::wcout << L"请输入 10-30 之间的数字。" << std::endl;
continue;
}
fs::path base = fs::path("paper") / current_user_->username;
fs::create_directories(base);
auto history_path = base / ".history.txt";
auto history = exam_.load_history(history_path);
auto questions = exam_.generate_unique(current_level_, n, history);
// 保存试卷
std::string ts = now_timestamp_str();
fs::path outfile = base / (ts + ".txt");
std::ofstream fout(outfile);
for (size_t i = 0; i < questions.size(); ++i) {
fout << (i + 1) << ". " << questions[i] << "\n\n";
}
fout.close();
exam_.append_history(history_path, questions);
std::wcout << L"已生成试卷:" << outfile.wstring() << std::endl;
} catch (...) {
std::wcout << L"请输入正确的数字,或使用指令如:切换为初中。" << std::endl;
}
}
}
void App::run() {
init_console_locale();
std::wcout << L"中小学数学卷子自动生成程序" << std::endl;
while (true) {
if (!current_user_) {
auto u = login_.prompt_login();
if (!u) return; // EOF 退出
current_user_ = u;
current_level_ = current_user_->level;
} else {
handle_logged_in();
}
}
}
} // namespace meg

@ -1,4 +1,4 @@
#include "include/auth.hpp"
#include "include/auth.h"
namespace meg {

@ -1,4 +1,4 @@
#include "include/exam.hpp"
#include "include/exam.h"
#include <fstream>
#include <iostream>
@ -33,14 +33,15 @@ void ExamGenerator::append_history(const std::filesystem::path& history_path, co
}
}
std::vector<std::string> ExamGenerator::generate_unique(Level level, int count, std::unordered_set<std::string>& history) {
// 生成不重复题目:按难度生成并去重,限制尝试次数避免极端情况
std::vector<std::string> ExamGenerator::GenerateUnique(Level level, int count, std::unordered_set<std::string>& history) {
std::vector<std::string> out;
int attempts = 0;
while ((int)out.size() < count && attempts < count * 50) {
std::string q;
if (level == Level::Primary) q = gen_primary();
else if (level == Level::Middle) q = gen_middle();
else q = gen_high();
if (level == Level::Primary) q = GenPrimary();
else if (level == Level::Middle) q = GenMiddle();
else q = GenHigh();
if (history.insert(q).second) {
out.push_back(q);
@ -50,7 +51,8 @@ std::vector<std::string> ExamGenerator::generate_unique(Level level, int count,
return out;
}
static std::string join_ops(const std::vector<int>& nums, const std::vector<char>& ops) {
// 将数字与运算符拼接为表达式字符串
static std::string JoinOps(const std::vector<int>& nums, const std::vector<char>& ops) {
std::string s;
for (size_t i = 0; i < nums.size(); ++i) {
s += std::to_string(nums[i]);
@ -63,37 +65,45 @@ static std::string join_ops(const std::vector<int>& nums, const std::vector<char
return s;
}
std::string ExamGenerator::gen_primary() {
// 生成小学题目2-3 个操作数的四则运算
// 生成小学题目2-3 个操作数的四则运算
std::string ExamGenerator::GenPrimary() {
int n_ops = rand_int(rng_, 1, 2); // 2-3个操作数 => 1-2个操作符
std::vector<int> nums;
for (int i = 0; i < n_ops + 1; ++i) nums.push_back(rand_int(rng_, 1, 50));
static const char all_ops[] = {'+', '-', '*', '/'};
static const char kAllOps[] = {'+', '-', '*', '/'};
std::vector<char> ops;
for (int i = 0; i < n_ops; ++i) ops.push_back(all_ops[rand_int(rng_, 0, 3)]);
std::string expr = join_ops(nums, ops);
// 适度加括号
if (nums.size() >= 3 && rand_int(rng_, 0, 1)) {
size_t pos = expr.find(' ');
if (pos != std::string::npos) {
expr = "(" + expr.substr(0, pos) + ")" + expr.substr(pos);
for (int i = 0; i < n_ops; ++i) ops.push_back(kAllOps[rand_int(rng_, 0, 3)]);
std::string s;
if (n_ops == 1) {
// 两个操作数:不加括号
s = std::to_string(nums[0]) + " " + std::string(1, ops[0]) + " " + std::to_string(nums[1]);
} else {
// 三个操作数:随机选择包裹首或末二元表达式
bool wrap_first = (rand_int(rng_, 0, 1) == 1);
if (wrap_first) {
s = "(" + std::to_string(nums[0]) + " " + std::string(1, ops[0]) + " " + std::to_string(nums[1]) + ")";
s += " " + std::string(1, ops[1]) + " " + std::to_string(nums[2]);
} else {
s = std::to_string(nums[0]) + " " + std::string(1, ops[0]) + " ";
s += "(" + std::to_string(nums[1]) + " " + std::string(1, ops[1]) + " " + std::to_string(nums[2]) + ")";
}
}
return expr + " = ?";
return s + " = ?";
}
std::string ExamGenerator::gen_middle() {
// 生成初中题目:包含平方或开方的表达式
std::string ExamGenerator::GenMiddle() {
int n_ops = rand_int(rng_, 2, 3); // 3-4 操作数
std::vector<int> nums;
for (int i = 0; i < n_ops + 1; ++i) nums.push_back(rand_int(rng_, 1, 100));
static const char all_ops[] = {'+', '-', '*', '/'};
static const char kAllOps[] = {'+', '-', '*', '/'};
std::vector<char> ops;
for (int i = 0; i < n_ops; ++i) ops.push_back(all_ops[rand_int(rng_, 0, 3)]);
for (int i = 0; i < n_ops; ++i) ops.push_back(kAllOps[rand_int(rng_, 0, 3)]);
// 随机把一个数变成平方或开方
int idx = rand_int(rng_, 0, (int)nums.size() - 1);
bool use_sqrt = rand_int(rng_, 0, 1) == 1;
std::string expr = join_ops(nums, ops);
std::string expr = JoinOps(nums, ops);
// 找到替换位置(简单方式:直接重新拼接)
std::string s;
for (size_t i = 0; i < nums.size(); ++i) {
@ -110,26 +120,24 @@ std::string ExamGenerator::gen_middle() {
return s + " = ?";
}
std::string ExamGenerator::gen_high() {
// 生成高中题目:带三角函数项并可能平方或开方
std::string ExamGenerator::GenHigh() {
int n_ops = rand_int(rng_, 3, 4); // 4-5 操作数
std::vector<int> nums;
for (int i = 0; i < n_ops + 1; ++i) nums.push_back(rand_int(rng_, 1, 100));
static const char all_ops[] = {'+', '-', '*', '/'};
static const char kAllOps[] = {'+', '-', '*', '/'};
std::vector<char> ops;
for (int i = 0; i < n_ops; ++i) ops.push_back(all_ops[rand_int(rng_, 0, 3)]);
for (int i = 0; i < n_ops; ++i) ops.push_back(kAllOps[rand_int(rng_, 0, 3)]);
// 先基础表达式
std::string base;
for (size_t i = 0; i < nums.size(); ++i) {
base += std::to_string(nums[i]);
if (i < ops.size()) { base += ' '; base += ops[i]; base += ' '; }
}
// 至少一个三角函数,角度用 30/45/60/90 之一,使用 "deg" 标识角度
static const char* funcs[] = {"sin", "cos", "tan"};
static const int angles[] = {30, 45, 60, 90};
std::string tri = std::string(funcs[rand_int(rng_, 0, 2)]) + "(" + std::to_string(angles[rand_int(rng_, 0, 3)]) + "deg)";
static const int kAngles[] = {30, 45, 60, 90};
std::string tri = std::string(funcs[rand_int(rng_, 0, 2)]) + "(" + std::to_string(kAngles[rand_int(rng_, 0, 3)]) + "deg)";
// 随机把一个数替换为三角项
size_t replace_pos = rand_int(rng_, 0, (int)nums.size() - 1);
// 重建字符串并替换
@ -139,7 +147,6 @@ std::string ExamGenerator::gen_high() {
s += term;
if (i < ops.size()) { s += ' '; s += ops[i]; s += ' '; }
}
// 同时可能再加平方或开方
if (rand_int(rng_, 0, 1)) {
s = "(" + s + ")^2";

@ -1,11 +1,12 @@
#ifndef MEG_APP_HPP
#define MEG_APP_HPP
#ifndef MEG_APP_H_
#define MEG_APP_H_
#include <optional>
#include <memory>
#include <filesystem>
#include "auth.hpp"
#include "login.hpp"
#include "exam.hpp"
#include "auth.h"
#include "login.h"
#include "exam.h"
namespace meg {
@ -17,7 +18,8 @@ public:
private:
Auth auth_;
LoginManager login_{auth_};
ExamGenerator exam_;
// 使用多态:题目生成器接口指针,便于后续替换实现
std::unique_ptr<IExamGenerator> exam_;
std::optional<User> current_user_;
Level current_level_ = Level::Primary;
@ -27,4 +29,4 @@ private:
} // namespace meg
#endif // MEG_APP_HPP
#endif // MEG_APP_H_

@ -1,10 +1,10 @@
#ifndef MEG_AUTH_HPP
#define MEG_AUTH_HPP
#ifndef MEG_AUTH_H_
#define MEG_AUTH_H_
#include <string>
#include <optional>
#include <map>
#include "utils.hpp"
#include "utils.h"
namespace meg {
@ -24,4 +24,4 @@ private:
} // namespace meg
#endif // MEG_AUTH_HPP
#endif // MEG_AUTH_H_

@ -0,0 +1,50 @@
#ifndef MEG_EXAM_H_
#define MEG_EXAM_H_
#include <string>
#include <vector>
#include <unordered_set>
#include <filesystem>
#include <random>
#include "utils.h"
namespace meg {
// 抽象题目生成器接口:定义题目生成与历史管理的统一协议
class IExamGenerator {
public:
virtual ~IExamGenerator() = default;
// 加载历史:用于避免重复题目
virtual std::unordered_set<std::string> load_history(const std::filesystem::path& history_path) = 0;
// 追加历史:将本次生成写入历史库
virtual void append_history(const std::filesystem::path& history_path, const std::vector<std::string>& qs) = 0;
// 生成不重复题目:按难度与数量生成题目,排除历史
virtual std::vector<std::string> GenerateUnique(Level level, int count, std::unordered_set<std::string>& history) = 0;
};
// 具体题目生成器实现:使用随机数生成不同难度的题目
class ExamGenerator : public IExamGenerator {
public:
ExamGenerator();
// 加载历史:从文件读取每行题目为历史集合
std::unordered_set<std::string> load_history(const std::filesystem::path& history_path) override;
// 追加历史:将题目列表逐行追加到文件末尾
void append_history(const std::filesystem::path& history_path, const std::vector<std::string>& qs) override;
// 生成不重复题目:依据难度选择生成函数并去重
std::vector<std::string> GenerateUnique(Level level, int count, std::unordered_set<std::string>& history) override;
private:
std::mt19937 rng_;
// 生成小学难度题目
std::string GenPrimary();
// 生成初中难度题目
std::string GenMiddle();
// 生成高中难度题目
std::string GenHigh();
};
} // namespace meg
#endif // MEG_EXAM_H_

@ -1,33 +0,0 @@
#ifndef MEG_EXAM_HPP
#define MEG_EXAM_HPP
#include <string>
#include <vector>
#include <unordered_set>
#include <filesystem>
#include <random>
#include "utils.hpp"
namespace meg {
class ExamGenerator {
public:
ExamGenerator();
// 加载/保存历史,防止同教师重复题目
std::unordered_set<std::string> load_history(const std::filesystem::path& history_path);
void append_history(const std::filesystem::path& history_path, const std::vector<std::string>& qs);
// 生成不重复题目
std::vector<std::string> generate_unique(Level level, int count, std::unordered_set<std::string>& history);
private:
std::mt19937 rng_;
std::string gen_primary();
std::string gen_middle();
std::string gen_high();
};
} // namespace meg
#endif // MEG_EXAM_HPP

@ -1,9 +1,9 @@
#ifndef MEG_LOGIN_HPP
#define MEG_LOGIN_HPP
#ifndef MEG_LOGIN_H_
#define MEG_LOGIN_H_
#include <optional>
#include <string>
#include "auth.hpp"
#include "auth.h"
namespace meg {
@ -17,4 +17,4 @@ private:
} // namespace meg
#endif // MEG_LOGIN_HPP
#endif // MEG_LOGIN_H_

@ -0,0 +1,29 @@
#ifndef MEG_UTILS_H_
#define MEG_UTILS_H_
#include <string>
#include <filesystem>
namespace meg {
enum class Level { Primary, Middle, High };
// 将难度枚举转换为中文
std::wstring LevelToChinese(Level level);
// 初始化控制台本地化,解决中文输入/输出问题
// 初始化控制台本地化,解决中文输入/输出问题
void InitConsoleLocale();
// 生成时间戳YYYY-MM-DD-HH-MM-SS
// 生成时间戳YYYY-MM-DD-HH-MM-SS
std::string NowTimestampStr();
// 字符串工具
// 字符串工具:判断前缀与去除首尾空白
bool StartsWith(const std::wstring& s, const std::wstring& prefix);
std::wstring Trim(const std::wstring& s);
} // namespace meg
#endif // MEG_UTILS_H_

@ -1,25 +0,0 @@
#ifndef MEG_UTILS_HPP
#define MEG_UTILS_HPP
#include <string>
#include <filesystem>
namespace meg {
enum class Level { Primary, Middle, High };
std::wstring level_to_chinese(Level level);
// 初始化控制台本地化,解决中文输入/输出问题
void init_console_locale();
// 生成时间戳YYYY-MM-DD-HH-MM-SS
std::string now_timestamp_str();
// 字符串工具
bool starts_with(const std::wstring& s, const std::wstring& prefix);
std::wstring trim(const std::wstring& s);
} // namespace meg
#endif // MEG_UTILS_HPP

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,11 +1,12 @@
#include "include/login.hpp"
#include "include/utils.hpp"
#include "include/login.h"
#include "include/utils.h"
#include <iostream>
#include <sstream>
namespace meg {
// 登录交互:读取“用户名 密码”验证成功返回用户EOF 返回空
std::optional<User> LoginManager::prompt_login() {
while (true) {
std::wcout << L"请输入用户名和密码(用空格隔开): ";
@ -14,7 +15,7 @@ std::optional<User> LoginManager::prompt_login() {
if (!std::getline(std::wcin, line)) {
return std::nullopt;
}
line = trim(line);
line = Trim(line);
if (line.empty()) continue;
// 拆分为两段:用户名 密码
@ -22,15 +23,15 @@ std::optional<User> LoginManager::prompt_login() {
std::wstring u, p;
iss >> u >> p;
if (u.empty() || p.empty()) {
std::wcout << L"输入格式不正确,请重新输入。" << std::endl;
std::wcout << L"输入格式不正确,请重新输入。" << '\n';
continue;
}
auto user = auth_.authenticate(u, p);
if (user) {
std::wcout << L"登录成功,欢迎您," << u << L"" << std::endl;
std::wcout << L"登录成功,欢迎您," << u << L"" << '\n';
return user;
} else {
std::wcout << L"用户名或密码错误,请重试。" << std::endl;
std::wcout << L"用户名或密码错误,请重试。" << '\n';
}
}
}

@ -1,4 +1,4 @@
#include "include/app.hpp"
#include "include/app.h"
int main() {
meg::App app;

Binary file not shown.

@ -1,30 +1,30 @@
40 + 31 * 38 = ?
46 * 6 = ?
(8) - 32 / 31 = ?
36 + 20 + 17 = ?
(7) + 14 / 39 = ?
(19) - 24 * 20 = ?
(13) - 27 * 43 = ?
43 / 17 - 39 = ?
17 - 43 = ?
9 / 30 = ?
48 / 31 = ?
17 - 24 = ?
(3) - 23 * 30 = ?
26 / 38 = ?
(48) / 46 * 33 = ?
11 * 7 = ?
(47) / 17 * 31 = ?
36 * 10 / 14 = ?
47 * 23 / 32 = ?
(29) - 14 * 33 = ?
33 * 46 + 38 = ?
(4) * 11 * 9 = ?
(39) / 36 - 36 = ?
25 - 4 = ?
12 - 8 = ?
39 - 32 = ?
13 / 25 = ?
40 - 43 = ?
(48) + 44 + 28 = ?
(12) / 9 + 44 = ?
7 + 2 = ?
(16 * 15) + 25 = ?
(35 - 33) + 38 = ?
3 - (32 * 47) = ?
(15 + 4) + 26 = ?
36 / 30 = ?
50 / (6 - 11) = ?
(3 + 25) + 3 = ?
14 / 12 = ?
26 + 1 = ?
43 * (15 + 8) = ?
30 * 10 = ?
41 / 37 = ?
38 + (30 / 28) = ?
(38 * 27) * 45 = ?
5 / 8 = ?
43 - 35 = ?
(6 / 39) + 44 = ?
(47 / 6) * 40 = ?
5 - 43 = ?
(11 - 44) - 1 = ?
30 - 36 = ?
(44 + 43) / 38 = ?
11 - 29 = ?
2 - (18 - 17) = ?
14 * (33 - 10) = ?
46 - 27 = ?
11 - 15 = ?
39 / 4 = ?
10 + (41 / 45) = ?

@ -1,60 +0,0 @@
1. 40 + 31 * 38 = ?
2. 46 * 6 = ?
3. (8) - 32 / 31 = ?
4. 36 + 20 + 17 = ?
5. (7) + 14 / 39 = ?
6. (19) - 24 * 20 = ?
7. (13) - 27 * 43 = ?
8. 43 / 17 - 39 = ?
9. 17 - 43 = ?
10. 9 / 30 = ?
11. 48 / 31 = ?
12. 17 - 24 = ?
13. (3) - 23 * 30 = ?
14. 26 / 38 = ?
15. (48) / 46 * 33 = ?
16. 11 * 7 = ?
17. (47) / 17 * 31 = ?
18. 36 * 10 / 14 = ?
19. 47 * 23 / 32 = ?
20. (29) - 14 * 33 = ?
21. 33 * 46 + 38 = ?
22. (4) * 11 * 9 = ?
23. (39) / 36 - 36 = ?
24. 25 - 4 = ?
25. 12 - 8 = ?
26. 39 - 32 = ?
27. 13 / 25 = ?
28. 40 - 43 = ?
29. (48) + 44 + 28 = ?
30. (12) / 9 + 44 = ?

@ -0,0 +1,60 @@
1. 7 + 2 = ?
2. (16 * 15) + 25 = ?
3. (35 - 33) + 38 = ?
4. 3 - (32 * 47) = ?
5. (15 + 4) + 26 = ?
6. 36 / 30 = ?
7. 50 / (6 - 11) = ?
8. (3 + 25) + 3 = ?
9. 14 / 12 = ?
10. 26 + 1 = ?
11. 43 * (15 + 8) = ?
12. 30 * 10 = ?
13. 41 / 37 = ?
14. 38 + (30 / 28) = ?
15. (38 * 27) * 45 = ?
16. 5 / 8 = ?
17. 43 - 35 = ?
18. (6 / 39) + 44 = ?
19. (47 / 6) * 40 = ?
20. 5 - 43 = ?
21. (11 - 44) - 1 = ?
22. 30 - 36 = ?
23. (44 + 43) / 38 = ?
24. 11 - 29 = ?
25. 2 - (18 - 17) = ?
26. 14 * (33 - 10) = ?
27. 46 - 27 = ?
28. 11 - 15 = ?
29. 39 / 4 = ?
30. 10 + (41 / 45) = ?

@ -1,10 +1,11 @@
#include "include/utils.hpp"
#include "include/utils.h"
#include <locale>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <algorithm>
#ifdef _WIN32
# include <io.h>
@ -13,7 +14,8 @@
namespace meg {
std::wstring level_to_chinese(Level level) {
// 将难度枚举转换为中文
std::wstring LevelToChinese(Level level) {
switch (level) {
case Level::Primary: return L"小学";
case Level::Middle: return L"初中";
@ -22,7 +24,8 @@ std::wstring level_to_chinese(Level level) {
return L"小学";
}
void init_console_locale() {
// 初始化控制台本地化,解决中文输入/输出问题
void InitConsoleLocale() {
#ifdef _WIN32
_setmode(_fileno(stdout), _O_U16TEXT);
_setmode(_fileno(stdin), _O_U16TEXT);
@ -40,7 +43,8 @@ void init_console_locale() {
#endif
}
std::string now_timestamp_str() {
// 生成时间戳YYYY-MM-DD-HH-MM-SS
std::string NowTimestampStr() {
using namespace std::chrono;
auto now = system_clock::now();
std::time_t t = system_clock::to_time_t(now);
@ -55,19 +59,21 @@ std::string now_timestamp_str() {
return oss.str();
}
bool starts_with(const std::wstring& s, const std::wstring& prefix) {
// 判断字符串是否以指定前缀开头
bool StartsWith(const std::wstring& s, const std::wstring& prefix) {
if (prefix.size() > s.size()) return false;
return std::equal(prefix.begin(), prefix.end(), s.begin());
}
static inline bool is_space(wchar_t c) {
static inline bool IsSpace(wchar_t c) {
return c == L' ' || c == L'\t' || c == L'\n' || c == L'\r' || c == L'\f' || c == L'\v';
}
std::wstring trim(const std::wstring& s) {
// 去除字符串首尾空白字符
std::wstring Trim(const std::wstring& s) {
size_t b = 0, e = s.size();
while (b < e && is_space(s[b])) ++b;
while (e > b && is_space(s[e-1])) --e;
while (b < e && IsSpace(s[b])) ++b;
while (e > b && IsSpace(s[e-1])) --e;
return s.substr(b, e - b);
}
Loading…
Cancel
Save