数据结构之实现“通讯录”

                                               大家先赞后看,养成好习惯

你们的点赞和关注还有收藏就是我的动力!!!

目录

前言

一、通讯录文件的创建和联系人结构体定义

1.1 文件创建

1.2 联系人结构体定义

二、通讯录的功能实现

2.1通讯录初始化

2.2通讯录销毁

2.3添加联系人

2.4删除联系人

2.5查找联系人(包含显现联系人)

2.6修改通讯录

2.7展示通讯录

2.8菜单的创建 (与扫雷、猜数字相似)

三、使用通讯录储存联系人

四、结合文件操作来储存信息

五、代码展示

5.1通讯录头文件

5.2通讯录源文件 

总结


前言

“通讯录”是基于顺序表的基础上实现的项目,要熟悉顺序表才比较容易看懂和完成通讯录项目。在这个博客里面不会来介绍之前的东西,之前没看懂的可以到这【数据结构之“顺序表”】-CSDN博客

一、通讯录文件的创建和联系人结构体定义

1.1 文件创建

加上之前顺序表的两个文件一共是五个文件。

test.c是实现联系人储存的文件,contact.c是通讯录的源文件,contact.h是通讯录的头文件,seqlist.c和seqlist.h是之前的顺序表的源文件和头文件。(源文件是功能实现的代码,头文件是用来包含一些头文件和定义一些东西)

1.2 联系人结构体定义

我们这里的联系人信息包含:姓名、性别、年龄 、电话、地址

typedef struct PersonInfo//通讯录
{
	char name[Max_name];//姓名
	char gender[Max_gender];//性别
	int age;//年龄
	char tel[Max_tel];//电话
	char addr[Max_addr];//地址
}PeoInfo;//命名为PeoInfo

二、通讯录的功能实现

2.1通讯录初始化

我们就调用一下顺序表的初始化就可以了,因为在顺序表的arr中存放每一个结构体(也就是联系人的信息)就是PersonInfo。

//通讯录初始化
void contactInit(contact * con)
{
	//这里的con就是sl也就是一个结构体指针初始化为NULL
	//我们直接调用顺序表的初始化
	SLInit(con);//初始化
}

2.2通讯录销毁

销毁也同初始化,直接调用顺序表的销毁。

//通讯录销毁
void contactDestroy(contact* con)
{
	SLDestroy(con);//销毁
}

2.3添加联系人

也就是给结构体里面的人赋初值,然后调用一下顺序表的插入函数(头插、尾插都行)。

//添加通讯录联系人
void contactAdd(contact* con)
{
	PeoInfo info;//同SL sl;定义一个结构体,方便使用
	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);

	SLPushFront(con,info);//头插联系人
	printf("添加联系人成功!\n");
}

2.4删除联系人

删除联系人有很多方法,可以通过姓名、性别、年龄 、电话、地址 五种方法随便选择一种。

我这里演示的是通过姓名来删除联系人,剩下的几种大家可以自行尝试!!。

想法我们要遍历每一个结构体里面的info.name然后判断与要被删除的联系人姓名,然后返回下标进行了(顺序表本质就是一个数组,可以通过下标来找到),调用查找联系人返回下标函数,我们比较的是字符使用要用strcmp函数,然后调用一下顺序表指定位置的删除就可以了。

//查找联系人,并返回下标
int contactFindName(contact* con,char name[Max_name])
{
	//还可以通过其他来返回下标,地址,电话都行,要看传来的参数是什么。
	for (int i = 0;i < con->size;i++)
	{
		if (0 == strcmp(con->arr[i].name, name))//strcmp字符串比较函数
		{
			//找到了
			return i;
		}
	}
	//没找到
	return -1;
}

//删除联系人
 void contactDel(contact* con)
{
	 //删除前要检查删除的数据是否存在
	 //就要先查找数据
	 char name[Max_name];
	 printf("请输入你要删除的联系人姓名:\n");
	 scanf("%s", name);
	 int pos = contactFindName(con, name);
	 if (pos < 0)
	 {
		 printf("删除的联系人不存在!\n");
		 return;
	 }
	 SLErase(con,pos);//pos是删除元素的下标
	 printf("删除成功!\n");
}

2.5查找联系人(包含显现联系人)

