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

C語言控制台四則運算練習系統:隨機出題、自動評分、用戶管理、排名統計完整實現

     編輯:關於C語言

結對編程實戰:從需求到可運行的 C 語言控制台應用

本項目是一個基於 C 語言的控制台四則運算練習軟件,實現了用戶註冊/識別、難度選擇、隨機出題、實時計時、自動評分、錯題重做、歷史排名、結果持久化等完整功能。代碼採用模塊化設計,通過文件存儲用戶數據與測試記錄,展示了 C 語言在文件操作、隨機數、時間管理、結構體數組排序等方面的綜合應用。

一、 系統功能架構

模塊核心功能關鍵技術點
用戶管理首次輸入用戶名/學號,後續自動識別文件讀寫 (fread/fwrite)、結構體序列化
出題引擎加減乘除四模式,三級難度(1-3位數),指定題量srand(time(0))、rand() 範圍控制、整數/浮點除法區分
交互評分即時判對錯,記錄用時,生成詳細報告time() 計時、文件追加寫入、正確率統計
數據持久化測試過程、錯題、正確答案分文件存儲多文件指針管理、fprintf/fscanf 格式化
排名系統按平均正確率降序排序,顯示歷史最佳結構體數組冒泡排序、文件讀取重構數組
錯題重做讀取錯題文件重新作答,對照標準答案文件讀取解析、交互式輸入驗證

二、 核心數據結構

#define MAX_STUDENTS 50
#define MAX_NAME_LEN 20

struct Student {
    char name[MAX_NAME_LEN + 1];
    char num[11];      // 學號/ID
    float avscore;     // 平均正確率百分比
} students[MAX_STUDENTS];

// 全局統計變量
float total_score = 0; // 累計正確率和
int test_count = 0;    // 測試次數
time_t start_time, end_time; // 計時

三、 關鍵模塊代碼詳解

1. 用戶註冊與識別 (Judge/SaveMessage)

void Judge() {
    FILE *fp = fopen("studentmessage.txt", "rb+");
    if (!fp) { fp = fopen("studentmessage.txt", "wb+"); } // 首次運行創建
    
    int i = 0;
    while (fread(&students[i], sizeof(struct Student), 1, fp) == 1) {
        i++;
        if (i >= MAX_STUDENTS) { printf("用戶已滿\n"); exit(0); }
    }
    // 若文件為空,i=0,進入註冊流程
    fclose(fp);
}

void SaveMessage() {
    FILE *fp = fopen("studentmessage.txt", "ab"); // 追加二進制
    FILE *fp1 = fopen("TestResult.txt", "a");     // 文本日誌
    printf("輸入姓名: "); scanf("%s", students[0].name);
    printf("輸入學號: "); scanf("%s", students[0].num);
    fwrite(&students[0], sizeof(struct Student), 1, fp);
    fprintf(fp1, "姓名:%s\n學號:%s\n", students[0].name, students[0].num);
    fclose(fp); fclose(fp1);
}

2. 四則運算核心邏輯(以加法為例)

void Addition(int count) {
    FILE *fp = fopen("TestResult.txt", "a");
    FILE *fp_err = fopen("failedResult.txt", "a");
    FILE *fp_ans = fopen("rightResult.txt", "a");
    
    int difficulty, range;
    printf("選擇難度 1.簡單 2.一般 3.困難: "); scanf("%d", &difficulty);
    range = (difficulty==1)?10 : (difficulty==2)?100 : 1000;
    
    int correct = 0;
    fprintf(fp, "加法測試:\n被加數 + 加數 = 你的答案 正確答案 結果\n");
    
    for (int i = 0; i < count; i++) {
        int a, b, ans, user_ans;
        if (difficulty == 1) { a = rand()%range; b = rand()%range; }
        else { a = range/10 + rand()%(range - range/10); b = range/10 + rand()%(range - range/10); }
        ans = a + b;
        printf("%d + %d = ", a, b);
        scanf("%d", &user_ans);
        
        if (user_ans == ans) {
            fprintf(fp, "%d + %d = %d %d √\n", a, b, user_ans, ans);
            correct++;
        } else {
            fprintf(fp, "%d + %d = %d %d ×\n", a, b, user_ans, ans);
            fprintf(fp_err, "%d + %d =\n", a, b);      // 錯題供重做
            fprintf(fp_ans, "%d + %d = %d\n", a, b, ans); // 標準答案
        }
    }
    float rate = (float)correct / count;
    fprintf(fp, "正確 %d 錯誤 %d 正確率 %.2f%%\n\n", correct, count-correct, rate*100);
    total_score += rate * 100; test_count++;
    fclose(fp); fclose(fp_err); fclose(fp_ans);
}

