洛谷B3843 [GESP202306 三级]密码合规
[GESP202306 三级] 密码合规
题目链接:https://www.luogu.com.cn/problem/B3843
题目描述
网站注册需要有用户名和密码,编写程序以检查用户输入密码的有效性。合规的密码应满足以下要求:。
1.只能由a-z之间26个小写字母, A-Z之间26个大写字母、0-9之间10个数字以及!@#$四个特殊字符构成。
2.密码最短长度:6个字符,密码最大长度:12个字符。
3.大写字母,小写字母和数字必须至少有其中两种,以及至少有四个特殊字符中的一个。
输入格式
输入一行不含空格的字符串。约定长度不超过100。该字符串被英文逗号分隔为多段,作为多组被检测密码。
输出格式
输出若干行,每行输出一组合规的密码。输出顺序以输入先后为序,即先输入则先输出。
样例 #1
样例输入 #1
seHJ12!@,sjdkffH$123,sdf!@&12HDHa!,123&^YUhg@!
样例输出 #1
seHJ12!@
sjdkffH$123
提示
【样例 1 解释】
输入被英文逗号分为了四组被检测密码:seHJ12!@
、sjdkffH$123
、sdf!@&12HDHa!
、123&^YUhg@!
。其中 sdf!@&12HDHa!
长度超过 12 个字符,不合规;123&^YUhg@!
包含四个特殊字符之外的字符不合规。
这题我们可以使用getline函数读取一行的字符串,接收输入的字符串。
随后我们可以利用一个动态数组,存放每一个需要鉴定的字符串,我们这里拿vector来操作,因为vector提供了丰富的成员函数,操作起来较为方便。
我们使用一个string类的字符串current,来存取当前需要读取的字符串。然后就是一个逻辑问题了,我们如何能够跳过每一个空格读取字符串呢?——
我们可以在for循环中遍历这个大的字符串input,然后在遍历的过程中,以是否碰见','为判断条件,如果没有遇见空格的话,就一直读取,如果碰见了空格,就将当前字符串传入vector数组中,并且将当前
字符串置空,这样我们就可以读取下一个字符串了。
提醒:
但是,这种方法无法提取到最后一个字符串,因为input字符串不是以','结尾的。不过没关系,我们给它提供一个特殊处理逻辑就可以了
以上逻辑的C++示例代码如下:
string input;
cin >> input;
vector<string> result(100);
//用来遍历当前所需要读取的字符串
string current;
//遍历input字符串(基于范围的for循环)
for (char ch : input) {
//如果没遇到逗号,就继续读取
if (ch != ',') current.push_back(ch);
else {
//遇见了逗号说明该遍历下一个字符串了
if (!current.empty()) {
result.push_back(current);
current.clear();
}
}
}
//单独处理最后一个字符串
if (!current.empty()) result.push_back(current);
然后,我们只需要定义一个函数,用来判断这个字符串是否合规,最后,遍历这个vector数组中的每一个字符串进行判断即可。
如何定义这个函数呢?
首先,我们需要传入的参数是一个字符串类型的变量,我们可以设置三个bool类型的值,用来判断三个条件中是否至少满足其中两个(大写字母,小写字母和数字)。
然后,用一个变量typeCount,用来判断即可。剩下的“不能出现#@!$”这四个符号以外的符号,这个逻辑,我们也只需要用一个bool类型的变量hasSpecial来判断即可,将这个bool类型的值初始化为false,
如果出现了这四个符号以及上述字母和数字之外的变量,那么我们就将其置为false即可,最后,看hasSpecial的值和typeCount的值即可判断。
C++示例代码如下:
int check(const string& s) {
int size = s.size();
//字符串长度小于6或者大于12,肯定不合规
if (size < 6 || size > 12) return 0;
//定义四个bool类型的变量,用于判断
bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
for (char ch : s) {
//判断出现字母,数字,和其他四个符合的if判断语句一定要写在一起
if (ch >= 'a' && ch <= 'z') hasLower = true;
else if (ch >= 'A' && ch <= 'Z') hasUpper = true;
else if (ch >= '0' && ch <= '9') hasDigit = true;
else if (ch == '!' || ch == '@' || ch == '#' || ch == '$') hasSpecial = true;
else return 0; // 如果包含不允许的字符,则返回不符合要求
}
// 检查是否至少有两种不同的字符类型
int typeCount = (hasLower ? 1 : 0) + (hasUpper ? 1 : 0) + (hasDigit ? 1 : 0);
if (typeCount >= 2 && hasSpecial) return 1;
return 0;
}
最后,整个程序的代码如下:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int check(const string& s) {
int size = s.size();
//字符串长度小于6或者大于12,肯定不合规
if (size < 6 || size > 12) return 0;
//定义四个bool类型的变量,用于判断
bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
for (char ch : s) {
//判断出现字母,数字,和其他四个符合的if判断语句一定要写在一起
if (ch >= 'a' && ch <= 'z') hasLower = true;
else if (ch >= 'A' && ch <= 'Z') hasUpper = true;
else if (ch >= '0' && ch <= '9') hasDigit = true;
else if (ch == '!' || ch == '@' || ch == '#' || ch == '$') hasSpecial = true;
else return 0; // 如果包含不允许的字符,则返回不符合要求
}
// 检查是否至少有两种不同的字符类型
int typeCount = (hasLower ? 1 : 0) + (hasUpper ? 1 : 0) + (hasDigit ? 1 : 0);
if (typeCount >= 2 && hasSpecial) return 1;
return 0;
}
int main()
{
string input;
cin >> input;
vector<string> result(100);
//用来遍历当前所需要读取的字符串
string current;
//遍历input字符串(基于范围的for循环)
for (char ch : input) {
//如果没遇到逗号,就继续读取
if (ch != ',') current.push_back(ch);
else {
//遇见了逗号说明该遍历下一个字符串了
if (!current.empty()) {
result.push_back(current);
current.clear();
}
}
}
//单独处理最后一个字符串
if (!current.empty()) result.push_back(current);
for (const string& password : result) {
if (check(password) == 1) cout << password << endl;
}
return 0;
}