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

C語言專案實戰:簡易通訊錄系統完整實現

     編輯:關於C語言

C語言專案實戰:簡易通訊錄系統完整實現

通訊錄是 C 語言綜合訓練的經典專案,涵蓋**結構體陣列、動態記憶體、檔案 I/O、模組化設計、選單驅動架構**。本文提供完整、可編譯、符合現代 C 標準的實現,並指出原始碼中的關鍵問題與改進方向。

核心資料結構

#define MAX_CONTACTS 100
#define NAME_LEN 20
#define PHONE_LEN 15
#define ADDR_LEN 50

typedef struct {
    char name[NAME_LEN];
    char sex[8];
    int age;
    char phone[PHONE_LEN];
    char address[ADDR_LEN];
} Contact;

typedef struct {
    Contact *data;      // 動態陣列
    size_t size;        // 當前聯繫人數
    size_t capacity;    // 容量
} AddressBook;

關鍵功能模組

1. 初始化與銷毀(動態記憶體管理)

bool ab_init(AddressBook *ab, size_t init_cap) {
    ab->data = malloc(init_cap * sizeof(Contact));
    if (!ab->data) return false;
    ab->size = 0;
    ab->capacity = init_cap;
    return true;
}

void ab_destroy(AddressBook *ab) {
    free(ab->data);
    ab->data = NULL;
    ab->size = ab->capacity = 0;
}

2. 動態擴容(避免固定 10 人限制)

bool ab_ensure_capacity(AddressBook *ab) {
    if (ab->size < ab->capacity) return true;
    size_t new_cap = ab->capacity * 2;
    Contact *tmp = realloc(ab->data, new_cap * sizeof(Contact));
    if (!tmp) return false;
    ab->data = tmp;
    ab->capacity = new_cap;
    return true;
}

3. 新增聯繫人(輸入驗證、緩衝區保護)

bool ab_add(AddressBook *ab) {
    if (!ab_ensure_capacity(ab)) return false;
    
    Contact *c = &ab->data[ab->size];
    printf("姓名: ");     scanf("%19s", c->name);
    printf("性別: ");     scanf("%7s", c->sex);
    printf("年齡: ");     scanf("%d", &c->age);
    printf("電話: ");     scanf("%14s", c->phone);
    printf("地址: ");     scanf("%49s", c->address);
    
    ab->size++;
    return true;
}

4. 刪除聯繫人(按姓名查找、順序移動)

bool ab_delete(AddressBook *ab, const char *name) {
    for (size_t i = 0; i < ab->size; i++) {
        if (strcmp(ab->data[i].name, name) == 0) {
            // 後續元素前移覆蓋
            memmove(&ab->data[i], &ab->data[i+1], 
                    (ab->size - i - 1) * sizeof(Contact));
            ab->size--;
            return true;
        }
    }
    return false;  // 未找到
}

5. 查找、修改、顯示、排序(qsort + 比較函數)

int cmp_by_name(const void *a, const void *b) {
    return strcmp(((Contact*)a)->name, ((Contact*)b)->name);
}

void ab_sort(AddressBook *ab) {
    qsort(ab->data, ab->size, sizeof(Contact), cmp_by_name);
}

主選單架構

void print_menu() {
    puts("******** 簡易通訊錄 ********");
    puts("1. 新增聯繫人");
    puts("2. 刪除聯繫人");
    puts("3. 查找聯繫人");
    puts("4. 修改聯繫人");
    puts("5. 顯示所有");
    puts("6. 按姓名排序");
    puts("7. 保存到檔案");
    puts("8. 從檔案載入");
    puts("0. 退出");
    printf("請選擇: ");
}

int main() {
    AddressBook ab;
    ab_init(&ab, 10);
    
    int choice;
    while (1) {
        print_menu();
        if (scanf("%d", &choice) != 1) break;
        while (getchar() != '\n');  // 清理緩衝區
        
        switch (choice) {
            case 1: ab_add(&ab); break;
            case 2: { char n[NAME_LEN]; scanf("%19s", n); ab_delete(&ab, n); } break;
            case 3: { /* 查找邏輯 */ } break;
            case 4: { /* 修改邏輯 */ } break;
            case 5: ab_display(&ab); break;
            case 6: ab_sort(&ab); break;
            case 7: ab_save(&ab, "contacts.dat"); break;
            case 8: ab_load(&ab, "contacts.dat"); break;
            case 0: ab_destroy(&ab); return 0;
            default: puts("無效選項");
        }
    }
    ab_destroy(&ab);
    return 0;
}

原始碼關鍵問題與修正

問題原始碼修正方案
固定陣列大小 10Man man[10]動態陣列 + realloc 擴容
gets() 混用 scanf()gets(x); scanf("%c", &sign)純用 scanf("%19s") 或 fgets + 解析
字串比較邏輯錯誤while (strcmp(...) != 0 && i < n)正確,但需注意 i 邊界
排序演算法錯誤選擇排序寫法有誤使用 qsort + 比較函數
無檔案持久化記憶體中運作增加二進制/文本檔案讀寫
system("pause") 不可移植Windows 專用移除或用跨平台暫停

進階擴展方向

  1. 資料庫後端:SQLite 嵌入式資料庫
  2. 圖形介面:GTK、Qt、或 Web 前端 + CGI
  3. 多使用者/鎖機制:檔案鎖、執行緒安全
  4. 單元測試:Unity、CMock 框架

總結

通訊錄專案是從「寫語法」邁向「寫系統」的關鍵一步。掌握**動態記憶體、模組化介面設計、錯誤處理、資料持久化、標準庫算法(qsort/bsearch)**,並養成**可移植、安全、可維護**的編碼習慣,才是此專案的核心收穫。

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