檔案式訂閱管理系統設計
需求分析
- 訂戶 ≤ 10 人,信息:姓名、性別、電話、單位、訂閱數、期限
- 功能:增刪改查、到期清理、統計報表
- 數據持久化:文本文件
record.txt
- 菜單驅動交互
數據結構設計
#define MAX 20
struct Magazine {
char name[11];
char sex[6];
char addr[11];
char phone[12];
char unitPrice[5];
char amount[4];
char timeLimit[11]; // 格式: YYYYMM
} orders[MAX];
核心模塊實現
文件讀寫
int loadRecords() {
FILE *fp = fopen("record.txt", "rb");
if (!fp) return 0;
int n = 0;
while (fread(&orders[n], sizeof(struct Magazine), 1, fp) == 1) n++;
fclose(fp);
return n;
}
void saveRecords(int n) {
FILE *fp = fopen("record.txt", "wb");
if (!fp) { perror("save"); return; }
fwrite(orders, sizeof(struct Magazine), n, fp);
fclose(fp);
}
新增訂戶
void addSubscriber() {
int n = loadRecords(), m;
printf("新增數量: "); scanf("%d", &m);
for (int i = 0; i < m; i++) {
printf("姓名 性別 地址 電話 單價 數量 期限: ");
scanf("%s %s %s %s %s %s %s",
orders[n+i].name, orders[n+i].sex, orders[n+i].addr,
orders[n+i].phone, orders[n+i].unitPrice,
orders[n+i].amount, orders[n+i].timeLimit);
}
saveRecords(n + m);
}
到期清理與查詢
void checkExpired() {
int n = loadRecords();
char today[11];
printf("輸入今天日期(YYYYMM): "); scanf("%s", today);
FILE *fp = fopen("record.txt", "wb");
int kept = 0;
for (int i = 0; i < n; i++) {
if (strcmp(orders[i].timeLimit, today) >= 0) {
fwrite(&orders[i], sizeof(struct Magazine), 1, fp);
kept++;
} else {
printf("清理到期: %s 期限 %s\n", orders[i].name, orders[i].timeLimit);
}
}
fclose(fp);
printf("剩餘 %d 位訂戶\n", kept);
}
統計報表
void statistics() {
int n = loadRecords();
float total = 0;
printf("%-10s %-6s %-8s %-8s\n", "訂戶", "訂閱數", "單價", "全額");
for (int i = 0; i < n; i++) {
float price = atof(orders[i].unitPrice);
int cnt = atoi(orders[i].amount);
float sum = price * cnt;
printf("%-10s %-6d %-8.1f %-8.1f\n", orders[i].name, cnt, price, sum);
total += sum;
}
printf("合計 %-6d %-8s %-8.1f\n", n, "", total);
}
主菜單驅動
int main() {
int choice;
while (1) {
printf("\n=== 雜志訂閱管理 ===\n");
printf("1.新增 2.到期清理 3.統計 0.退出\n選擇: ");
if (scanf("%d", &choice) != 1) { while(getchar()!='\n'); continue; }
switch (choice) {
case 1: addSubscriber(); break;
case 2: checkExpired(); break;
case 3: statistics(); break;
case 0: return 0;
default: printf("無效選項\n");
}
}
}
改進建議
- 輸入驗證:日期格式、電話格式、數值範圍
- 用結構體數組改為鏈表支援動態擴展
- 增加修改/刪除單條記錄功能
- 文件改用 CSV/JSON 便於跨工具處理
- 引入單元測試框架 (Check/Unity) 保證質量