news 2026/5/6 11:47:39

C语言基于顺序表实现通讯录:从原理到实战运用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言基于顺序表实现通讯录:从原理到实战运用

📚 前言:通讯录是C语言数据结构应用的经典案例,而顺序表作为线性表的基础存储结构,凭借随机访问效率高的特点,非常适合实现小型通讯录。本文将从需求分析、结构设计、功能实现到实战测试,完整讲解基于顺序表的通讯录开发过程,适合C语言初学者和数据结构入门者参考。

一、需求分析:通讯录需要实现哪些功能?📋

一个基础的通讯录应满足日常联系人管理需求,核心功能包括:

  • ✅ 新增联系人:录入姓名、电话、地址等信息

  • ✅ 查找联系人:按姓名/电话快速检索

  • ✅ 修改联系人:更新已有联系人的信息

  • ✅ 删除联系人:移除不需要的联系人

  • ✅ 显示所有联系人:遍历展示通讯录内容

  • ✅ 清空通讯录:快速删除所有数据

二、核心设计:顺序表如何适配通讯录?🔧

顺序表的本质是用数组存储数据,结合通讯录的需求,我们需要设计两个核心结构:

1. 联系人信息结构(Contact)

存储单个联系人的详细信息,可根据需求扩展字段:

#define MAX_NAME 20 // 姓名最大长度 #define MAX_PHONE 15 // 电话最大长度(含区号) #define MAX_ADDR 50 // 地址最大长度 // 联系人信息结构体 typedef struct { char name[MAX_NAME]; // 姓名 char phone[MAX_PHONE]; // 电话 char addr[MAX_ADDR]; // 地址 int age; // 年龄(可选扩展) } Contact;

2. 顺序表通讯录结构(SeqListAddrBook)

管理联系人数据的顺序表,包含数据数组、当前长度和最大容量:

#define MAX_SIZE 100 // 通讯录最大容量(可调整) // 顺序表通讯录结构体 typedef struct { Contact data[MAX_SIZE]; // 存储联系人的数组 int length; // 当前通讯录中的联系人数量 } SeqListAddrBook;

三、功能实现:逐步搭建通讯录核心逻辑 🛠️

接下来按功能模块实现,每个模块对应一个函数,逻辑清晰易维护。

1. 初始化通讯录

将顺序表长度初始化为0,确保后续操作的安全性:

// 初始化通讯录 void InitAddrBook(SeqListAddrBook *ab) { if (ab == NULL) return; // 避免空指针 ab->length = 0; // 初始长度为0,无联系人 printf("📌 通讯录初始化成功!\n"); }

2. 新增联系人

先判断通讯录是否已满,未满则录入联系人信息并更新长度:

// 新增联系人 void AddContact(SeqListAddrBook *ab) { if (ab == NULL) return; // 判断通讯录是否已满 if (ab->length >= MAX_SIZE) { printf("❌ 通讯录已满,无法新增联系人!\n"); return; } // 录入联系人信息 Contact newContact; printf("请输入联系人姓名:"); scanf("%s", newContact.name); printf("请输入联系人电话:"); scanf("%s", newContact.phone); printf("请输入联系人地址:"); getchar(); // 吸收缓冲区的换行符 fgets(newContact.addr, MAX_ADDR, stdin); // 去除fgets读取的换行符 newContact.addr[strcspn(newContact.addr, "\n")] = '\0'; printf("请输入联系人年龄:"); scanf("%d", &newContact.age); // 存入顺序表 ab->data[ab->length] = newContact; ab->length++; printf("✅ 联系人新增成功!\n"); }

3. 查找联系人(按姓名)

遍历顺序表,对比姓名实现查找,找到后返回索引(未找到返回-1):

// 按姓名查找联系人,返回索引(-1表示未找到) int FindContactByName(SeqListAddrBook *ab, char *name) { if (ab == NULL || name == NULL) return -1; // 遍历顺序表查找 for (int i = 0; i < ab->length; i++) { if (strcmp(ab->data[i].name, name) == 0) { return i; // 找到,返回索引 } } return -1; // 未找到 } // 显示查找结果 void ShowFindResult(SeqListAddrBook *ab, int index) { if (index == -1) { printf("❌ 未找到该联系人!\n"); return; } printf("📋 查找结果:\n"); printf("姓名:%s\n", ab->data[index].name); printf("电话:%s\n", ab->data[index].phone); printf("地址:%s\n", ab->data[index].addr); printf("年龄:%d\n", ab->data[index].age); }

