ITPub博客

首页 > 应用开发 > IT综合 > C语言项目实战:动态通讯录系统开发全流程解析

C语言项目实战:动态通讯录系统开发全流程解析

投稿 IT综合 作者:bhluo 时间:2025-11-25 14:14:28 0 删除 编辑

**C语言项目实战:动态通讯录系统开发全流程解析**


通讯录系统是学习C语言的经典项目,它综合运用了结构体、指针、动态内存管理和文件操作等核心概念。本文将完整展示从零构建一个功能完善的动态通讯录系统。


### 项目需求分析与设计


首先明确通讯录系统的功能需求和技术架构。


```c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>


#define MAX_NAME_LEN 50

#define MAX_PHONE_LEN 20

#define MAX_ADDRESS_LEN 100

#define INITIAL_CAPACITY 10


// 联系人结构体设计

typedef struct {

    int id;                    // 联系人ID

    char name[MAX_NAME_LEN];   // 姓名

    char phone[MAX_PHONE_LEN]; // 电话

    char address[MAX_ADDRESS_LEN]; // 地址

    int age;                   // 年龄

    char group[20];            // 分组

} Contact;


// 通讯录管理系统结构体

typedef struct {

    Contact *contacts;         // 动态数组指针

    int count;                 // 当前联系人数量

    int capacity;              // 当前容量

    int next_id;               // 下一个可用的ID

} AddressBook;


// 函数声明

void initAddressBook(AddressBook *book);

void addContact(AddressBook *book);

void displayContacts(const AddressBook *book);

void searchContact(const AddressBook *book);

void deleteContact(AddressBook *book);

void modifyContact(AddressBook *book);

void saveToFile(const AddressBook *book);

void loadFromFile(AddressBook *book);

void freeAddressBook(AddressBook *book);

void sortContacts(AddressBook *book);

```


### 核心数据结构实现


实现通讯录的初始化、扩容和内存管理。


```c

// 初始化通讯录

void initAddressBook(AddressBook *book) {

    book->contacts = (Contact *)malloc(INITIAL_CAPACITY * sizeof(Contact));

    if (book->contacts == NULL) {

        printf("内存分配失败!\n");

        exit(1);

    }

    book->count = 0;

    book->capacity =<"BN.6370.HK"> INITIAL_CAPACITY;

    book->next_id = 1;

    printf("通讯录初始化成功,初始容量:%d\n", INITIAL_CAPACITY);

}


// 动态扩容

void expandCapacity(AddressBook *book) {

    int new_capacity = book->capacity * 2;

    Contact *new_contacts = (Contact *)realloc(book->contacts, new_capacity * sizeof(Contact));

    if (new_contacts == NULL) {

        printf("内存扩容失败!\n");

        return;

    }

    book->contacts = new_contacts;

    book->capacity = new_capacity;

    printf("通讯录已扩容,新容量:%d\n", new_capacity);

}


// 释放内存

void freeAddressBook(AddressBook *book) {

    if (book->contacts != NULL) {

        free(book->contacts);

        book->contacts = NULL;

    }

    book->count = 0;

    book->capacity = 0;

    book->next_id = 1;

    printf("通讯录内存已释放\n");

}


// 输入工具函数

void getInput(char *buffer, int max_len, const char *prompt) {

    printf("%s", prompt);

    fgets(buffer, max_len, stdin);

    buffer[strcspn(buffer, "\n")] = '\0'; // 移除换行符

}


int getIntInput(const char *prompt) {

    char buffer[20];

    getInput(buffer, sizeof(buffer), prompt);

    return atoi(buffer);

}

```


### 联系人管理功能实现


实现联系人的增删改查等核心功能。


