C语言通讯录课程设计如何实现?

99ANYc3cd6 课程介绍 1

下面我将为你提供一个完整的通讯录课程设计方案,包括项目需求、功能设计、数据结构选择、模块划分、核心代码实现以及扩展方向


项目需求分析

基本功能

  1. 添加联系人:能够输入联系人的姓名、电话、邮箱、地址等信息,并将其添加到通讯录中。
  2. 显示所有联系人:能够以列表形式清晰、整齐地展示通讯录中所有联系人的信息。
  3. 查找联系人:可以通过姓名或电话号码精确查找联系人,并显示其详细信息。
  4. 删除联系人:可以通过姓名或电话号码删除指定的联系人。
  5. 修改联系人信息:可以通过姓名或电话号码找到联系人,并修改其任意一项信息。
  6. 清空通讯录:一键清空通讯录中的所有联系人。
  7. 退出系统:安全退出程序,并提示用户保存数据。

扩展功能(可选,用于拿高分)

  1. 数据持久化:将通讯录数据保存到文件中(如 contacts.datcontacts.txt),程序启动时自动加载,退出时自动保存。
  2. 按条件排序:可以按照姓名或添加日期对联系人进行排序后显示。
  3. 模糊查找:支持按姓名首字母或电话号码部分内容进行模糊查找。
  4. 界面美化:使用简单的清屏、颜色输出等函数,让用户界面更友好。
  5. 统计功能:显示通讯录中联系人的总数。

数据结构设计

通讯录的核心是存储联系人信息,每个联系人都是一个独立的数据单元,在C语言中,使用结构体来定义联系人信息是最合适的方式。

C语言通讯录课程设计如何实现?-第1张图片-指南针培训网
// 联系人结构体
typedef struct {
    char name[50];      // 姓名
    char phone[20];     // 电话
    char email[50];     // 邮箱
    char address[100];  // 地址
} Contact;
// 通讯录结构体
// 将联系人数组和当前联系人数量封装在一起,便于管理
typedef struct {
    Contact contacts[1000]; // 假设最多存储1000个联系人
    int count;              // 当前通讯录中的联系人数量
} AddressBook;

选择理由

  • 结构体Contact 结构体能将一个联系人的所有相关属性(姓名、电话等)捆绑在一起,逻辑清晰。
  • 定长数组AddressBook 中使用一个固定大小的 Contact 数组,这是最简单的方式,适合初学者,缺点是空间固定,无法动态扩展。
  • 动态数组:更高级的做法是使用动态内存分配(malloc, realloc)来创建数组,这样可以实现动态扩容,但会增加代码复杂度,课程设计初期不建议。

功能模块划分

为了使代码结构清晰、易于维护,我们将程序的功能划分为不同的函数模块。

模块 函数名 功能描述
主菜单 showMenu() 显示操作选项,接收用户输入,并调用相应功能函数。
核心功能 addContact(AddressBook *book) 添加联系人,需要修改 bookcountcontacts 数组。
showContacts(const AddressBook *book) 显示所有联系人,使用 const 防止误修改。
findContact(const AddressBook *book) 查找联系人。
deleteContact(AddressBook *book) 删除联系人,需要修改 book
modifyContact(AddressBook *book) 修改联系人信息,需要修改 book
clearContacts(AddressBook *book) 清空通讯录,重置 bookcount
文件操作 saveToFile(const AddressBook *book) 将通讯录数据保存到文件。
loadFromFile(AddressBook *book) 从文件加载通讯录数据。
辅助功能 pauseForInput() 暂停程序,等待用户按任意键后继续。

核心代码实现

下面是完整的、带有详细注释的C语言代码。

address_book.h (头文件)

#ifndef ADDRESS_BOOK_H
#define ADDRESS_BOOK_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 定义最大联系人数量
#define MAX_CONTACTS 1000
// 联系人结构体
typedef struct {
    char name[50];
    char phone[20];
    char email[50];
    char address[100];
} Contact;
// 通讯录结构体
typedef struct {
    Contact contacts[MAX_CONTACTS];
    int count;
} AddressBook;
// 函数声明
void showMenu();
void addContact(AddressBook *book);
void showContacts(const AddressBook *book);
void findContact(const AddressBook *book);
void deleteContact(AddressBook *book);
void modifyContact(AddressBook *book);
void clearContacts(AddressBook *book);
void saveToFile(const AddressBook *book);
void loadFromFile(AddressBook *book);
void pauseForInput();
#endif // ADDRESS_BOOK_H

address_book.c (主程序文件)