減法/乘法 邏輯同加法,僅運算符與生成範圍調整。除法 需處理浮點精度:

// 除法:生成非零除數,保留小數點後一位比較
int a = ...; int b = range/10 + rand()%(range - range/10); // 確保 b != 0
float ans = (float)a / b;
ans = (int)(ans * 10) / 10.0; // 強制截斷到 0.1 位
printf("%d / %d = ", a, b);
float user_ans; scanf("%f", &user_ans);
if (user_ans == ans) ... // 直接比較浮點(因已截斷)

3. 排名排序與持久化 (Sort/FileCopy)

void Sort() {
    // 讀取歷史記錄 nrecord.txt 到 students 數組
    FILE *fp = fopen("nrecord.txt", "a+");
    fprintf(fp, "%s %s %.2f\n", students[0].name, students[0].num, total_score/test_count);
    rewind(fp);
    int n = 0;
    while (fscanf(fp, "%s %s %f", students[n].name, students[n].num, &students[n].avscore) == 3) n++;
    fclose(fp);
    
    // 簡單冒泡排序(降序)
    for (int i = 0; i < n-1; i++)
        for (int j = 0; j < n-1-i; j++)
            if (students[j].avscore < students[j+1].avscore) {
                struct Student tmp = students[j];
                students[j] = students[j+1];
                students[j+1] = tmp;
            }
    
    printf("排名:\n姓名 學號 正確率\n");
    for (int i = 0; i < n; i++)
        printf("%s %s %.2f%%\n", students[i].name, students[i].num, students[i].avscore);
}

void FileCopy() {
    // 以學號命名備份測試詳情
    char filename[20];
    sprintf(filename, "%s.txt", students[0].num);
    FILE *in = fopen("TestResult.txt", "r");
    FILE *out = fopen(filename, "w");
    int ch;
    while ((ch = fgetc(in)) != EOF) fputc(ch, out);
    fclose(in); fclose(out);
}

4. 主菜單狀態機 (ChooseFunc/Begin)

void ChooseFunc() {
    int choice;
    while (1) {
        printf("\n1.開始測試 2.查看結果 3.查看排名 4.錯題重做 5.結束測試\n選擇: ");
        scanf("%d", &choice);
        switch (choice) {
            case 1: start_time = time(NULL); Begin(); break;
            case 2: ShowResult(); break;
            case 3: Sort(); break;
            case 4: Rework(); break;
            case 5: 
                end_time = time(NULL);
                printf("本次答題用時: %ld 秒\n", end_time - start_time);
                FileCopy(); TestOver(); return;
        }
    }
}

四、 已知不足與改進方向

  1. 用戶識別缺陷:當前僅支持單用戶(students[0]),多用戶切換邏輯缺失。需實現「查找現有用戶 → 找到則加載歷史 → 否則新建」流程。
  2. 輸入健壯性:scanf 遇非預期輸入(如輸入字符串)會陷入死循環。需檢查返回值並清理輸入緩衝區。
  3. 排序算法:冒泡排序 O(n²),用戶量大時應改用 qsort 或堆排序。
  4. 文件併發:無鎖機制,多進程同時寫入會損壞數據。
  5. 界面美化:system("color b0") 僅 Windows 有效,跨平台建議用 ANSI 轉義序列或 ncurses。

五、 完整代碼結構概覽

main.c
├── main()                    // 初始化、清空臨時文件、啟動流程
├── Judge()                   // 用戶識別/創建
├── SaveMessage()             // 保存用戶信息
├── ChooseFunc()              // 主菜單循環
├── Begin()                   // 運算類型選擇子菜單
├── Addition/Subtracter/Multiplication/Division() // 四則運算實現
├── Rework()                  // 錯題重做
├── Sort()                    // 排名排序顯示
├── ShowResult()              // 顯示詳細測試記錄
├── FileCopy()                // 備份測試結果
├── TestOver()                // 結束提示
└── 結構體定義、全局變量

項目感悟:這是一個典型的「練手級」控制台應用,雖代碼風格較為樸素(大量重複代碼、全局變量、固定數組),但完整覆蓋了文件持久化、隨機數、時間統計、結構體數組操作、菜單狀態機等 C 語言核心實戰技能。重構方向:提取公共出題函數、引入鏈表/動態數組支持多用戶、使用 qsort、增加輸入驗證、分離業務邏輯與 IO。結對編程過程中,雙人協作快速暴露邏輯漏洞(如除法浮點比較、文件指針管理),驗證了「兩人腦力 > 單人」的工程效能。

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