本專案實作一個互動式公司薪資統計系統,核心資料結構採用結構體指標陣列(`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;
設計考量:
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])` 即可安全判斷是否有資料。
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]);` 再賦值。
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` 參數復用邏輯,區間邊界自動排序,條件判斷合併減少重複碼。
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 下自行實作無回顯輸入。
薪資統計系統以結構體指標陣列為骨架,枚舉驅動邏輯復用為靈魂,展示了 C 語言在中小型資料處理任務中的高效與靈活。代碼中暴露的記憶體管理細節(覆蓋洩漏、缺少統一釋放),正是進階學習者必須攻克的關卡。建議在修復這些問題後,嘗試引入檔案存儲與動態擴容,將其演進為一個完整的迷你 HR 系統。