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

基於堆疊實現的密碼驗證系統:C語言完整源碼解析

     編輯:關於C語言

專案概述

利用堆疊 (Stack) 的後進先出 (LIFO) 特性,實現一個支持退格刪除、掩碼顯示 (星號)、限制嘗試次數 的控制台密碼驗證程序。代碼包含完整的堆疊 ADT 實現 (動態擴容)、密碼輸入交互邏輯、驗證核對流程,適合作為數據結構課程實驗或嵌入式終端項目參考。

核心數據結構:順序堆疊

#define STACK_INIT_SIZE 10
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR 0

typedef char SElemType;

typedef struct STACK {
    SElemType *base;   // 動態數組基址
    SElemType *top;    // 棧頂指針 (指向下一可用位置)
    int stacksize;     // 當前分配容量
    int length;        // 當前元素個數
} SqStack, *Stack;

typedef int Status;

堆疊核心操作實現

1. 初始化與銷毀

void InitStack(Stack *S) {
    *S = (SqStack*)malloc(sizeof(SqStack));
    (*S)->base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if (!(*S)->base) exit(-1);
    (*S)->top = (*S)->base;
    (*S)->stacksize = STACK_INIT_SIZE;
    (*S)->length = 0;
}

Status DestroyStack(Stack *S) {
    free((*S)->base);
    free(*S);
    return OK;
}

2. 清空、判空、取頂


void ClearStack(Stack *S) {
    (*S)->top = (*S)->base;
    (*S)->length = 0;
}

Status StackEmpty(SqStack S) {
    return (S.top == S.base) ? TRUE : FALSE;
}

Status GetTop(Stack S, SElemType *e) {
    if (S->top == S->base) return ERROR;
    *e = *(S->top - 1);  // 核心:top指向下一位置,頂元素在top-1
    return OK;
}

3. 入棧 (支持動態擴容)


void Push(Stack *S, SElemType e) {
    // 滿棧擴容:每次增加2個單元
    if ((*S)->top - (*S)->base >= (*S)->stacksize) {
        (*S)->base = (SElemType*)realloc((*S)->base,
            ((*S)->stacksize + 2) * sizeof(SElemType));
        if (!(*S)->base) exit(-1);
        (*S)->top = (*S)->base + (*S)->stacksize;
        (*S)->stacksize += 2;
    }
    *((*S)->top++) = e;
    ++(*S)->length;
}

4. 出棧 (僅移動指針,不清除數據)


Status Pop(Stack *S) {
    if ((*S)->top == (*S)->base) return ERROR;
    (*S)->top--;
    --(*S)->length;
    return OK;
}

5. 反序導出 (用於驗證)


void Change(SqStack S, char *a) {
    int n = S.length - 1;
    while (!StackEmpty(S)) {
        GetTop(&S, &a[n--]);  // 從棧頂彈出,填入數組尾部 → 正序
    }
}

密碼控制邏輯:Control()


void Control(Stack *s) {
    int i = 0, k, j = 0;
    SElemType ch, *a;
    k = strlen(PASSWORD);  // 全局密碼 "abcdef"

    printf("輸入一個 %d 位密碼,你只有 3 次機會:\n", k);
    printf("C:\\>");

    for (;;) {
        // 超過3次失敗 → 退出
        if (i >= 3) {
            i++; clrscr(); gotoxy(1,1); break;
        }
        // 第2、3次嘗試:清屏重置顯示
        else if (i > 0 && i < 3) {
            gotoxy(5,2);
            for (j = 1; j <= (*s)->length; j++) printf(" ");
            gotoxy(5,2); ClearStack(s);
        }

        // 密碼輸入循環 (支持退格)
        for (;;) {
            ch = getch();  // 無回顯讀取
            if (ch != 13) {  // 非回車
                if (ch == 8) {  // 退格鍵 ASCII 8
                    Pop(s);
                    gotoxy(4 + j, 2); printf(" "); gotoxy(4 + j, 2);  // 擦除星號
                } else {
                    printf("*");  // 掩碼顯示
                    Push(s, ch);
                }
                j = (*s)->length;
            } else break;  // 回車結束輸入
        }

        i++;  // 嘗試次數+1

        // 長度不匹配直接繼續下一次
        if (k != j) continue;

        // 逐字符比對 (Change已將棧內容按正序存入a)
        a = (SElemType*)malloc((*s)->length * sizeof(SElemType));
        Change(*s, a);
        for (j = 1; j <= (*s)->length; ) {
            if (a[j-1] == PASSWORD[j-1]) j++;
            else { j = (*s)->length + 2; break; }
        }
        if (j == (*s)->length + 2) continue;  // 不匹配
        else break;  // 匹配成功
    }

    if (i == 4) printf("\n密碼錯誤,即將退出");
    else printf("\n密碼正確\n");
    free(a);
}

主程序入口


char PASSWORD[10] = "abcdef";  // 全局預設密碼

int main() {
    Stack s;
    clrscr();           // 清屏 (conio.h)
    InitStack(&s);
    Control(&s);
    getch();            // 暫停查看結果
    DestroyStack(&s);
    return 0;
}

編譯與運行環境

  • 編譯器:Turbo C 2.0 / Borland C++ / 支持 conio.h 的 DOS/Windows 編譯器
  • 依賴庫:stdio.h, string.h, conio.h, stdlib.h
  • 關鍵函數:clrscr() 清屏、gotoxy(x,y) 光標定位、getch() 無回顯讀鍵

代碼亮點與改進方向

亮點說明
動態擴容堆疊避免固定大小限制,realloc策略簡單有效
退格可視化配合gotoxy實現星號擦除,用戶體驗佳
嘗試次數限制防暴力破解基礎機制
堆疊反序導出驗證巧妙利用LIFO特性將輸入順序還原

現代化改進建議

  1. 移除 conio.h 依賴:使用跨平台終端庫 (ncurses / Windows Console API) 或標準輸入非規範模式 (termios / SetConsoleMode)。
  2. 密碼安全性:不明文存儲,改用哈希 (SHA-256 + salt) 比對;支持配置文件/環境變量注入。
  3. 輸入長度限制:防緩衝區溢出 (雖堆疊動態擴容,但建議設最大長度)。
  4. 錯誤處理:malloc/realloc 失敗時優雅退出而非 exit(-1)。
  5. 模塊化:將堆疊 ADT 拆分為 stack.h/.c,密碼邏輯獨立 auth.h/.c。

總結

本程序以堆疊為核心數據結構,完整演示了從底層 ADT 實現到上層交互邏輯的構建過程。代碼雖基於經典 Turbo C 環境,但其算法邏輯 (動態棧、退格處理、掩碼、限嘗試) 具備普遍參考價值。理解並移植它,將有助於掌握「數據結構服務於業務邏輯」的工程思維。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved