动态通讯录(并不难都能拿下)

请添加图片描述

文章目录

  • 🚀前言
  • 🚀通讯录
    • 实现动态通讯录的初期准备
    • 模块化框架搭建
  • 🚀实现接口函数

🚀前言

铁子们好啊!今天咱们来整一个有意思的玩意——通讯录,相信大家对通讯录并不陌生,那接下来就跟着阿辉把它拿捏了😉

🚀通讯录

实现动态通讯录的初期准备

铁子们都知道通讯录是用来存放联系人信息的,首先我们得定义一个结构体来描述联系人的各项特征,比如:姓名、年龄、性别、电话号、地址等。

#define NAME_MAX 20 //姓名
#define SEX_MAX 5 //性别
#define TELE_MAX 12 //电话
#define ADDR_MAX 30 //地址
//联系人信息
typedef struct people
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char numb[TELE_MAX];
	char addr[ADDR_MAX];
}peo;//重定义

对于通讯录这种数据我们可以通过下面这样的结构体来实现:

//通讯录
typedef struct contact
{
	peo* data;
	int size;//记录管理联系人个数
	int capacity;//记录通讯录容量
}contact;

实际上,上述通讯录的本质是一个顺序表,怎么理解呢?给铁子们上图👇
请添加图片描述
有了数组的首元素地址data、数组的元素个数size以及数组空间的大小capacity,我们可以轻易的管理数组中的元素以及数组的大小
对于通讯录我们要实现六大功能的接口函数:增加联系人信息、删除联系人信息、查找联系人信息、修改联系人信息、打印通讯录以及对通讯录信息排序。

不过为了实现用户和计算机的交互我们首先要实现一个菜单来供用户选择:

void menu()
{
	printf("------------------------------\n");
	printf("----     1.添加联系人     ----\n");
	printf("----     2.删除联系人     ----\n");
	printf("----     3.查找联系人     ----\n");
	printf("----     4.修改联系人     ----\n");
	printf("----     5.打印通讯录     ----\n");
	printf("----     6.排序通讯录     ----\n");
	printf("----     0.退出通讯录     ----\n");
	printf("------------------------------\n");
}

模块化框架搭建

有了以上的准备我们可以搭建出通讯录的框架,同样这里我们使用模块化的方式进行设计
通讯录分为test.c、contact.c两个源文件和contact.h一个头文件:

  • test.c:主函数接口引入

  • contact.c:函数功能的实现

  • contact.h:头文件引入、函数声明、结构体声明

contact.h头文件

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

#define NAME_MAX 20 //姓名
#define SEX_MAX 5 //性别
#define TELE_MAX 12 //电话
#define ADDR_MAX 30 //地址
//联系人信息
typedef struct people
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char numb[TELE_MAX];
	char addr[ADDR_MAX];
}peo;
//通讯录
typedef struct contact
{
	peo* data;
	int size;//管理联系人
	int capacity;//记录通讯录容量
}contact;

//接口函数实现通讯录各项功能
//增加联系人
void AddCon(contact* p);
//删除联系人
void DeteleCon(contact* p);
//查找联系人
void SearchCon(contact* p);
//修改联系人
void ModifyCon(contact* p);
//打印通讯录
void PrintCon(contact* p);
//释放通讯录内存
void DistroyCon(contact* p);
//给联系人排序
void SortCon(contact* p);

test.c源文件

#include"contact.h"
enum Op//使用枚举维护代码的可读性
{
	Exit,//0
	Add,//1
	Delete,//2
	Search,//3
	Modify,//4
	Print,//5
	sort,//6
};

void menu()//打印菜单
{
	printf("------------------------------\n");
	printf("----     1.添加联系人     ----\n");
	printf("----     2.删除联系人     ----\n");
	printf("----     3.查找联系人     ----\n");
	printf("----     4.修改联系人     ----\n");
	printf("----     5.打印通讯录     ----\n");
	printf("----     6.排序通讯录     ----\n");
	printf("----     0.退出通讯录     ----\n");
	printf("------------------------------\n");
}
	
int main()
{
	//声明通讯录变量con并初始化通讯录
	contact con = { NULL, 0, 0 };
	int input = 0;
	do {
		menu();
		printf("请选择要使用的功能:>");
		scanf("%d", &input);
		switch (input)
		{
		case Add:
			AddCon(&con);
				break;
		case Delete:
			DeteleCon(&con);
			break;
		case Search:
			SearchCon(&con);
			break;
		case Modify:
			ModifyCon(&con);
			break;
		case Print:
			PrintCon(&con);
			break;
		case sort:
			SortCon(&con);
			break;
		case Exit:
			DistroyCon(&con);//退出程序时释放内存
			break;
		default:
			printf("输入错误,请重新输入!\n");
		}
	} while (input);

	return 0;
}

