[GESP202306 三级] 密码合规
借以此问题实践指定范围的子串截取方法。
题目描述
网站注册需要有用户名和密码,编写程序以检查用户输入密码的有效性。合规的密码应满足以下要求 :。
- 只能由
a
∼
z
\texttt a \sim \texttt z
a∼z 之间
26
26
26 个小写字母、
A
∼
Z
\texttt A \sim \texttt Z
A∼Z 之间
26
26
26 个大写字母、
0
∼
9
0 \sim 9
0∼9 之间
10
10
10 个数字以及
!@#$
四个特殊字符构成。 - 密码最短长度 : 6 :6 :6 个字符,密码最大长度 : 12 :12 :12 个字符。
- 大写字母,小写字母和数字必须至少有其中两种,以及至少有四个特殊字符中的一个。
输入格式
输入一行不含空格的字符串。约定长度不超过 100 100 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@!
包含四个特殊字符之外的字符不合规。
思路
本问题分三步来解决:
- 以逗号分割,保证每次迭代都可提取出一个待检测密码(注意判断原字符串结束位置);
- 设计一个指定范围的子串分割方法,其中区间为左闭右开;
- 按照问题要求,设计一个判断密码是否符合要求的方法。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define OK 1
#define NO 0
typedef long long LL;
// const int INF = 2e9;
// const double pi = 3.14;
char* substr(char a[], int l, int r) {
char *ans = (char*)malloc(sizeof(char) * 101);
int i, j = 0;
for (i = l; i < r; i++) {
ans[j++] = a[i];
}
ans[j] = '\0';
return ans;
}
int check(char* s, int sz) {
if (sz < 6 || sz > 12)
return NO;
int i, lowcase = 0, uppercase = 0, num = 0, sp = 0;
for (i = 0; i < sz; i++) {
if (s[i] > 'a' && s[i] <= 'z') {
lowcase = 1;
} else if (s[i] >= 'A' && s[i] <= 'Z') {
uppercase = 1;
} else if (s[i] == '!' || s[i] == '@'
|| s[i] == '#' || s[i] == '$') {
sp = 1;
} else if (s[i] >= '0' && s[i] <= '9') {
num = 1;
} else {
return NO;
}
}
if (lowcase + uppercase + num < 2) {
return NO;
}
return OK;
}
int main() {
char ci[101]; gets(ci);
int len = strlen(ci);
int i = 0, j;
while (i < len) {
int pre = i;
while (i != len && ci[i] != ',') i++;
char *t = substr(ci, pre, i);
// printf("%d\n", i - pre);
if (check(t, i - pre)) {
printf("%s\n", t);
}
i++;
}
return 0;
}
小结
记录本问题的原因在于一个点 —— 实现了范围指定的子串截取方法,其中的函数 substr(char a[], int l , int r) 可作为一个C语言版本模板,在类似问题中实现并调用。
每一个不曾起舞的日子,都是对生命的辜负。