查找联系人和删除联系人很像,只比删除联系人少了删除数据。


 //查找通讯录联系人
 void contactFind(contact* con)
 {
	 char name[Max_name];
	 printf("请输入查找的联系人姓名:\n");
	 scanf("%s", name);
	 int pos = contactFindName(con, name);
	 if (pos < 0)
	 {
		 printf("查找的联系人不存在,查找失败!\n");
		 return;
	 }
	 printf("查找成功\n");
	 printf("姓名 性别 年龄 电话 地址\n");
	 printf("%-5s %2s %3d %5s %5s\n", con->arr[pos].name,
		 con->arr[pos].gender,
		 con->arr[pos].age,
		 con->arr[pos].tel,
		 con->arr[pos].addr);
 }

2.6修改通讯录

本质上和删除差不多,还是通过返回下标来重新修改联系人

//修改通讯录联系人
void contactModify(contact* con)
{
 char name[Max_name];
 printf("请输入要修改的联系人名字:\n");
 scanf("%s", name);

 int pos = contactFindName(con,name);

 if (pos < 0)
 {
	 printf("修改的联系人不存在,修改失败!\n");
	 return;
 }
 PeoInfo info;
 printf("请输入修改后联系人姓名:\n");
 scanf("%s", con->arr[pos].name);
 printf("请输入修改后联系人性别:\n");
 scanf("%s", con->arr[pos].gender);
 printf("请输入修改后联系人年龄:\n");
 scanf("%d", &con->arr[pos].age);
 printf("请输入修改后联系人电话:\n");
 scanf("%s", con->arr[pos].tel);
 printf("请输入修改后联系人地址:\n");
 scanf("%s", con->arr[pos].addr);

 printf("修改成功!\n");
}

2.7展示通讯录

通过循环来打印联系人信息,这时就要用到顺序表里面的有效个数(size)来作为循环的判断条件。

//展示通讯录联系人
void contactShow(contact* con)
{
 for (int i = 0;i < con->size;i++)//呈现所有的信息
 {
	 printf("姓名 性别 年龄 电话 地址\n");
	 printf("%-5s %2s %3d %5s %5s\n", con->arr[i].name,
		 con->arr[i].gender,
		 con->arr[i].age,
		 con->arr[i].tel,
		 con->arr[i].addr);
 }
 printf("呈现完毕!\n");
}

2.8菜单的创建 (与扫雷、猜数字相似)

void menu()//菜单  目录
{
	printf("***********通讯录**********\n");
	printf("**1.添加用户***2.删除用户**\n");
	printf("**3.查找用户***4.修改用户**\n");
	printf("**5.显示用户***0.退出程序**\n");
}

三、使用通讯录储存联系人

#define _CRT_SECURE_NO_WARNINGS
//用来测试代码
#include"Seqlist.h"

int main()
{
	contact con;
	contactInit(&con);//初始化
	int input = -1;

	do
	{
		menu();
		printf("请你选择操作:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1: 
			contactAdd(&con);
			break;
		case 2:
			contactDel(&con);
			break;
		case 3:
			contactFind(&con);
			break;
		case 4:
			contactModify(&con);
			break;
		case 5:
			contactShow(&con);
			break;
		default:
			printf("输入操作错误,重新输入!\n");
			break;//default 后面break 可写可不写
		}
	} 
	while (input);//input 等价于 input!=0
	contactDestroy(&con);//销毁
	return 0;
}

这是主函数(切忌俩个头文件互相包含)

我来演示一下

联系人 姓名:恐龙、性别:男、年龄:18、电话:666666、地址:侏罗纪公园。

拼音不好见谅!!!!

四、结合文件操作来储存信息

这里就不细讲了文件操作,可以看之前的​​​​​​喉咙疼的恐龙又来给大家介绍”芝士了“ 那就是文件操作-CSDN博客

//读取数据到contact.txt文件中
void contactLoad(contact* con)
{
	FILE* pf = fopen("contact.txt","rb");//二进制读
	if (pf = NULL)
	{
		perror("fopen error:");
		return;
	}
	PeoInfo info;
	while (fread(&info, sizeof(info), 1, pf))
	{
		SLPushFront(con, info);
	}
	fclose(pf);//关闭
	pf = NULL;//防止出现空指针
	printf("历史数据读取成功!\n");
}

//写数据到contact.txt文件中
void contactSave(contact* con)
{
	FILE* pf = fopen("contact.txt","wb");
	if (pf == NULL)
	{
		perror("fopen error!");
		return;
	}
	for (int sz = 0;sz < con->size;sz++)
	{
		fwrite(con->arr+sz, sizeof(PeoInfo), 1, pf);//con->arr[sz]不行,这里要地址,&con->arr[sz].
	}
	fclose(pf);//关闭
	pf = NULL;//防止出现空指针
	printf("通讯录数据保存成功!\n");
}