🚀实现接口函数

有了上述的框架,我们只需要在contact.c源文件中实现各项功能的接口函数通讯录就完成了
添加联系人接口:

void AddCon(contact* p)
{
	if (p == NULL)//先判断传过来的指针是否为空
		return;//为空直接返回
	if (p->capacity == p->size)//判断容量与数组元素个数是否相等,相等说明数组该扩容了
	{
		//如果进来初始化数组还未分配空间,先让capacity+1
		if (p->capacity == 0)  p->capacity++;
		//然后使用realloc开辟空间,后续数组空间不够直接增加一倍原本空间,一举两得
		peo* pd = (peo*)realloc(p->data, sizeof(peo) * p->capacity);
		if (pd == NULL)//空间开辟失败直接返回
			return;
		p->data = pd;//把开辟空间的首地址赋给data
		p->capacity *= 2;//开辟完空间capacity倍增
	}
	printf("请输入姓名:>");
	scanf("%s", p->data[p->size].name);
	printf("请输入年龄:>");
	scanf("%d", &(p->data[p->size].age));
	printf("请输入姓别:>");
	scanf("%s", p->data[p->size].sex);
	printf("请输入电话:>");
	scanf("%s", p->data[p->size].numb);
	printf("请输入地址:>");
	scanf("%s", p->data[p->size].addr);
	printf("添加成功!\n");
	p->size++;//联系人添加成功size自增
}

删除指定联系人接口:
先遍历数组找到要删除的元素,后续我们的查找修改联系人都需要遍历数组进行查找,这里我们封装好一个函数check通过对比名字来实现
查找函数:

//这个函数我们使用static修饰,使其只能在源文件contact.c中使用
static int check(contact* p,char a[])
{
	int i = 0;
	for (i = 0; i < p->size; i++)
	{
		if (strcmp(a, p->data[i].name) == 0)
			break;//找到后跳出循环
	}
	if (i >= p->size)//i如果超出size说明数组中没有改联系人
		return -1;//返回-1
	return i;//找到则返回该联系人下标
}

删除指定联系人接口:
如何实现,铁子们看图
请添加图片描述

void DeteleCon(contact* p)
{
	if (p == NULL)//判断穿入指针是否为空
		return;
	if (p->size == 0)//看数组中是否有元素
	{
		printf("空的我删个锤子啊!\n");
		return;
	}
	char str[20] = {0};//输入要删除的联系人的姓名
	printf("请输入要删除联系人的名字:>");
	scanf("%s", str);
	int ret = check(p, str);//查找要删除联系人的下标
	if (ret == -1)
	{
		printf("查无此人!\n");
		return;
	}
	//上述图片的功能,至删除元素起后一个元素覆盖前一个元素
	for (int i = ret; i < p->size - 1; i++)
	{
		p->data[i] = p->data[i + 1];
	}
	printf("已成功删除!\n");
	p->size--;//size自减
}

查找指定联系人接口:
这个很简单

void SearchCon(contact* p)
{
	if (p == NULL)
		return;
	if (p->size == 0)
	{
		printf("空的我查个锤子!\n");
		return;
	}
	char str[20] = { 0 };
	printf("请输入要查找的联系人的名字:>");
	scanf("%s", str);
	int ret = check(p, str);//查找要找的联系人的下标
	if (ret == -1)
	{
		printf("查无此人!\n");
		return;
	}
	//打印要找的联系人的信息
	printf("%-15s	%-5d	%-8s	%-12s	%-20s\n",
		p->data[ret].name,
		p->data[ret].age,
		p->data[ret].sex,
		p->data[ret].numb,
		p->data[ret].addr);
}

修改指定联系人接口:
这个也很简单,找到后修改

void ModifyCon(contact* p)
{
	if (p == NULL)
		return;
	if(p->size == 0)
	{
		printf("空的我改个锤子!\n");
		return;
	}
	char str[20] = { 0 };
	printf("请输入要修改的联系人的名字:>");
	scanf("%s", str);
	int ret = check(p, str);//查找要找的联系人的下标
	if (ret == -1)
	{
		printf("查无此人!\n");
		return;
	}
	//修改联系人内容
	printf("请输入姓名:>");
	scanf("%s", p->data[ret].name);
	printf("请输入年龄:>");
	scanf("%d", &(p->data[ret].age));
	printf("请输入姓别:>");
	scanf("%s", p->data[ret].sex);
	printf("请输入电话:>");
	scanf("%s", p->data[ret].numb);
	printf("请输入地址:>");
	scanf("%s", p->data[ret].addr);
	printf("修改成功!\n");
}

