C语言用户名密码验证程序无输出问题排查求助
问题:验证用户账号并输出有效用户名
需求说明
- 收集n组格式为「username:password」的输入(空格可忽略),需遵循以下规则:
- n为输入的用户组数;
- 用户名需为4位字符,首字符不能是数字,且包含至少一个大写或小写字母;
- 密码长度4-8位,至少包含2个数字,且同时包含大写和小写字母。
- 验证通过则输出对应的有效用户名。
示例输入
4 Std1: jEb20j //ps. I add the white space intentionally to tell that the white space isn’t matter. cs1r:9i9J9T a2Mn:cat88 User5:feb20E
示例输出
Std1 cs1r
我的代码(存在问题,无输出)
#include <stdio.h> #include <string.h> void checking(char []); int main() { int n; scanf("%d", &n); getchar(); char users[14]; int i; for(i=0;i<n;i++) { gets(users); checking(users); } } void checking(char users[]) { int len = strlen(users); char num[10] = "0123456789"; if(users[4] == ":") { //check username int i, checknum=0; for(i=0;i<10;i++) { checknum = 0; if(users[0] == num[i]) { checknum = 1; } } if(!checknum) { int checkul = 0; for(i=0;i<4;i++) { checkul = 0; if(users[i] >= 'A' && users[i] <= 'Z') { if(users[i] >= 'a' && users[i] <= 'z') { checkul = 1; } else checkul = 0; } else checkul = 0; } //check password if(checkul) { int j,f = len-5; int numcheck = 0; if(f >= 4 && f <= 8) { int check2 = 0; for(i=5;i<f;i++) { check2 = 0; if(users[i] >= 'A' && users[i] <= 'Z') { if(users[i] >= 'a' && users[i] <= 'Z') { check2 = 1; } else check2 = 0; } else check2 = 0; if(check2) { for(j=0;j<10;j++) { if(num[j] == users[i]) { numcheck++; } } } } } if(numcheck >= 2) { for(i=0;i<4;i++) { printf("%s " ,users[i]); } } } } } }
问题分析与修正
你的代码存在多处语法错误和逻辑漏洞,导致无输出,以下是逐一修正方案:
1. 字符与字符串比较错误
if(users[4] == ":") 中,":"是字符串常量,而users[4]是单个字符,应改为单引号包裹的字符:
if(users[4] == ':')
2. 用户名首字符检测逻辑错误
原代码循环中每次都会重置checknum为0,导致只有当首字符是数字9时才会被正确标记。修正为找到匹配后立即退出循环:
int checknum = 0; for(i=0;i<10;i++) { if(users[0] == num[i]) { checknum = 1; break; } }
3. 用户名字母检测逻辑错误
原代码判断一个字符同时是大写和小写,逻辑矛盾。应改为只要存在任意一个字母就标记为有效:
int checkul = 0; for(i=0;i<4;i++) { if((users[i] >= 'A' && users[i] <= 'Z') || (users[i] >= 'a' && users[i] <= 'z')) { checkul = 1; break; } }
4. 忽略空格的逻辑缺失
需求要求忽略空格,但原代码未处理密码部分的空格,需先过滤空格再验证密码。
5. 密码遍历范围错误
原代码中for(i=5;i<f;i++)的范围计算错误,应遍历冒号后的所有字符(跳过空格)。
6. 密码大小写检测逻辑错误
原代码无法正确判断密码是否同时包含大小写,需分别标记大写、小写的存在状态。
7. 用户名输出错误
printf("%s ", users[i]) 中%s用于输出字符串,但users[i]是单个字符,应改为%.4s直接输出前4位用户名。
修正后的完整代码
#include <stdio.h> #include <string.h> #include <ctype.h> void checking(char []); int main() { int n; scanf("%d", &n); getchar(); // 读取换行符 char users[100]; // 扩大数组容量避免溢出 int i; for(i=0;i<n;i++) { fgets(users, sizeof(users), stdin); // 替换不安全的gets // 去除换行符 size_t len = strlen(users); if(len > 0 && users[len-1] == '\n') { users[len-1] = '\0'; } checking(users); } return 0; } void checking(char users[]) { // 定位冒号,验证用户名长度为4位 char *colon_pos = strchr(users, ':'); if(!colon_pos || colon_pos - users != 4) { return; } // 检查用户名首字符是否为数字 if(isdigit(users[0])) { return; } // 检查用户名是否包含至少一个字母 int has_alpha = 0; for(int i=0;i<4;i++) { if(isalpha(users[i])) { has_alpha = 1; break; } } if(!has_alpha) { return; } // 过滤密码部分的空格 char password[20] = {0}; int pwd_idx = 0; for(char *p = colon_pos + 1; *p != '\0'; p++) { if(!isspace(*p)) { password[pwd_idx++] = *p; } } // 检查密码长度 int pwd_len = strlen(password); if(pwd_len <4 || pwd_len >8) { return; } // 检查密码的数字、大小写要求 int digit_count = 0; int has_upper = 0; int has_lower = 0; for(int i=0;i<pwd_len;i++) { if(isdigit(password[i])) { digit_count++; } else if(isupper(password[i])) { has_upper = 1; } else if(islower(password[i])) { has_lower = 1; } } // 所有条件满足则输出用户名 if(digit_count >=2 && has_upper && has_lower) { printf("%.4s\n", users); } }
测试验证
使用示例输入测试,修正后的代码会输出预期结果:
Std1 cs1r
内容的提问来源于stack exchange,提问作者doeeyes
相关产品推荐
相关产品推荐

