C语言密码校验器代码异常:合法密码组合被判无效
密码校验代码的问题分析与修复
原代码如下:
#include <stdio.h> #include <ctype.h> #include <string.h> int main() { char pass[99]; int i, x; while(1) { printf("Enter a password:"); scanf("%s", pass); // Check if first character is uppercase if (!isupper(pass[0])) { printf("Password Invalid!\n"); continue; } x = 0; // Check each character in the password for (i = 0; i < strlen(pass); i++) { // If the character is not a digit or a valid special character, password is invalid if (!isdigit(pass[i]) && pass[i] != '?' && pass[i] != '_' && pass[i] != '$' && pass[i] != '!') { printf("Password Invalid!\n"); x = 0; break; } x++; } // If the password length is less than 8 characters, password is invalid if (x < 8) { printf("Password Invalid!\n"); continue; } // If password passes all checks, password is valid printf("Password Valid\n"); break; } return 0; }
问题说明
这段代码的核心逻辑错误导致合法密码被判定无效:
- 首字符规则冲突:代码单独校验首字符为大写字母后,遍历所有字符时又要求每个字符必须是数字或指定特殊字符,而大写字母既不属于数字也不属于指定特殊字符,因此只要首字符合法,就会触发无效判定。
- 需求未完全实现:原需求要求密码“包含数字或指定特殊字符”,但当前代码仅限制非首字符必须是数字/特殊字符,未校验是否至少存在一个这类字符(比如全大写字母的长密码会被误判为合法,但不符合需求)。
修复后的代码
#include <stdio.h> #include <ctype.h> #include <string.h> int main() { char pass[99]; int i; int has_valid_char = 0; // 标记是否包含数字或特殊字符 while(1) { printf("Enter a password:"); scanf("%s", pass); int len = strlen(pass); has_valid_char = 0; // 检查首字符是否为大写字母 if (!isupper(pass[0])) { printf("Password Invalid!\n"); continue; } // 检查长度是否大于8位(即至少9位) if (len <= 8) { printf("Password Invalid!\n"); continue; } // 从第2个字符开始检查,同时确认是否有数字或特殊字符 for (i = 1; i < len; i++) { // 字符必须是数字或指定特殊字符 if (isdigit(pass[i]) || pass[i] == '?' || pass[i] == '_' || pass[i] == '$' || pass[i] == '!') { has_valid_char = 1; // 标记存在有效字符 } else { // 存在非法字符,直接判定无效 printf("Password Invalid!\n"); goto next_attempt; // 跳转到下一次输入 } } // 检查是否包含至少一个数字或特殊字符 if (!has_valid_char) { printf("Password Invalid!\n"); continue; } // 所有校验通过 printf("Password Valid\n"); break; next_attempt: continue; } return 0; }
修复要点
- 跳过首字符检查:遍历从索引1开始,不再检查首字符,避免与大写字母的要求冲突。
- 添加有效字符标记:用
has_valid_char跟踪是否存在至少一个数字或指定特殊字符,满足“包含”的需求。 - 明确长度判断:直接用
strlen(pass)判断长度是否大于8,逻辑更清晰。 - 优化错误处理:遇到非法字符时直接跳转到下一次输入,减少冗余判断。
内容的提问来源于stack exchange,提问作者Boo Man
相关产品推荐
相关产品推荐

