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

C++ 實戰:數據結構技能考試系統——防作弊、自動抽題、雙端架構完整實現

     編輯:關於C語言

專案背景與設計目標

本系統為數據結構課程技能考試開發,採用 C++(含 C 風格系統程式設計) 實現,採雙端架構:

  • 學生端:身份驗證、防作弊監控、隨機抽題、倒計時、答案提交、加密上傳
  • 教師端:自動收集學生檔案、解密資訊、批覽代碼、錄入成績、自動生成 CSV 成績單

核心創新點:**系統級防作弊機制**——即時檢測 USB 存儲裝置插入、禁止 Word/PPT/記事本等輔助工具運行。

系統架構總覽

┌─────────────────────┐     局域網/共享目錄      ┌─────────────────────┐
│      學生端          │  ◄──────────────────►  │      教師端          │
│  (考試客戶端)        │   提交 .cpp + 加密.txt  │  (閱卷管理端)        │
├─────────────────────┤                          ├─────────────────────┤
│ • 身份驗證 (姓名/學號) │                          │ • 掃描考生目錄       │
│ • 防作弊監控執行緒    │                          │ • 批次解密資訊檔     │
│ • 學號尾碼抽題演算法  │                          │ • 啟動編輯器看代碼   │
│ • 雙階段倒計時 (60+20)│                          │ • 錄入分數生成 CSV   │
│ • 代碼寫入 .cpp 檔案  │                          │                     │
│ • 資訊檔 XOR 加密     │                          │                     │
└─────────────────────┘                          └─────────────────────┘

核心模組深度解析

1. 防作弊監控引擎(學生端核心)

採用 Windows API 實現兩大檢測:

USB 存儲裝置檢測

int GetDriverInfo(LPSTR szDrive) {
    UINT uDriverType = GetDriveType(szDrive);
    return (uDriverType == DRIVE_REMOVABLE) ? 1 : 0;  // 可移動裝置
}

int checkUdisk() {
    CHAR szLogicDriveStrings[1024];
    GetLogicalDriveStrings(1023, szLogicDriveStrings);
    PCHAR szDrive = szLogicDriveStrings;
    for (int i = 0; i < 7; i++) {  // 掃描 A: 到 G: 槽位
        if (GetDriverInfo(szDrive)) return 1;
        szDrive += (lstrlen(szDrive) + 1);  // 移至下一個驅動器字串
    }
    return 0;
}

原理: GetLogicalDriveStrings 取得所有邏輯磁碟機代號,GetDriveType 判斷是否為 `DRIVE_REMOVABLE`(USB、SD 卡等)。檢測到時強制阻塞並彈窗警告,直到拔除裝置。

禁止程序檢測(Word/PPT/記事本)

int checkTask() {
    string cmd = "tasklist | find \"WINWORD\" > 1.txt";
    system(cmd.c_str());  // 依次檢查 WINWORD, POWERPNT, notepad
    // ... 讀取 1.txt 判斷是否有進程輸出 ...
}

機制: 呼叫系統命令 `tasklist` 管道 `find` 篩選特定進程名,輸出導向暫存檔,讀取檔案長度判斷進程是否存在。發現違規程序立即強制關閉並重顯試題。

2. 抽題演算法:學號尾碼 ASCII 取模

int chuti(int a) {  // a 為學號後四位 ASCII 碼總和
    a = a % 8;        // 映射到 0-7
    int b = a + 10;   // 第二題固定偏移 10(對應題庫 11-18 題)
    // 載入題目檔案:Ti\1.txt ~ Ti\18.txt
    // 記錄抽題資訊至 xinxi.txt
}

設計意圖: 學號後四位具隨機性,ASCII 碼總和再模 8,實現「同學號固定抽題、不同學號均勻分布」的偽隨機效果。兩題固定間距 10,確保題目類型覆蓋面(如基本操作+綜合應用)。

3. 雙階段倒計時機制

// 正式考試 60 分鐘
void daojishi(int a, int m[0], int sec[0]) {
    m[0] = 59; sec[0] = 59;
    while (m[0] >= 0) {
        // 每 10 秒執行一次防作弊掃描
        if (sec[0] % 10 == 0) {
            if (checkUdisk() || checkTask()) {
                system("cls");
                chongchuti(a);  // 重顯試題
            }
        }
        // _kbhit() 檢測鍵盤輸入(學生提前交卷)
        Sleep(1000); sec[0]--;
    }
}

// 超時容忍 20 分鐘
void chaoshi(int a, int m1[0], int sec1[0]) { ... }

人性化設計: 60 分鐘正式考試 + 20 分鐘緩衝期。緩衝期同樣啟用防作弊掃描,超時自動交卷。每 10 秒掃描一次平衡了即時性與 CPU 佔用。

4. 資訊加密與上傳

void jiami() {
    FILE *fp = fopen("xinxi.txt", "rb+");
    while ((n = fread(buf, 1, NORMAL_SIZ, fp)) > 0) {
        for (int i = 0; i < n; i++) buf[i] ^= CHMSK_KEY;  // XOR 0xA5
        fseek(fp, -n, SEEK_CUR);
        fwrite(buf, 1, n, fp);
        fflush(fp);  // 關鍵:強制刷新緩衝區,確保小檔案也能寫入磁碟
    }
    fclose(fp);
}

XOR 加密特點: 速度極快、對稱加密(再執行一次即解密)、足夠防止學生直接閱讀純文字資訊檔。`fflush(fp)` 解決了 C 標準庫緩衝區導致小檔案寫入失效的經典問題。

5. 教師端自動化批改流程

void read(int num) {
    system("dir *.cpp /b > cpp1.dat");  // 獲取所有 .cpp 檔案列表
    for (int i = 0; i < num; i++) {
        fscanf(in, "%s", str1[i]);      // 讀取檔名
        system(str);                    // 用關聯程式打開 .cpp(如 VS Code/Dev C++)
        // 修改副檔名為 .txt 並解密
        str2[j-1] = 't'; str2[j-2] = 'x'; str2[j-3] = 't';
        jiemi(str2);
        system(str2);                   // 打開解密後的資訊檔
        // 讀取姓名、學號、作答時間等
        // 提示教師輸入分數
        fprintf(fq, "%s,%s,%.1f\n", name, id, score);  // 寫入 CSV
    }
}

效率提升: 教師無需手動複製檔案、解壓、打開編輯器、記錄分數。一鍵啟動即可依次瀏覽所有學生代碼與資訊,專注於「閱讀代碼邏輯」與「給分」。

系統部署與注意事項

  • 路徑硬編碼問題:代碼中大量使用 `d:\\數據結構技能考試\\`,部署時需修改為實際共享目錄,或改為相對路徑/配置檔讀取。
  • 權限需求:學生端需 `system()` 執行權限、寫入共享目錄權限;教師端需讀取共享目錄權限。
  • 編碼問題:中文路徑在 Windows 控制台可能顯示亂碼,建議源檔案存為 GBK/ANSI 編碼或使用寬字元 API。
  • 擴展建議:引入 SQLite 替代文字檔儲存、使用 JSON 替代自定義格式、改用 Socket/HTTP 替代檔案共享傳輸、增加代碼編譯自動測試(OJ 模式)。

總結: 這套系統雖代碼風格偏 C 風格(大量指標、手動記憶體管理、Win32 API 直接呼叫),但完整展示了**系統程式設計**在實際教學場景中的落地能力:進程管理、檔案操作、加密、進程間通訊(檔案共享)、定時器、硬體監控。對於學習 C/C++ 系統程式設計、Windows API 應用、考試系統架構的開發者,極具參考價值。

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