下面我将为你提供一个完整的通讯录课程设计方案,包括项目需求、功能设计、数据结构选择、模块划分、核心代码实现以及扩展方向。
项目需求分析
基本功能
- 添加联系人:能够输入联系人的姓名、电话、邮箱、地址等信息,并将其添加到通讯录中。
- 显示所有联系人:能够以列表形式清晰、整齐地展示通讯录中所有联系人的信息。
- 查找联系人:可以通过姓名或电话号码精确查找联系人,并显示其详细信息。
- 删除联系人:可以通过姓名或电话号码删除指定的联系人。
- 修改联系人信息:可以通过姓名或电话号码找到联系人,并修改其任意一项信息。
- 清空通讯录:一键清空通讯录中的所有联系人。
- 退出系统:安全退出程序,并提示用户保存数据。
扩展功能(可选,用于拿高分)
- 数据持久化:将通讯录数据保存到文件中(如
contacts.dat或contacts.txt),程序启动时自动加载,退出时自动保存。 - 按条件排序:可以按照姓名或添加日期对联系人进行排序后显示。
- 模糊查找:支持按姓名首字母或电话号码部分内容进行模糊查找。
- 界面美化:使用简单的清屏、颜色输出等函数,让用户界面更友好。
- 统计功能:显示通讯录中联系人的总数。
数据结构设计
通讯录的核心是存储联系人信息,每个联系人都是一个独立的数据单元,在C语言中,使用结构体来定义联系人信息是最合适的方式。

// 联系人结构体
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) |
添加联系人,需要修改 book 的 count 和 contacts 数组。 |
showContacts(const AddressBook *book) |
显示所有联系人,使用 const 防止误修改。 |
|
findContact(const AddressBook *book) |
查找联系人。 | |
deleteContact(AddressBook *book) |
删除联系人,需要修改 book。 |
|
modifyContact(AddressBook *book) |
修改联系人信息,需要修改 book。 |
|
clearContacts(AddressBook *book) |
清空通讯录,重置 book 的 count。 |
|
| 文件操作 | 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;
}
编译与运行
- 将上述两个代码块分别保存为
address_book.h和address_book.c文件。 - 打开命令行(如 Windows 的 CMD 或 PowerShell,Linux/macOS 的 Terminal)。
- 使用 GCC 进行编译:
gcc address_book.c -o address_book
- 运行生成的可执行文件:
- 在 Windows 上:
address_book.exe - 在 Linux/macOS 上:
./address_book
- 在 Windows 上:
课程设计报告要点
撰写课程设计报告时,应包含以下几个部分:

- 摘要:简述项目目的、主要功能和实现技术。
- 需求分析:详细列出项目的功能需求和非功能需求(如易用性、可靠性)。
- 总体设计:
- 功能模块图:用框图展示各个功能模块及其关系。
- 数据结构设计:说明为什么选择
Contact和AddressBook结构体,并画出其结构图。
- 详细设计:
- 函数设计:列出每个核心函数(如
addContact,deleteContact)的功能、参数和返回值。 - 算法设计:描述关键算法的实现思路,例如删除联系人时的“元素前移”算法。
- 界面设计:展示程序运行时的界面截图。
- 函数设计:列出每个核心函数(如
- 编码实现:附上核心代码,并加上必要的注释。
- 测试与分析:
- 测试用例:设计多组测试数据,覆盖所有功能(正常情况、边界情况、异常情况)。
- 测试结果:记录测试过程和结果,可以用表格或截图展示。
- 问题与解决:记录在开发过程中遇到的问题以及你是如何解决的。
- 总结与展望:
- 回顾整个项目,总结学到的知识和技能。
- 展望:提出可以进一步改进或扩展的方向(如动态扩容、图形界面、网络功能等)。
扩展方向(挑战自己)
如果你已经完成了基本功能,可以尝试以下扩展来提升你的项目:
- 动态数组:将
AddressBook中的contacts[MAX_CONTACTS]改为Contact *contacts,使用malloc初始分配,realloc在空间不足时进行扩容,这会让你对内存管理有更深的理解。 - 链表实现:使用链表来存储联系人,链表可以克服数组大小固定的限制,插入和删除操作也更高效(不需要移动大量元素),这会让你掌握更复杂的数据结构。
- 多文件组织:将
showMenu()和addContact()等函数分别放在不同的.c文件中(如menu.c,contact_ops.c),通过头文件声明,然后编译链接,这能更好地模拟大型项目的结构。 - 更友好的输入:使用
fgets()代替scanf()来读取字符串,这样可以正确处理包含空格的输入(如地址),需要注意fgets会读取换行符,需要手动去除。 - 排序功能:实现一个
sortContacts函数,使用qsort标准库函数对联系人按姓名进行排序。
这个通讯录项目是一个绝佳的C语言综合练习,祝你顺利完成课程设计!

版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。