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

C語言實作通訊錄系統:從需求分析到完整程式碼教學

     編輯:關於C語言

C語言實作通訊錄系統:完整開發教學

本文將帶領讀者從零開始,使用 C 語言開發一個功能完整的命令列通訊錄系統。專案涵蓋需求分析、資料結構設計、檔案持久化、模組化程式碼架構,適合 C 語言初學者鞏固指標、結構體、檔案操作與模組化設計等核心概念。

一、專案需求與功能規劃

1.1 核心需求

  • 支援聯絡人新增、刪除、修改、查看、搜尋五大基本操作。
  • 資料採用二進位檔案持久化,程式重啟後資料不遺失。
  • 介面為純文字命令列選單,操作直覺簡單。
  • 聯絡人資料包含姓名與電話號碼兩個欄位。

1.2 系統原型與流程

啟動時顯示歡迎選單,使用者輸入 1-6 選擇操作:

  1. 添加聯絡人
  2. 刪除聯絡人
  3. 修改聯絡人
  4. 查看所有聯絡人
  5. 搜尋聯絡人
  6. 退出系統

每項操作完成後自動返回主選單,直到使用者選擇退出。

1.3 功能模組分析

模組核心邏輯關鍵資料結構
初始化嘗試讀取資料檔;不存在則建立新檔並寫入聯絡人數量 0檔案指標、結構體陣列
新增輸入姓名/電話 → 確認 → 寫入陣列尾端 → 更新檔案Person 結構體、全域計數器
刪除顯示列表 → 輸入編號 → 確認 → 陣列元素前移覆蓋 → 更新檔案陣列位移演算法
修改顯示列表 → 輸入編號 → 確認 → 輸入新資料 → 覆蓋陣列元素 → 更新檔案暫存緩衝區避免輸入中途污染資料
查看遍歷陣列列印所有聯絡人;空陣列提示迴圈索引
搜尋輸入姓名 → 線性搜尋陣列 → 找到顯示電話、否則提示無紀錄strcmp 字串比對

二、核心資料結構與巨集定義

// 常數定義
#define MAX_CONTACTS 100      // 最大聯絡人數
#define NAME_LEN     13       // 姓名最大長度(含結束符)
#define PHONE_LEN    12       // 電話最大長度

// 聯絡人結構體
typedef struct {
    char name[NAME_LEN];
    char phone[PHONE_LEN];
} Person;

// 全域變數
Person contacts[MAX_CONTACTS]; // 聯絡人陣列
int contactCount = 0;          // 目前聯絡人數量
const char *DATA_FILE = "contacts.dat"; // 資料檔名

// 函式宣告
void initSystem(void);
void addContact(void);
void deleteContact(void);
void editContact(void);
void listContacts(void);
void searchContact(void);
int saveToFile(void);
int validateIndex(int idx, int min, int max);
void showMenu(void);

三、關鍵模組實作詳解

3.1 系統初始化 initSystem()

程式啟動時自動呼叫,負責從二進位檔案載入資料:

void initSystem(void) {
    FILE *fp = fopen(DATA_FILE, "rb");
    if (fp) {
        fread(&contactCount, sizeof(int), 1, fp);
        for (int i = 0; i < contactCount; i++) {
            fread(&contacts[i], sizeof(Person), 1, fp);
        }
        fclose(fp);
        printf("通訊錄初始化完成,共載入 %d 筆資料。\n", contactCount);
    } else {
        // 檔案不存在,建立空檔
        fp = fopen(DATA_FILE, "wb");
        if (fp) {
            fwrite(&contactCount, sizeof(int), 1, fp);
            fclose(fp);
            printf("建立新通訊錄檔案。\n");
        }
    }
}

設計重點:務必先寫入/讀取 contactCount,否則重啟後無法知道陣列有效長度。

3.2 新增聯絡人 addContact()

void addContact(void) {
    if (contactCount >= MAX_CONTACTS) {
        printf("通訊錄已滿,無法新增。\n");
        return;
    }
    printf("請輸入姓名 (無空格):");
    scanf("%12s", contacts[contactCount].name);
    printf("請輸入電話 (無空格):");
    scanf("%11s", contacts[contactCount].phone);

    int confirm;
    printf("確定新增 \"%s\" 嗎?(1=是/0=否):", contacts[contactCount].name);
    scanf("%d", &confirm);
    if (confirm) {
        contactCount++;
        saveToFile();
        printf("新增成功!\n");
    }
}

3.3 刪除聯絡人 deleteContact()

採用「後續元素前移」覆蓋被刪除位置,最後遞減計數器:

void deleteContact(void) {
    listContacts();
    if (contactCount == 0) return;

    int idx;
    printf("請輸入要刪除的編號 (1-%d):", contactCount);
    scanf("%d", &idx);
    if (!validateIndex(idx, 1, contactCount)) return;

    int confirm;
    printf("確定刪除 \"%s\"?資料無法復原 (1=是/0=否):", contacts[idx-1].name);
    scanf("%d", &confirm);
    if (!confirm) return;

    // 陣列前移
    for (int i = idx - 1; i < contactCount - 1; i++) {
        contacts[i] = contacts[i + 1];
    }
    contactCount--;
    saveToFile();
    printf("刪除完成。\n");
}

3.4 檔案儲存 saveToFile()

每次資料異動後呼叫,確保持久化一致性:

int saveToFile(void) {
    FILE *fp = fopen(DATA_FILE, "wb");
    if (!fp) {
        perror("檔案開啟失敗");
        return -1;
    }
    fwrite(&contactCount, sizeof(int), 1, fp);
    for (int i = 0; i < contactCount; i++) {
        fwrite(&contacts[i], sizeof(Person), 1, fp);
    }
    fclose(fp);
    return 0;
}

3.5 輸入驗證工具 validateIndex()

int validateIndex(int num, int min, int max) {
    if (num >= min && num <= max) return 1;
    printf("輸入編號超出範圍!\n");
    return 0;
}

四、主程式流程控制

int main(void) {
    initSystem();
    int choice;
    while (1) {
        showMenu();
        scanf("%d", &choice);
        switch (choice) {
            case 1: addContact(); break;
            case 2: deleteContact(); break;
            case 3: editContact(); break;
            case 4: listContacts(); break;
            case 5: searchContact(); break;
            case 6:
                printf("感謝使用,再見!\n");
                return 0;
            default:
                printf("無效選項,請輸入 1-6。\n");
        }
    }
}

五、進階優化方向

  1. 動態記憶體:改用連結串列或 realloc 動態陣列,突破 100 筆上限。
  2. 索引加速:引入雜湊表或二元搜尋樹,將搜尋從 O(n) 降為 O(log n) 或 O(1)。
  3. 輸入健壯性:處理 scanf 緩衝區殘留換行符、支援含空格姓名(改用 fgets + 去除換行)。
  4. 資料完整性:採用「寫入暫存檔 → 重新命名」原子操作,防止寫入中斷導致資料損毀。

六、完整程式碼下載

本專案完整原始碼(含註解與 Makefile)可從 GitHub Repository 取得,歡迎 Fork 練習擴充功能。

總結

這個通訊錄專案雖然規模不大,卻完整串聯了 C 語言的核心技能:結構體陣列、檔案二進位讀寫、指標操作、模組化設計、錯誤處理與使用者互動流程。建議初學者先完整抄寫並執行,再嘗試加入「依姓名排序」、「匯出 CSV」等擴充功能,將知識內化為實戰能力。

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