代碼詳細注釋:文件IO在用戶管理系統中的應用實踐:C語言實現用戶名查重與密碼確認與支持日志記錄的終端用戶認證解決方案的注冊登錄系統

代碼

/* 作業增強版注冊登錄系統 - 帶日志和安全性增強功能 */
#include <stdio.h>      // 標準輸入輸出函數(printf, scanf等)
#include <stdlib.h>     // 標準庫函數(exit, malloc等)
#include <string.h>     // 字符串處理函數(strcmp, strcspn等)
#include <fcntl.h>      // 文件控制選項(open, O_RDWR等)
#include <unistd.h>     // POSIX系統調用(read, write等)
#include <time.h>       // 時間函數(time, localtime等)
#include <stdarg.h>     // 可變參數支持(va_list, va_start等)/* 系統常量定義 */
#define MAX_ATTEMPTS 3   // 允許的最大登錄嘗試次數
#define LOCK_TIME 8      // 賬號鎖定時間(秒) 
#define LOCK_FILE "login.lock"  // 存儲鎖定狀態的文件名
#define USER_FILE "user.txt"    // 存儲用戶數據的文件名
#define LOG_FILE "system.log"   // 日志文件名/* 日志記錄函數* 參數:format - 格式化字符串,... - 可變參數* 功能:將帶時間戳的日志信息寫入日志文件*/
void log_message(const char *format, ...) {FILE *log_file = fopen(LOG_FILE, "a");  // 以追加模式打開日志文件if (log_file) {  // 檢查文件是否成功打開time_t now;  // 存儲當前時間time(&now);  // 獲取當前時間戳char time_str[20];  // 存儲格式化后的時間字符串// 將時間轉換為本地時間并格式化為字符串strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", localtime(&now));// 寫入時間戳到日志文件fprintf(log_file, "[%s] ", time_str);// 處理可變參數va_list args;  // 定義可變參數列表va_start(args, format);  // 初始化可變參數vfprintf(log_file, format, args);  // 寫入格式化內容到日志va_end(args);  // 結束可變參數處理fprintf(log_file, "\n");  // 寫入換行符fclose(log_file);  // 關閉日志文件}
}/* 檢查用戶名是否已存在* 參數:username - 要檢查的用戶名* 返回值:1-存在,0-不存在*/
int is_username_exist(const char *username) {FILE *fp = fopen(USER_FILE, "r");  // 以只讀方式打開用戶文件if (fp) {  // 文件打開成功char file_user[20];  // 存儲從文件讀取的用戶名// 逐行讀取用戶文件while (fgets(file_user, sizeof(file_user), fp)) {file_user[strcspn(file_user, "\n")] = '\0';  // 去除換行符// 比較用戶名是否匹配if (strcmp(username, file_user) == 0) {fclose(fp);  // 關閉文件return 1;  // 返回1表示用戶名已存在}// 跳過密碼行(用戶名和密碼交替存儲)if (!fgets(file_user, sizeof(file_user), fp)) break;}fclose(fp);  // 關閉文件}return 0;  // 返回0表示用戶名不存在
}/* 檢查賬號是否處于鎖定狀態* 返回值:1-鎖定中,0-未鎖定*/
int is_locked() {FILE *fp = fopen(LOCK_FILE, "r");  // 打開鎖定狀態文件if (fp) {  // 文件存在time_t lock_time;  // 存儲鎖定時間fscanf(fp, "%ld", &lock_time);  // 讀取鎖定時間fclose(fp);  // 關閉文件time_t current = time(NULL);  // 獲取當前時間// 檢查是否仍在鎖定期內if (current - lock_time < LOCK_TIME) {// 顯示剩余鎖定時間printf("賬號鎖定中,請等待%ld秒后重試\n", LOCK_TIME - (current - lock_time));// 記錄鎖定狀態到日志log_message("賬號鎖定中,剩余時間: %ld秒", LOCK_TIME - (current - lock_time));return 1;  // 返回1表示仍處于鎖定狀態} else {remove(LOCK_FILE);  // 鎖定已過期,刪除鎖定文件log_message("賬號鎖定已自動解除");  // 記錄解鎖日志}}return 0;  // 返回0表示未鎖定
}/* 設置賬號鎖定狀態* 功能:創建鎖定文件并記錄當前時間*/
void set_lock() {FILE *fp = fopen(LOCK_FILE, "w");  // 創建/覆蓋鎖定文件if (fp) {  // 文件創建成功fprintf(fp, "%ld", time(NULL));  // 寫入當前時間戳fclose(fp);  // 關閉文件log_message("賬號因連續登錄失敗被鎖定");  // 記錄鎖定日志}
}/* 主函數 */
int main() {log_message("程序啟動");  // 記錄程序啟動日志int flag = 0;  // 用戶選擇的功能標志(1=注冊,2=登錄)char username[20], password[20], confirm_pass[20];  // 注冊用變量char user[20], pass[20];  // 登錄用變量// 檢查賬號鎖定狀態if (is_locked()) {log_message("嘗試訪問被鎖定的賬號");return 1;  // 賬號鎖定中,直接退出程序}// 顯示功能菜單printf("請選擇功能:\n1.注冊\n2.登錄\n");scanf("%d", &flag);  // 讀取用戶選擇getchar();  // 清除輸入緩沖區中的換行符log_message("用戶選擇功能: %d", flag);  // 記錄用戶選擇/* 注冊功能處理 */if (flag == 1) {// 用戶名輸入循環while (1) {printf("請輸入用戶名:\n");fgets(username, 20, stdin);  // 安全讀取用戶名(防止緩沖區溢出)username[strcspn(username, "\n")] = '\0';  // 去除換行符// 檢查用戶名是否已存在if (is_username_exist(username)) {printf("用戶名已存在,請重新輸入\n");log_message("注冊失敗: 用戶名 %s 已存在", username);continue;  // 用戶名存在,重新輸入}break;  // 用戶名可用,退出循環}// 密碼輸入循環while (1) {printf("請輸入密碼:\n");fgets(password, 20, stdin);password[strcspn(password, "\n")] = '\0';printf("請再次輸入密碼確認:\n");fgets(confirm_pass, 20, stdin);confirm_pass[strcspn(confirm_pass, "\n")] = '\0';// 檢查兩次密碼是否一致if (strcmp(password, confirm_pass) != 0) {printf("兩次輸入的密碼不一致,請重新輸入\n");log_message("注冊失敗: 密碼不一致");continue;  // 密碼不一致,重新輸入}break;  // 密碼一致,退出循環}// 保存用戶信息FILE *fp = fopen(USER_FILE, "a");  // 以追加模式打開用戶文件if (fp) {  // 文件打開成功fprintf(fp, "%s\n%s\n", username, password);  // 寫入用戶名和密碼fclose(fp);  // 關閉文件printf("注冊成功!\n");log_message("用戶 %s 注冊成功", username);  // 記錄注冊成功} else {perror("注冊失敗");  // 顯示系統錯誤信息log_message("注冊失敗: 無法打開用戶文件");  // 記錄錯誤日志}}/* 登錄功能處理 */else if (flag == 2) {int attempts = 0;  // 登錄嘗試次數計數器// 登錄嘗試循環(最多MAX_ATTEMPTS次)while(attempts < MAX_ATTEMPTS) {// 獲取用戶名printf("請輸入用戶名:\n");fgets(user, 20, stdin);user[strcspn(user, "\n")] = '\0';// 獲取密碼printf("請輸入密碼:\n");fgets(pass, 20, stdin);pass[strcspn(pass, "\n")] = '\0';// 驗證用戶憑據FILE *fp = fopen(USER_FILE, "r");  // 打開用戶文件int found = 0;  // 標記是否找到匹配用戶if (fp) {  // 文件打開成功char file_user[20], file_pass[20];  // 存儲文件中的用戶名和密碼// 逐行讀取用戶文件while (fgets(file_user, sizeof(file_user), fp)) {file_user[strcspn(file_user, "\n")] = '\0';  // 去除換行符// 讀取對應的密碼行if (fgets(file_pass, sizeof(file_pass), fp)) {file_pass[strcspn(file_pass, "\n")] = '\0';  // 去除換行符// 比較用戶名和密碼if (strcmp(user, file_user) == 0 && strcmp(pass, file_pass) == 0) {found = 1;  // 標記為找到匹配用戶break;}}}fclose(fp);  // 關閉文件}// 檢查驗證結果if (found) {  // 驗證成功printf("登錄成功!\n");log_message("用戶 %s 登錄成功", user);  // 記錄登錄成功break;  // 退出登錄循環} else {  // 驗證失敗attempts++;  // 增加嘗試次數log_message("登錄失敗: 用戶名 %s 嘗試失敗 %d/%d", user, attempts, MAX_ATTEMPTS);if (attempts < MAX_ATTEMPTS) {  // 還有嘗試機會printf("用戶名或密碼錯誤,請重新輸入(剩余嘗試次數: %d)\n",MAX_ATTEMPTS - attempts);} else {  // 達到最大嘗試次數set_lock();  // 鎖定賬號printf("連續錯誤%d次,賬號已鎖定,請%d秒后再試。\n",MAX_ATTEMPTS, LOCK_TIME);}}}} else {  // 非法選擇處理printf("非法選擇!\n");log_message("非法功能選擇: %d", flag);  // 記錄非法選擇}log_message("程序結束");  // 記錄程序結束return 0;  // 正常退出
}