```c

// 添加联系人

void addContact(AddressBook *book) {

    // 检查是否需要扩容

    if (book->count >= book->capacity) {

        expandCapacity(book);

    }

    

    Contact *new_contact = &book->contacts[book->count];

    

    // 自动分配ID

    new_contact-><"ES.6370.HK">id = book->next_id++;

    

    // 输入联系人信息

    printf("\n=== 添加新联系人 ===\n");

    getInput(new_contact->name, MAX_NAME_LEN, "请输入姓名: ");

    getInput(new_contact->phone, MAX_PHONE_LEN, "请输入电话: ");

    getInput(new_contact->address, MAX_ADDRESS_LEN, "请输入地址: ");

    new_contact->age = getIntInput("请输入年龄: ");

    getInput(new_contact->group, 20, "请输入分组: ");

    

    book->count++;

    printf("联系人添加成功!ID: %d\n", new_contact->id);

}


// 显示所有联系人

void displayContacts(const AddressBook *book) {

    printf("\n=== 通讯录列表 (共%d个联系人) ===\n", book->count);

    printf("%-4s %-15s %-15s %-8s %-10s %-20s\n", 

           "ID", "姓名", "电话", "年龄", "分组", "地址");

    printf("------------------------------------------------------------------------\n");

    

    for (int i = 0; i < book->count; i++) {

        Contact *contact = &book->contacts[i];

        printf("%-4d %-15s %-15s %-8d %-10s %-20s\n",

               contact->id, contact->name, contact->phone,

               contact->age, contact->group, contact->address);

    }

}


// 查找联系人(支持按姓名和电话查找)

void searchContact(const AddressBook *book) {

    if (book->count == 0) {

        printf("通讯录为空,无法查找!\n");

        return;

    }

    

    char keyword[MAX_NAME_LEN];

    getInput(keyword, sizeof(keyword), "请输入姓名或电话进行搜索: ");

    

    printf("\n=== 搜索结果 ===\n");

    printf("%-4s %-15s %-15s %-8s %-10s %-20s\n", 

           "ID", "姓名", "电话", "年龄", "分组", "地址");

    printf("------------------------------------------------------------------------\n");

    

    int found = 0;

    for (int i = 0; i < book->count; i++) {

        Contact *contact = &book->contacts[i];

        if (strstr(contact->name, keyword) != NULL || 

            strstr(contact->phone, keyword) != NULL) {

            printf("%-4d %-15s %-15s %-8d %-10s %-20s\n",

                   contact->id, contact->name, contact->phone,

                   contact->age, contact->group, contact->address);

            found = 1;

        }

    }

    

    if (!found) {

        printf("未找到匹配的联系人!\n");

    }

}


// 删除联系人

void deleteContact(AddressBook *book) {

    if (book->count == 0) {

        printf("通讯录为空,无法删除!\n");

        return;

    }

    

    displayContacts(book);

    int id = getIntInput("\n请输入要删除的联系人ID: ");

    

    int found_index = -1;

    for (int i = 0; i < book->count; i++) {

        if (book->contacts[i].id == id) {

            found_index = i;

            break;

        }

    }

    

    if (found_index == -1) {

        printf("未找到ID为%d的联系人!\n", id);

        return;

    }

    

    // 显示要删除的联系人信息

    Contact *contact = &book->contacts[found_index];

    printf("即将删除联系人:\n");

    printf("ID: %d, 姓名: %s, 电话: %s\n", contact->id, contact->name, contact->phone);

    

    char confirm;

    printf("确认删除?(y/n): ");

    scanf<"PX.6370.HK">(" %c", &confirm);

    getchar(); // 清除缓冲区

    

    if (confirm == 'y' || confirm == 'Y') {

        // 将后面的元素前移

        for (int i = found_index; i < book->count - 1; i++) {

            book->contacts[i] = book->contacts[i + 1];

        }

        book->count--;

        printf("联系人删除成功!\n");

    } else {

        printf("取消删除操作。\n");

    }

}


// 修改联系人

void modifyContact(AddressBook *book) {

    if (book->count == 0) {

        printf("通讯录为空,无法修改!\n");

        return;

    }

    

    displayContacts(book);

    int id = getIntInput("\n请输入要修改的联系人ID: ");

    

    int found_index = -1;

    for (int i = 0; i < book->count; i++) {

        if (book->contacts[i].id == id) {

            found_index = i;

            break;

        }

    }

    

    if (found_index == -1) {

        printf("未找到ID为%d的联系人!\n", id);

        return;

    }

    

    Contact *contact = &book->contacts[found_index];

    printf("\n当前联系人信息:\n");

    printf("ID: %d\n", contact->id);

    printf("1. 姓名: %s\n", contact->name);

    printf("2. 电话: %s\n", contact->phone);

    printf("3. 地址: %s\n", contact->address);

    printf("4. 年龄: %d\n", contact->age);

    printf("5. 分组: %s\n", contact->group);

    

    int choice = getIntInput("\n请选择要修改的字段 (1-5): ");

    

    switch (choice) {

        case 1:

            getInput(contact->name, MAX_NAME_LEN, "请输入新姓名: ");

            break;

        case 2:

            getInput(contact->phone, MAX_PHONE_LEN, "请输入新电话: ");

            break;

        case 3:

            getInput(contact->address, MAX_ADDRESS_LEN, "请输入新地址: ");

            break;

        case 4:

            contact->age = getIntInput("请输入新年龄: ");

            break;

        case 5:

            getInput(contact->group, 20, "请输入新分组: ");

            break;

        default:

            printf("无效的选择!\n");

            return;

    }

    

    printf("联系人信息修改成功!\n");

}

```