#include "address_book.h"
// 清屏函数 (Windows)
void clearScreen() {
    system("cls");
}
// 暂停函数
void pauseForInput() {
    printf("\n按任意键返回主菜单...");
    getchar(); // 吸收上一个输入产生的换行符
    getchar(); // 等待用户输入
}
// 显示主菜单
void showMenu() {
    clearScreen();
    printf("=============== 通讯录管理系统 ===============\n");
    printf("||  1. 添加联系人                          ||\n");
    printf("||  2. 显示所有联系人                      ||\n");
    printf("||  3. 查找联系人                          ||n");
    printf("||  4. 删除联系人                          ||\n");
    printf("||  5. 修改联系人信息                      ||\n");
    printf("||  6. 清空通讯录                          ||\n");
    printf("||  0. 退出系统                            ||\n");
    printf("============================================\n");
    printf("请输入您的选择: ");
}
// 添加联系人
void addContact(AddressBook *book) {
    if (book->count >= MAX_CONTACTS) {
        printf("通讯录已满,无法添加!\n");
        pauseForInput();
        return;
    }
    Contact newContact;
    printf("请输入姓名: ");
    scanf("%s", newContact.name);
    printf("请输入电话: ");
    scanf("%s", newContact.phone);
    printf("请输入邮箱: ");
    scanf("%s", newContact.email);
    printf("请输入地址: ");
    scanf("%s", newContact.address); // 注意:这里如果地址有空格会出问题,可用 gets 但需小心
    book->contacts[book->count] = newContact;
    book->count++;
    printf("联系人添加成功!\n");
    pauseForInput();
}
// 显示所有联系人
void showContacts(const AddressBook *book) {
    if (book->count == 0) {
        printf("通讯录为空!\n");
        pauseForInput();
        return;
    }
    printf("\n%-20s %-15s %-25s %-30s\n", "姓名", "电话", "邮箱", "地址");
    printf("-----------------------------------------------------------------\n");
    for (int i = 0; i < book->count; i++) {
        printf("%-20s %-15s %-25s %-30s\n",
               book->contacts[i].name,
               book->contacts[i].phone,
               book->contacts[i].email,
               book->contacts[i].address);
    }
    pauseForInput();
}
// 查找联系人 (按姓名)
void findContact(const AddressBook *book) {
    if (book->count == 0) {
        printf("通讯录为空!\n");
        pauseForInput();
        return;
    }
    char name[50];
    printf("请输入要查找的联系人姓名: ");
    scanf("%s", name);
    int found = 0;
    for (int i = 0; i < book->count; i++) {
        if (strcmp(book->contacts[i].name, name) == 0) {
            printf("\n找到了!联系人信息如下:\n");
            printf("姓名: %s\n", book->contacts[i].name);
            printf("电话: %s\n", book->contacts[i].phone);
            printf("邮箱: %s\n", book->contacts[i].email);
            printf("地址: %s\n", book->contacts[i].address);
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("未找到名为 %s 的联系人,\n", name);
    }
    pauseForInput();
}
// 删除联系人 (按姓名)
void deleteContact(AddressBook *book) {
    if (book->count == 0) {
        printf("通讯录为空!\n");
        pauseForInput();
        return;
    }
    char name[50];
    printf("请输入要删除的联系人姓名: ");
    scanf("%s", name);
    int foundIndex = -1;
    for (int i = 0; i < book->count; i++) {
        if (strcmp(book->contacts[i].name, name) == 0) {
            foundIndex = i;
            break;
        }
    }
    if (foundIndex == -1) {
        printf("未找到名为 %s 的联系人,\n", name);
    } else {
        // 将后面的所有联系人前移一位,覆盖掉要删除的联系人
        for (int i = foundIndex; i < book->count - 1; i++) {
            book->contacts[i] = book->contacts[i + 1];
        }
        book->count--;
        printf("联系人删除成功!\n");
    }
    pauseForInput();
}
// 修改联系人信息 (按姓名)
void modifyContact(AddressBook *book) {
    if (book->count == 0) {
        printf("通讯录为空!\n");
        pauseForInput();
        return;
    }
    char name[50];
    printf("请输入要修改的联系人姓名: ");
    scanf("%s", name);
    int foundIndex = -1;
    for (int i = 0; i < book->count; i++) {
        if (strcmp(book->contacts[i].name, name) == 0) {
            foundIndex = i;
            break;
        }
    }
    if (foundIndex == -1) {
        printf("未找到名为 %s 的联系人,\n", name);
    } else {
        printf("找到了联系人,请输入新的信息:\n");
        printf("姓名 (原: %s): ", book->contacts[foundIndex].name);
        scanf("%s", book->contacts[foundIndex].name);
        printf("电话 (原: %s): ", book->contacts[foundIndex].phone);
        scanf("%s", book->contacts[foundIndex].phone);
        printf("邮箱 (原: %s): ", book->contacts[foundIndex].email);
        scanf("%s", book->contacts[foundIndex].email);
        printf("地址 (原: %s): ", book->contacts[foundIndex].address);
        scanf("%s", book->contacts[foundIndex].address);
        printf("联系人信息修改成功!\n");
    }
    pauseForInput();
}
// 清空通讯录
void clearContacts(AddressBook *book) {
    char confirm;
    printf("确定要清空所有联系人吗?(y/n): ");
    scanf(" %c", &confirm); // 注意空格,用于吸收换行符
    if (confirm == 'y' || confirm == 'Y') {
        book->count = 0;
        printf("通讯录已清空!\n");
    } else {
        printf("操作已取消,\n");
    }
    pauseForInput();
}
// 保存数据到文件
void saveToFile(const AddressBook *book) {
    FILE *fp = fopen("contacts.dat", "wb"); // "wb" 表示二进制写入
    if (fp == NULL) {
        printf("无法打开文件进行保存!\n");
        return;
    }
    fwrite(book, sizeof(AddressBook), 1, fp);
    fclose(fp);
    printf("数据保存成功!\n");
}
// 从文件加载数据
void loadFromFile(AddressBook *book) {
    FILE *fp = fopen("contacts.dat", "rb"); // "rb" 表示二进制读取
    if (fp == NULL) {
        printf("未找到数据文件,将创建新的通讯录,\n");
        return;
    }
    fread(book, sizeof(AddressBook), 1, fp);
    fclose(fp);
    printf("数据加载成功!\n");
}
// 主函数
int main() {
    AddressBook book;
    book.count = 0;
    // 程序启动时尝试加载数据
    loadFromFile(&book);
    int choice;
    do {
        showMenu();
        scanf("%d", &choice);
        switch (choice) {
            case 1: addContact(&book); break;
            case 2: showContacts(&book); break;
            case 3: findContact(&book); break;
            case 4: deleteContact(&book); break;
            case 5: modifyContact(&book); break;
            case 6: clearContacts(&book); break;
            case 0:
                printf("退出前是否保存数据?(y/n): ");
                char saveChoice;
                scanf(" %c", &saveChoice);
                if (saveChoice == 'y' || saveChoice == 'Y') {
                    saveToFile(&book);
                }
                printf("感谢使用,再见!\n");
                break;
            default:
                printf("无效的输入,请重新选择!\n");
                pauseForInput();
        }
    } while (choice != 0);
    return 0;
}

编译与运行

  1. 将上述两个代码块分别保存为 address_book.haddress_book.c 文件。
  2. 打开命令行(如 Windows 的 CMD 或 PowerShell,Linux/macOS 的 Terminal)。
  3. 使用 GCC 进行编译:
    gcc address_book.c -o address_book
  4. 运行生成的可执行文件:
    • 在 Windows 上:address_book.exe
    • 在 Linux/macOS 上:./address_book

课程设计报告要点

撰写课程设计报告时,应包含以下几个部分:

C语言通讯录课程设计如何实现?-第2张图片-指南针培训网
  1. 摘要:简述项目目的、主要功能和实现技术。
  2. 需求分析:详细列出项目的功能需求和非功能需求(如易用性、可靠性)。
  3. 总体设计
    • 功能模块图:用框图展示各个功能模块及其关系。
    • 数据结构设计:说明为什么选择 ContactAddressBook 结构体,并画出其结构图。
  4. 详细设计
    • 函数设计:列出每个核心函数(如 addContact, deleteContact)的功能、参数和返回值。
    • 算法设计:描述关键算法的实现思路,例如删除联系人时的“元素前移”算法。
    • 界面设计:展示程序运行时的界面截图。
  5. 编码实现:附上核心代码,并加上必要的注释。
  6. 测试与分析
    • 测试用例:设计多组测试数据,覆盖所有功能(正常情况、边界情况、异常情况)。
    • 测试结果:记录测试过程和结果,可以用表格或截图展示。
    • 问题与解决:记录在开发过程中遇到的问题以及你是如何解决的。
  7. 总结与展望
    • 回顾整个项目,总结学到的知识和技能。
    • 展望:提出可以进一步改进或扩展的方向(如动态扩容、图形界面、网络功能等)。

扩展方向(挑战自己)

如果你已经完成了基本功能,可以尝试以下扩展来提升你的项目:

  1. 动态数组:将 AddressBook 中的 contacts[MAX_CONTACTS] 改为 Contact *contacts,使用 malloc 初始分配,realloc 在空间不足时进行扩容,这会让你对内存管理有更深的理解。
  2. 链表实现:使用链表来存储联系人,链表可以克服数组大小固定的限制,插入和删除操作也更高效(不需要移动大量元素),这会让你掌握更复杂的数据结构。
  3. 多文件组织:将 showMenu()addContact() 等函数分别放在不同的 .c 文件中(如 menu.c, contact_ops.c),通过头文件声明,然后编译链接,这能更好地模拟大型项目的结构。
  4. 更友好的输入:使用 fgets() 代替 scanf() 来读取字符串,这样可以正确处理包含空格的输入(如地址),需要注意 fgets 会读取换行符,需要手动去除。
  5. 排序功能:实现一个 sortContacts 函数,使用 qsort 标准库函数对联系人按姓名进行排序。

这个通讯录项目是一个绝佳的C语言综合练习,祝你顺利完成课程设计!

C语言通讯录课程设计如何实现?-第3张图片-指南针培训网

标签: 文件操作 动态内存

抱歉,评论功能暂时关闭!