用戶注冊登錄系統功能說明

代碼功能概述

這段代碼實現了一個完整的用戶注冊和登錄系統,具有以下核心功能:

  1. 用戶注冊功能

    • 允許新用戶創建賬戶

    • 包含用戶名唯一性檢查

    • 密碼二次確認機制

  2. 用戶登錄功能

    • 驗證用戶憑據

    • 提供有限次數的嘗試機會

    • 安全鎖定機制防止暴力破解

  3. 安全保護機制

    • 連續登錄失敗后賬號鎖定(8秒)

    • 自動解鎖功能

  4. 日志記錄系統

    • 記錄所有關鍵操作和事件

    • 包含時間戳的詳細日志

    • 用于系統監控和故障排查

可能的標題建議

技術性標題

  1. "基于文件存儲的用戶認證系統實現"

  2. "C語言實現的注冊登錄系統(含日志功能)"

  3. "帶賬號鎖定機制的終端用戶認證程序"

功能性標題

  1. "安全用戶注冊與登錄管理系統"

  2. "支持日志記錄的終端用戶認證解決方案"

  3. "防暴力破解的用戶登錄系統實現"

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88128.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88128.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88128.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Go與JS無縫協作:Goja引擎實戰之錯誤處理最佳實踐

引言&#xff1a;當Go邂逅JavaScript 在現代軟件開發中&#xff0c;跨語言協作已成為提升效率的關鍵。想象一下&#xff1a;用Go的高性能處理核心邏輯&#xff0c;同時用JavaScript的靈活性實現動態規則——這不再是夢想。Goja&#xff0c;這個純Go語言實現的JavaScript引擎&am…

