C顺序表:通讯录

news2024/11/14 12:20:09

目录

前言

通讯录数据结构

通讯录初始化 

查找名字

增加联系人

删除联系人

展示所有联系人

查找联系人

修改信息

销毁通讯录

完整通讯录代码


前言

数据结构中的顺序表如果已经学会了,那么我们就可以基于顺序表来完成一个通讯录了

通讯录其实我们使用前面学习过的顺序表就能完成不过,相比较来说,前面的顺序表就是个整型数组,但通讯录就是一个多信息的自定义类型了

如果没了解过顺序表的可以看看我前篇博客

C数据结构:顺序表-CSDN博客

下面直接来开始完成我们的通讯录吧

通讯录数据结构

typedef struct PersonInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef PeoInfo SLDataType;
//typedef int SLDataType;

typedef struct SeqList
{
    SLDataType* a;
    int size;     // 有效数据个数
    int capacity; // 空间容量
}SL;

通讯里结构体里定义了五个成员,名字、性别、年龄、电话、地址

数组大小使用了宏定义,因为有需要更改的时候就比较方便,不需要一个个去更改

下面就开始通讯录的实现吧

如果文件中有顺序表的.c文件,请务必屏蔽以下函数,否则会引起报错

 

 

1. SLPrint函数中含有 %d,%d是整型的占位符,如果我们需要打印自定义类型是不能使用%d占位符的

2. SLFind函数中if的判断条件 ps->a[i] == x这个有错误,我们的a数组的类型是个自定义类型,该类型里含有5个成员,怎么能直接让两个自定义类型直接比较呢?

通讯录初始化 

void InitContact(contact* con)
{
	SLInit(con);
}

初始化一个联系人就和初始化一个顺序表一样,所以直接使用顺序表的函数对里面的参数con进行初始化即可 

查找名字

int FindByName(contact* con, char name[])
{
	assert(con);

	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->a[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

为什么要先写查找名字呢?

因为我们后面删除联系人、查找联系人、修改联系人都会使用到这个模板,如果都按一个模板来写会显得代码很冗余,并且浪费时间,所以我们直接写一个函数就可以有效的解决这个问题

我们直接遍历整个联系人a数组里面的名字,当名字匹配的时候,我们就返回它的下标,否则出了循环之后说明没找到名字,则返回-1

我们不能直接写

con->a[i].name == name作为if语句的条件

因为这个name是个char类型的数组名,而数组名是地址,用地址来比较是得不出答案的,所以需要借助到string.h里的strcmp函数 

对string.h库函数有兴趣的可以看看我前面的博客 

ctype.h的了解string.h库函数中各个函数的使用和模拟实现-CSDN博客

增加联系人

void AddContact(contact* con)
{
	assert(con);

	PeoInfo c;
	printf("请输入姓名:>");
	scanf("%s", c.name);
	printf("请输入性别:>");
	scanf("%s", c.sex);
	printf("请输入年龄:>");
	scanf("%d", &c.age);
	printf("请输入电话:>");
	scanf("%s", c.tel);
	printf("请输入地址:>");
	scanf("%s", c.addr);

	SLPushBack(con, c);
}
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapacity(ps); //检查数组大小是否足够
	ps->a[ps->size] = x;
	ps->size++;
}

 先是定义了一个通讯录c变量,并把我们需要增加的联系人的信息先暂时放到c中

最后使用顺序表里的SLPushBack函数将这些信息放到我们的通讯录数组中即可

删除联系人

void DelContact(contact* con)
{
	assert(con);

	char name[NAME_MAX];
	printf("请输入要删除的姓名:>");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("要删除的用户不存在!\n");
		return;
	}
	SLErase(con, pos);
	printf("删除成功\n");
}
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos <= ps->size && pos >= 0);
	assert(ps->size > 0);

	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

先定义了一个name数组接收我们要删除的人的名字,然后使用我们前面写到的FindByName找到这个名字的下标,最后使用SLErase函数删除掉通讯录数组这个下标所在的位置即可

展示所有联系人

void ShowContact(contact* con)
{
	assert(con);

	//打印表头
	printf("姓名\t性别\t年龄\t电话\t地址\n");
	for (int i = 0; i < con->size; i++)
	{
		printf("%s\t%s\t%d\t%s\t%s\n", con->a[i].name,
			con->a[i].sex,
			con->a[i].age,
			con->a[i].tel,
			con->a[i].addr
		);
	}
}

展示这一步就是给使用者看的,为了美观对齐所以在每一个信息的后面加了一个\t

最后用for循环遍历通讯录数组打印所有的信息即可

查找联系人