五、代码展示

5.1通讯录头文件

contact.h
#pragma once
#define Max_name 20
#define Max_gender 10
#define Max_tel 15
#define Max_addr 20

typedef struct Seqlist contact;//前置声明,因为不可以相互包含头文件,会报错。
//总结通讯录项目的原理:基于顺序表,在顺序表的数组中存放每一个结构体(也就是联系人的信息)
typedef struct PersonInfo//通讯录
{
	char name[Max_name];//姓名
	char gender[Max_gender];//性别
	int age;//年龄
	char tel[Max_tel];//电话
	char addr[Max_addr];//地址
}PeoInfo;

//通讯录初始化
void contactInit(contact* con);
//通讯录的销毁
void contactDestroy(contact* con);
//添加通讯录联系人
void contactAdd(contact* con);
//删除通讯录联系人
void contactDel(contact* con);
//查找通讯录联系人
void contactFind(contact* con);
//修改通讯录联系人
void contactModify(contact* con);
//展示通讯录联系人
void contactShow(contact* con);

5.2通讯录源文件 

contact.c
#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
#include"Seqlist.h"

//读取数据到contact.txt文件中
void contactLoad(contact* con)
{
	FILE* pf = fopen("contact.txt","rb");//二进制读
	if (pf = NULL)
	{
		perror("fopen error:");
		return;
	}
	PeoInfo info;
	while (fread(&info, sizeof(info), 1, pf))
	{
		SLPushFront(con, info);
	}
	fclose(pf);//关闭
	pf = NULL;//防止出现空指针
	printf("历史数据读取成功!\n");
}

//写数据到contact.txt文件中
void contactSave(contact* con)
{
	FILE* pf = fopen("contact.txt","wb");
	if (pf == NULL)
	{
		perror("fopen error!");
		return;
	}
	for (int sz = 0;sz < con->size;sz++)
	{
		fwrite(con->arr+sz, sizeof(PeoInfo), 1, pf);//con->arr[sz]不行,这里要地址,&con->arr[sz].
	}
	fclose(pf);//关闭
	pf = NULL;//防止出现空指针
	printf("通讯录数据保存成功!\n");
}

//通讯录初始化
void contactInit(contact * con)
{
	//这里的con就是sl也就是一个结构体指针初始化为NULL
	//我们直接调用顺序表的初始化
	SLInit(con);//初始化
}

//通讯录销毁
void contactDestroy(contact* con)
{
	SLDestroy(con);//销毁
}

//添加通讯录联系人
void contactAdd(contact* con)
{
	PeoInfo info;//同SL sl;定义一个结构体,方便使用
	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);

	SLPushFront(con,info);//头插联系人
	printf("添加联系人成功!\n");
}

//查找联系人,并返回下标
int contactFindName(contact* con,char name[Max_name])
{
	//还可以通过其他来返回下标,地址,电话都行,要看传来的参数是什么。
	for (int i = 0;i < con->size;i++)
	{
		if (0 == strcmp(con->arr[i].name, name))//strcmp字符串比较函数
		{
			//找到了
			return i;
		}
	}
	//没找到
	return -1;
}