### 文件操作实现


实现数据的持久化存储和加载。


```c

// 保存到文件

void saveToFile(const AddressBook *book) {

    FILE *file = fopen("addressbook.dat", "wb");

    if (file == NULL) {

        printf("无法创建文件!\n");

        return;

    }

    

    // 先写入联系人数量

    fwrite(&book->count, sizeof(int), 1, file);

    fwrite(&book->next_id, sizeof(int), 1, file);

    

    // 写入所有联系人数据

    for (int i = 0; i < book->count; i++) {

        fwrite(&book-><"QJ.6370.HK">contacts[i], sizeof(Contact), 1, file);

    }

    

    fclose(file);

    printf("数据已保存到文件,共保存%d个联系人\n", book->count);

}


// 从文件加载

void loadFromFile(AddressBook *book) {

    FILE *file = fopen("addressbook.dat", "rb");

    if (file == NULL) {

        printf("文件不存在或无法打开,将创建新的通讯录\n");

        return;

    }

    

    // 读取联系人数量和下一个ID

    int count, next_id;

    fread(&count, sizeof(int), 1, file);

    fread(&next_id, sizeof(int), 1, file);

    

    if (count <= 0) {

        fclose(file);

        printf("文件数据无效\n");

        return;

    }

    

    // 确保容量足够

    while (book->capacity < count) {

        expandCapacity(book);

    }

    

    // 读取联系人数据

    for (int i = 0; i < count; i++) {

        fread(&book->contacts[i], sizeof(Contact), 1, file);

    }

    

    book->count = count;

    book->next_id = next_id;

    

    fclose(file);

    printf("从文件加载成功,共加载%d个联系人\n", count);

}


// 导出为文本文件

void exportToTextFile(const AddressBook *book) {

    FILE *file = fopen("addressbook.txt", "w");

    if (file == NULL) {

        printf("无法创建文本文件!\n");

        return;

    }

    

    fprintf(file, "=== 通讯录导出数据 ===\n");

    fprintf(file, "总联系人数量: %d\n\n", book->count);

    

    for (int i = 0; i < book->count; i++) {

        Contact *contact = &book->contacts[i];

        fprintf(file, "联系人 #%d:\n", i + 1);

        fprintf(file, "  ID: %d\n", contact->id);

        fprintf(file, "  姓名: %s\n", contact->name);

        fprintf(file, "  电话: %s\n", contact->phone);

        fprintf(file, "  地址: %s\n", contact->address);

        fprintf(file, "  年龄: %d\n", contact->age);

        fprintf(file, "  分组: %s\n", contact->group);

        fprintf(file, "------------------------\n");

    }

    

    fclose(file);

    printf("数据已导出到文本文件 addressbook.txt\n");

}

```


### 排序和统计功能


```c

// 比较函数用于排序

int compareByName(const void *a, const void *b) {

    const Contact *contactA = (const Contact *)a;

    const Contact *contactB = (const Contact *)b;

    return strcmp(contactA->name, contactB->name);

}


int compareByAge(const void *a, const void *b) {

    const Contact *contactA = (const Contact *)a;

    const Contact *contactB = (const Contact *)b;

    return contactA->age - contactB->age;

}


// 排序联系人

void sortContacts(AddressBook *book) {

    if (book->count == 0) {

        printf("通讯录为空,无法排序!\n");

        return;

    }

    

    printf("\n请选择排序方式:\n");

    printf("1. 按姓名排序\n");

    printf("2. 按年龄排序\n");

    

    int choice = getIntInput("请选择 (1-2): ");

    

    switch (choice) {

        case 1:

            qsort(book->contacts, book->count, sizeof(Contact), compareByName);

            printf("已按姓名排序\n");

            break;

        case 2:

            qsort(book->contacts, book->count, sizeof(Contact), compareByAge);

            printf("已按年龄排序\n");

            break;

        default:

            printf("无效的选择!\n");

            return;

    }

    

    displayContacts(book);

}


// 统计信息

void showStatistics(const AddressBook *book) {

    if (book->count == 0) {

        printf("通讯录为空,无法统计!\n");

        return;

    }

    

    printf("\n=== 通讯录统计信息 ===\n");

    printf("总联系人数量: %d\n", book->count);

    printf("当前容量: %d\n", book->capacity);

    printf("空间使用率: %.1f%%\n", (float)book->count / book->capacity * 100);

    

    // 分组统计

    int group_count = 0;

    char groups[100][20];

    int group_sizes[100] = {0};

    

    for (int i = 0; i < book->count; i++) {

        char *group = book->contacts[i].group;

        int found = 0;

        

        for (int j = 0; j < group_count; j++) {

            if (strcmp(groups[j], group) == 0) {

                group_sizes[j]++;

                found = 1;

                break;

            }

        }

        

        if (!found && group_count < 100) {

            strcpy(groups[group_count], group);

            group_sizes[group_count] = 1;

            group_count++<"HL.6370.HK">;

        }

    }

    

    printf("\n分组统计:\n");

    for (int i = 0; i < group_count; i++) {

        printf("  %s: %d人\n", groups[i], group_sizes[i]);

    }

    

    // 年龄统计

    int age_groups[6] = {0}; // 0: <18, 1: 18-25, 2: 26-35, 3: 36-50, 4: 51-65, 5: >65

    const char *age_labels[] = {"未成年(<18)", "青年(18-25)", "青壮年(26-35)", 

                               "中年(36-50)", "中老年(51-65)", "老年(>65)"};

    

    for (int i = 0; i < book->count; i++) {

        int age = book->contacts[i].age;

        if (age < 18) age_groups[0]++;

        else if (age <= 25) age_groups[1]++;

        else if (age <= 35) age_groups[2]++;

        else if (age <= 50) age_groups[3]++;

        else if (age <= 65) age_groups[4]++;

        else age_groups[5]++;

    }

    

    printf("\n年龄分布:\n");

    for (int i = 0; i < 6; i++) {

        if (age_groups[i] > 0) {

            printf("  %s: %d人 (%.1f%%)\n", age_labels[i], age_groups[i],

                   (float)age_groups[i] / book->count * 100);

        }

    }

}

```


