通讯录----顺序表版本

1.通讯录的实现逻辑

对于通讯录,我们做的无非就是初始化,销毁。添加联系人数据,修改联系人数据,删除联系人数据,查找联系人数据,展示联系人数据;

这个不就和我们的顺序表的逻辑如出一辙吗,顺序表实现的功能不就是数据的初始化,修改,删除(头删和尾删),添加(头插和尾插),顺序表的打印,这些我们是可以直接进行使用的;

我们的顺序表是整形的数据的删除,插入等等,那么我们的通讯录不是对整形数据进行相关的操作了,而是对联系人的信息进行相应的操作,我们把联系人及其相关的信息放到一个结构体里面,我们联系人的信息包括姓名性别年龄,电话以及地址这5项信息;

2.通讯录实现

(1)一些前期的准备

我们要在顺序表的基础上进行相应的操作,所以我们的解决方案在原来的seqlist.c---seqlist.h----test.c这三个基础上加上contact.c---contact.h这两个表示的是通讯录的源文件和头文件;

我们在通讯录的同文件里面定义结构体以及相关的函数的声明:

这里我们使用宏定义结构体里面数组(名字性别电话),方便我们对数组的大小进行相应的修改;

我们同时要把顺序表的头文件里面的int修改为我们联系人对应的结构体类型的数据,这个时候要包含通讯录对应的头文件;

通讯录的头文件要使用应该是对于顺序表进行初始化(实际上是对通讯录进行初始化),我们对顺序表进行初始化contactinit(sl* sl1),这个里面的sl就是我们的顺序表重定义之后的名字,sl1是形参,但是我们明明是要对通讯录进行初始化,参数确是顺序表这让人很难理解,我们于是写作contactinit(contact* con)这样就会很直观,但是两个头文件之间不能重复的包含,我们进行前置声明重定义:

因为我们的顺序表头文件里面的数据类型不是int ,我们的测试文件插入数据应该注释掉;顺序表的源文件里面打印整形数据,查找整形数据应该也注释掉,否则会报错

(2)通讯录的初始化和销毁

(3)添加联系人数据

我们定义一个结构体类型的变量:info把添加的信息写入到对应的成员里面去;

最后我们调用尾插函数插入到通讯录里面(也可以是头插函数);

(4)删除联系人数据

我们首先要判断删除的联系人是否存在,存在才能删除,不存在无法进行相应的操作;

我们后续进修改联系人数据的时候,也要进行判断我们想要修改的联系人是否存在,我们可以根据姓名进行判断是否存在,这个时候我们行定义一个函数fingbyname,因为是输入的联系人姓名和我们的通讯录里面的联系人姓名这两个字符串进行比较看是否相同,我们需要遍历整个通讯录,使用strcmp函数将我们输入的姓名和通讯录里面的姓名,进行比较,存在就返回0,不存在函数就返回-1;

我们最后是调用顺序表里面的slerase函数实现在指定的位置进行删除的操作,我们要传入通讯录和指定位置的下标;

(5)修改联系人数据

和删除的逻辑一样,先进行判断修改的联系人是否存在,调用findbyname函数根据返回值进行判断,最后输入新的联系人的相关的信息;

(6)查找联系人数据

和删除的逻辑一样,先进行判断查找的联系人是否存在,调用findbyname函数根据返回值进行判断,最后输出新的联系人的相关的信息;我们不使用展示是因为展示的是全部的,查找的时候只会展示我们想要查找的联系人的相关的信息,这个和展示的代码基本相同,只需要把数组对应的下标修改为我们的findbyname函数的返回值了;

(7)展示联系人数据

先打印表头栏目,在把我们的联系人的信息对应表头打印出来;

(8)项目的完善

作为一个项目,我们不能停留在测试功能上面,我们打印菜单栏,让用户可以自己选择相应的的功能进行实现,我们把所有的可以实现的功能放在菜单栏里面供用户进行选择:

我们的函数都已经实现了,所以设置switch循环的时候,直接调用就可以了;

3.完整代码

(1)seqlist.h

#pragma once
#include"contact.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef perinfo sldatatype;

typedef struct seqlist
{
	sldatatype* arr;
	int size;
	int capacity;
}sl;

//顺序表的初始化
void slinit(sl* ps);

//顺序表的销毁
void sldestory(sl* ps);

//顺序表的尾部插入数据
void slpushback(sl* ps, sldatatype x);

//顺序表的数组元素的打印
void slprint(sl s);

//顺序表的头部插入数据
void slpushfront(sl* ps, sldatatype x);

//顺序表的尾删
void slpopback(sl* ps);

//顺序表的头删
void slpopfront(sl* ps);

