代码详细注释:C语言实现控制台用户注册登录系统
代码
/*4.注册登录练习*/
#include <stdio.h> // 标准输入输出头文件
#include <stdlib.h> // 标准库头文件
#include <string.h> // 字符串处理头文件
#include <strings.h> // 字符串操作头文件(兼容旧版)
#include <fcntl.h> // 文件控制头文件
#include <sys/types.h> // 系统数据类型头文件
#include <sys/stat.h> // 文件状态头文件
#include <unistd.h> // UNIX标准头文件
#include <time.h> // 时间处理头文件int error_cnt = 0; // 记录登录错误次数typedef struct // 定义用户结构体
{char username[20]; // 用户名(最大19字符+1结束符)char password[20]; // 密码(最大19字符+1结束符)
}User;//注册函数
void user_reg()
{User user; // 用户结构体变量int fd; // 文件描述符printf("请输入用户名:\n"); fgets(user.username, 20, stdin); // 获取用户名输入(包含换行符)printf("请输入密码:\n");fgets(user.password, 20, stdin); // 获取密码输入(包含换行符)// 打开用户文件(不存在则创建,追加模式)fd = open("user.txt", O_RDWR | O_CREAT | O_APPEND, 0666);if (fd == -1) // 检查文件是否成功打开{perror("open"); // 打印错误信息exit(1); // 退出程序}//将用户信息写入文件write(fd, &user, sizeof(user)); // 写入整个结构体close(fd); // 关闭文件
}//登录函数
void user_login()
{User user, tmp_user; // 用户结构体(文件读取和临时输入)int fd; // 文件描述符//检查是否存在保护锁文件if(access("time.dat", F_OK) == 0){ // 检查time.dat文件是否存在int time_fd = open("time.dat", O_RDWR); // 打开时间记录文件if (time_fd == -1){perror("open");exit(1);}//读取错误时间time_t error_time; // 时间变量read(time_fd, &error_time, sizeof(time_t)); // 读取上次错误时间close(time_fd); // 关闭文件//检查是否仍在60秒保护期内if(time(NULL) - error_time < 60){ // 比较当前时间与错误时间printf("用户名或密码错误次数过多,请稍后再试!\n");return; // 直接返回,不允许登录}}printf("请输入用户名:\n"); fgets(tmp_user.username, 20, stdin); // 获取输入的用户名printf("请输入密码:\n");fgets(tmp_user.password, 20, stdin); // 获取输入的密码fd = open("user.txt", O_RDWR); // 打开用户数据文件if (fd == -1){ perror("open");exit(1);}while(1){//从文件读取用户信息int res = read(fd, &user, sizeof(user)); // 读取一个用户记录if (res == -1){perror("read");exit(1);}if(res == 0) // 读到文件末尾{printf("用户名或密码错误\n");error_cnt++; // 错误计数增加if(error_cnt == 3) // 达到3次错误{printf("用户名或密码连续错误3次,请60秒后再试!\n");//创建/清空时间记录文件int time_fd = open("time.dat", O_RDWR | O_CREAT | O_TRUNC, 0666);if (time_fd == -1){perror("open");exit(1);}//记录当前时间time_t t = time(NULL); // 获取当前时间write(time_fd, &t, sizeof(t)); // 写入时间close(time_fd); // 关闭文件error_cnt = 0; // 重置错误计数}break; // 退出循环}//比较用户名和密码if(strcmp(user.username, tmp_user.username) == 0 && strcmp(user.password, tmp_user.password) == 0) // 验证匹配{printf("登录成功!\n");error_cnt = 0; // 重置错误计数break; // 退出循环}}close(fd); // 关闭用户文件
}int main()
{int flag = 0; // 用户选择标志while(1) // 主循环{printf("请选择功能:\n1.注册\n2.登录\n3.退出\n");if(scanf("%d", &flag)!=1) // 读取用户选择{printf("输入错误\n");exit(1);}getchar(); // 清除输入缓冲区中的换行符if (flag == 1) // 注册功能{user_reg();}else if (flag == 2) // 登录功能{user_login();}else if (flag == 3) // 退出程序{break;}else // 无效输入{printf("非法选择!\n");}}return 0; // 程序正常结束
}
代码功能说明:
用户注册:
将用户名和密码保存到
user.txt
文件中使用结构体存储用户信息
文件以追加模式打开,允许多用户注册
用户登录:
验证用户名和密码
实现错误计数保护机制
连续3次错误后锁定60秒
安全机制:
使用
time.dat
文件记录错误时间检查时间差实现临时锁定功能
错误计数器自动重置
主菜单:
提供注册、登录、退出选项
处理用户输入错误
注意事项:
密码以明文形式存储(实际应用中应该加密)
用户名和密码包含换行符(fgets特性)
文件操作使用低级I/O(open/read/write)
没有实现用户名的唯一性检查