打印联系人接口:
打印就更简单了

void PrintCon(contact* p)
{
	if (p == NULL)
		return;
	//下面这一行是为了便于观察
	printf("%-15s	%-5s	%-8s	%-12s	%-20s\n", "名字", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < p->size; i++)//遍历数组打印
	{
		printf("%-15s	%-5d	%-8s	%-12s	%-20s\n",
			p->data[i].name,
			p->data[i].age,
			p->data[i].sex,
			p->data[i].numb,
			p->data[i].addr);
	}
}

排序联系人接口:

//比较器,利用名字字典序排列
int cmp(const void* p1,const void* p2)
{
	return strcmp(((peo*)p1)->name, ((peo*)p2)->name);
}
void SortCon(contact* p)
{
	if (p == NULL)
		return;
	if (p->size < 2)//元素小于两个不需要排序
		return;
	//利用库函数qsort排序,得自己定义比较器
	qsort(p->data, p->size, sizeof(p->data[0]), cmp);
	printf("排序完成!\n");
}

释放通讯录空间接口:

void DistroyCon(contact* p)
{
	free(p->data);//释放动态内存
	p->data = NULL;//指针置空
	//下面变量置0
	p->size = 0;
	p->capacity = 0;
	printf("内存释放!\n");
}

到这里动态通讯录也是实现完成了,并不是很难相信大家都能轻易拿下,希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,你们的支持是我创作的最大动力🌹

请添加图片描述

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

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

相关文章

机械设备企业网站建设的效果如何

机械设备涵盖的类目比较广&#xff0c;其市场需求也是稳增不减&#xff0c;也因此无论大小企业都有增长的机会&#xff0c;当然这也需要靠谱的工具及正确的决策。 对机械设备企业来说&#xff0c;产品品质自然是首位&#xff0c;而向外打造品牌、扩展信息及拓客转化自然也是非…

HarmonyOS NEXT:技术革新与生态挑战的交汇点

背景 在上周&#xff08;2023年12月11日&#xff09;我有幸参加了在上海举办的华为鸿蒙生态学堂创新实训营。 参加这个活动的原因是近期关于华为的HarmonyOS NEXT不再兼容Android的消息&#xff0c;也就是说我们的Apk无法在纯血版的HarmonyOS NEXT上运行。 随后就是一些头部的…

opencv中叠加Sobel算子与Laplacian算子实现边缘检测

1 边缘检测介绍 图像边缘检测技术是图像处理和计算机视觉等领域最基本的问题&#xff0c;也是经典的技术难题之一。如何快速、精确地提取图像边缘信息&#xff0c;一直是国内外的研究热点&#xff0c;同时边缘的检测也是图像处理中的一个难题。早期的经典算法包括边缘算子方法…

windows10 php8连接sql server

一、环境安装 文章目录 一、环境安装1.安装php拓展2.在 Windows 上安装PHP驱动程序3.在 Windows 上安装ODBC驱动 二、php连接sqlserver三、注意事项数据库相关设置相关语法sqlsrv_fetch_array 的示例&#xff1a;sqlsrv_fetch 的示例&#xff1a;echo 和 print_r 的不同 所用资…

数据结构 | 查漏补缺之顺式存储和链式存储、如何评价哈希函数的好坏、链地址法、树的遍历、关键路径、完全图、连通图、迪杰斯特拉、b树

目录 顺式存储和链式存储 优缺点比较 顺序存储 ​编辑 链式存储 如何评价哈希函数的好坏 简述哈希查找中链地址法解决冲突的方法 树的遍历 关键路径 完全图 连通图 迪杰斯特拉 b树 特点&#xff1a; 插入&#xff08;索引不能大于&#xff1a;最大为 M-1 个&#…

TrustGeo代码理解(六)utils.py

代码链接:https://github.com/ICDM-UESTC/TrustGeo 一、导入常用库和模块 from __future__ import print_function from distutils.version import LooseVersion from matplotlib.scale import LogisticTransform import numpy as np import torch import warnings import t…

测序名词解释

测序深度&#xff08;Sequencing Depth&#xff09;是指&#xff1a;测序得到的碱基总量&#xff08;bp&#xff09;与基因组&#xff08;转录组或测序目标区域大小&#xff09;的比值&#xff0c;是评价测序量的指标之一。 测序深度的计算公式为&#xff1a; 测序深度 &…

Java数据结构-通过数组封装-结构分析

1、默认arrayList的数组未初始化&#xff0c;长度为0&#xff0c;容量默认是10 ArrayList<Integer> arrayList new ArrayList<>();System.out.println(ClassLayout.parseInstance(arrayList).toPrintable()); java.util.ArrayList object internals: OFF SZ …

