当前位置: 首页 > news >正文

代码详细注释: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;                          // 程序正常结束
}

代码功能说明:

  1. 用户注册

    • 将用户名和密码保存到user.txt文件中

    • 使用结构体存储用户信息

    • 文件以追加模式打开,允许多用户注册

  2. 用户登录

    • 验证用户名和密码

    • 实现错误计数保护机制

    • 连续3次错误后锁定60秒

  3. 安全机制

    • 使用time.dat文件记录错误时间

    • 检查时间差实现临时锁定功能

    • 错误计数器自动重置

  4. 主菜单

    • 提供注册、登录、退出选项

    • 处理用户输入错误

注意事项:

  1. 密码以明文形式存储(实际应用中应该加密)

  2. 用户名和密码包含换行符(fgets特性)

  3. 文件操作使用低级I/O(open/read/write)

  4. 没有实现用户名的唯一性检查

http://www.dtcms.com/a/269681.html

相关文章:

  • Google AI 刚刚开源 MCP 数据库工具箱,让 AI 代理安全高效地查询数据库
  • 前后端分离(java) 和 Nginx在服务器上的完整部署方案(redis、minio)
  • JxBrowser 7.43.4 版本发布啦!
  • 人工智能驱动下的可再生能源气象预测:构建绿色能源时代的新大脑
  • 微服务化采集平台:可扩展性与容错机制
  • 相机Camera日志实例分析之五:相机Camx【萌拍闪光灯后置拍照】单帧流程日志详解
  • AiPy实战:问界汽车交付速度破纪录的背后是什么?
  • Vue的初步学习
  • 146.在 Vue3 中使用 OpenLayers 地图上 ECharts 模拟飞机循环飞行
  • OS学习笔记
  • B站视频下载器 Bili23-Downloader v1.63.1 绿色版
  • LLMs之DeepSeek:AI模型市场深度分析:DeepSeek的挑战与机遇,模型市场份额、Token经济学与未来发展
  • 力扣 239 题:滑动窗口最大值的两种高效解法
  • 【python】 time_str = time_str.strip() 与 time_str = str(time_str).strip() 的区别
  • 基于物联网的智能交通灯控制系统设计
  • 使用 Docker 搭建 Java(SpringBoot)开发环境——AI教你学Docker
  • 零基础|宝塔面板|frp内网穿透|esp32cam远程访问|微信小程序
  • 电商业务是如何防护DDoS攻击的?
  • 2563、统计公平数对的数目
  • ElasticSearch集群状态查询及_cat 命令详解
  • JDBC 获取新增行主键值详解
  • 向量与向量组的线性相关性 线性代数
  • 【Android】搭配安卓环境及设备连接
  • 17-C#的socket通信TCP-1
  • 静态路由实验以及核心原理
  • 计算机网络第九章——数据链路层《局域网》
  • 裂变时刻:全球关税重构下的券商交易系统跃迁路线图(2025-2027)
  • 3.springboot2使用selenium(java8)
  • 多模态大语言模型arxiv论文略读(152)
  • 【LeetCode 热题 100】142. 环形链表 II——快慢指针