首页 > 其他分享 >结构体应用--通讯录

结构体应用--通讯录

时间:2024-03-30 22:05:07浏览次数:40  
标签:name -- 联系人 pc Contact 通讯录 应用 printf data

在上一篇文章中我们详细讲解了自定义类型,这篇文章我们就使用结构体实现一个简单的通讯录。

数据的存储

通讯录要存储每个联系人的信息,每个联系人的信息又由姓名,年龄,性别,电话,地址这五个因素组成,所以我们首先要创建一个结构体类型来保存每个联系人的信息。我们在头文件中声明一个People的结构体。这样一个人的信息存储方式就有了,然后我们还需要创建一个结构体来存储我们的通讯录,通讯录首先要有一个数组,整个数组的每个成员都是People的,然后我们还需要一个count变量来记录联系人的总数,因为后续我们要显示结构体和排序结构体都要用到联系人数量。所以我们再声明一个结构体类型Contact,这个结构体有两个成员,一个结构体数组,长度为100,我们用#define来定义一个MAX表示联系人的最大数量,也就是我们的结构体的数组的大小,方便后续修改结构体数组大小,另一个成员变量是count用来记录联系人数量。

#pragma once

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

#define MAX 100
typedef struct People
{
	char name[20];
	int age;
	char sex[5];
	char tele[15];
	char address[20];
}People;

typedef struct Contact
{
	People data[MAX];
	size_t count;
}Contact;

菜单以及通讯录初始化

我们需要一个菜单来让用户选择要进行的操作,增删查改排序显示和退出,我们都要在菜单中显示出来,在用户进行操作之前,我们还要对体现了进行初始化,否则通讯录里面都是一些随机值,将count初始化为0;

#include"contact.h"

void Menu()
{
	printf("*******************************\n");
	printf("***** 1.Add      2.Delete *****\n");
	printf("***** 3.Search   4.Modify *****\n");
	printf("***** 5.Sort     6.Show   *****\n");
	printf("******0.Exit              *****\n");
	printf("*******************************\n");
}
void Init_Contact(Contact* pc)
{
	int i = 0;
	for (i = 0; i < MAX; i++)
	{
		*((pc->data[i]).name) = 0;
		(pc->data[i]).age = 0;
		*((pc->data[i]).sex) = 0;
		*((pc->data[i]).tele) = 0;
		*((pc->data[i]).address) = 0;
	}
	pc->count = 0;

}


int main()
{
	int input = 0;
	Contact contact;
	Init_Contact(&contact);
	do
	{
		Menu();
		printf("请选择_>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//增加联系人
			break;
		case 2:
			//删除联系人
			break;
		case 3:
			//查找联系人
			break;
		case 4:
			//修改联系人
			break;
		case 5:
			//排序联系人
			break;
		case 6:
			//显示联系人
			break;
		case 0:
			//退出
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,请重新选择:\n");
			break;
		}

	} while (input);

	return 0;
}

增加联系人

当用户选择增加联系人时,我们需要调用Add_Contact函数,在这个函数中,首先需要用户输入联系人的五项信息,如果增加成功,打印提示信息,如果容量满了,打印提示信息。

void Add_Contact(Contact* pc)
{
	assert(pc);
	if (pc->count <= MAX)
	{
		printf("请输入姓名:");
		scanf("%s", pc->data[pc->count].name);
		printf("请输入年龄:");
		scanf("%d", &(pc->data[pc->count].age));
		printf("请输入性别:");
		scanf("%s", pc->data[pc->count].sex);
		printf("请输入电话:");
		scanf("%s", pc->data[pc->count].tele);
		printf("请输入地址:");
		scanf("%s", pc->data[pc->count].address);
		(pc->count)++;
		printf("增加完成\n");
	}
	else
	{
		printf("联系人已满,请删除一些联系人\n");
	}
}

显示联系人

因为我们后面的的代码的测试都要显示联系人列表来观察,所以我们把这个函数实现在前面以便于我们测试程序是否正常运行。

显示联系人只需要我们循环打印count个联系人的信息出来就行了。

