news 2026/4/8 8:19:13

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/4/3 9:10:40

Linly-Talker支持语音重点内容高亮显示吗?

Linly-Talker 支持语音重点内容高亮显示吗&#xff1f; 在数字人技术日益普及的今天&#xff0c;用户不再满足于“能说会动”的基础交互体验。越来越多的应用场景——比如在线课程讲解、企业培训播报、智能客服回应——都对信息传递的有效性与可读性提出了更高要求。我们常常遇…

作者头像 李华
网站建设 2026/4/6 22:29:12

24、服务器高可用性配置全解析

服务器高可用性配置全解析 在当今数字化的时代,服务器的高可用性对于企业的稳定运行至关重要。无论是应对大量的用户请求,还是确保关键业务数据的安全和可访问性,都需要有效的服务器配置策略。本文将深入探讨服务器高可用性的相关技术,包括网络负载均衡(NLB)、故障转移集…

作者头像 李华
网站建设 2026/4/7 12:11:38

34、网络安全认证与联邦服务技术解析

网络安全认证与联邦服务技术解析 1. 公钥基础设施(PKI)相关概念 公钥基础设施(PKI)是一种安全系统,它将用户或设备的身份与加密密钥绑定,通过加密确保数据传输的安全性,并使用数字证书保证数据的真实性。以下是一些与 PKI 相关的重要概念: - 在线响应器(OR) :一…

作者头像 李华
网站建设 2026/4/3 14:49:31

Linly-Talker能否用于法院普法宣传教育?

Linly-Talker能否用于法院普法宣传教育&#xff1f; 在数字化浪潮席卷公共服务的今天&#xff0c;如何让严肃的法律知识“飞入寻常百姓家”&#xff0c;成为各地法院积极探索的新课题。传统的普法方式往往依赖纸质手册、公告栏或录播视频&#xff0c;内容枯燥、形式单一&#x…

作者头像 李华
网站建设 2026/4/5 5:51:01

手术导航轨迹偏移 补生物力学约束才校准PINN模型

&#x1f4dd; 博客主页&#xff1a;jaxzheng的CSDN主页 目录 医疗数据科学&#xff1a;当Excel表格遇上手术刀 我差点把CT片当成了奶茶订单 数据江湖的三大痛点 数据清洗的血泪史 当AI遇见中医 数据共享的尴尬现场 未来可能的样子 写在最后 医疗数据科学&#xff1a;当Excel表…

作者头像 李华
网站建设 2026/4/1 11:32:40

Linly-Talker如何处理长时间对话的记忆衰减问题?

Linly-Talker如何处理长时间对话的记忆衰减问题&#xff1f; 在虚拟主播流畅推荐商品、AI客服耐心解答复杂问题的表象之下&#xff0c;隐藏着一个长期困扰开发者的核心难题&#xff1a;数字人真的“记得”你之前说过什么吗&#xff1f; 当用户与智能体连续对话超过十几轮后&…

作者头像 李华