-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMy_Input_Module.cpp
More file actions
216 lines (202 loc) · 7.41 KB
/
My_Input_Module.cpp
File metadata and controls
216 lines (202 loc) · 7.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
export module My_Input_Module;
import std;
import std.compat;
namespace My_Input {
void printf_error_message(std::string_view message) {
std::print("{}", message);
}
namespace buffer_size_define {
constexpr int min_buffer_size = 2;
}
export struct InputConfig {
std::string_view message;
int buffer_size;
std::function<std::expected<bool, std::string>(std::string const&)> validator;
};
export template<typename T>
struct Verify_Config {
T max;
T min;
const std::string field_name;
};
export std::function<std::expected<bool, std::string>(const std::string&)> create_range_validator(Verify_Config<long long>& verify_config) {
return [verify_config](const std::string& input)->std::expected<bool, std::string> {
//这里创建一个Lamaba函数,来作为验证器,这下输入一个字符串,它能检测数字的范围进行验证
//相当于把这个函数作为一个工厂函数,返回一个函数对象
try {
if (long long int const value = std::stoll(input); value < verify_config.min || value > verify_config.max) {
return std::unexpected{ verify_config.field_name + "必须在" + std::to_string(verify_config.min) + "到" + std::to_string(verify_config.max) + "之间" };
}
return true;
}
catch (...) {
return std::unexpected{ verify_config.field_name + "格式无效" };
}
};
}
//浮点数验证工厂函数
export std::function<std::expected<bool, std::string>(const std::string&)> create_float_validator(Verify_Config<long double> const& verify_config,
int const max_decimal_places = 6,
bool const allow_scientific = true
) {
return [=](const std::string& input) -> std::expected<bool, std::string> {
try {
size_t pos;
long double const value = std::stold(input, &pos);
//检查完整转换
if (pos != input.size()) {
return std::unexpected{ verify_config.field_name + "包含非法后缀字符" };
}
//范围验证
if (value < verify_config.min || value > verify_config.max) {
return std::unexpected{
std::format("{}必须在{:.{}f}到{:.{}f}之间",
verify_config.field_name, verify_config.min, max_decimal_places, verify_config.max, max_decimal_places)
};
}
//精度控制
if (!allow_scientific) {
if (input.find('e') != std::string::npos ||
input.find('E') != std::string::npos) {
return std::unexpected{ verify_config.field_name + "不允许科学计数法" };
}
}
//小数位数检查
size_t dot_pos = input.find('.');
if (dot_pos != std::string::npos) {
size_t const decimal_count = input.size() - dot_pos - 1;
if (decimal_count > static_cast<size_t>(max_decimal_places)) {
return std::unexpected{
std::format("{}最多允许{}位小数", verify_config.field_name, max_decimal_places)
};
}
}
return true;
}
catch (...) {
return std::unexpected{ verify_config.field_name + "不是有效的浮点数" };
}
};
}
std::expected<int, std::string> for_input(std::string& input_buffer, int const buffer_size, const std::string_view message) {
if (buffer_size < static_cast<size_t>(buffer_size_define::min_buffer_size)) {
return std::unexpected(std::string{ "缓冲区大小错误" });
}
std::cin.clear();
std::print("{}", message);
std::string buffer{ "" };
buffer.resize(buffer_size + 1);
if (!std::getline(std::cin, buffer)) {
input_buffer.clear();
return std::unexpected("输入操作失败");
}
if (buffer.empty()) {
input_buffer.clear();
return std::unexpected("输入不能为空");
}
if (buffer.size() >= static_cast<size_t>(buffer_size)) {
input_buffer.clear();
return std::unexpected("输入过长");
}
input_buffer.assign(buffer);
return 0;
}
std::expected<long long, std::string> input_number(std::string& input_buffer, const InputConfig& input_config) {
long long number = 0;
if (auto const ret = for_input(input_buffer, input_config.buffer_size, input_config.message); !ret.has_value()) {
return std::unexpected{ ret.error() };
}
for (char const c : input_buffer) {
if (!std::isdigit(c) && c != '+' && c != '-') {
return std::unexpected{ "您输入的数字格式不正确,请只包含数字!" };
}
}
if (input_config.validator) {
if (auto const ret = input_config.validator(input_buffer); !ret.has_value()) {
return std::unexpected{ ret.error() };
}
}
try {
number = std::stoll(input_buffer);
}
catch ([[maybe_unused]] std::exception const& e) {
return std::unexpected{ "转换数字失败,请输入有效的数字!" };
}
return number;
}
std::expected<long double, std::string> input_double(std::string& input_buffer, const InputConfig& input_config) {
long double number = 0.0;
if (auto const ret = for_input(input_buffer, input_config.buffer_size, input_config.message); !ret.has_value()) {
return std::unexpected{ ret.error() };
}
try {
size_t pos = 0;
number = std::stold(input_buffer, &pos);
if (!pos == input_buffer.size()) {
return std::unexpected{ "输入含有非法字符" };
}
}
catch ([[maybe_unused]] std::out_of_range& e) {
return std::unexpected{ "超越双精度浮点数范围" };
}
catch ([[maybe_unused]] std::invalid_argument& e) {
return std::unexpected{ "无效的浮点数格式" };
}
catch ([[maybe_unused]] std::exception& e) {
return std::unexpected{ "未知错误" };
}
if (input_config.validator) {
if (auto const ret = input_config.validator(input_buffer); !ret.has_value()) {
return std::unexpected{ ret.error() };
}
}
return number;
}
std::expected<std::string, std::string> input_string(std::string& input_buffer, const InputConfig& input_config) {
if (auto const ret = for_input(input_buffer, input_config.buffer_size, input_config.message); !ret.has_value()) {
return std::unexpected{ ret.error() };
}
if (input_config.validator) {
if (auto const ret = input_config.validator(input_buffer); !ret.has_value()) {
return std::unexpected{ "验证失败" + ret.error() };
}
}
return input_buffer;
}
export std::expected<long long, std::vector<std::string>> input_number_auto_retry(std::string& input_buffer, const InputConfig& input_config, int const retry_time = 5) {
std::vector<std::string> error_messages;
for (int i = 0; i < retry_time; ++i) {
auto ret = input_number(input_buffer, input_config);
if (ret.has_value()) {
return *ret;
}
printf_error_message(ret.error());
error_messages.push_back(ret.error());
}
return std::unexpected{ error_messages };
}
export std::expected<long double, std::vector<std::string>> input_double_auto_retry(std::string& input_buffer, const InputConfig& input_config, int const retry_time = 5) {
std::vector<std::string> error_messages;
for (int i = 0; i < retry_time; ++i) {
auto ret = input_double(input_buffer, input_config);
if (ret.has_value()) {
return *ret;
}
printf_error_message(ret.error());
error_messages.push_back(ret.error());
}
return std::unexpected{ error_messages };
}
export std::expected<std::string, std::vector<std::string>> input_string_auto_retry(std::string& input_buffer, const InputConfig& input_config, int const retry_time = 5) {
std::vector<std::string> error_messages;
for (int i = 0; i < retry_time; ++i) {
auto ret = input_string(input_buffer, input_config);
if (ret.has_value()) {
return *ret;
}
printf_error_message(ret.error());
error_messages.push_back(ret.error());
}
return std::unexpected{ error_messages };
}
}