通讯录(C语言详细版)

1. 前言

通讯录是在动态顺序表的基础上实现的,其实就是顺序表的每个元素存储的不再是数字,而是存储一个联系人的结构体,所以如果有些小伙伴看不懂的话,可以移步参考一下动态顺序表的实现:顺序表(C语言详细版)-CSDN博客。

1.1 通讯录的功能

1)至少能够存储每个用户的通讯信息;

2)能够保存用户信息:名字、性别、年龄、电话、地址等;

3)增加联系人信息;

4)删除指定联系人;

5)查找制定联系人;

6)修改指定联系人;

7)显示联系人信息。

2. 定义联系人的结构体

#define NAME_MAX  20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100
// 定义联系人数据结构
// 姓名 性别 年龄 电话 地址
typedef struct personInfo
{char name[NAME_MAX];	// 姓名char gender[GENDER_MAX];// 性别int age;				// 年龄char tel[TEL_MAX];		// 电话char addr[ADDR_MAX];	// 地址
}peoInfo;

3. 通讯录的初始化

如果我们要对通讯录初始化,我们可以通过对顺序表初始化,来实现对通讯录的初始化。要使用顺序表方法,所以我们必须前置声明 struct SeqList,然后将它重新命名为 Contact (通讯录英文)。

typedef struct SeqList Contact;	// 前置声明

通讯录初始化声明:

/* 要用到顺序表相关的方法,对通讯录的操作,实际上就是对顺序表进行操作 * 给顺序表改个名字,叫做通讯录 */
//typedef SL Contact;
typedef struct SeqList Contact;	// 必须要这样前置声明
// 通讯录相关的方法// 通讯录的初始化
//void ContactInit(SL* sl);
void ContactInit(Contact* con);

通讯录初始化定义:

// 通讯录的初始化
void ContactInit(Contact* con)//sl
{// 实际上要进行的是顺序表的初始化// 顺序表的初始化已经实现好了SLInit(con);
}

测试代码:

// 通讯录的测试方法
void ContactTest01()
{Contact con;	// 创建的通讯录对象 实际上就是顺序表对象 等价于 SL sl// 通讯录初始化ContactInit(&con);
}int main()
{ContactTest01();return 0;
}

调试结果:有效联系人的人数为0,容纳联系人的总数也为0

4. 通讯录的销毁

对通讯录的销毁就是对顺序表的销毁,所以通讯录的销毁函数可以调用顺序表的销毁函数接口。

// 通讯录的销毁
void ContactDesTroy(Contact* con)
{SLDestroy(con);
}

测试程序:

// 通讯录的测试方法
void ContactTest01()
{Contact con;	// 创建的通讯录对象 实际上就是顺序表对象 等价于 SL sl// 通讯录初始化ContactInit(&con);// 通讯录销毁ContactDesTroy(&con);
}int main()
{ContactTest01();return 0;
}

调试结果:其实跟初始化效果是一样的,因为我们通讯录里面没有数据嘛

5. 展示通讯录数据

为了更好地测试我们程序,我们可以先写一个打印程序,这样就不用一个个调试观察了。

// 展示通讯录数据
void ContactShow(Contact* con)
{// 表头:姓名 性别 年龄 电话 地址printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");// 遍历通讯录,按照格式打印每个联系人数据for (int i = 0; i < con->size; i++){// 调整一下格式printf("%3s %3s    %3d   %3s   %3s\n", \con->arr[i].name, \con->arr[i].gender, \con->arr[i].age, \con->arr[i].tel, \con->arr[i].addr);}
}

6. 通讯录添加联系人

往通讯录添加联系人,就是往顺序表插入数据,所以我们这里可以调用顺序表的尾插、头插、指定位置插入,我们这里就用尾插接口来实现吧!(其他插入接口函数也是能实现的,等会可以试试)