4. 修改联系人

先通过查找获取联系人索引,再更新对应字段的信息:

// 修改联系人信息 void ModifyContact(SeqListAddrBook *ab) { if (ab == NULL) return; char name[MAX_NAME]; printf("请输入要修改的联系人姓名:"); scanf("%s", name); int index = FindContactByName(ab, name); if (index == -1) { printf("❌ 未找到该联系人!\n"); return; } // 重新录入信息(可优化为选择修改单个字段) printf("请输入新的姓名:"); scanf("%s", ab->data[index].name); printf("请输入新的电话:"); scanf("%s", ab->data[index].phone); printf("请输入新的地址:"); getchar(); fgets(ab->data[index].addr, MAX_ADDR, stdin); ab->data[index].addr[strcspn(ab->data[index].addr, "\n")] = '\0'; printf("请输入新的年龄:"); scanf("%d", &ab->data[index].age); printf("✅ 联系人信息修改成功!\n"); }

5. 删除联系人

找到联系人后,通过“后续元素前移”的方式覆盖待删除元素,实现删除效果:

// 删除联系人 void DeleteContact(SeqListAddrBook *ab) { if (ab == NULL) return; char name[MAX_NAME]; printf("请输入要删除的联系人姓名:"); scanf("%s", name); int index = FindContactByName(ab, name); if (index == -1) { printf("❌ 未找到该联系人!\n"); return; } // 后续元素前移,覆盖待删除元素 for (int i = index; i < ab->length - 1; i++) { ab->data[i] = ab->data[i + 1]; } ab->length--; // 长度减1 printf("✅ 联系人删除成功!\n"); }

6. 显示所有联系人

遍历顺序表,依次输出所有联系人信息,无数据时给出提示:

// 显示所有联系人 void ShowAllContacts(SeqListAddrBook *ab) { if (ab == NULL) return; if (ab->length == 0) { printf("📭 通讯录为空,暂无联系人!\n"); return; } printf("📋 通讯录所有联系人(共%d人):\n", ab->length); printf("----------------------------------------\n"); for (int i = 0; i < ab->length; i++) { printf("第%d人:\n", i + 1); printf("姓名:%s\n", ab->data[i].name); printf("电话:%s\n", ab->data[i].phone); printf("地址:%s\n", ab->data[i].addr); printf("年龄:%d\n", ab->data[i].age); printf("----------------------------------------\n"); } }

7. 清空通讯录

直接将顺序表长度置为0,无需清空数组(后续操作会覆盖):

// 清空通讯录 void ClearAddrBook(SeqListAddrBook *ab) { if (ab == NULL) return; ab->length = 0; // 长度置0,相当于清空所有数据 printf("✅ 通讯录清空成功!\n"); }

四、实战测试:设计主菜单交互 🖥️

通过主菜单让用户选择功能,实现完整的交互流程:

#include <stdio.h> #include <string.h> // 此处粘贴上述所有结构体定义和函数声明 int main() { SeqListAddrBook ab; InitAddrBook(&ab); int choice; while (1) { // 循环菜单 printf("\n======= 顺序表通讯录 =======\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("请输入你的选择:"); scanf("%d", &choice); switch (choice) { case 1: AddContact(&ab); break; case 2: { char name[MAX_NAME]; printf("请输入要查找的联系人姓名:"); scanf("%s", name); int index = FindContactByName(&ab, name); ShowFindResult(&ab, index); break; } case 3: ModifyContact(&ab); break; case 4: DeleteContact(&ab); break; case 5: ShowAllContacts(&ab); break; case 6: ClearAddrBook(&ab); break; case 0: printf("👋 程序退出,感谢使用!\n"); return 0; default: printf("❌ 输入错误,请重新选择!\n"); break; } } return 0; }