void FindContact(contact* con)
{
	assert(con);

	char name[NAME_MAX];
	printf("请输入要查找的姓名:>");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("查找的用户不存在!\n");
		return;
	}
	printf("查找成功\n");
	printf("%s\t%s\t%d\t%s\t%s\t", con->a[pos].name,
		con->a[pos].sex,
		con->a[pos].age,
		con->a[pos].tel,
		con->a[pos].addr
	);
}

 还是一样先找到名字所在通讯录数组的下标,如果能找到说明联系人存在,利用下标打印出该人的信息即可

修改信息

void ModifyContact(contact* con)
{
	assert(con);

	char name[NAME_MAX];
	printf("请输入要修改的姓名:>");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("查找的用户不存在!\n");
		return;
	}
	
	printf("请输入姓名:>");
	scanf("%s", con->a[pos].name);
	printf("请输入性别:>");
	scanf("%s", con->a[pos].sex);
	printf("请输入年龄:>");
	scanf("%d", &con->a[pos].age);
	printf("请输入电话:>");
	scanf("%s", con->a[pos].tel);
	printf("请输入地址:>");
	scanf("%s", con->a[pos].addr);
	printf("修改成功\n");
}

也是一样先查找该名字所在通讯录数组的下标,然后重新使用scanf输入该下标的所有信息即可 

销毁通讯录

void DestroyContact(contact* con)
{
	assert(con);

	SLDestroy(con);
}
void SLDestroy(SL* ps)
{
	assert(ps);

	if (ps->a)
	{
		free(ps->a);
	}
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

销毁直接用顺序表中的SLDestroy实现即可

完整通讯录代码

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100

//前置声明
typedef struct SeqList contact;

//用户数据
typedef struct PersonInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

//初始化通讯录
void InitContact(contact* con);

//添加通讯录数据
void AddContact(contact* con);

//删除通讯录数据
void DelContact(contact* con);

//展示通讯录数据
void ShowContact(contact* con);

//查找通讯录数据
void FindContact(contact* con);

//修改通讯录数据
void ModifyContact(contact* con);

//销毁通讯录数据
void DestroyContact(contact* con);

typedef PeoInfo SLDataType;
//typedef int SLDataType;

// 动态顺序表 -- 按需申请
typedef struct SeqList
{
    SLDataType* a;
    int size;     // 有效数据个数
    int capacity; // 空间容量
}SL;

//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);

//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);

//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);

void SLInit(SL* ps)
{
	assert(ps);

	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

void SLDestroy(SL* ps)
{
	assert(ps);

	if (ps->a)
	{
		free(ps->a);
	}
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

//void SLPrint(SL* ps)
//{
//	assert(ps);
//
//	for (int i = 0; i < ps->size; i++)
//	{
//		printf("%d ", ps->a[i]);
//	}
//	printf("\n");
//}

void SLCheckCapacity(SL* ps)
{
	assert(ps);

	if (ps->capacity == 0)
	{
		ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);
		ps->capacity = 4;
	}

	if (ps->capacity == ps->size && ps->capacity != 0)
	{
		//定义tmp接收防止扩容失败原数组被覆盖
		SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!\n");
			return;
		}
		//扩容成功
		ps->a = tmp;
		ps->capacity *= 2;
	}
}

void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);

	ps->size--;
}

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapacity(ps);

	for (int i = ps->size - 1; i >= 0; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;
	ps->size++;
}

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);

	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos <= ps->size && pos >= 0);

	SLCheckCapacity(ps);

	for (int i = ps->size; i >= pos; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;
}

void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos <= ps->size && pos >= 0);
	assert(ps->size > 0);

	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

//int SLFind(SL* ps, SLDataType x)
//{
//	assert(ps);
//	
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->a[i] == x)
//		{
//			return i;
//		}
//	}
//
//	return -1;
//}

void InitContact(contact* con)
{
	SLInit(con);
}

void AddContact(contact* con)
{
	assert(con);

	PeoInfo c;
	printf("请输入姓名:>");
	scanf("%s", c.name);
	printf("请输入性别:>");
	scanf("%s", c.sex);
	printf("请输入年龄:>");
	scanf("%d", &c.age);
	printf("请输入电话:>");
	scanf("%s", c.tel);
	printf("请输入地址:>");
	scanf("%s", c.addr);

	SLPushBack(con, c);
}

int FindByName(contact* con, char name[])
{
	assert(con);

	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->a[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DelContact(contact* con)
{
	assert(con);

	char name[NAME_MAX];
	printf("请输入要删除的姓名:>");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("要删除的用户不存在!\n");
		return;
	}
	SLErase(con, pos);
	printf("删除成功\n");
}

void ShowContact(contact* con)
{
	assert(con);

	//打印表头
	printf("姓名\t性别\t年龄\t电话\t地址\n");
	for (int i = 0; i < con->size; i++)
	{
		printf("%s\t%s\t%d\t%s\t%s\n", con->a[i].name,
			con->a[i].sex,
			con->a[i].age,
			con->a[i].tel,
			con->a[i].addr
		);
	}
}

void FindContact(contact* con)
{
	assert(con);

	char name[NAME_MAX];
	printf("请输入要查找的姓名:>");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("查找的用户不存在!\n");
		return;
	}
	printf("查找成功\n");
	printf("%s\t%s\t%d\t%s\t%s\t", con->a[pos].name,
		con->a[pos].sex,
		con->a[pos].age,
		con->a[pos].tel,
		con->a[pos].addr
	);
}