【论文极速读】LVM,视觉大模型的GPT时刻?

【论文极速读】LVM&#xff0c;视觉大模型的GPT时刻&#xff1f; FesianXu 20231210 at Baidu Search Team 前言 这一周&#xff0c;LVM在arxiv上刚挂出不久&#xff0c;就被众多自媒体宣传为『视觉大模型的GPT时刻』&#xff0c;笔者抱着强烈的好奇心&#xff0c;在繁忙工作之…

威联通硬盘休眠后修改系统定时任务

按照网上一些教程&#xff0c;成功将威联通的机械硬盘设置了自动休眠。但是发现每天有多个整点硬盘会自动唤醒&#xff0c;怀疑是系统内置的定时任务触发了硬盘唤醒。 通过查看系统日志中事件和访问记录&#xff0c;判断出一些引发硬盘唤醒的自动任务&#xff0c;将这些定时任…

学习使用echarts漏斗图的参数配置和应用场景

学习使用echarts漏斗图的参数配置和应用场景 前言什么是漏斗图漏斗图的特点及应用场景漏斗图的特点漏斗图常见的的应用场景&#xff1a; echarts中漏斗的常用属性echart漏斗代码美化漏斗图样式1、设置标题字体大小2、设置标签样式3、设置漏斗图为渐变颜色4、设置高亮效果5、设置…

自动化测试(终章)webdriver的常用api(2)以及新的开始

目录 多层框架/窗口定位 多层框架的定位 frame是什么&#xff1f; 多层窗口定位 层级定位 使用 XPath 进行层级定位&#xff1a; 使用 CSS 选择器进行层级定位&#xff1a; 下拉框处理 alert、confirm、prompt 的处理 Alert 弹窗&#xff1a; Confirm 弹窗&#xff…

vue3 elementplus左侧无限级菜单

使用的组件是 element Plus Menu 菜单 注意&#xff1a;Menu 菜单属性参数可以自己配置 链接: Menu 菜单 //父级页面 <el-container><el-aside width"320px"><el-menuopen"handleOpen"close"handleClose":default-active"…

openmediavault debian linux安装配置企业私有网盘(三 )——raid5与btrfs文件系统无损原数据扩容

一、适用环境 1、企业自有物理专业服务器&#xff0c;一些敏感数据不外流时&#xff0c;使用openmediavault自建NAS系统&#xff1b; 2、在虚拟化环境中自建NAS系统&#xff0c;用于内网办公&#xff0c;或出差外网办公时&#xff0c;企业内的文件共享&#xff1b; 3、虚拟化环…

jmeter,http cookie管理器

Http Cookie管理器自动实现Cookie关联的原理&#xff1a; (默认:作用域在同级别的组件) 一:当Jmeter第1次请求服务器的时候,如果说服务器有通过响应头的Set-Cookie有返回Cookie,那么Http Cookie管理器就会自动的保存这些Cookie的值。 二&#xff1a;当Jmeter第2-N次请求服务器的…

PyQt6 QSpacerItem弹簧控件

锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计46条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话版…

【报错栏】(vue)Module not found: Error: Can‘t resolve ‘element-ui‘ in xxx

Module not found: Error: Cant resolve element-ui in xxx 报错原因是&#xff1a; 未安装 element-ui 依赖 解决&#xff1a; npm install element-ui 运行

生物信息学分析领域领先的特制语言环境NGLess(Next Generation Less)介绍、安装配置和详细使用方法

介绍 NGLess&#xff08;Next Generation Less&#xff09;是一种用于生物信息学分析的领先的领域特定语言&#xff08;DSL&#xff09;。它旨在简化和加速NGS&#xff08;Next Generation Sequencing&#xff09;数据的分析过程。NGLess具有清晰的语法和功能&#xff0c;使用户…

带你学C语言~指针(1)

Hello,CSDN的各位家人们&#xff0c;你们好啊&#xff01;今天&#xff0c;小赵要给大家分享的C语言知识是指针&#xff0c;相信不少家人们都或多或少被指针搞得晕头转向&#xff0c;小赵一开始也是&#xff0c;但后来小赵经过不断地努力学习&#xff0c;终于将这里面的知识弄懂…

线程的介绍

首先我们来了解一下线程是什么&#xff1a; 首先我们介绍一下程序是什么&#xff1f;程序就是我们编写的代码就叫程序&#xff0c;当我们程序运行的时候则称为进程&#xff0c;在我们现实生活中哪些用到了进程&#xff0c;就比如说我们qq&#xff0c;微信&#xff0c;百度网盘…