繼承與多態:面向對象編程的兩大支柱

引言&#xff1a;為什么必須掌握繼承與多態&#xff1f; 在Java開發中&#xff0c;繼承與多態是構建可擴展、易維護系統的基石&#xff1a; 繼承&#xff1a;實現代碼復用&#xff0c;建立清晰的類層次結構多態&#xff1a;提升代碼靈活性&#xff0c;實現"編寫一次&#…

2025使用VM虛擬機安裝配置Macos蘋果系統下Flutter開發環境保姆級教程--上篇

前言 我們在學習Flutter開發的過程中&#xff0c;永遠都跳不過去的一個問題就是如何在MAC下開發并打包Flutter工程項目&#xff0c;但MAC開發首先要解決的問題就是我們一般技術人員的電腦都是WINDOWS操作系統&#xff0c;專門配置一臺MAC的話成本又是不得不考慮的因素&#xf…

250708-Svelte項目從Debian遷移到無法聯網的RHEL全流程指南

&#x1f4cc; 背景 在 Debian 上使用以下命令創建了一個 Svelte 項目&#xff1a; npm install -g sv npx sv create my-svelte-demo cd my-svelte-demo npm install npm run dev現在需要將該項目遷移到一臺 無法聯網的 RHEL 9.4 服務器 上運行&#xff0c;出現如下報錯&…

力扣 hot100 Day39

118. 楊輝三角 給定一個非負整數 numRows&#xff0c;生成「楊輝三角」的前 numRows 行。 class Solution { public:vector<vector<int>> generate(int numRows) {vector<vector<int>> res(numRows);for (int i 0; i < numRows; i) {res[i].resi…

HuggingFists: 無代碼處理復雜PDF

有過使用LLM搭建RAG或其它類知識系統的朋友一定會對文檔數據的復雜多樣性有著深刻的理解。各行各業的磁盤中都沉睡了數年到數十年的各類文檔信息&#xff0c;包括&#xff1a;Doc、Docx、PPT、PDF、XLS、PNG、JPEG等各類格式。利用LLM激活這些數據價值的首要工作就是能夠正確的…

Vue 3 框架實現理念、架構與設計哲學深度解析

第一部分&#xff1a;Vue 3 的起源&#xff1a;架構演進與設計哲學 Vue 3 的誕生并非一次簡單的版本迭代&#xff0c;而是一場深刻的架構革命。它的出現是前端技術演進、應用規模擴張以及對更高性能和可維護性追求的必然結果。要全面理解 Vue 3 的各項實現理念&#xff0c;必須…

SQL Server使用存儲過程導出數據到Excel實現方式

在SQL Server數據庫管理中,存儲過程作為預編譯的T-SQL語句集合,能顯著提升數據操作效率與安全性。將數據導出到Excel的需求廣泛存在于報表生成、數據遷移等場景。本文詳細解析四種通過存儲過程實現數據導出的技術方案,涵蓋代碼實現、適用場景及優化策略,為不同業務需求提供…

OpenGL 2. 著色器

#include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> #include <stdexcept>// 函數聲明 void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow* window); void checkShaderCom…