//顺序表的打印
void slprint(sl s);

//顺序表的指定插入
void slinsert(sl* ps, int pos, sldatatype x);

//顺序表的指定删除
void slerase(sl* ps, int pos);

//顺序表的数据的查找
int slfind(sl* ps, sldatatype x);

(2)seqlist.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"seqlist.h"
void check(sl* ps)
{
	if (ps->size == ps->capacity)
	{
		//我们插入数据,需要增大空间,动态内存开辟空间
		int newcapacity = ps->arr == 0 ? 4 : 2 * ps->capacity;
		sldatatype* temp = realloc(ps->arr, newcapacity * 2 * sizeof(sldatatype));
		if (temp == NULL)
		{
			perror("realloc");
			exit(1);//直接退出,不再继续执行
		}
		ps->arr = temp;
		ps->capacity = newcapacity;
	}
}
//顺序表的初始化
void slinit(sl* ps)
{
	ps->arr = NULL;
	ps->size = 0;
	ps->capacity = 0;
}
//顺序表的销毁
void sldestory(sl* ps)
{
	if (ps->arr != NULL)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}
//顺序表的尾部插入数据
void slpushback(sl* ps, sldatatype x)
{
	//对传进来的指针进行断言
	assert(ps);
	//判断数组大小和空间的容量是否相同
	check(ps);
	ps->arr[ps->size] = x;
	ps->size++;
}
//顺序表的头部插入数据
void slpushfront(sl* ps, sldatatype x)
{
	assert(ps);
	check(ps);
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}
//顺序表的打印
//void slprint(sl s)
//{
//	for (int i = 0; i < s.size; i++)
//	{
//		printf("%d ", s.arr[i]);
//	}
//	printf("\n");
//}
//顺序表的尾删
void slpopback(sl* ps)
{
	assert(ps);
	assert(ps->size);//如果我们顺序表本来就没有数据,我们进行减减就会变为-1了,显然不对,进行断言
	ps->size--;//渐渐就减少了范围,直接把最后的元素删除,就相当于最后一个元素不属于顺序表了
}
//顺序表的头删
void slpopfront(sl* ps)
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];//最后是arr[size-2]=arr[size-1];
	}
	ps->size--;
}

//顺序表的指定位置之前插入
void slinsert(sl* ps, int pos, sldatatype x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	check(ps);
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}

//顺序表的指定删除
void slerase(sl* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

//顺序表的数据的查找
//int slfind(sl* ps, sldatatype x)
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		//找到了
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	}
//	//没有找到
//	return -1;//无效的下标
//}

(3)contact.h

#pragma once
#define name_max 20
#define gender_max 10
#define tel_max 20
#define addr_max 20
typedef struct personinfo
{
	char name[name_max];
	char gender[gender_max];
	int age;
	char tel[tel_max];
	char addr[addr_max];
}perinfo;

typedef struct seqlist contact;
//通讯录初始化
void contactinit(contact* con);
//通讯录销毁
void contactdestory(contact* con);
//通讯录添加联系人数据
void contactadd(contact* con);
//通讯录删除联系人数据
void contactdel(contact* con);
//通讯录修改联系人数据
void contactmodify(contact* con);
//通讯录查找联系人数据
void contactfind(contact* con);
//通讯录展示联系人数据
void contactshow(contact* con);

(4)contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
#include"seqlist.h"
void contactinit(contact* con)
{
	slinit(con);
}

void contactdestory(contact* con)
{
	sldestory(con);
}

void contactadd(contact* con)
{
	perinfo 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);
}

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 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 contactfind(contact* con)
{
	char name[name_max];
	printf("请输入要查找的联系人的姓名:\n");
	scanf("%s", name);

	int find = findbyname(con, name);
	if (find < 0)
	{
		printf("要查找的联系人的数据不存在\n");
		return;
	}
	printf("查找成功\n");

	printf("%s  %s  %s  %s  %s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%s    %s    %d    %s    %s\n",
			con->arr[find].name,
			con->arr[find].gender,
			con->arr[find].age,
			con->arr[find].tel,
			con->arr[find].addr);
	}
}

void contactshow(contact* con)
{
	printf("%s  %s  %s  %s  %s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%s    %s    %d    %s    %s\n",
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].addr);
	}
}

