题目入口:密码验证合格程序
问题描述
密码要求:
1.长度超过8位
2.包括大小写字母.数字.其它符号,以上四种至少三种
3.不能有长度大于2的不含公共元素的子串重复 (注:其他符号不含空格或换行)
数据范围:输入的字符串长度满足 1≤n≤100
输入:
一组字符串。
输出:
如果符合要求输出:OK,否则输出NG
解题思路
如常规的OJ一样,同样是while循环scanf接受。不过这次要接收字符串要用‘%s’。
本题主要是判断输入字符串是否符合规则,
下面,我会分别讲解符合规则的三个条件该怎么判断
1、长度超过8位
这个条件好解决,只需要用到strlen库函数即可得到字符串长度。
2、包括大小写字母.数字.其它符号,以上四种至少三种
因为要统计字符串里面字符的种类,所以我们要遍历每个字符串同时记录,但该如何记录呢?
如果我们定义一个变量,每次遍历到的字符在范围内就统计一次,最后再验证该边量是否等于四,这样可行吗?显然是不可行的,我们需要定义四个变量。
比如我们定义a、 b、 c 、d 四个变量并初始化为0,在遍历每个字符串时,添加下面的条件。
当循环字母满足(1)时就把a置为1(注意是置为1而不是++1)
当循环字母满足(2)时就把b置为1
当循环字母满足(3)时就把c置为1
当循环字母满足(4)时就把d置为1
当遍历结束,判断(a+b+c+d)的值,如果满足则进行下一个条件的检验
(1)'A' <= str[i] && str[i] <= 'Z'
(2)'1' <= str[i] && str[i] <= '9'
(3)'a' <= str[i] && str[i] <= 'w'
(4)其他
3、不能有长度大于2的不含公共元素的子串重复 (注:其他符号不含空格或换行)
第三个条件也是这三个条件中最难的,我解释一个不能有长度大于2的不含公共元素的子串重复
如下图:
该字符串中有两个子串重复,分别是'AbcA',但是大家看我画的方格有重叠的部分'A',这种就叫‘含公共子串重复’。
题义理解清楚了,那我们该怎么找出重复子串呢?大家想一个如果用两个for循环嵌套然后用外层和内层元素一个一个相比较那太麻烦了,而且需要创建的变量太多不行。我们能不能再赋值一份该字符串,然后一个动一个不动,一个一个比较
我们把固定不动的字符串称为str,把动的字符串称为cmp
当str中第i个字符与cmp中第j的字符相同时,就把str中i+1和i+2和cmp中j+1和j+2中的字符分别比对
如果比对成功,则该字符串不符合条件
最后,三个条件我们都分析完了,聪明的你肯定会发现,这三个条件判断难度是逐渐递增的。
当字符串不满足条件1时,那条件2和条件3也不用判断了,所以我们把条件1放到if语句的最外成,把条件3放到if语句的最内层,这样就可以节省时间。
代码实现
#include<stdio.h> #include<string.h> int main() { char str[100]; while (scanf("%s",str)!=EOF) { int sz = strlen(str); if (sz <= 8)//第一个条件判断 { printf("NG\n"); } else { int a = 0, b = 0, c = 0, d = 0; for (int i = 0; i < sz; i++) { if ('A' <= str[i] && str[i] <= 'Z') { a = 1; } else if ('1' <= str[i] && str[i] <= '9') { b = 1; } else if ('a' <= str[i] && str[i] <= 'w') { c = 1; } else { d = 1; } } if (((a + b + c + d) < 3))//第二个条件判断 { printf("NG\n"); } else { //判断长度大于2的不含公共元素的子串重复 char* cmp = (char*)malloc(sz * sizeof(char)); int m = 0; strcpy(cmp, str);//把str中的字符复制给cmp for (int i = 0; i < sz - 3; i++) { for (int j = i + 3; j < sz; j++) { if (str[i] == cmp[j] && str[i + 1] == cmp[j + 1] && str[i + 2] == cmp[j + 2]) { m = 1; break; } } } if (m == 1)//第三个条件判断 { printf("NG\n"); } else { printf("OK\n"); } } } }