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

C語言項目實戰:通訊錄管理系統與萬年曆雙模塊完整源碼解析

     編輯:關於C語言

C語言項目實戰:通訊錄管理系統與萬年曆雙模塊完整源碼解析

本項目包含兩大獨立模塊:密碼保護的通訊錄管理系統(增刪改查、權限分級、文件持久化)與萬年曆顯示程序(日期驗證、閏年計算、日曆渲染)。代碼展示了 C 語言結構體、文件操作、指針、控制流綜合應用,是課程設計、畢業設計的優秀參考範本。

模塊一:通訊錄管理系統架構設計

數據模型

struct Info {
    char name[15];
    char phone[12];
    char sex[2];      // "M"/"F"
    char age[4];
    char address[20];
};

核心功能矩陣

功能管理員普通用戶關鍵技術點
新增記錄✓✗二進制文件追加寫 fwrite
修改記錄✓✗臨時文件重寫 remove/rename
刪除記錄✓✗標記刪除 + 文件重建
顯示所有✓✓順序讀取 fread + 格式化輸出
多字段查詢✓✓strcmp 逐字段匹配
修改密碼✓✗舊密碼驗證 + 覆寫密碼文件

關鍵代碼片段解析

1. 密碼初始化與驗證流程
void InitializationPassword() {
    FILE *fp = fopen("password.txt", "rb");
    if (!fp) { Initial(); return; }  // 首次運行創建密碼
    
    fseek(fp, 0, SEEK_END);
    long len = ftell(fp);
    if (len == 0) { fclose(fp); Initial(); return; }
    
    fseek(fp, 0, SEEK_SET);
    fread(password_stored, 1, 10, fp);  // 讀取存儲密碼
    fclose(fp);
}

void EnterPassword() {
    printf("Enter password: ");
    gets(password_input);  // 注意:gets 不安全,教學代碼常用
}
2. 記錄修改:臨時文件法(經典 C 文件更新模式)
void Modify() {
    FILE *fp_src = fopen("info.dat", "rb");
    FILE *fp_tmp = fopen("temp.dat", "wb");
    
    char target_name[20];
    gets(target_name);
    
    struct Info record;
    while (fread(&record, sizeof(record), 1, fp_src)) {
        if (strcmp(record.name, target_name) == 0) {
            // 交互式獲取新字段值
            gets(record.name); gets(record.phone); ...
            fwrite(&record, sizeof(record), 1, fp_tmp);
        } else {
            fwrite(&record, sizeof(record), 1, fp_tmp);  // 原樣複製
        }
    }
    
    fclose(fp_src); fclose(fp_tmp);
    remove("info.dat");
    rename("temp.dat", "info.dat");  // 原子替換
}
3. 多字段查詢:統一入口 + switch 分發
void Search() {
    int mode; char keyword[20];
    scanf("%d", &mode); gets(keyword);
    
    FILE *fp = fopen("info.dat", "rb");
    struct Info record;
    
    while (fread(&record, sizeof(record), 1, fp)) {
        int match = 0;
        switch (mode) {
            case 1: match = strcmp(record.name, keyword) == 0; break;
            case 2: match = strcmp(record.phone, keyword) == 0; break;
            case 3: match = strcmp(record.sex, keyword) == 0; break;
            case 4: match = strcmp(record.age, keyword) == 0; break;
            case 5: match = strcmp(record.address, keyword) == 0; break;
        }
        if (match) print_record(&record);
    }
    fclose(fp);
}

模塊二:萬年曆算法核心

核心數學模型

  • 基準日:1900-01-01 為星期一(對應 days % 7 == 1)
  • 閏年規則:(year%4==0 && year%100!=0) || year%400==0
  • 總天數計算:1900 年至目標年份前累加 + 目標年內前累加月天數
  • 首日偏移:total_days % 7 決定 1 號對應星期幾

關鍵函數鏈

void DisplayTheCalendar() {
    February();      // 設置 2 月天數 (28/29)
    TotalDays();     // 計算距 1900-01-01 總天數
    Calendar();      // 打印表頭 + 首行偏移
    Showing();       // 打印日期網格
}

日期渲染邏輯

void Calendar() {
    printf("SUN\tMON\tTUE\tWED\tTHU\tFRI\tSAT\n");
    for (int i = days % 7; i > 0; i--)  // 關鍵:days%7 為 1號前空格數
        printf("\t");
}

void Showing() {
    for (int d = 1; d <= month_days[month]; d++) {
        printf("%d\t", d);
        if (days % 7 == 6) printf("\n");  // 週六換行
        days++;
    }
    printf("\n");
}

代碼質量評估與重構建議

現存問題(教學代碼典型特徵)

問題風險重構方向
gets() 無緩衝區保護緩衝區溢出漏洞改用 fgets(buf, sizeof(buf), stdin) 去除尾部 \n
全局/靜態變量濫用耦合度高,難測試封裝為 Context 結構體傳遞
無輸入驗證(年份/月份範圍)異常輸入導致邏輯錯誤增加 validate_date() 返回錯誤碼
魔術數字(10, 15, 20 等)維護困難定義常量 MAX_NAME_LEN 等
密碼明文存儲安全隱患至少存儲鹽值哈希 SHA256(salt+pass)
遞歸調用 EnterDate() 驗證失敗棧溢出風險改用循環 while(!valid) EnterDate()

工程化重構架構草圖

// 通訊錄模塊
typedef struct {
    FILE* db_file;
    char* password_hash;
    int is_admin;
} AddressBookContext;

AddressBookContext* ab_create(const char* db_path);
void ab_destroy(AddressBookContext* ctx);
int ab_add(AddressBookContext* ctx, const Contact* c);
int ab_find(AddressBookContext* ctx, const Query* q, Contact** results, int* count);
// ...

// 曆法模塊
typedef struct {
    int year, month;
} CalendarContext;

int cal_validate(CalendarContext* ctx);
void cal_render(const CalendarContext* ctx, char* buffer, size_t size);

編譯與運行指南

# GCC 編譯(需鏈接數學庫 -lm)
gcc address_book.c calendar.c -o ab_cal -Wall -Wextra -std=c99

# 運行
./ab_cal
# 首次運行提示設置密碼
# 後續運行驗證密碼進入對應權限界面

這個雙模塊項目雖屬教學級代碼,但完整覆蓋了「數據建模→文件持久化→用戶交互→權限控制→算法實現」軟件工程全鏈路。建議以此為藍本,逐步引入模塊化編譯、單元測試、錯誤碼體系、安全加固,將其進化為生產級組件庫。

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