(5)test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"seqlist.h"
//void sltest01()
//{
//	sl sl1;
//
//	//顺序表的初始化
//	slinit(&sl1);
//
//	//顺序表的尾部插入数据
//	slpushback(&sl1, 8);
//	slpushback(&sl1, 9);
//	slpushback(&sl1, 10);
//	slpushback(&sl1, 11);
//
//	//尾部插入之后打印
//	slprint(sl1);
//
//	//顺序表的头部插入数据
//	slpushfront(&sl1, 5);
//	slpushfront(&sl1, 6);
//
//	//头部插入之后打印
//	slprint(sl1);
//
//	//顺序表的尾删
//	slpopback(&sl1);
//	slprint(sl1);
//
//	//顺序表的头删
//	slpopfront(&sl1);
//	slprint(sl1);
//
//	//顺序表的指定位置之前插入
//	slinsert(&sl1, 1, 0);
//	slprint(sl1);
//
//	//顺序表的指定删除
//	slerase(&sl1, 1);
//	slprint(sl1);
//
//	//顺序表的数据的查找
//	int ret = slfind(&sl1, 100);
//	if (ret < 0)
//	{
//		printf("没有找到\n");
//	}
//	else
//	{
//		printf("找到了,下标是%d\n", ret);
//	}
//	//顺序表的销毁
//	sldestory(&sl1);
//}

//void contacttest01()
//{
//	contact con;
//	contactinit(&con);
//
//	contactadd(&con);
//	contactadd(&con);
//	contactshow(&con);
//
//	contactdel(&con);
//	contactshow(&con);
//
//	contactmodify(&con);
//	contactshow(&con);
//
//	contactfind(&con);
//
//
//	contactdestory(&con);
//}