void ModifyContact(contact* con)
{
	assert(con);

	char name[NAME_MAX];
	printf("请输入要修改的姓名:>");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("查找的用户不存在!\n");
		return;
	}
	
	printf("请输入姓名:>");
	scanf("%s", con->a[pos].name);
	printf("请输入性别:>");
	scanf("%s", con->a[pos].sex);
	printf("请输入年龄:>");
	scanf("%d", &con->a[pos].age);
	printf("请输入电话:>");
	scanf("%s", con->a[pos].tel);
	printf("请输入地址:>");
	scanf("%s", con->a[pos].addr);
	printf("修改成功\n");
}

void DestroyContact(contact* con)
{
	assert(con);

	SLDestroy(con);
}

void Test2()
{
	contact c;
	InitContact(&c);
	AddContact(&c);
	AddContact(&c);
	ShowContact(&c);
	//DelContact(&c);
	ModifyContact(&c);
	ShowContact(&c);
	FindContact(&c);
	DestroyContact(&c);
}

int main()
{
	//Test1();
	Test2();
	return 0;
}

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

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

相关文章

1.0-spring入门

文章目录 前言一、版本要求二、第一个spring程序1.引入pom2.代码部分2.1 spring bean2.2 springContext.xml2.3 测试2.4 执行结果 总结 前言 最近想要系统的学习下spring相关的框架,于是乎,来到了B站(真是个好地方),spring会专门开一个专栏出来,记录学习心得,与大家共勉。 Spri…

[每天一道面试题] HTTP,FTP,TFTP的底层实现协议是什么

HTTP、FTP和TFTP等这些协议都是属于互联网协议网络层模型中的应用层协议。它们的底层实现主要依赖于传输层的两种协议—— TCP(传输控制协议) 和 UDP(用户数据报协议)。 HTTP: 超文本传输协议(HTTP)通常在TCP协议的基础上操作。HTTP用于在网络上传输超文本&#xff0c;是万维网…

【Redis 知识储备】读写分离/主从分离架构 -- 分布系统的演进(4)

读写分离/主从分离架构 简介出现原因架构工作原理技术案例架构优缺点 简介 将数据库读写操作分散到不同的节点上, 数据库服务器搭建主从集群, 一主一从, 一主多从都可以, 数据库主机负责写操作, 从机只负责读操作 出现原因 数据库成为瓶颈, 而互联网应用一般读多写少, 数据库…

云仓酒庄旗下雷盛红酒入驻香港星怡SingLa餐厅共绘美食美酒新篇章

近日&#xff0c;云仓酒庄旗下品牌雷盛红酒正式入驻香港餐厅星怡SingLa&#xff0c;这一跨界合作不仅为香港市民和游客带来了全新的味蕾享受&#xff0c;也标志着美食与美酒文化的很好结合&#xff0c;共同绘就了一幅精彩绝伦的美食美酒新篇章。 云仓酒庄一直以来都致力于为消费…

MySQL基础练习题:创建数据库

这部分主要是为了帮助大家回忆回忆MySQL的基本语法&#xff0c;数据库来自于MySQL的官方简化版&#xff0c;题目也是网上非常流行的35题。这些基础习题基本可以涵盖面试中需要现场写SQL的问题。 创建数据库 在开始练习之前&#xff0c;我默认你的电脑上是没有本系列练习题需要…

项目管理与经济决策(项目投资经济决策)

1.现金流量 流出系统的现金称为现金流出(CO) 流入系统的现金称为现金流入(CI) 现金流入&#xff0d;现金流出&#xff1d;净现金流量(NCF) 构成现金流量的基本因素&#xff1a;投资、&#xff08;付现&#xff09;成本、 &#xff08;现金&#xff09;收入、税金、利润等&a…

ICLR 2024 | 联邦学习后门攻击的模型关键层

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 联邦学习使多个参与方可以在数据隐私得到保护的情况下训练机器学习模型。但是由于服务器无法…

Java初始——IDEA-web的启动

Tomcat 文件夹作用 bin 启动 关闭的脚本文件 conf 配置 lib 依赖的jar包 logs 日志 temp 临时文件 webapps 存放的网站 Maven 1.在javaweb中&#xff0c;需要使用大量的jar包&#xff0c;手动导入 2.Maven 架构管理工具 核心&#xff1a;约定大于配置 必须按照规则 web idea-we…