### 主程序与用户界面


```c

// 显示菜单

void showMenu() {

    printf("\n=== 动态通讯录管理系统 ===\n");

    printf("1. 添加联系人\n");

    printf("2. 显示所有联系人\n");

    printf("3. 查找联系人\n");

    printf("4. 删除联系人\n");

    printf("5. 修改联系人\n");

    printf("6. 排序联系人\n");

    printf("7. 统计信息\n");

    printf("8. 保存到文件\n");

    printf("9. 从文件加载\n");

    printf("10. 导出为文本文件\n");

    printf("0. 退出系统\n");

    printf("------------------------\n");

}


// 主函数

int main() {

    AddressBook addressBook;

    

    printf("欢迎使用动态通讯录管理系统!\n");

    

    // 初始化通讯录

    initAddressBook(&addressBook);

    

    // 尝试从文件加载数据

    loadFromFile(&addressBook);

    

    int choice;

    do {

        showMenu();

        choice = getIntInput("请选择操作 (0-10): ");

        

        switch (choice) {

            case 1:

                addContact(&addressBook);

                break;

            case 2:

                displayContacts(&addressBook);

                break;

            case 3:

                searchContact(&addressBook);

                break;

            case 4:

                deleteContact(&addressBook);

                break;

            case 5:

                modifyContact(&addressBook);

                break;

            case 6:

                sortContacts(&addressBook);

                break;

            case 7:

                showStatistics(&addressBook);

                break;

            case 8:

                saveToFile(&addressBook);

                break;

            case 9:

                loadFromFile(&addressBook);

                break;

            case 10:

                exportToTextFile(&addressBook);

                break;

            case 0:

                printf("感谢使用通讯录管理系统!\n");

                break;

            default:

                printf("无效的选择,请重新输入!\n");

        }

        

        // 每次操作后暂停

        if (choice != 0) {

            printf("\n按回车键继续...");

            getchar();

        }

        

    } while (choice != 0);

    

    // 退出前保存数据

    char save;

    printf("是否保存数据到文件?(y/n): ");

    scanf(" %c", &save);

    if (save == 'y' || save == 'Y') {

        saveToFile(&addressBook);

    }

    

    // 释放内存

    freeAddressBook(&addressBook);

    

    return 0;

}

```


### 项目总结与扩展建议


通过这个动态通讯录系统项目,我们实践了以下C语言核心概念:


1. **结构体应用**:合理设计数据结构表示现实世界实体

2. **动态内存管理**:使用malloc/realloc/free实现动态数组

3. **文件操作**:二进制文件和文本文件的读写操作

4. **指针运用**:结构体指针、数组指针的灵活使用

5. **模块化设计**:功能分解为独立的函数模块


**扩展建议**:

- 添加联系人去重功能

- 实现分组管理和批量操作

- 添加生日提醒功能

- 支持多种排序方式

- 实现数据备份和恢复功能

- 添加密码保护功能


这个项目为学习更复杂的C语言应用程序开发奠定了坚实基础。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3103363/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-11-01

  • 博文量
    895
  • 访问量
    933836