通讯录(C语言详细版)

news2024/10/6 20:32:54

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.coloradmin.cn/o/1895241.html

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

相关文章

强强联合!当RAG遇到长上下文,滑铁卢大学发布LongRAG,效果领先GPT-4 Turbo 50%

过犹不及——《论语先进》 大学考试时&#xff0c;有些老师允许带备cheet sheet&#xff08;忘纸条&#xff09;,上面记着关键公式和定义,帮助我们快速作答提高分数。传统的检索增强生成(RAG)方法也类似,试图找出精准的知识片段来辅助大语言模型(LLM)。 但这种方法其实有问题…

Oracle Database 23ai新特性:DB_DEVELOPER_ROLE角色

角色介绍 从 Oracle Database 23ai 开始&#xff0c;新角色“DB_DEVELOPER_ROLE”允许管理员快速分配开发人员为 Oracle 数据库设计、构建和部署应用程序所需的所有必要权限。&#xff08;包括构建数据模型所需的系统权限以及监视和调试应用程序所需的对象权限&#xff09;。通…

【期末复习】数据库系统概论(附带考点汇总)

第1章.绪论 目录 第1章.绪论1.1. 数据库系统概述1.1.1.基本概念1.1.2.产生和发展 1.2.概念模型1.2.1.三种模型1.2.2.概念模型1.2.3.关系模型 1.3.数据库系统结构1.3.1三级模式结构1.3.2.两级映像与数据独立性 第2章.关系型数据库2.1.关系2.2.关系操作2.2.1.基本关系操作2.2.2.关…

价格很实惠,希喂、爱立方、生生不息主食冻干抗得住实测吗?

在挑选主食冻干时&#xff0c;许多宠物主人都会感到头疼。尽管主食冻干相较于普通猫粮具有诸多优势&#xff0c;但其价格也相对高昂。这导致许多宠物主人担心高价购买的主食冻干可能营养价值并不理想。然而&#xff0c;在选择时&#xff0c;我们还需要考虑其他重要因素&#xf…

精密微型导轨加工工艺流程!

微型导轨是一种用于小型化机械设备和机床上的一种传动部件&#xff0c;多用于精密设备上&#xff0c;主要作用是支撑和导向滑块运动。想要让微型导轨长期保持高精度、高耐磨、高寿命、高效率运作&#xff0c;加工工艺是非常关键的步骤。 微型导轨的制造工艺主要包括机械加工、热…

三、【源码】Bean有参构造实例化

源码地址&#xff1a;https://github.com/spring-projects/spring-framework 仓库地址&#xff1a;https://gitcode.net/qq_42665745/spring/-/tree/03-parameter-constructor-instantiation Bean有参构造实例化 有参构造的实例化分两种&#xff1a; java自带的反射cglib代…

手把手教程教你_一键获取安居客全国小区数据

软件简介 安居客二手房小区全国实时数据&#xff0c;含小区名称、价格、地区、地址、商圈、标签、经纬度、物业类型、交易权属、竣工时间、产权年限、开发商、总户数、总建面积、绿化率、容积率、统一供暖 供水供电、停车位、停车费、物业费、物业公司 车位管理费、在售房源、…

应用案例 | 基于物联网工控屏的工业离心机设备监控系统

案例概况 客户&#xff1a;博鲁班特&#xff08;BROADBENT&#xff09; 应用产品&#xff1a;宏集物联网工控屏 应用场景&#xff1a;离心机设备监控系统 一、前言 在现代工业生产中&#xff0c;离心机作为关键的分离设备&#xff0c;在生产过程中扮演着至关重要的角色。随…

创新驱动,智享未来:电动车仪表盘之蓝牙芯方案

电动车行业不断发展的浪潮中&#xff0c;我们自豪地推出引领时代的电动车仪表盘蓝牙芯方案&#xff0c;为您的骑行之旅带来前所未有的智能与便捷。 精准掌控&#xff0c;一目了然 我们的蓝牙芯方案搭载了高性能BLE 5.0蓝牙芯片-HS6621CG-C 内核ARM Cortex-M4F, max 64MHZ,SRAM…

期权开户零门槛怎么操作?期权不满50w的开户方式