void menu()
{
	printf("*************通讯录*************\n");
	printf("*****1、添加用户 2、删除用户****\n");
	printf("*****3、修改用户 4、查找用户****\n");
	printf("*****5. 展示用户 0.退出通讯录***\n");
	printf("********************************\n");
}
int main()
{
	//顺序表的功能测试函数
	//sltest01();
	/*contacttest01();*/
	int input = -1;
	contact con;
	contactinit(&con);
	do
	{
		menu();
		printf("请选择");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			contactadd(&con);
			break;
		case 2:
			contactdel(&con);
			break;
		case 3:
			contactmodify(&con);
			break;
		case 4:
			contactfind(&con);
			break;
		case 5:
			contactshow(&con);
			break;
		case 0:
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
	contactdestory(&con);
	return 0;
}

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

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

相关文章

docker安装nacos,单例模式(standalone),使用mysql数据库

文章目录 前言安装创建文件夹"假装"安装一下nacos拷贝文件夹删除“假装”安装的nacos容器生成nacos所需的mysql表获取mysql-schema.sql文件创建一个mysql的schema 重新生成新的nacos容器 制作docker-compose.yaml文件查看网站 前言 此处有本人写得简易版本安装&…

SQLite 查询优化器概述(九)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite中的隔离(八&#xff09; 下一篇&#xff1a;SQLite下一代查询规划器(十&#xff09; 1. 引言 本文档概述了查询规划器和优化器如何 用于 SQLite 工作。 给定一个 SQL 语句&#xff0c;可能有几十个、几百…

C++——位图和布隆过滤器

在C中&#xff0c;哈希这种思想的应用场景有很多&#xff0c;位图就是其中的一种。 位图 位图&#xff1a;位图是一种哈希思想的产物&#xff0c;可以通过它来对数据进行快速的查找的方法&#xff0c;在位图中&#xff0c;有2种状态来表示在或者不在&#xff0c;即1/0。 位图…

2024 年广东省职业院校技能大赛(高职组)“云计算应用”赛项样题 4

#需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件…

vue快速入门(八)绑定方法

注释很详细&#xff0c;直接上代码 上一篇 新增内容 v-if与button响应回顾事件方法写法 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, …

115.不同的子序列

给你两个字符串 s 和 t &#xff0c;统计并返回在 s 的 子序列 中 t 出现的个数&#xff0c;结果需要对 109 7 取模。 示例 1&#xff1a; 输入&#xff1a;s "rabbbit", t "rabbit" 输出&#xff1a;3 解释&#xff1a; 如下所示, 有 3 种可以从 s 中…

Coding and Paper Letter(八十八)

系列重启之CPL。 1 Coding: 1.一个Python库用来分析城市路网的工具箱&#xff0c;城市形态分析工具。 Madina 2.SkyPilot&#xff1a;在任何云上运行 LLM、AI 和 Batch。 通过简单的界面即可实现最大程度的节省性能、最高的 GPU 可用性和托管执行。 skypilot 3.探索美国卫…

寻找排序数组中的最小值

题目描述 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2]若旋转 7 次…

企业信息化建设之MCS/WCS的知识点精讲

0、背景: 近日,再做售前方案的时候,碰到WMS和WCS的对接的场景,有同事质疑MCS和WMS不会对接,其实大家在日常工作中碰到的都是一套系统, MCS和WCS都是指仓储控制系统,不过它们的应用场景和功能有所不同。 在制造业中,MCS系统主要负责全厂物料的搬送路径指派和管理…

whatsapp 语音通话基本实现(二)

Whatsapp VoiceCall 客户端通过websocket连接到服务器&#xff0c;客户端发起语音通话请求&#xff0c;并且完成必要的协商之后&#xff0c;就可以直接将语音数据发送给服务器&#xff0c;服务器接收到对方的语音数据之后也会通过websocket将语音数据转发给客户端。 websocke…

RuoYi-Vue若依框架-在框架内用颜色选择器,页面显示色块

在用若依框架进行二次开发的时候写到自己的一个模块&#xff0c;其中涉及到颜色&#xff0c;我就想着是手动输入还是采用颜色选择器呢&#xff0c;考虑到后续涉及到另一个字段编码于时就采用了颜色选择器&#xff0c;选择完的颜色显示的是十六进制的颜色选择器&#xff0c;这时…

Transformers in Vision:A Survey 阅读笔记

ACM上的一篇综述&#xff0c;讨论Transformer在CV上的应用。 摘要&#xff1a; Among their salient benefits,Transformers enable modeling long dependencies between inputsequence elements and support parallel processing of sequence as compared to recurrent networ…

深度剖析:网络安全中的红蓝对抗策略

红蓝对抗 红蓝对抗服务方案 在蓝队服务中&#xff0c;作为攻击方将开展对目标资产的模拟入侵&#xff0c;寻找攻击路径&#xff0c;发现安全漏洞和隐患。除获取目标系统的关键信息&#xff08;包括但不限于资产信息、重要业务数据、代码或管理员账号等&#xff09;外&#x…

【移动安全】对webview漏洞的一些分析

这次分析的app如下&#xff1a; 打开发现该app发现需要登录界面&#xff1a; 拖进jadx看一下&#xff0c;先来看一下AndroidManifest.xml文件 发现有两个类是导出&#xff0c;再来分析这两个类 这个RegistrationWebView类利用webview.loadUrl进行加载网页 java public class…

Vue基础知识:声明式导航——跳转传参,声明式导航有哪几种路由传值方式,查询参数传参语法,动态路由传参语法,两者的区别

在跳转路由时&#xff0c;进行传值 1.查询参数传参 1.语法格式如下&#xff1a; to"/path?参数名值" 2.对应页面组件接收传递过来的值 $route.query.参数名 案例演示&#xff1a; 此时点击“跳转并携带参数”这个链接&#xff0c;就会跳转到search这个页面并携带参…

SpringCloud学习(10)-SpringCloudAlibaba-Nacos服务注册、配置中心

Spring Cloud Alibaba 参考文档 Spring Cloud Alibaba 参考文档 nacos下载Nacos 快速开始 直接进入bin包 运行cmd命令&#xff1a;startup.cmd -m standalone 运行成功后通过http://localhost:8848/nacos进入nacos可视化页面&#xff0c;账号密码默认都是nacos Nacos服务注…

断网了,还能 ping 通 127.0.0.1 吗?

什么是127.0.0.1 什么是 ping TCP发数据和ping的区别 为什么断网了还能 ping 通 127.0.0.1 ping回环地址和ping本机地址有什么区别 127.0.0.1 和 localhost 以及 0.0.0.0 有区别吗 总结 你女神爱不爱你 &#xff0c;你问她&#xff0c;她可能不会告诉你。 但网通不通 &#xf…

CLCD 流水线发布SpringBoot项目

目录 一、流水线 1.1 点击进入流水线 1.2 新建流水线 二、添加流水线 三、构建上传和构建镜像 ​编辑 四、Docker部署 一、流水线 1.1 点击进入流水线 1.2 新建流水线 二、添加流水线 三、构建上传和构建镜像 在构建上传里添加一个步骤&#xff1a;构建镜像&#xff0c;这…

房企如何驱动新“三驾马车”,穿越地产周期?

今年以来&#xff0c;房地产行业在不确定性的周期中&#xff0c;逐渐显露出部分确定性。 今年两会期间&#xff0c;住建部明确指出&#xff0c;构建发展新模式是破解房地产发展难题的治本之策&#xff0c;在新模式下今后拼的是高质量、新科技、好服务。可以说&#xff0c;国家…

Android与RN远程过程调用的原理

Android与RN远程过程调用的原理是通过通信协议进行远程过程调用。RPC(Remote Procedure Call)是分布式系统常见的一种通信方式&#xff0c;从跨进程到跨物理机已经有几十年历史。 在React Native中&#xff0c;通信机制是一个C实现的桥&#xff0c;打通了Java和JS,实现了两者的…