【c++】容器擴容導致的類實例資源被錯誤釋放

BUG記錄 表現為新實例被存入前&#xff0c;容器內部的舊實例的析構被意外調用 因為 std::vector 在容量不足時&#xff0c;會自動擴容&#xff0c;把舊元素「搬」到新內存&#xff0c;然后析構舊內存上的那些對象。然后由于LKMotorController 類里沒有正確處理移動語義&#xf…

TypeScript 集成

下面&#xff0c;我們來系統的梳理關于 Vue TypeScript 深度集成 的基本知識點&#xff1a;一、TypeScript 與 Vue 集成概述 1.1 為什么需要 TypeScript 類型安全&#xff1a;編譯時類型檢查&#xff0c;減少運行時錯誤代碼智能&#xff1a;強大的IDE智能提示和自動補全可維護…

npm proxy

背景 前端項目下載依賴時經常會出現timeout的情況&#xff0c;此時有三種解決方案。 切換鏡像源。 適用于對依賴版本要求不嚴格的情況。延長超時時間。設置npm proxy。一些生產環境對依賴版本有著嚴格要求&#xff0c;并且指定了依賴的下載地址&#xff08;如下圖&#xff09;&…

TVS管工作原理是什么?主要的應用場景都有哪些?

什么是TVS管&#xff1f; TVS&#xff08;Transient Voltage Suppressors&#xff09;&#xff0c;即瞬態電壓抑制器&#xff0c;也被稱為雪崩擊穿二極管&#xff0c;是一種二極管形式的高效能保護器件&#xff0c;常用來防止端口瞬間的電壓沖擊造成后級電路的損壞。 TVS 有單…

分布式微服務系統架構第156集:JavaPlus技術文檔平臺日更-Java線程池使用指南

title: java線程池使用 author: 哪吒 date: 2023-06-15點擊勘誤issues&#xff0c;哪吒感謝大家的閱讀Java線程池使用指南1. 線程池基礎使用1.1 創建線程池的方式方式一&#xff1a;使用Executors工具類&#xff08;不推薦&#xff09;// 1. 固定大小線程池 ExecutorService fi…

【最新版】點大全能版v2.6.7.1 含匯付斗拱插件+uniapp前端

一.介紹V2全能版本、獨立版本全開源&#xff0c;含鏈動21&#xff0c;匯付斗拱?、排隊免單、推三返1 &#xff0c;扶持金&#xff0c;平級獎&#xff0c;團隊業績獎&#xff0c;酒店管理&#xff0c;約車&#xff0c;餐飲等眾多營銷功能&#xff0c;商城系統版本號為2.6.7.1&a…

Go語言高級面試必考:切片(slice)你真的掌握了嗎?

目錄 1. 切片是個啥?從數組到切片的靈魂進化 數組與切片的愛恨情仇 切片的內存結構:三巨頭共舞 切片的初始化方式:靈活到飛起 切片的“引用”特性:福也是禍 源碼初探:切片的誕生 2. 切片三劍客:len、cap 和底層數組的三角戀 len 和 cap 的微妙關系 切片共享的秘密…

monorepo + Turborepo --- 開發應用程序

目錄 配置開發任務 在 dev 之前運行設置任務 運行特定應用程序 使用終端 UI 與任務交互 監聽模式 watch 將 turbo watch 與持久任務一起使用 依賴感知的持久任務 沒有依賴感知的持久任務 緩存 任務輸出 局限性 在 Monorepo 中開發應用程序可以解鎖強大的工作流程&…

C#字符串相關庫函數運用梳理總結 + 正則表達式詳解

C# 字符串常用庫函數總結 &#x1f539; 1. 字符串比較 方法說明示例string.Equals()比較兩個字符串是否相等&#xff08;可忽略大小寫&#xff09;string.Equals("abc", "ABC", StringComparison.OrdinalIgnoreCase) / !判斷兩個字符串是否相等/不等&quo…

投機采樣(Speculative Decoding)

投機采樣&#xff08;Speculative Decoding&#xff09; 是一種加速大型語言模型&#xff08;LLM&#xff09;推理的技術&#xff0c;其核心思想是通過預生成候選token序列并異步校驗&#xff0c;從而減少主模型的計算量&#xff0c;同時保持生成結果的準確性。 核心思想是通過…

如何將華為手機中的照片傳輸到電腦

華為手機在眾多手機品牌中以其出色的品質脫穎而出&#xff0c;尤其是其攝像頭功能。有時&#xff0c;你可能在華為手機上積累了太多有意義的照片&#xff0c;想要將這些照片上傳到電腦以釋放手機存儲空間。然而&#xff0c;出于用戶信息安全的考慮&#xff0c;一些便捷的方法可…