C语言登录系统:输入正确凭证仍触发重新登录问题求助
问题分析与修复方案
核心问题
你的代码触发误判重新登录的关键原因是验证逻辑过于激进:每读取一个用户条目,只要当前条目不匹配就直接调用relogin(),完全跳过了后续用户的校验。比如第一个管理员凭证不对,程序直接触发重新登录,不会继续检查其他管理员或普通员工账号。
除此之外还有几个潜在问题需要修复:
具体问题与修复步骤
遍历所有用户后再判断是否重新登录
原代码中,只要单个用户不匹配就立即调用relogin(),正确逻辑应该是遍历完所有目标用户,确认无匹配账号后再触发重新登录。替换不安全的输入函数与未定义行为
gets()已被C标准废弃,存在缓冲区溢出风险,改用fgets()。fflush(stdin)属于未定义行为,用字符串处理函数清空输入末尾的换行符。
检查文件打开状态
若文件不存在或无法读取,fopen()会返回NULL,必须先检查避免后续fread出错。匹配成功后终止当前函数
进入管理员/员工页面后,应通过return终止loginPage(),避免后续代码继续执行。
修复后的完整代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <conio.h> // 若使用getch()需包含此头文件 // 需确保该结构与写入文件时的定义完全一致 struct form { char username[30]; char password[20]; char roles[10]; char status[10]; }; void adminPage(); void OUsersPage(); void relogin(); void loginPage(){ char username[30], password[20]; struct form login; FILE *admin; FILE *staff; int admin_found = 0, staff_found = 0; // 检查管理员文件是否成功打开 admin = fopen("adminAcc.txt", "r"); if(admin == NULL){ printf("Failed to open admin account file!\n"); getch(); return; } // 检查员工文件是否成功打开 staff = fopen("ordinaryUsers.txt", "r"); if(staff == NULL){ printf("Failed to open staff account file!\n"); fclose(admin); getch(); return; } // 登录输入处理 printf("\nLogin Page"); printf("\n================"); printf("\nEnter Username: "); fgets(username, sizeof(username), stdin); username[strcspn(username, "\n")] = '\0'; // 移除输入末尾的换行符 printf("Enter Password: "); fgets(password, sizeof(password), stdin); password[strcspn(password, "\n")] = '\0'; // 遍历所有管理员账号 while(fread(&login, sizeof(struct form), 1, admin)){ if(strcmp(login.roles, "Admin") == 0){ if(strcmp(username, login.username) == 0 && strcmp(password, login.password) == 0){ system("cls"); adminPage(); admin_found = 1; break; } } } fclose(admin); if(admin_found){ return; // 管理员匹配成功,终止当前函数 } // 遍历所有员工账号 while(fread(&login, sizeof(struct form), 1, staff)){ if(strcmp(login.roles, "OU") == 0){ if(strcmp(username, login.username) == 0 && strcmp(password, login.password) == 0){ if(strcmp(login.status, "Disable") == 0){ printf("\nPlease wait for Admin to verify the account!"); getch(); system("cls"); relogin(); }else{ system("cls"); OUsersPage(); } staff_found = 1; break; } } } fclose(staff); // 所有账号均不匹配,触发重新登录 if(!admin_found && !staff_found){ relogin(); } }
额外注意事项
- 确保写入
adminAcc.txt和ordinaryUsers.txt时使用的struct form结构与读取时完全一致,否则fread会读取到错误数据。 - 避免直接调用
main()进行页面跳转,建议通过relogin()或重新调用loginPage()实现,防止栈溢出。 - 修复后的逻辑支持多管理员/多员工账号,会遍历所有条目直到找到匹配项。
内容的提问来源于stack exchange,提问作者wanmoranIwhaledye
相关产品推荐
相关产品推荐

