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

菜鳥修煉C語言:薪資統計系統——結構體指標陣列與枚舉應用

     編輯:關於C

專案概覽

本專案實作一個互動式公司薪資統計系統,核心資料結構採用結構體指標陣列(`PEMP company[EMP_NUM]`),結合枚舉型別切換統計模式,完整展示 C 語言處理複雜資料聚合的能力。

核心資料結構設計

#define EMP_NUM 10

typedef struct employee {
    int age;
    char name[20];
    unsigned salary;
} *PEMP;  // PEMP 即 struct employee*

typedef enum sel_analy {
    TOTAL,    // 總和模式
    AVERAGE   // 平均模式
} sel_c;

設計考量:

  • 指標陣列 `PEMP company[10]`:每個元素指向獨立 `malloc` 的員工節點,靈活支援稀疏存儲(ID 可跳號)。
  • 枚舉 `sel_c`:語意化統計類型,避免魔術數字,`salary_analysis(company, TOTAL)` 碼可讀性極高。
  • 結構體內直接嵌入 `char name[20]` 而非 `char*`,簡化記憶體管理(無需額外 `malloc` 字串)。

功能模組詳解

1. 主選單與流程控制 (main)

int main() {
    PEMP company[EMP_NUM];
    memset(company, NULL, sizeof(company)); // 關鍵:初始化全為 NULL

    char select;
    do {
        printf("  <-----薪資統計系統------->\n");
        printf("1:更新職工信息  2:薪資求和\n");
        printf("3:薪資求平均值  4:顯示職工信息\n");
        printf("0:退出\n");
        select = getch();

        switch(select) {
            case '1': update_msg(company); break;
            case '2': salary_analysis(company, TOTAL); break;
            case '3': salary_analysis(company, AVERAGE); break;
            case '4': display_msg(company); break;
        }
    } while(select != '0');
    // TODO: 退出前應遍歷 company 釋放所有 malloc 記憶體
    return 0;
}

`memset(company, NULL, ...)` 確保未初始化槽位為空指標,後續 `if(company[i])` 即可安全判斷是否有資料。

2. 員工資料錄入與驗證 (update_msg)

void update_msg(PEMP company[]) {
    while (1) {
        PEMP new_emp = (PEMP)malloc(sizeof(*new_emp));
        int id;
        printf("請輸入員工信息,ID=-1 退出:\nID: ");
        scanf("%d", &id);
        if (id == -1) { free(new_emp); return; }
        if (id < 0 || id >= EMP_NUM) continue; // 簡易驗證

        printf("姓名: "); scanf("%s", new_emp->name);
        printf("年齡: "); scanf("%d", &new_emp->age);
        while (new_emp->age < 0 || new_emp->age > 60) { /* 重輸 */ }
        printf("薪水: "); scanf("%u", &new_emp->salary);
        while (new_emp->salary > 20000) { /* 重輸 */ }

        company[id] = new_emp; // 直接覆蓋舊指標(舊記憶體洩漏風險!)
    }
}

⚠ 潛在記憶體洩漏:若 `company[id]` 原有指向舊員工節點,直接覆蓋會導致舊節點無法 `free`。建議先 `if(company[id]) free(company[id]);` 再賦值。

3. 彈性薪資統計核心 (salary_analysis)

void salary_analysis(PEMP company[], sel_c which) {
    char sel;
    int age1, age2, low_age, high_age;
    unsigned long sum = 0;
    int count = 0, i;

    while (1) {
        // 子選單:1=區間統計 2=全員統計 0=返回
        if (which == TOTAL)
            printf("1:某年齡段總和  2:全員總和\n");
        else
            printf("1:某年齡段平均  2:全員平均\n");
        printf("0:返回\n");
        sel = getch();
        if (sel == '0') return;
        if (sel != '1' && sel != '2') continue;

        if (sel == '1') {
            // 輸入區間並自動修正順序
            printf("開始年齡: "); scanf("%d", &age1);
            printf("結束年齡: "); scanf("%d", &age2);
            low_age = (age1 < age2) ? age1 : age2;
            high_age = (age1 > age2) ? age1 : age2;
        }

        sum = 0; count = 0;
        for (i = 0; i < EMP_NUM; i++) {
            if (company[i]) {
                if (sel == '2' || (company[i]->age >= low_age && company[i]->age <= high_age)) {
                    sum += company[i]->salary;
                    count++;
                }
            }
        }

        if (count == 0) {
            printf(sel == '1' ? "沒有該年齡段員工!\n" : "沒有員工信息!\n");
        } else if (which == TOTAL) {
            printf(sel == '1' ? "年齡 %d-%d 總薪資: %lu\n" : "全員總薪資: %lu\n", low_age, high_age, sum);
        } else {
            printf(sel == '1' ? "年齡 %d-%d 平均薪資: %lu\n" : "全員平均薪資: %lu\n", low_age, high_age, sum / count);
        }
        return; // 統計一次即返回上層選單
    }
}

亮點:單一函式透過 `which` 參數復用邏輯,區間邊界自動排序,條件判斷合併減少重複碼。

4. 資料顯示 (display_msg)

void display_msg(PEMP company[]) {
    for (int i = 0; i < EMP_NUM; i++) {
        if (company[i])
            printf("ID:%d  姓名:%s  年齡:%d  薪水:%u\n", i, company[i]->name, company[i]->age, company[i]->salary);
    }
}

關鍵技術總結表

技術應用場景注意事項
結構體指標陣列主資料容器 `company[10]`需手動 `malloc`/`free` 每個節點
枚舉型別統計模式切換 `TOTAL`/`AVERAGE`僅限整數常量,不可動態擴展
動態記憶體分配`update_msg` 中 `malloc` 新員工必須配對 `free`,注意覆蓋洩漏
輸入驗證迴圈年齡 0-60、薪水 0-20000`scanf` 失敗需清緩衝區,否則死循環
函式參數復用`salary_analysis` 統一總和/平均邏輯透過枚舉與條件判斷消除重複

編譯與執行

gcc salary.c -o salary_sys
./salary_sys

需連結 `conio.h`(`getch`)或在 Linux 下自行實作無回顯輸入。

改進建議與擴展方向

  1. 記憶體安全:`update_msg` 加入覆蓋前 `free`;`main` 結束前遍歷釋放所有節點。
  2. 資料持久化:參考通訊錄專案,加入 `save/load` 至二進位檔或 CSV。
  3. 動態擴容:將固定陣列改為 `realloc` 管理的動態指標陣列,支援無上限員工數。
  4. 統計維度擴展:新增「部門」、「職級」欄位,支援多維度群組統計。
  5. 輸入健壯性:替換 `scanf` 為 `fgets` + `sscanf`,徹底解決緩衝區殘留問題。

總結

薪資統計系統以結構體指標陣列為骨架,枚舉驅動邏輯復用為靈魂,展示了 C 語言在中小型資料處理任務中的高效與靈活。代碼中暴露的記憶體管理細節(覆蓋洩漏、缺少統一釋放),正是進階學習者必須攻克的關卡。建議在修復這些問題後,嘗試引入檔案存儲與動態擴容,將其演進為一個完整的迷你 HR 系統。

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