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

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

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

目录

前言

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

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动态数组里面的一个成员。我们还可以把这些联系人的信息以文件的形式储存起来,这就要运用到我们之前学习过的文件操作。本人感觉顺序表和通讯录会比链表复杂,后面还会为大家介绍单链表和双链表,大家敬请期待吧!!

  • 45
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值