B3843 [GESP202306 三级] 密码合规
题目描述
网站注册需要有用户名和密码,编写程序以检查用户输入密码的有效性。合规的密码应满足以下要求 :。
-
只能由 <math xmlns="http://www.w3.org/1998/Math/MathML"> a ∼ z \texttt a \sim \texttt z </math>a∼z 之间 <math xmlns="http://www.w3.org/1998/Math/MathML"> 26 26 </math>26 个小写字母、 <math xmlns="http://www.w3.org/1998/Math/MathML"> A ∼ Z \texttt A \sim \texttt Z </math>A∼Z 之间 <math xmlns="http://www.w3.org/1998/Math/MathML"> 26 26 </math>26 个大写字母、 <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 ∼ 9 0 \sim 9 </math>0∼9 之间 <math xmlns="http://www.w3.org/1998/Math/MathML"> 10 10 </math>10 个数字以及
!@#$
四个特殊字符构成。 -
密码最短长度 <math xmlns="http://www.w3.org/1998/Math/MathML"> : 6 :6 </math>:6 个字符,密码最大长度 <math xmlns="http://www.w3.org/1998/Math/MathML"> : 12 :12 </math>:12 个字符。
-
大写字母,小写字母和数字必须至少有其中两种,以及至少有四个特殊字符中的一个。
输入格式
输入一行不含空格的字符串。约定长度不超过 <math xmlns="http://www.w3.org/1998/Math/MathML"> 100 100 </math>100。该字符串被英文逗号分隔为多段,作为多组被检测密码。
输出格式
输出若干行,每行输出一组合规的密码。输出顺序以输入先后为序,即先输入则先输出。
输入输出样例 #1
输入 #1
bash
seHJ12!@,sjdkffH$123,sdf!@&12HDHa!,123&^YUhg@!
输出 #1
bash
seHJ12!@
sjdkffH$123
说明/提示
【样例 1 解释】
输入被英文逗号分为了四组被检测密码:seHJ12!@
、sjdkffH$123
、sdf!@&12HDHa!
、123&^YUhg@!
。其中 sdf!@&12HDHa!
长度超过 12 个字符,不合规;123&^YUhg@!
包含四个特殊字符之外的字符不合规。
✅ 带注释的简化代码 + 思路解释
arduino
cpp
复制编辑
#include <iostream> // 用于输入输出
#include <sstream> // 用于字符串分割
#include <string> // 使用 string 类型
using namespace std;
// 检查一个密码是否合规的函数
bool isValid(string pwd) {
int len = pwd.length();
// 【规则1】判断长度是否在6到12之间
if (len < 6 || len > 12) return false;
// 【规则2】准备四个布尔变量,分别表示是否包含这四种字符
bool hasLower = false; // 是否有小写字母
bool hasUpper = false; // 是否有大写字母
bool hasDigit = false; // 是否有数字
bool hasSpecial = false; // 是否有特殊字符 !@#$
// 遍历密码中的每个字符
for (int i = 0; i < len; i++) {
char ch = pwd[i];
// 分别判断是哪种字符
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 false; // 出现不允许的字符,直接不合规
}
// 【规则3】必须至少包含三种中的两种:小写、大写、数字
int count = 0;
if (hasLower) count++;
if (hasUpper) count++;
if (hasDigit) count++;
// 【规则4】必须至少有一个特殊字符
if (count >= 2 && hasSpecial) return true;
else return false;
}
// 主函数:读取整行输入,并按逗号分割每段密码进行判断
int main() {
string line;
getline(cin, line); // 一行输入,比如 "abcD12@,1234,Hello$World"
stringstream ss(line); // 用 stringstream 把这行按逗号分割
string word;
while (getline(ss, word, ',')) { // 每次取一个密码
if (isValid(word)) {
cout << word << endl; // 如果合规,就输出
}
}
return 0;
}
✅ 为什么这样设计思路?
步骤 | 为什么这么做? |
---|---|
getline(cin, line) |
一次读取整行,方便用逗号分割出多个密码 |
stringstream + getline(..., ',', ...) |
用逗号分段处理,自动分组,不用手动写切割逻辑 |
for (char ch : pwd) |
检查每个字符类型,统计字符分类,逐个判断是否合规 |
四个布尔变量 | 使用布尔变量判断是否至少包含两种类型字符,更清晰、容易判断 |
提前返回 false |
遇到非法字符时立即退出,减少不必要判断,提高效率 |
count >= 2 && hasSpecial |
最核心的合规逻辑判断 |
✅ 小总结(适合讲课时说)
- 本题的难点不在语法,而在规则拆解 和清晰判断逻辑。
- 我们用布尔变量去标记"是否出现过某类字符",这样比一大堆 if 嵌套更容易维护。
- 特别注意提前判断非法字符,一旦发现直接返回 false,不要再继续检查其他条件。