【ELK】搭建elk日志平台(使用docker-compose),并接入springboot项目

1、环境搭建 前提条件&#xff1a;请自行安装docker以及docker-compose环境 version: 3 services:elasticsearch:image: elasticsearch:7.14.0container_name: elasticsearchports:- "9200:9200"- "9300:9300"environment:# 以单一节点模式启动discovery…

Git 配置BCompare工具

一、Git配置BCompare工具 1、安装BCompare工具 下载BCompare安装包&#xff0c;打开安装包直接安装即可&#xff0c;如下&#xff1a; 2、禁止BCompare访问网络 网络进出站进行配置&#xff0c;限制BCompare访问网络&#xff0c;如果不进行上网限制&#xff0c;可能存在被封的…

CloudCompare 点云工具

CloudCompare 点云工具 1. CloudCompare简介1.1 CloudCompare下载 2. CloudCompare安装 1. CloudCompare简介 CloudCompare 是一款开源的三维点云处理软件&#xff0c;它提供了一系列功能来处理、查看和分析三维点云数据。这个软件可以用于许多不同的应用领域&#xff0c;包括…

OKR应用层级与试点部门选择:管理层与员工层的应用探讨

OKR&#xff08;Objectives and Key Results&#xff09;作为一种高效的目标管理工具&#xff0c;其应用层级的选择对于企业的实施效果至关重要。在管理层和员工层之间&#xff0c;并没有绝对的先后顺序&#xff0c;而是需要根据企业的具体情况和需求进行灵活应用。同时&#x…

题目:【序列中删除指定数字】【变种水仙花数】【数组串联】【交换奇偶位】【offsetof宏的实现】

题目一:序列中删除指定数字 #include <stdio.h>int main(){int a0;int arr[50]{0};int c0;scanf("%d",&a);for(int i0;i<a;i){scanf("%d",&arr[i]);//输入a个值}scanf("%d",&c);//输入要删除的数据int i0;int j0;for(i0;i&…

简历模板100+套 (免费下载)

01、计算机02、大数据开发工程师03、测试工程师04、Java工程师05、行政专员06、人力资源主管07、市场专员08、人事专员09、银行、金融10、活动策划、人力资源11、医院、疾控、卫生12、外语翻译13、财务会计师14、产品开发15、服装设计师16、营销策划17、贸易外贸18、经济师19、…

端到端单倍型参考基因组揭示了三倍体香芽蕉型香蕉亚基因组的分歧和疾病抵抗力-文献精读-5

T2T基因组文献分享Telomere-to-telomere haplotype-resolved reference genome reveals subgenome divergence and disease resistance in triploid Cavendish banana 三倍体植物基因组的文献&#xff0c;各位同仁还有什么有特色的基因组评论区留言~ 摘要 香蕉是世界上最重要…

[图像处理] MFC载入图片并绘制ROI矩形

上一篇&#xff1a; [图像处理] MFC载入图片并进行二值化处理和灰度处理及其效果显示 文章目录 前言完整代码重要代码效果 前言 上一篇实现了MFC通过Picture控件载入图片。 这一篇实现ROI功能的第一部分&#xff0c;在Picture控件中&#xff0c;通过鼠标拖拽画出一个矩形。 完…

JavaScript高级应用

学习作用域、变量提升、闭包等语言特征&#xff0c;加深对 JavaScript 的理解&#xff0c;掌握变量赋值、函数声明的简洁语法&#xff0c;降低代码的冗余度。 理解作用域对程序执行的影响 能够分析程序执行的作用域范围 理解闭包本质&#xff0c;利用闭包创建隔离作用域 了解…

OpenFOAM学习笔记

OpenFOAM 计算流体力学&#xff1a;用计算机求解流体控制方程&#xff0c;来模拟真实情况下&#xff0c;流体的流动状态OpenFOAM的离散方法&#xff1a;有限体积法&#xff0c;将整个空间划分成若干个控制体OpenFOAM使用的网格系统&#xff1a;同位网格&#xff08;Collocated…

博客部署002-centos安装nginx

1、centos 如何安装nginx? 在CentOS系统上安装Nginx的过程相对直接&#xff0c;通常可以通过系统自带的Yum包管理器来安装。以下是安装Nginx的最新稳定版的步骤&#xff1a; 1.1 更新系统软件包 在安装Nginx之前&#xff0c;首先确保系统软件包是最新的&#xff0c;运行…

ES学习笔记01

1.ES安装 下载地址&#xff1a; es官网下载 这里使用的是7.8.0的版本信息 下载完成后解压即可完成安装 2.启动运行 点击bin目录下的elasticsearch.bat文件即可启动 在浏览器中输入localhost:9200显示如下&#xff1a; 在路径中加入对应访问后缀即可访问对应信息 如&#…