void Show_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("姓名          年龄    性别     电话          地址\n");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-15s %-5d %-5s %-15s %-20s\n", 
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele, 
			pc->data[i].address);
	}
}

查找联系人

因为在删除和修改联系人时我们也要用到查找联系人这个函数,所以我们先实现查找联系人。

查找联系人函数的设计我们采用按名字查找,然后遍历整个联系人列表,通过strcmp函数的返回值来判断是否是所查找的联系人,我们在这个函数可以给一个返回值,用于删除函数的使用,我们可以要查找返回联系人的下标。

//具体查找的函数
int Find_By_Name(Contact* pc, char* findname)
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(pc->data[i].name
			, findname) == 0)
		{
			//找到就直接返回
			return i;
		}
	}
	//遍历完了没有返回则说明找不到
	return -1;//返回-1表示找不到
}

//查找功能的函数
void  Search_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("请输入要查找的联系人姓名:");
	char search_name[20] = { 0 };
	scanf("%s", search_name);
	int ret = Find_By_Name(pc, search_name);
	if (ret == -1)
	{
		printf("找不到该联系人\n");
	}
	else
	{
		printf("%-15s %-5d %-5s %-15s %-20s\n",
			pc->data[ret].name,
			pc->data[ret].age,
			pc->data[ret].sex,
			pc->data[ret].tele,
			pc->data[ret].address);
	}
}

删除联系人

删除联系人的函数逻辑也十分简单,首先要通过前面的查找函数来找到要删除联系人的下标,然后从这个下标开始,后面的数据往前面覆盖,最末尾的一个数据我们可以删也可以不删,因为我们会让count-1,所以最末尾的那个数据无所谓。