//删除联系人
 void contactDel(contact* con)
{
	 //删除前要检查删除的数据是否存在
	 //就要先查找数据
	 char name[Max_name];
	 printf("请输入你要删除的联系人姓名:\n");
	 scanf("%s", name);
	 int pos = contactFindName(con, name);
	 if (pos < 0)
	 {
		 printf("删除的联系人不存在!\n");
		 return;
	 }
	 SLErase(con,pos);//pos是删除元素的下标
	 printf("删除成功!\n");
}

 //查找通讯录联系人
 void contactFind(contact* con)//err
 {
	 char name[Max_name];
	 printf("请输入查找的联系人姓名:\n");
	 scanf("%s", name);
	 int pos = contactFindName(con, name);
	 if (pos < 0)
	 {
		 printf("查找的联系人不存在,查找失败!\n");
		 return;
	 }
	 printf("查找成功\n");
	 printf("姓名 性别 年龄 电话 地址\n");
	 printf("%-5s %2s %3d %5s %5s\n", con->arr[pos].name,
		 con->arr[pos].gender,
		 con->arr[pos].age,
		 con->arr[pos].tel,
		 con->arr[pos].addr);
 }

 //修改通讯录联系人
 void contactModify(contact* con)
 {
	 char name[Max_name];
	 printf("请输入要修改的联系人名字:\n");
	 scanf("%s", name);

	 int pos = contactFindName(con,name);

	 if (pos < 0)
	 {
		 printf("修改的联系人不存在,修改失败!\n");
		 return;
	 }
	 PeoInfo info;
	 printf("请输入修改后联系人姓名:\n");
	 scanf("%s", con->arr[pos].name);
	 printf("请输入修改后联系人性别:\n");
	 scanf("%s", con->arr[pos].gender);
	 printf("请输入修改后联系人年龄:\n");
	 scanf("%d", &con->arr[pos].age);
	 printf("请输入修改后联系人电话:\n");
	 scanf("%s", con->arr[pos].tel);
	 printf("请输入修改后联系人地址:\n");
	 scanf("%s", con->arr[pos].addr);

	 printf("修改成功!\n");
 }

 //展示通讯录联系人
 void contactShow(contact* con)
 {
	 for (int i = 0;i < con->size;i++)//呈现所有的信息
	 {
		 printf("姓名 性别 年龄 电话 地址\n");
		 printf("%-5s %2s %3d %5s %5s\n", con->arr[i].name,
			 con->arr[i].gender,
			 con->arr[i].age,
			 con->arr[i].tel,
			 con->arr[i].addr);
	 }
	 printf("呈现完毕!\n");
 }

总结

通讯录这个项目你只要完全了解了顺序表解决不困难,要理解通讯录结构体每一个联系人就是顺序表中的arr动态数组里面的一个成员。我们还可以把这些联系人的信息以文件的形式储存起来,这就要运用到我们之前学习过的文件操作。本人感觉顺序表和通讯录会比链表复杂,后面还会为大家介绍单链表和双链表,大家敬请期待吧!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用手机小程序给证件照换底色

临时遇到一个需求&#xff0c;需要给证件照换底色。原始图像如下 最终需要换成红底的。 本次使用一款小程序&#xff02;泰世茂证件照&#xff02;&#xff0c;打开该小程序&#xff0c;如下图所示 单击开始制作&#xff0c;然后选择二寸红底&#xff0c;如下图所示 然后单击相…

【AIGC时代】探索AIGC的无限可能:释放你的创意,定制你的视觉世界

前言 在数字时代的浪潮中&#xff0c;我们的视觉体验正在经历前所未有的变革。随着科技的飞速发展&#xff0c;我们不再满足于传统的图片制作方式&#xff0c;而是渴望拥有更具创意、更富个性的视觉呈现。在这样的背景下&#xff0c;AIGC&#xff08;人工智能生成内容&#xf…

IF:83.5!一作兼通讯,​Nature系列综述:可以吃的机器人!

在当今科技与生物工程快速融合的时代&#xff0c;传统领域之间的界限正在逐渐模糊&#xff0c;创造了许多前所未有的创新机会。机器人设计与食品加工这两个看似无关的研究领域&#xff0c;正在通过材料特性、制造工艺和功能的交叉融合&#xff0c;展现出巨大的潜力。 可食用机器…

Flutter 验证码输入框

前言&#xff1a; 验证码输入框很常见&#xff1a;处理不好 bug也会比较多 想实现方法很多&#xff0c;这里列举一种完美方式&#xff0c;完美兼容 软键盘粘贴方式 效果如下&#xff1a; 之前使用 uniapp 的方式实现过一次 两种方式&#xff08;原理相同&#xff09;&#xff1…

【TB作品】MSP430F5529,单片机,电子秒表,秒表

硬件 MSP430F5529开发板7针0.96寸OLED /* OLED引脚分配 绿色板子DO(SCLK)------P4.3D1(DATA)------P4.0RES-----------P3.7DC------------P8.2CS------------P8.1 */ 程序功能 该程序是一个用C语言编写的&#xff0c;用于msp430f5529微控制器上的简单电子秒表应用。它使用…

多源 BFS 详解

目录 一、多源与单源的区别 二、例题练习 2.1 例题1&#xff1a;01 矩阵 2.2 例题2&#xff1a;飞地的数量 2.3 例题3&#xff1a;地图中的最高点 2.4 例题4&#xff1a;地图分析 一、多源与单源的区别 单源最短路问题如何解决已经在上篇博客给出BFS 解决最短路问题&am…

Qt | Qt 资源简介(rcc、qmake)

1、资源系统是一种独立于平台的机制,用于在应用程序的可执行文件中存储二进制文件(前面所讨论的数据都存储在外部设备中)。若应用程序始终需要一组特定的文件(比如图标),则非常有用。 2、资源系统基于 qmake,rcc(Qt 的资源编译器,用于把资源转换为 C++代码)和 QFile …

