基于strcmp的多字符串验证登录代码运行异常问题排查
登录功能C代码问题排查与修复
问题描述
编写的登录功能代码在输入用户名和密码后直接终止,无法执行后续逻辑,代码如下:
typedef struct uLogin { char user1,user2,user3,user4; } uLogin; void loginUser() { uLogin x1; int i, m, n; char pass_list[20] = "12345678",name[10],pass[10]; x1.user1 = "DSET2G1"; x1.user2 = "DSET2G2"; x1.user3 = "DSET2G3"; x1.user4 = "DSET2G4"; printf("\nEnter username: "); scanf("%s",&name); fflush(stdout); printf("\nEnter Password :"); scanf("%s",&pass); fflush(stdout); m = (strcmp(name,x1.user1)==0 && strcmp(name,x1.user2)==0 && strcmp(name,x1.user3)==0 && strcmp(name,x1.user4)==0); n = strcmp(pass,pass_list); if(m == 0 && n == 0) { system("CLS"); printf("Hello"); } else { system("CLS"); printf("Bye"); } }
核心问题与原因
- 结构体成员类型错误:
uLogin结构体中的user1到user4被定义为char类型,单个char仅能存储一个字符,无法容纳完整字符串。将字符串字面量(如"DSET2G1")赋值给char变量,本质是把字符串的首地址(指针值)强制转换为char,直接破坏内存布局,触发未定义行为。 - scanf传参错误:
name和pass是字符数组名,本身就是指向数组首元素的指针,不需要加&。使用scanf("%s",&name)会传入数组的地址(指针的指针),导致scanf向错误内存地址写入数据,直接引发程序崩溃或异常终止。 - 用户名匹配逻辑完全错误:代码用
&&连接四个strcmp判断,意味着输入的用户名必须同时等于四个不同的字符串,这在逻辑上不可能成立,m的值永远为0,后续判断逻辑完全失效。 - 缺少必要头文件:
strcmp函数需要<string.h>头文件,system函数需要<stdlib.h>头文件,未包含这些头文件会导致编译器无法识别函数,引发未定义行为。
修正后的代码
#include <stdio.h> #include <string.h> #include <stdlib.h> // 修改结构体成员为字符串指针类型,支持存储字符串地址 typedef struct uLogin { const char* user1; const char* user2; const char* user3; const char* user4; } uLogin; void loginUser() { uLogin x1; int is_valid_user = 0; int is_valid_pass = 0; char pass_list[20] = "12345678", name[10], pass[10]; // 正确赋值字符串指针 x1.user1 = "DSET2G1"; x1.user2 = "DSET2G2"; x1.user3 = "DSET2G3"; x1.user4 = "DSET2G4"; printf("\nEnter username: "); // 数组名直接作为参数,无需加& scanf("%s", name); fflush(stdout); printf("\nEnter Password :"); scanf("%s", pass); fflush(stdout); // 修改匹配逻辑:用户名匹配任意一个合法用户即有效 if (strcmp(name, x1.user1) == 0 || strcmp(name, x1.user2) == 0 || strcmp(name, x1.user3) == 0 || strcmp(name, x1.user4) == 0) { is_valid_user = 1; } is_valid_pass = (strcmp(pass, pass_list) == 0); if (is_valid_user && is_valid_pass) { system("CLS"); printf("Hello"); } else { system("CLS"); printf("Bye"); } }
关键修改说明
- 补充
<string.h>、<stdlib.h>头文件,确保标准函数能被正确识别。 - 将结构体成员改为
const char*类型,用于存储字符串字面量的地址,正确存储用户名。 - 移除
scanf参数中的&,直接传入数组名,保证写入地址正确。 - 将用户名匹配逻辑从
&&改为||,只要输入用户名匹配任意一个合法用户即判定为有效。 - 变量命名更具语义化,提升代码可读性。
内容的提问来源于stack exchange,提问作者renlovescookies
相关产品推荐
相关产品推荐