五、注意事项与优化方向 ⚠️

  • 📌 顺序表的局限性:最大容量固定(MAX_SIZE),满了无法扩容,可优化为动态顺序表(用malloc/realloc动态分配内存)。

  • 📌 查找效率:按姓名查找是线性查找,时间复杂度O(n),可通过排序+二分查找优化(需先实现通讯录排序功能)。

  • 📌 数据持久化:当前程序退出后数据丢失,可添加文件操作(fwrite/fread),将数据保存到本地文件。

  • 📌 输入校验:目前未对输入数据合法性校验(如电话长度、年龄范围),实际开发中需补充。

六、总结 📝

本文通过顺序表实现了通讯录的核心功能,从结构体设计到函数实现,再到主菜单交互,完整覆盖了小型项目的开发流程。顺序表的“数组存储”特性让通讯录的随机访问更高效,但也存在容量固定的缺陷,适合入门学习数据结构的实际应用。

如果需要进一步优化,可以尝试实现动态顺序表、数据持久化或更高效的查找算法,欢迎大家在评论区交流讨论!

#C语言 #数据结构 #顺序表 #通讯录实现 #C语言实战项目

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 6:25:48

铝合金三通阀体金属型重力铸造数值模拟与优化

铝合金三通阀体金属型重力铸造数值模拟与优化 本研究针对铝合金三通阀体金属型重力铸造工艺,采用Box-Behnken试验设计方法,以浇注时间、浇注温度、模具温度和铸件传热系数为变量,缩松缩孔体积和二次枝晶臂间距为优化目标,通过数值模拟与NSGA-Ⅱ多目标优化算法获得最优工艺…

作者头像 李华
网站建设 2026/5/4 17:50:43

23、服务器高可用性之故障转移集群配置全解析

服务器高可用性之故障转移集群配置全解析 1. 利用 PowerShell 配置 NLB 集群 在配置网络负载均衡(NLB)集群时,PowerShell 提供了一系列实用的 cmdlet。若要查看与 NLB 相关的完整 PowerShell cmdlet 列表,可在命令行输入 Get-Command *nlb* 。以下是一些常用的 NLB 集群…

作者头像 李华
网站建设 2026/5/1 18:09:54

Linly-Talker镜像通过ISO信息安全认证

Linly-Talker镜像通过ISO信息安全认证 在金融、政务、医疗等行业对数据安全要求日益严苛的今天&#xff0c;一个数字人系统即便再智能&#xff0c;若无法确保用户信息“不出内网”&#xff0c;就很难真正落地。而最近&#xff0c;一款名为 Linly-Talker 的“一站式数字人对话系…

作者头像 李华
网站建设 2026/5/1 10:12:03

Linly-Talker在养老院陪伴老人的应用探索

Linly-Talker在养老院陪伴老人的应用探索 在全球老龄化加速的今天&#xff0c;许多国家和地区正面临一个共同难题&#xff1a;老年人口持续增长&#xff0c;而专业护理资源却捉襟见肘。护工短缺、服务成本高企、情感支持不足——这些问题不仅困扰着养老机构&#xff0c;也让无数…

作者头像 李华
网站建设 2026/5/1 11:13:28

21、Active Directory 对象管理与计算机账户管理全解析

Active Directory 对象管理与计算机账户管理全解析 1. Active Directory 对象重命名与移动 在 Active Directory 中,重命名和移动对象可以使用 DSMOVE 命令。这是因为重命名对象实际上就是将其从当前的可分辨名称(DN)移动到新的 DN。DN 由通用名称(RDN)和位置两部分组…

作者头像 李华
网站建设 2026/5/5 19:41:18

Linly-Talker支持HTTPS加密传输吗?保障数据安全

Linly-Talker 支持 HTTPS 加密传输吗&#xff1f;数据安全的底层逻辑 在今天这个万物互联的时代&#xff0c;AI 数字人早已不再是实验室里的概念玩具。从直播间里24小时不打烊的虚拟主播&#xff0c;到银行客服端口耐心解答问题的数字员工&#xff0c;Linly-Talker 这类集成了大…

作者头像 李华