Java扩展机制:SPI与Spring.factories详解

一、SPI SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。 整体机制图如下: Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。 系统设计的各个抽象,往往有很多不…

【车载开发系列】汽车开发常用工具说明

【车载开发系列】汽车开发常用工具说明 【车载开发系列】汽车开发常用工具说明 【车载开发系列】汽车开发常用工具说明一. CANbedded二. Davinci Configurator Pro三. Davinci Developer-AUTOSAR软件组件设计工具四. MICROSAR五. MICROSAR OS六. CANdelaStudio七. Volcano VSB八…

css动态导航栏鼠标悬停特效

charset "utf-8"; /*科e互联特效基本框架CSS*/ body, ul, dl, dd, dt, ol, li, p, h1, h2, h3, h4, h5, h6, textarea, form, select, fieldset, table, td, div, input {margin:0;padding:0;-webkit-text-size-adjust: none} h1, h2, h3, h4, h5, h6{font-size:12px…

Nodejs-- 网络编程

网络编程 构建tcp服务 TCP tcp全名为传输控制协议。再osi模型中属于传输层协议。 tcp是面向连接的协议&#xff0c;在传输之前需要形成三次握手形成会话 只有会话形成了&#xff0c;服务端和客户端才能想发送数据&#xff0c;在创建会话的过程中&#xff0c;服务端和客户…

【计算机毕业设计】353微信小程序零食批发交易管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

如何进行时间管理

1.一项调查显示&#xff0c;每个人在睡觉上花费的平均时间大约为25年&#xff0c;这无疑是非常重要的。但排名第二的项目却让人大跌眼镜——看电视是8.3年。接下来分别是工作7.5年、吃饭6年、等待和家务各5年、身体护理4.1年、做白日梦4年&#xff0c;等等。 远远落后的是读书时…

ChatTTS+Python编程搞定语音报时小程序

文字转语音神器Python编程搞定语音报时小程序 今天一个好哥们发了一个文字转语音的AI神器的短视频。这个神器的网站是[ChatTTS - Text-to-Speech for Conversational Scenarios][https://chattts.com/]&#xff0c;如下图所示&#xff1a; 这个开源项目可以从github.com上下载…

[数据集][目标检测]轮胎检测数据集VOC+YOLO格式439张1类别

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

智慧商砼搅拌车安监运营管理的创新实践

随着城市化进程的加速&#xff0c;商砼搅拌车作为城市建设的重要设备&#xff0c;其安全管理与运营效率直接关系到工程质量和施工进度。近年来&#xff0c;通过引入先进的4G无线视频智能车载终端套件&#xff0c;我们实现了对商砼搅拌车的高精度定位、实时音视频调度、实时油量…

队列——一种操作受限的线性表

队列 队列&#xff08;Queue&#xff09;简称队&#xff0c;也是一种操作受限的线性表&#xff0c;只允许在表的一端进行插入&#xff0c;而在表的另一端进行删除。向队列中插入元素称为入队或进队&#xff0c;删除元素称为出队或离队。队列中的元素是先进先出&#xff08;Fir…

C++设计模式-桥接模式

运行在VS2022&#xff0c;x86&#xff0c;Debug下。 29. 桥接模式 桥接模式将抽象与实现分离&#xff0c;使二者可以独立地变化。 应用&#xff1a;如在游戏开发中&#xff0c;多个角色和多个武器交叉组合时。可以使用桥接模式&#xff0c;定义角色抽象类&#xff0c;武器抽象…

注册北京个体工商户条件和办理时间

在北京这座充满活力的城市中&#xff0c;每天都有无数的创业者怀揣着梦想&#xff0c;踏上创业之路。然而&#xff0c;对于许多初次接触企业注册的人来说&#xff0c;往往对注册流程和时间感到困惑。特别是选择代理服务时&#xff0c;更希望了解一个大概的时间范围。那么&#…

Flutter开发效率提升1000%,Flutter Quick教程之对Widget进行删除,剪切,粘贴

一&#xff0c;删除操作 1&#xff0c;首先我们选中要删除的Widget。 2&#xff0c;在左边的侧边栏&#xff0c;点击删除按钮&#xff0c;即可完成对组件的删除操作。 二&#xff0c;剪切。剪切是相同的道理&#xff0c;都是先选中&#xff0c;再点击对应的按钮。 1&#xff…