// 通讯录添加数据
void ContactAdd(Contact* con)
{// 获取用户输入的内容:姓名+性别+年龄+电话+地址peoInfo info;printf("请输入要添加的联系人的姓名:\n");scanf("%s", info.name);printf("请输入要添加的联系人的性别:\n");scanf("%s", info.gender);printf("请输入要添加的联系人的年龄:\n");scanf("%d", &info.age);printf("请输入要添加的联系人的电话:\n");scanf("%s", info.tel);printf("请输入要添加的联系人的地址:\n");scanf("%s", info.addr);// 往通讯录中添加联系人的数据 -- 尾插,也可使用其他方法插入数据SLPushBack(con, info);//SLPushFront(con, info);    // 头插//SLInsert(con, 0, info);    // 指定位置插入
}

测试尾插联系人程序:

// 通讯录的测试方法
void ContactTest01()
{Contact con;	// 创建的通讯录对象 实际上就是顺序表对象 等价于 SL sl// 通讯录初始化ContactInit(&con);// 添加数据ContactAdd(&con);ContactAdd(&con);ContactShow(&con);// 通讯录销毁ContactDesTroy(&con);
}int main()
{ContactTest01();return 0;
}

运行结果:

测试头插联系人结果:

测试指定位置插入联系人:

7. 通讯录删除联系人

通讯录删除联系人,我们可以调用顺序表的指定位置删除删除函数接口。在删除联系人之前,我们还必须找到该联系人,然后再把该联系人删除。我们查找联系人是根据联系人的姓名来查找(我们也可以根据其它信息来查找,这里就不实现了),找到联系人的下标,然后将下标返回。