今天带你了解期权开户零门槛怎么操作&#xff1f;期权不满50w的开户方式。在股票期权市场上&#xff0c;期权交易是一种非常受欢迎的投资方式。它不仅可以增加投资组合的多样性&#xff0c;还可以为投资者提供一定的保护和利润机会&#xff0c;比如通过买入认股期权做空对冲大盘…

新建vue3项目

提示&#xff1a;请确定自己已将安装好环境以及一系列用到的工具包&#xff0c;例如node&#xff08;10以上&#xff09;&#xff0c;pnpm或npm vue官网&#xff1a;https://cn.vuejs.org/ vue-cli官网&#xff1a;Vue CLI vite官网&#xff1a;Vite | 下一代的前端工具链 …

高薪程序员必修课-Java中 Synchronized和ReentrantLock有哪些不同?

目录 前言 1. 原理和基础 synchronized ReentrantLock 2. 功能比较 2.1 锁的可重入性 示例&#xff1a; 2.2 锁的公平性 示例&#xff1a; 2.3 锁的中断响应 示例&#xff1a; 2.4 尝试锁定 示例&#xff1a; 2.5 条件变量 示例&#xff1a; 3. 性能比较 4. 使…

【CT】LeetCode手撕—232. 用栈实现队列

目录 题目1- 思路2- 实现⭐232. 用栈实现队列——题解思路 3- ACM 实现 题目 原题连接&#xff1a;232. 用栈实现队列 1- 思路 思路 ① 用两个栈来实现队列&#xff0c;一个 in 入栈 和一个 out 出栈② push 入队&#xff1a;入栈逻辑&#xff1a;即将元素加入到 in 栈 里即…

基于Redisson实现分布式锁

基于redisson实现分布式锁 之前背过分布式锁几种实现方案的八股文&#xff0c;但是并没有真正自己实操过。现在对AOP有了更深一点的理解&#xff0c;就自己来实现一遍。 1、分布式锁的基础知识 分布式锁是相对于普通的锁的。普通的锁在具体的方法层面去锁&#xff0c;单体应…

Android-卷积神经网络(Convolutional Neural Network, CNN)

一个复杂且在Android开发中常见的算法是图像处理中的卷积神经网络(Convolutional Neural Network, CNN)。CNN被广泛用于图像识别、物体检测和图像分割等任务,其复杂性在于需要处理大量的图像数据、复杂的神经网络结构和高效的计算。 1. 卷积操作(Convolution) 数学原理:…

爬虫-豆瓣电影排行榜

获取数据 requests库 获取数据环节需要用到requests库。安装方式也简单 pip install requests 爬取页面豆瓣读书 Top 250 用requests库来访问 import requests res requests.get(https://book.douban.com/top250/) 解析&#xff1a; 导入requests库调用了requests库中的…

界面材料知识

界面材料是用于填充芯片和散热器之间的空隙&#xff0c;将低导热系数的空气挤出&#xff0c;换成较高导热系数的材料&#xff0c;以提高芯片散热能力。参考下图 图片来源网上 热阻是衡量界面材料性能最终的参数&#xff0c;其中与热阻有关的有&#xff1a; 1、导热系数&#x…

Land survey boundary report (template)

Land survey boundary report (template) 土地勘测定界报告&#xff08;模板&#xff09;.doc

介绍几种 MySQL 官方高可用方案

前言&#xff1a; MySQL 官方提供了多种高可用部署方案&#xff0c;从最基础的主从复制到组复制再到 InnoDB Cluster 等等。本篇文章以 MySQL 8.0 版本为准&#xff0c;介绍下不同高可用方案架构原理及使用场景。 1.MySQL Replication MySQL Replication 是官方提供的主从同…

Games101学习笔记 Lecture16 Ray Tracing 4 (Monte Carlo Path Tracing)

Lecture16 Ray Tracing 4 (Monte Carlo Path Tracing 一、蒙特卡洛积分 Monte Carlo Integration二、路径追踪 Path tracing1.Whitted-Style Ray Tracings Problems2.只考虑直接光照时3.考虑全局光照①考虑物体的反射光②俄罗斯轮盘赌 RR &#xff08;得到正确shade函数&#x…