void Delete_Contact(Contact* pc)
{
	assert(pc);
	char delete_name[20] = { 0 };
	printf("请输入要删除的联系人姓名:");
	scanf("%s", delete_name);
	int ret = Find_By_Name(pc,delete_name);
	if (ret == -1)
	{
		printf("找不到要删除的联系人\n");
	}
	else
	{
		int i = 0;
		for (i = ret; i < pc->count - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->count--;
		printf("删除成功\n");
	}
}

修改联系人

修改联系人的逻辑和删除联系人相同,先找到下标,再进行修改,修改就是让用户重新输入一个信息。

//修改联系人
void Modify_Contact(Contact* pc)
{
	assert(pc);
	if (pc->count == 0)
	{
		printf("当前无联系人\n");
		return;
	}
	char modify_name[20] = { 0 };
	printf("请输入要修改的联系人名字;");
	scanf("%s", modify_name);
	int ret = Find_By_Name(pc, modify_name);
	if (ret == -1)
	{
		printf("找不到该联系人\n");
	}
	else
	{
		printf("请重新输入修改后的联系人信息\n");
		printf("请输入姓名:");
		scanf("%s", pc->data[ret].name);
		printf("请输入年龄:");
		scanf("%d", &(pc->data[ret].age));
		printf("请输入性别:");
		scanf("%s", pc->data[ret].sex);
		printf("请输入电话:");
		scanf("%s", pc->data[ret].tele);
		printf("请输入地址:");
		scanf("%s", pc->data[ret].address);
		printf("修改完成\n");
	}
}

排序联系人

排序联系人这个函数我们可以用库里面的qsort函数来实现。

//qsort的比较函数,按名字排序
int cmp_by_name(const void* a, const void* b)
{
	assert(a && b);
	return strcmp( ((People*)a)->name, ((People*)b)->name);
}

//排序联系人
void Sort_Contact(Contact* pc)
{
	assert(pc);
	qsort(pc->data, pc->count, sizeof(People), cmp_by_name);
	printf("排序成功\n");
}

这样一个简单的通讯录就实现了,目前我们的通讯录联系人数量是固定的,而且每次退出程序后联系人的信息就销毁了,说明我们的通讯录还不是最终版本,后续更新完动态内存分配和文件操作后还会有两个升级的版本。

标签:name,--,联系人,pc,Contact,通讯录,应用,printf,data
From: https://blog.csdn.net/weixin_64099089/article/details/137081184

相关文章

  • [linux] ubuntu 下安装qtcreate遇到“无法加载Qt平台插件‘xcb’问题”解决方案
    [linux]ubuntu下安装qtcreate遇到“无法加载Qt平台插件‘xcb’问题”解决方案以下是遇到的三种报错情况From6.5.0,xcb-cursor0orlibxcb-cursor0isneededtoloadtheQtxcbplatformplugin.CouldnotloadtheQtplatformplugin“xcb”in“”eventhough......
  • spring多数据源动态切换的实现原理及实现
    AbstractRoutingDataSource是Spring框架中的一个抽象类,可以实现多数据源的动态切换和路由,以满足复杂的业务需求和提高系统的性能、可扩展性、灵活性。应用场景多租户支持:对于多租户的应用,根据当前租户来选择其对应的数据源,实现租户级别的隔离和数据存储。分库分表:为了提高性......
  • 【BlossomRPC】如何自定义一个RPC协议?
    文章目录如何设计一个RPC协议?RPC项目配置中心项目网关项目如何设计一个RPC协议?在上面的需求描述中我们知道,RPC非常重要的一环,就是自己制定符合自己需求的通信协议,这里,我简单的列出了我的协议。publicclassRpcHeaderimplementsSerializable{//publicst......
  • 【BlossomRPC】手把手教你写一个RPC协议
    文章目录新的开始什么是RPC?设计一个RPC需要些什么?新的开始经常会遇到一些项目,看着看着就发现看不懂文档了,也就是会出现一些跳过讲解的文章,使得自己很难了解某种中间件的开发全貌,所以想着自己先设计一个比较简易的RPC框架,在实现所有功能的前提下,向公司内部的技术分享......
  • 栈实现及其应用
    一、栈-顺序栈的原理1.1栈栈:限制在一端进行插入操作和删除操作的线性表(俗称堆栈)。栈顶:允许进行操作的一端称为“栈顶”。栈底:另一固定端称为“栈底”。空栈:当栈中没有元素时称为“空栈”。特点:后进先出(LIFO)。1.2栈的应用1、浏览器的前进后退功能:通过顺序栈......
  • Python之Opencv教程(2):图像边缘检测
    1、什么是边缘检测OpenCV中的边缘检测是一种常见的图像处理技术,用于检测图像中物体边缘的位置。常用的边缘检测算法包括Sobel算子、Scharr算子、Laplacian算子和Canny边缘检测算法等。下面将介绍使用OpenCV实现这些边缘检测算法的方法。2、边缘检测的作用边缘检测是图像......
  • 数据剑舞,图表如潮!Matplotlib傲视数据可视化江湖
    在代码的世界中,隐藏着一座神秘而神奇的画图殿堂,它就是Matplotlib。这座殿堂矗立在数据的海洋中,每一行代码都是一笔神奇的咒语,让数据在图像之间舞动,展现出无限可能。Matplotlib的大门上镶嵌着闪烁的彩虹宝石,每当有开发者走近,便散发出五彩斑斓的光芒,仿佛在诉说着这里的神秘。而在宫......
  • 前端应用开发实验:事件处理
    目录实验目的相关知识点实验内容购物车功能的拓展代码实现效果实验目的(1)熟练掌握v-on指令的用法,学会使用v-on指令监听DOM元素的事件,并通过该事件触发调用事件处理程序。(2)掌握v-on指令修饰符的基本用法。相关知识点(1)事件监听:使用v-on指令、事件处理方法......
  • auto-install-peers=true strict-peer-dependencies=false 这两个配置的作用是什么
    auto-install-peers=true和strict-peer-dependencies=false是与软件包管理器相关的配置选项,它们通常用于控制如何处理项目的依赖关系,特别是涉及到“peerdependencies”的情况。虽然您没有指明具体的包管理器(如npm、yarn等),但这些配置项的概念在许多包管理器中是通用的。下面是......
  • 2024/3/30 21点的lambda表达式
    packagecom.atguigu;interfaceMyInterface{intsum(inti,intj);}interfaceMyhaha{inthaha();}//检查注解,帮我们快速检查我们写的接口是否函数式接口@FunctionalInterfaceinterfaceMyhehe{inthehe(inti);}//1.自己写实现类classMyInetfaceI......