| 平台 | 頭文件 | 函數 | 備註 |
| Windows | | getch(), _getch() | MSVC/MinGW 內建 |
| Linux/Unix | | 修改終端屬性 tcsetattr | 標準 POSIX |
| 跨平台 | - | 自封裝抽象層 | 推薦生產做法 |
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 是交互細節關鍵;
- 狀態機邏輯:輸入 → 驗證 → 計數 → 鎖定/成功;
- 安全性:明文密碼僅教學用,生產必須哈希存儲、傳輸加密。
- 上一篇文章: C 語言溫度轉換:華氏度轉攝氏度公式實現與浮點精度陷阱
- 下一篇文章: C 語言排序基礎:三數由小到大排序的交換邏輯與邊界測試
Copyright ©
程式碼之家 All Rights Reserved