如何让C语言strcmp函数逐行校验存储文件中的用户登录凭证
问题根因分析
- 登录函数仅执行了一次
fread读取操作,仅能获取文件中存储的第一个用户信息,没有循环遍历所有用户记录 - 注册逻辑存在冗余操作:写完二进制结构体数据后额外调用
fputs("\n", fp)写入了换行符,会导致文件内每个用户记录后面多1个无效字节,后续循环读取时会出现偏移错误,无法正确解析后续用户的结构体数据 - 登录流程逻辑不合理:校验失败直接调用
main()会导致函数递归栈溢出,属于未定义行为
修复方案
1. 注册函数修改
删除多余的换行符写入操作,使用二进制追加模式打开文件,避免数据污染:
void cadastrar_user() { FILE *fp; struct usuario_t usuario; memset(&usuario,0,sizeof(struct usuario_t)); printf("\n ----Cadastro de usuario----"); printf("\n\n Insira um login> "); scanf("%s", usuario.login); printf("\n Insira uma senha> "); scanf("%s", usuario.senha); fp = fopen("login", "ab"); fwrite(&usuario, sizeof(struct usuario_t), 1, fp); fclose(fp); printf("\n"); printf("\n ---- Usuario cadastrado, redirecionando para login! ----"); login(); }
2. 登录函数修改
新增循环遍历逻辑,读取所有用户记录逐一比对登录凭证:
int login(){ FILE *fp; struct usuario_t usuario_tmp; char login[LOGIN_MAX]; char senha[SENHA_MAX]; int login_success = 0; fp = fopen("login","rb"); if(fp == NULL) { printf("\n ----Cadastro nao encontrado, redirecionando para cadastro!----\n"); cadastrar_user(); return 0; } printf("\n Login> "); scanf("%s", login); printf(" Senha> "); scanf("%s", senha); while(fread(&usuario_tmp, sizeof(struct usuario_t), 1, fp) == 1) { if (!strcmp(login, usuario_tmp.login) && !strcmp(senha, usuario_tmp.senha)) { login_success = 1; break; } } fclose(fp); if(login_success) { printf("\n Bem vindo %s!\n", login); menu_crud(); } else { printf(" \n----Usuario ou senha invalidos!----\n"); printf("\n Tente novamente! Redirecionando para a pagina inicial\n\n"); return -1; } return 0; }
补充注意事项
scanf读取字符串时不需要加取地址符&,字符数组名本身就是首地址,加&属于语法不规范,部分编译器会报错- 不要在业务函数中直接调用
main(),会导致递归调用栈不断叠加,运行多次后会出现栈溢出崩溃 - 存储密码建议做哈希加密,不要明文存储到文件中,避免信息泄露
内容的提问来源于stack exchange,提问作者Davi Cabral
相关产品推荐
相关产品推荐