// 根据用户的姓名来查找
int FindByName(Contact* con, char name[])
{for (int i = 0; i < con->size; i++){if (0 == strcmp(con->arr[i].name, name)){// 找到了return i;}}// 没有找到return -1;
}// 通讯录删除数据
void ContactDel(Contact* con)
{// 要删除的数据必须存在,才能执行删除操作// 查找char name[NAME_MAX];printf("请输入要删除的联系人的姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要删除的联系人数据不存在!\n");return;}// 要删除的联系人数据存在-->知道了要删除联系人数据对应的下标SLErase(con, find);	// 指定位置删除数据printf("删除成功!\n");
}

测试程序:

// 通讯录的测试方法
void ContactTest01()
{Contact con;	// 创建的通讯录对象 实际上就是顺序表对象 等价于 SL sl// 通讯录初始化ContactInit(&con);// 添加数据ContactAdd(&con);ContactAdd(&con);ContactShow(&con);// 测试删除数据ContactDel(&con);ContactShow(&con);// 通讯录销毁ContactDesTroy(&con);
}int main()
{ContactTest01();return 0;
}

运行结果:

8. 通讯录的修改

先找要修改的联系人的下标,返回该下标,然后再进行修改。

// 通讯录的修改
void ContactModify(Contact* con)
{// 要修改的联系人数据存在char name[NAME_MAX];printf("请输入要修改的用户姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要修改的联系人数据不存在!\n");return;}// 要修改的联系人数据存在-->知道了要修改联系人数据对应的下标printf("请输入新的姓名:\n");scanf("%s", con->arr[find].name);printf("请输入新的性别:\n");scanf("%s", con->arr[find].gender);printf("请输入新的年龄:\n");scanf("%d", &con->arr[find].age);printf("请输入新的电话:\n");scanf("%s", con->arr[find].tel);printf("请输入新的住址:\n");scanf("%s", con->arr[find].addr);printf("修改成功!\n");
}

测试程序:

// 通讯录的测试方法
void ContactTest01()
{Contact con;	// 创建的通讯录对象 实际上就是顺序表对象 等价于 SL sl// 通讯录初始化ContactInit(&con);// 添加数据ContactAdd(&con);ContactAdd(&con);ContactShow(&con);// 测试修改信息ContactModify(&con);ContactShow(&con);// 通讯录销毁ContactDesTroy(&con);
}int main()
{ContactTest01();return 0;
}

运行结果:

9. 通讯录查找

通讯录的查找,我们也是通过姓名来查找,找到了联系人的下标,然后返回下标,最后把找到的联系人打印出来。

// 通讯录查找
void ContactFind(Contact* con)
{// 通过姓名查找char name[NAME_MAX];printf("请输入要查找的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要删除的联系人数据不存在!\n");return;}// 表头:姓名 性别 年龄 电话 地址printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");// 调整一下格式printf("%3s %3s %3d %3s %3s\n", \con->arr[find].name, \con->arr[find].gender, \con->arr[find].age, \con->arr[find].tel, \con->arr[find].addr);
}

测试程序:

// 通讯录的测试方法
void ContactTest01()
{Contact con;	// 创建的通讯录对象 实际上就是顺序表对象 等价于 SL sl// 通讯录初始化ContactInit(&con);// 添加数据ContactAdd(&con);ContactAdd(&con);ContactShow(&con);// 测试查找ContactFind(&con);// 通讯录销毁ContactDesTroy(&con);
}int main()
{ContactTest01();return 0;
}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/866193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】auto 关键字

在C语言中&#xff0c;auto关键字用于声明局部变量&#xff0c;但它的使用已经变得很少见。事实上&#xff0c;从C99标准开始&#xff0c;auto关键字的默认行为就是隐含的&#xff0c;因此在大多数情况下无需显式使用它。 基本用法 在C语言中&#xff0c;auto关键字用于指定变…

ntp服务

https://blog.csdn.net/weixin_39168541/article/details/123741031

SpringBoot应用配置桥接Prometheus入门

SpringBoot应用配置Prometheus步骤 SpringBoot应用依赖要求PrometheusGrafanaGrafana监控界面模板 SpringBoot应用依赖要求 <!-- 监控系统健康情况的工具 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot…

【3分钟准备前端面试】vue3

目录 Vue3比vue2有什么优势vue3升级了哪些重要功能生命周期变化Options APIComposition APIreftoRef和toRefstoReftoRefsHooks (代码复用)Vue3 script setupsetupdefineProps和defineEmitsdefineExposeVue3比vue2有什么优势 性能更好体积更小更好的TS支持更好的代码组织更好的逻…

104.二叉树的最大深度——二叉树专题复习

深度优先搜索&#xff08;DFS&#xff09;是一种常用的递归算法&#xff0c;用于解决树形结构的问题。在计算二叉树的最大深度时&#xff0c;DFS方法会从根节点开始&#xff0c;递归地计算左右子树的最大深度&#xff0c;然后在返回时更新当前节点所在路径的最大深度。 如果我…

PyAutoGUI 使用详解

文章目录 简介PyAutoGUI 的原理安装 PyAutoGUI基本使用示例鼠标控制键盘控制截屏图像识别消息框 高级功能防止误操作多屏幕支持鼠标平滑移动 结论 简介 PyAutoGUI 是一个用于自动化控制鼠标和键盘的 Python 库。它可以帮助开发者编写脚本&#xff0c;以模拟用户在计算机上的操…

每日复盘-20240704

今日关注&#xff1a; 20240704 六日涨幅最大: ------1--------300391--------- 长药控股 五日涨幅最大: ------1--------300391--------- 长药控股 四日涨幅最大: ------1--------300391--------- 长药控股 三日涨幅最大: ------1--------300391--------- 长药控股 二日涨幅最…

[笔记]小米CyberDog机器狗仿真调试记录

从官方github的所有源码库来看&#xff0c;所有的source命令只有两条&#xff0c;执行它以配置环境变量&#xff1a; source /opt/ros/galactic/setup.bash source /home/cyberdog_ws/install/setup.bash 如果运行脚本之后gazebo正常启动及机器狗模型在悬空状态&#xff0c;问…

三位数重新排列c++

题目描述 给你一个三位数 n&#xff08;保证最高位不是 0&#xff09;&#xff0c;你可以重新调整它三个数位的顺序&#xff0c;请输出结果最小的一种。 输入 第一行一个整数 n。 输出 一行一个整数&#xff0c;重新调整顺序后&#xff0c;最小的结果。 注意&#xff0c;…

文心一言 VS 讯飞星火 VS chatgpt (295)-- 算法导论21.4 4题

四、利用练习 21.4-2 &#xff0c;请给出一个简单的证明&#xff0c;证明在一个不相交集合森林上使用按秩合并策略而不使用路径压缩策略的运行时间为 O(m lgn) 。21.4-2 的内容是&#xff1a;“证明&#xff1a;每个结点的秩最多为 ⌊lgn⌋ 。”。如果要写代码&#xff0c;请用…

objdump

objdump是一个用于在Linux系统中查看和解析对象文件&#xff08;如可执行文件、目标文件和共享库&#xff09;的命令行工具。它可以展示文件的多种信息&#xff0c;包括汇编代码、符号表、调试信息等。objdump的常用选项包括&#xff1a; -d 或 --disassemble&#xff1a;反汇编…

vue模板语法v-html

模板语法v-html vue使用一种基于HTML的模板语法&#xff0c;使我们能够声明式的将其组件实例的数据绑定到呈现的DOM上&#xff0c;所有的vue模板都是语法层面的HTML&#xff0c;可以被符合规范的浏览器和HTML解释器解析。 一.文本插值 最基本的数据绑定形式是文本插值&#…

Kafka 为何如此之快?深度解析其背后的秘密

目录 前言 一、生产者 1. 异步发送 2. 多分区并行 3. 消息批量发送 4.支持消息压缩 二、存储端 1. 分区和副本 2. 页缓存 3. 磁盘顺序写入 4. 零拷贝技术 5. 稀疏索引 三、消费端 1. 消费者群组 2. 批量拉取 3. 高效的偏移量管理 4. 并行消费 总结 前言 Kafk…

CS算法(二)—— 斜视SAR点目标仿真

SAR成像专栏目录 我们按照Cumming教授所著的《合成孔径雷达成像——算法与实现》7.6节的点目标参数进行仿真,斜视角设置为8,中心斜距改为1000km。先放最终的仿真结果: 1. 参数配置 在中心点和中心的的上下左右方向设置5个点目标 : function para=config_sar_para_cumming(…

【python数据处理】— “2020-01-01 05:20:15“日期格式数据

文章目录 一、数据说明及目标二、实现方式1.提取date2.提取hour3.提取weekday4.提取month 一、数据说明及目标 数据说明 数据表有一列名为"datetime"表示时间数据&#xff0c;该列的数据格式是"2020-01-01 05:20:15"。 import pandas as pd datapd.read_e…

[数据集][目标检测]刀具匕首持刀检测数据集VOC+YOLO格式8810张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8810 标注数量(xml文件个数)&#xff1a;8810 标注数量(txt文件个数)&#xff1a;8810 标注…

C++基础语法:引用

前言 "打牢基础,万事不愁" .C的基础语法的学习 引入 引用是C里的概念,和C语言里的"指针常量"是类似的.在C里用得还挺多的,书中明确说明了类对象做参数时,传入类对象的引用.在<<C Prime Plus>> 6th Edition第274页有使用推荐 .用引用来回顾指针…

uniapp+python使用临时签名上传腾讯云oss对象储存方案

概述 uniapp使用临时签名上传腾讯云oss对象储存方案&#xff0c;支持小程序、app、h5&#xff1b; 前端不依赖腾讯云SDK工具类&#xff1b; 后端使用python实现&#xff0c;需要安装qcloud-python-sts&#xff1b; 其中计算文件md5值使用了条件编译&#xff0c;因为每个环境获…

堆结构、堆排序

堆 是完全二叉树&#xff0c;类似这种样式的 而这种有右子节点&#xff0c;没左子节点的就不是完全二叉树 分为大根堆和小根堆 大根堆是二叉树里每一颗子树的父节点都是这颗子树里最大的&#xff0c;即每一棵子树最大值是头节点的值 小根堆相反 把数组中从0开始的一段数人…

Spring Bean生命周期

Bean生命周期&#xff1a; 创建 Bean 的实例&#xff1a;Bean 容器首先会找到配置文件中的 Bean 定义&#xff0c;然后使用 Java 反射 API 来创建 Bean 的实例。 Bean 属性赋值/填充&#xff1a;为 Bean 设置相关属性和依赖&#xff0c;例如Autowired 等注解注入的对象、Value…