- C++
[GESP202306 三级] 密码合规
- 2025-7-14 20:18:38 @
B3843 [GESP202306 三级] 密码合规
题目描述
网站注册需要有用户名和密码,编写程序以检查用户输入密码的有效性。合规的密码应满足以下要求 :。
-
只能由 之间 个小写字母、 之间 个大写字母、 之间 个数字以及
!@#$
四个特殊字符构成。 -
密码最短长度 个字符,密码最大长度 个字符。
-
大写字母,小写字母和数字必须至少有其中两种,以及至少有四个特殊字符中的一个。
输入格式
输入一行不含空格的字符串。约定长度不超过 。该字符串被英文逗号分隔为多段,作为多组被检测密码。
输出格式
输出若干行,每行输出一组合规的密码。输出顺序以输入先后为序,即先输入则先输出。
输入输出样例 #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@!
包含四个特殊字符之外的字符不合规。
2 条评论
-
admin SU @ 2025-7-14 20:20:04
下面是优化变量名称后的C++密码合规检测程序学习笔记,变量名更直观,代码注释更详细,便于理解:
C++密码合规检测程序学习笔记(优化版)
一、程序目标
编写程序检测密码是否合规,合规密码需满足3个条件(见题目描述)。程序需读取用逗号分隔的多个密码,逐个检测后输出所有合规的密码。
二、优化后的代码(带详细注释)
#include<iostream> #include<string> // 注意:原代码漏了<string>头文件,这里补充,否则string操作可能报错 using namespace std; // 函数功能:检查单个密码是否合规 // 参数:待检测的密码字符串 // 返回值:true(合规)/ false(不合规) bool isPasswordValid(string password) { // 1. 检查长度是否在6-12之间(条件2) int passwordLen = password.size(); // 获取密码长度 if (passwordLen < 6 || passwordLen > 12) { return false; // 长度不合格 } // 2. 检查是否只包含允许的字符(条件1) int validCharCount = 0; // 记录合法字符的数量 for (int i = 0; i < passwordLen; i++) { char currentChar = password[i]; // 当前遍历的字符 // 判断是否为小写字母 if (currentChar >= 'a' && currentChar <= 'z') { validCharCount++; } // 判断是否为大写字母 else if (currentChar >= 'A' && currentChar <= 'Z') { validCharCount++; } // 判断是否为数字 else if (currentChar >= '0' && currentChar <= '9') { validCharCount++; } // 判断是否为允许的特殊字符(!@#$) else if (currentChar == '!' || currentChar == '@' || currentChar == '#' || currentChar == '$') { validCharCount++; } // 如果以上都不是,说明是非法字符,直接返回不合格 else { return false; } } // 注意:上面的else已经处理了非法字符,这里其实可以省略这个判断,不过保留更稳妥 if (validCharCount != passwordLen) { return false; } // 3. 检查字符类型是否满足要求(条件3) bool hasUpper = false; // 是否包含大写字母 bool hasLower = false; // 是否包含小写字母 bool hasDigit = false; // 是否包含数字 bool hasSpecial = false; // 是否包含特殊字符 // 遍历密码,标记各类字符是否存在 for (int i = 0; i < passwordLen; i++) { char currentChar = password[i]; if (currentChar >= 'A' && currentChar <= 'Z') { hasUpper = true; // 标记有大写字母 } else if (currentChar >= 'a' && currentChar <= 'z') { hasLower = true; // 标记有小写字母 } else if (currentChar >= '0' && currentChar <= '9') { hasDigit = true; // 标记有数字 } else { hasSpecial = true; // 能走到这一步,说明是!@#$中的一个 } } // 检查是否满足:大写/小写/数字至少有两种,且至少有一个特殊字符 int letterOrDigitType = 0; // 记录大写/小写/数字的类型数量 if (hasUpper) letterOrDigitType++; if (hasLower) letterOrDigitType++; if (hasDigit) letterOrDigitType++; if (letterOrDigitType < 2) { // 不足两种类型 return false; } if (!hasSpecial) { // 没有特殊字符 return false; } // 所有条件都满足,返回合规 return true; } int main() { string inputStr; // 存储输入的整行字符串(多个密码用逗号分隔) cin >> inputStr; // 读取输入 // 在输入末尾加一个逗号,方便统一处理最后一个密码(避免单独判断边界) inputStr += ","; string passwords[200]; // 存储分割后的所有密码 int passwordCount = 0; // 记录密码的总数量 int inputLen = inputStr.size(); // 输入字符串的长度 int startIndex = 0; // 记录当前密码在输入字符串中的起始位置 // 分割输入字符串,提取每个密码(按逗号分割) for (int i = 0; i < inputLen; i++) { if (inputStr[i] == ',') { // 遇到逗号,说明前面是一个完整的密码 passwordCount++; // 密码数量加1 // 提取从startIndex到i-1的子字符串(即当前密码) // substr(起始位置, 长度):长度 = 结束位置 - 起始位置 passwords[passwordCount] = inputStr.substr(startIndex, i - startIndex); startIndex = i + 1; // 更新下一个密码的起始位置 } } // 逐个检查密码是否合规,合规则输出 for (int i = 1; i <= passwordCount; i++) { if (isPasswordValid(passwords[i])) { // 调用检查函数 cout << passwords[i] << endl; } } return 0; }
三、变量名优化说明
原代码的变量名较为简略(如
cnt
、str
、a/b/c/d
),优化后更直观:cnt
→validCharCount
(合法字符计数)、passwordCount
(密码总数)str
→password
(单个密码)、inputStr
(输入字符串)a/b/c/d
→hasUpper
(有大写字母)、hasLower
(有小写字母)、hasDigit
(有数字)、hasSpecial
(有特殊字符)len
→passwordLen
(密码长度)、inputLen
(输入字符串长度)start
→startIndex
(起始索引)
优化后的变量名能直接反映变量的含义,减少理解成本。
四、核心逻辑拆解
-
输入处理
- 读取整行输入,通过在末尾加逗号,统一处理所有密码的分割(无需单独判断最后一个密码)
- 用
substr
函数提取子字符串,实现按逗号分割密码
-
合规检查(
isPasswordValid
函数)- 长度检查:先判断密码长度是否在6-12之间,不满足则直接返回不合格
- 字符合法性检查:遍历每个字符,若存在不允许的字符(如
^
、&
等),返回不合格 - 类型检查:通过4个布尔变量标记是否存在大写/小写/数字/特殊字符,最终判断是否满足“至少两种字母/数字 + 至少一个特殊字符”
五、关键知识点
-
字符串操作
size()
:获取字符串长度(如password.size()
)substr(pos, len)
:提取子字符串(从pos
开始,长度为len
)- 字符遍历:通过
for
循环逐个访问password[i]
-
布尔变量的应用
- 用
hasXXX
系列布尔变量标记“是否存在某类字符”,避免重复判断,逻辑更清晰 - 示例:
hasUpper = true
表示密码中存在大写字母
- 用
-
函数封装
- 将密码检查逻辑封装到
isPasswordValid
函数中,使主函数更简洁,代码可复用
- 将密码检查逻辑封装到
六、测试案例分析(输入样例)
输入:
seHJ12!@,sjdkffH$123,sdf!@&12HDHa!,123&^YUhg@!
- 分割后得到4个密码,逐个检查:
seHJ12!@
:长度8(合规),含小写、大写、数字、!@
(合法字符),满足“3种字母/数字 + 特殊字符”→ 合规sjdkffH$123
:长度11(合规),含小写、大写、数字、$
→ 合规sdf!@&12HDHa!
:长度14(超过12)→ 不合规123&^YUhg@!
:含非法字符^
→ 不合规
输出:前两个合规的密码
七、常见问题
- 头文件遗漏:使用
string
类需包含<string>
头文件,否则可能编译报错 - 边界处理:输入末尾不加逗号可能导致最后一个密码无法正确分割,加逗号是简化逻辑的技巧
- 字符判断顺序:特殊字符判断需放在最后(因为字母/数字的判断范围更明确)
通过这个程序,我们可以掌握字符串处理、函数封装、条件判断等基础知识点,同时学习如何通过清晰的变量名和逻辑拆分提高代码可读性。
-
2025-7-14 20:18:46@
下面是一份关于密码合规检测程序的C++学习笔记教程,包含详细注释和分步解释:
C++密码合规检测程序学习笔记
一、题目分析
网站注册时,密码需要满足以下条件:
- 只能包含小写字母(a-z)、大写字母(A-Z)、数字(0-9)和特殊字符(!@#$)
- 长度要求:6-12个字符
- 必须包含至少两种类型的字符(大写、小写、数字)和至少一个特殊字符
二、程序设计思路
程序需要完成以下工作:
- 读取输入字符串并分割为多个密码
- 检查每个密码是否满足所有条件
- 输出符合条件的密码
三、代码实现与详细注释
#include<iostream> #include<string> using namespace std; // 检查密码是否合规的函数 bool check(string str) { int len = str.size(); // 条件2:检查密码长度是否在6-12个字符之间 if (len < 6 || len > 12) { return false; } // 条件1:检查所有字符是否都属于允许的类型 int cnt = 0; for (int i = 0; i < len; i++) { if ('a' <= str[i] && str[i] <= 'z') { cnt += 1; // 小写字母计数 } else if ('A' <= str[i] && str[i] <= 'Z') { cnt += 1; // 大写字母计数 } else if ('0' <= str[i] && str[i] <= '9') { cnt += 1; // 数字计数 } else if (str[i] == '!' || str[i] == '@' || str[i] == '#' || str[i] == '$') { cnt += 1; // 特殊字符计数 } } // 如果计数不等于字符串长度,说明有非法字符 if (cnt != len) { return false; } // 条件3:检查是否包含至少两种类型的字符和至少一个特殊字符 int a = 0, b = 0, c = 0, d = 0; for (int i = 0; i < len; i++) { if ('A' <= str[i] && str[i] <= 'Z') { a = 1; // 标记是否有大写字母 } if ('a' <= str[i] && str[i] <= 'z') { b = 1; // 标记是否有小写字母 } if ('0' <= str[i] && str[i] <= '9') { c = 1; // 标记是否有数字 } if (str[i] == '!' || str[i] == '@' || str[i] == '#' || str[i] == '$') { d = 1; // 标记是否有特殊字符 } } // 检查是否有至少两种字符类型 if (a + b + c < 2) { return false; } // 检查是否有特殊字符 if (d == 0) { return false; } return true; // 所有条件都满足,返回真 } int main() { string str; cin >> str; // 读取输入字符串 // 为了便于处理,在字符串末尾添加一个逗号 str += ","; string words[200]; // 存储分割后的密码 int cnt = 0; // 记录密码数量 int len = str.size(); int start = 0; // 记录当前密码的起始位置 // 分割字符串,提取每个密码 for (int i = 0; i < len; i++) { if (str[i] == ',') { cnt += 1; // 密码数量加1 // 提取从start到i的子字符串作为一个密码 words[cnt] = str.substr(start, i - start); start = i + 1; // 更新下一个密码的起始位置 } } // 检查并输出每个合规的密码 for (int i = 1; i <= cnt; i++) { if (check(words[i]) == true) { cout << words[i] << endl; } } return 0; }
四、核心知识点详解
-
字符串处理
str.size()
:获取字符串长度str.substr(start, length)
:提取子字符串- 字符串遍历:使用
for
循环逐个访问字符
-
条件判断
- 字符范围判断:
'a' <= str[i] && str[i] <= 'z'
- 逻辑组合判断:使用多个
if-else
和逻辑运算符
- 字符范围判断:
-
标记变量的使用
- 使用
a, b, c, d
四个标记变量记录是否存在不同类型的字符 - 通过标记变量的累加和判断是否满足条件
- 使用
-
字符串分割技巧
- 在字符串末尾添加分隔符简化处理
- 使用
substr
函数提取子字符串
五、测试与验证
对于输入样例:
seHJ12!@,sjdkffH$123,sdf!@&12HDHa!,123&^YUhg@!
程序会依次检查每个密码:seHJ12!@
:长度8,包含大写、小写、数字和特殊字符,符合条件sjdkffH$123
:长度11,包含小写、大写、数字和特殊字符,符合条件sdf!@&12HDHa!
:长度14,超过最大长度,不符合条件123&^YUhg@!
:包含非法字符^
,不符合条件
因此输出结果为:
seHJ12!@ sjdkffH$123
六、常见错误与注意事项
- 字符范围判断时要注意大小写和边界值
- 字符串分割时,处理最后一个子字符串的边界情况
- 标记变量的初始化和更新逻辑要清晰
- 注意字符串长度的有效范围检查
通过这个程序,我们学习了如何处理字符串、实现复杂条件判断以及使用标记变量来简化逻辑判断。这些技巧在日常编程中非常实用。
- 1