news 2026/4/18 1:56:08

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/1 10:01:23

20、配置 DAC 与 IPAM:企业网络管理的全面指南

配置 DAC 与 IPAM:企业网络管理的全面指南 在大型企业网络中,管理文件服务器访问权限和 IP 地址是一项复杂且关键的任务。合理的配置能够提高网络的安全性、可用性和管理效率。本文将详细介绍通过组策略配置访问被拒绝协助,以及如何部署和管理 IP 地址管理(IPAM)解决方案。…

作者头像 李华
网站建设 2026/4/14 4:26:45

27、服务器高可用性配置与灾难恢复全解析

服务器高可用性配置与灾难恢复全解析 在当今数字化的时代,服务器的高可用性和灾难恢复能力对于企业的稳定运营至关重要。本文将深入探讨服务器高可用性配置的关键概念、相关操作,以及如何进行有效的服务器备份和灾难恢复。 1. 服务器高可用性配置关键术语 在服务器高可用性…

作者头像 李华
网站建设 2026/4/18 0:43:45

28、Windows Server 灾难恢复全解析

Windows Server 灾难恢复全解析 1. Windows Server 恢复概述 备份服务器的目的是为了能够恢复丢失的数据。服务器恢复是一项你可能希望永远都不用执行的任务,但只要维护服务器一段时间,某种形式的恢复就是不可避免的。服务器恢复涵盖多种情况,从恢复单个文件或文件夹到完整…

作者头像 李华
网站建设 2026/4/13 13:05:05

20、使用 DSQUERY 命令进行目录查询

使用 DSQUERY 命令进行目录查询 在管理 Active Directory 时,我们常常需要根据特定条件搜索对象。DSQUERY 命令就是这样一个强大的工具,它可以帮助我们在 Active Directory 中查找符合特定条件的对象。 1. DSQUERY 子命令及语法 DSQUERY 提供了多个子命令,用于搜索不同类…

作者头像 李华
网站建设 2026/3/24 13:57:40

28、无线网络连接与认证全解析

无线网络连接与认证全解析 1. 无线网络安全标准选择 在设置无线网络时,选择合适的安全标准至关重要。系统通常支持WEP、WPA和WPA2,但部分网络设备(如连接无线网络的打印机)可能不支持WPA或WPA2。选择无线安全标准时,应优先选择所有客户端都支持的标准,顺序如下: 1. W…

作者头像 李华
网站建设 2026/4/5 4:33:31

Linly-Talker能否生成律师咨询形象提供法律帮助?

Linly-Talker能否生成律师咨询形象提供法律帮助&#xff1f; 在法律服务资源分布不均、咨询成本高企的今天&#xff0c;一个普通人想问一句“离婚需要什么手续”&#xff0c;可能要排队数小时&#xff0c;支付数百元费用。而与此同时&#xff0c;人工智能正悄然重塑专业服务的…

作者头像 李华