首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言控制台交互:銀行密碼輸入系統 (getch 隱藏輸入、三次鎖定、緩衝區處理)

     編輯:關於C語言

問題描述

模擬銀行密碼輸入:預設密碼 "aaaaaa",輸入時顯示 *,最多嘗試 3 次,失敗鎖定。核心考點:無回顯輸入 getch()、字符緩衝區處理、狀態機邏輯、平台相關性。

原代碼分析與 Bug 修正


// 原代碼主要問題:
// 1. 密碼比較邏輯錯誤: ch1[j] != ch[j] 應為 ch1[i] != ch[i]
// 2. getch() 非標準 C,需  (Windows) 或 termios (Linux)
// 3. 緩衝區殘留換行符導致後續輸入異常
// 4. 返回值語義混淆 (0 成功 vs 1 失敗)

跨平台無回顯輸入方案

Linux 終端屬性修改實現


#include 
#include 

int getch_unix() {
    struct termios oldt, newt;
    int ch;
    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);  // 關閉規範模式和回顯
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    ch = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);  // 恢復
    return ch;
}

修正版邏輯:狀態機清晰化


#include 
#include 
#include 

#ifdef _WIN32
#include 
#define GETCH _getch
#else
#include 
#include 
int GETCH() { /* 上述 Unix 實現 */ }
#endif

#define MAX_ATTEMPTS 3
#define PASS_LEN 6
const char CORRECT_PASS[PASS_LEN + 1] = "aaaaaa";

bool input_password(char *buf, int max_len) {
    int ch, i = 0;
    printf("輸入密碼 (%d 位): ", max_len);
    while (i < max_len && (ch = GETCH()) != '\r' && ch != '\n') {
        if (ch == 8 || ch == 127) {  // Backspace/Delete
            if (i > 0) {
                i--;
                printf("\b \b");  // 退格擦除星號
            }
            continue;
        }
        if (ch >= 32 && ch <= 126) {  // 可見字符
            buf[i++] = ch;
            putchar('*');
        }
    }
    buf[i] = '\0';
    printf("\n");
    return i == max_len;  // 必須滿 6 位
}

int main() {
    char input[PASS_LEN + 1];
    int attempts = 0;

    while (attempts < MAX_ATTEMPTS) {
        if (!input_password(input, PASS_LEN)) {
            printf("密碼長度必須為 %d 位\n", PASS_LEN);
            continue;
        }

        if (strcmp(input, CORRECT_PASS) == 0) {
            printf("登入成功!歡迎使用。\n");
            return 0;
        }

        attempts++;
        int left = MAX_ATTEMPTS - attempts;
        if (left > 0)
            printf("密碼錯誤!還有 %d 次機會。\n", left);
        else
            printf("錯誤次數過多,賬戶已鎖定。請至銀行櫃台解鎖。\n");
    }
    return 1;
}

關鍵改進點

1. 退格鍵支持 (\b \b 序列)

允許用戶刪除誤輸入,提升體驗。printf("\b \b"):退格、輸出空格覆蓋、再退格。

2. 輸入長度強制檢查

防止提交不足位數密碼繞過邏輯。

3. strcmp 標準比較

替代原代碼手寫逐字符比較,避免索引錯誤 (ch1[j]!=ch[j] Bug)。

4. 跨平台抽象層

#ifdef _WIN32 隔離平台差異,核心邏輯純標準 C。

5. 返回值語義標準化

main 返回 0 成功,非 0 失敗,符合 Unix 慣例。

安全性增強建議 (生產級)

  • 密碼不應硬編碼,應讀取加密配置或資料庫;
  • 傳輸/存儲應用哈希 (bcrypt/Argon2) 而非明文;
  • 輸入應有超時機制;
  • 鎖定後應記錄日誌、觸發告警;
  • 防暴力破解:IP 限流、驗證碼、設備指紋。

總結

銀行密碼輸入系統展示了終端控制、跨平台抽象、狀態機邏輯、用戶體驗細節。關鍵收穫:

  • getch() 類函數實現無回顯輸入,Windows/Linux 實現不同;
  • 終端屬性 ICANON|ECHO 控制行緩衝與回顯;
  • 退格處理 \b \b 是交互細節關鍵;
  • 狀態機邏輯:輸入 → 驗證 → 計數 → 鎖定/成功;
  • 安全性:明文密碼僅教學用,生產必須哈希存儲、傳輸加密。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
平台頭文件函數備註
Windowsgetch(), _getch()MSVC/MinGW 內建
Linux/Unix修改終端屬性 tcsetattr標準 POSIX
跨平台-自封裝抽象層推薦生產做法