[GESP202306 三级] 密码合规

247 阅读2分钟

B3843 [GESP202306 三级] 密码合规

题目描述

网站注册需要有用户名和密码,编写程序以检查用户输入密码的有效性。合规的密码应满足以下要求 :。

  1. 只能由 az\texttt a \sim \texttt z 之间 2626 个小写字母、AZ\texttt A \sim \texttt Z 之间 2626 个大写字母、090 \sim 9 之间 1010 个数字以及 !@#$ 四个特殊字符构成。

  2. 密码最短长度 :6:6 个字符,密码最大长度 :12:12 个字符。

  3. 大写字母,小写字母和数字必须至少有其中两种,以及至少有四个特殊字符中的一个。

输入格式

输入一行不含空格的字符串。约定长度不超过 100100。该字符串被英文逗号分隔为多段,作为多组被检测密码。

输出格式

输出若干行,每行输出一组合规的密码。输出顺序以输入先后为序,即先输入则先输出。

输入输出样例 #1

输入 #1

seHJ12!@,sjdkffH$123,sdf!@&12HDHa!,123&^YUhg@!

输出 #1

seHJ12!@
sjdkffH$123

说明/提示

【样例 1 解释】

输入被英文逗号分为了四组被检测密码:seHJ12!@sjdkffH$123sdf!@&12HDHa!123&^YUhg@!。其中 sdf!@&12HDHa! 长度超过 12 个字符,不合规;123&^YUhg@! 包含四个特殊字符之外的字符不合规。

✅ 带注释的简化代码 + 思路解释

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,不要再继续检查其他条件。