通讯录的实现

> 作者简介:დ旧言~,目前大一,现在学习Java,c,c++,Python等
> 座右铭:松树千年终是朽,槿花一日自为荣。
> 望小伙伴们点赞👍收藏✨加关注哟💕💕 

🌟前言 

       当我们需要办一些业务时,需要录入我们的个人信息,我们的个人信息放在一个系统中,我们简称这个系统为通讯录,而这个通讯录可以存储我们的名字,性别,电话,地址....等等等。今天我们实现一个简单的通讯录。

 🌙主体

咱们需要建立一个项目,项目里面有test.c,Contact.h,Contact.c

其实这里contact.c是重点,咱们一个一个文件看看它们是如何实现的。

 🌠contact.h的实现

这个文件用来声明的,其中包括函数声明,包含头文件,实现动态通讯录,枚举的实现,定义元素类型。咱们逐个实现。

💤定义枚举和元素类型

定义枚举是为了方便使用switch,枚举第一个元素以0为起始位置。

//定义枚举,方便使用switch改变
enum OPTION
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,//3
	MODIFY,//4
	SHOW,//5
	SORT//6
};

通讯录需要存入的数据有名字,性别,电话,地址,因此来定义类型。

//宏定义
#define MAX 100//为静态通讯录服务
#define MAX_NAME 20//名字的最大值
#define MAX_SEX 5//性别的最大值
#define MAX_TELE 12//电话的最大值
#define MAX_ADDR 30//地址的最大值

#define DEFAULT_SZ 3//开始通讯录空间大小
#define INC_SZ 2//开辟空间数值大小

//定义通讯录所包含的元素类型
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

 这里用typedef来给结构体重新定义名字。

💤动态通讯录

正常我们写入的代码是这样的

//静态通讯录
//typedef struct Contact
//{
//	PeoInfo data[MAX];
//	int sz;
//}Contact;

这样就把通讯录写死了,当通讯录的空间不够时,无法实现扩容,因此我们需要一个动态的通讯录,而动态的通讯录有什么呢?

1.存放数据的空间(这里需要结构体指针,才能指向下一个元素(这里在动态内存管理已经讲解过了哟))

2.当前放的有效元素的个数

3.通讯录当前的最大容量

//动态通讯录
typedef struct Contact
{
	PeoInfo* data;//指向了存放数据的空间
	int sz;//记录的当前放的有效元素的个数
	int capacity;//通讯录当前的最大容量
}Contact;

💤函数声明

这里就直接上代码了,具体内容咱们到contact.c里面讲解

//函数声明

//初始化通讯录
void InitContact(Contact* pc);

//增加联系人
void AddContact(Contact* pc);

//显示所有联系人的信息
void ShowContact(const Contact* pc);

//删除指定联系人
void DelContact(Contact* pc);

//查找指定联系人
void SearchContact(const Contact* pc);

//修改指定联系人
void ModifyContact(Contact* pc);

//销毁通讯录
void DestroyContact(Contact* pc);

//保存通讯录信息到文件
void SaveContact(Contact* pc);

//排序
void SortContact(Contact* pc)

 🌠test.c的实现

       这里的内容和博主写的三子棋与扫雷极其相似,首先打印菜单,其次能实现循环(进行多次玩),最后根据自己选定内容进行不同的程序。

1.首先需要包含头文件,包含#include"contact.h"

2.其次写上简单的void  menu(),实现打印菜单

3.然后写上void test(),来实现通讯录的各种功能

4.最后写上主函数

#include"contact.h"

//续写菜单
void menu()
{
	printf("*******************************\n");
	printf("***** 1.add      2.del    *****\n");
	printf("***** 3.search   4.modify *****\n");
	printf("***** 5.show     6.sort   *****\n");
	printf("*****       0.exit        *****\n");
	printf("*******************************\n");
}

void test()
{
	//定义变量来实现输入
	int input = 0;
	
	//创建结构体
	Contact con;
	
	//初始化通讯录
	InitContact(&con);
	
	//循环
	do
	{
		//先打印菜单
		menu();

		printf("请选择->");
		scanf("%d", &input);

		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			//排序
			//按照名字排序?
			//按照年龄排序?
			break;
		case EXIT:
			SaveContact(&con);
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误, 重新选择\n");
			break;
		}
	} while (input);
}

//主函数
int main()
{
    //调用函数
	test();
	return 0;
}

 🌠contact.c的实现(重点)

       其实contact.c是通讯录的核心,也是通讯录最难的部分,咱们把这部分分成一块一块,一起来学习这部分。

💤初始化讯录

        如果我们写上静态版本的通讯录就无法实现录入多个用户信息,因此我们只能续写动态版本的通讯录。

💦1.需要为data(指向了存放数据的空间)开辟空间

💦2.判断data是否为空,防止在增删查找本身为空

💦3.对sz(记录的当前放的有效元素的个数)和capacity(通讯录当前的最大容量)初始化

💦4.保存在文件(调用函数,后面会讲解)

//静态版本
//void InitContact(Contact* pc)
//{
//	assert(pc);
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//}

//初始化通讯录(动态)
void InitContact(Contact* pc)
{
	//判断pc是否为空
	assert(pc);
	//开辟空间
	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo));
	//判断是否为空
	if (pc->data == NULL)
	{
		perror("InitContact");
		return 0;
	}
	//初始化
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	//文件中保存的信息加载到通讯录中
	LoadContact(pc);
}

 💤保存文件

这里因为还没讲到文件管理,大家就算看看啦。

void LoadContact(Contact* pc)
{
	//打开文件
	FILE* pf = fopen("contact.dat", "rb");
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
        //这里如果内存不足需要扩容
		if (0 == CheckCapacity(pc))
			return;
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

//保存通讯录信息到文件
void SaveContact(Contact* pc)
{
	FILE* pf = fopen("contact.dat", "wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写数据
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

 💤扩容

        当我们的内存不够时我们就需要括容。我们这里的sz(记录的当前放的有效元素的个数),等于capacity(通讯录当前的最大容量)时,就需要扩容。这里我们用realloc来开辟空间,做到对动态开辟内存大小的调整。

💦1.开辟空间,采用结构体指针来接收开辟的空间。

💦2.判断是否开好相应的空间。

💦3.赋值

//是否需要扩容
int CheckCapacity(Contact* pc)
{
	//判断sz是否等于capacity
	if (pc->sz == pc->capacity)
	{
		//开辟空间
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
		//判断
		if (ptr == NULL)
		{
			perror("CheckCapacity");
			return;
		}
		else
		{
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("增容成功\n");
			return 1;
		}
	}
}

 💤增加联系人

        这个函数我们已经熟清熟路了,这里我们只需注意sz(记录的当前放的有效元素的个数)需要++,因为需要指向下一个元素的位置

//增加联系人
void AddContact(Contact* pc)
{
	//断言
	assert(pc);
	//如果通讯录为空直接跳出循环
	if (CheckCapacity(pc) == 0)
	{
		return;
	}
	//输入
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);
	
    //当空间不够时需要扩容
	CheckCapacity(pc);
	
	//指向下个元素
	pc->sz++;
	printf("成功增加联系人\n");
}

 💤显示所有联系人的信息

这里和打印没啥区别,太简单了。

//显示所有联系人的信息
void ShowContact(const Contact* pc)
{
	//断言
	assert(pc);
	int i = 0;
	//打印列标题
	printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	//打印数据
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

💤删除指定联系人

       因为这里删除指定联系人和查找指定联系人都需要查找指定的人,因此我们这里直接再写一个函数,来遍历整个通讯录。

       我们采用向前覆盖的方式来删除指定联系人。这里和数据结构的重合了,大家有兴趣可以看看博主写的数据结构相关内容。

//查找元素下标
static int FindByName(const Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到了
		}
	}
	return -1;//找不到
}

//删除指定联系人
void DelContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[MAX_NAME] = { 0 };
	assert(pc);
	//删除
	printf("请输入要删除的人名字:>");
	scanf("%s", name);

	//找到要删除的人
	int del = FindByName(pc, name);
	if (del == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	int i = 0;
	//删除坐标位del的联系人(向前覆盖)
	for (i = del; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	
	//要向后退一个元素
	pc->sz--;

	printf("成功删除联系人\n");
}

 注意需要让sz(记录的当前放的有效元素的个数)--.

💤查找指定联系人

有了删除指定联系人的函数,实现这个函数太简单了。

//查找指定联系人
void SearchContact(const Contact* pc)
{
	//断言
	assert(pc);

	char name[MAX_NAME] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
		printf("要查找的人不存在\n");
	else
	{
		printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		//打印数据
		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}

💤修改指定联系人

有了删除指定联系人的函数,实现这个函数太简单了。

//修改指定联系人
void ModifyContact(Contact* pc)
{
	//断言
	assert(pc);

	char name[MAX_NAME] = { 0 };
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
		printf("要修改的人不存在\n");
	else
	{
		printf("请输入名字:>");
		scanf("%s", pc->data[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入性别:>");
		scanf("%s", pc->data[pos].sex);
		printf("请输入电话:>");
		scanf("%s", pc->data[pos].tele);
		printf("请输入地址:>");
		scanf("%s", pc->data[pos].addr);

		printf("修改成功\n");
	}
}

💤销毁通讯录

当我们不再使用通讯录了,就要释放内存,所有的元素置0。

//销毁通讯录
void DestroyContact(Contact* pc)
{
	//释放
	free(pc->data);
	//置为空和0
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

 💤排序

        这里我们就不得不提快排了,博主写过一篇关于快排的博客,大家可以仔细阅读一下,在这里我们就不再多多赘述了。

//排序
int cmp_s(const void* elem1, const void* elem2)
{
	return strcmp((char*)elem1, (char*)elem2);
}

void SortContact(Contact* pc)
{
	qsort(pc, pc->sz, sizeof(pc->data[0]), cmp_s);
	printf("%-10s\t%-5s\t%-10s\t%-5s\t%-10s\n", "姓名", "年龄", "电话", "性别", "地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-5d\t%-10s\t%-5s\t%-10s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].tele,
			pc->data[i].sex,
			pc->data[i].addr);
	}
}

 🌠整体代码

 💤contact.h

#pragma once

//包含头文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

//宏定义
#define MAX 100//为静态通讯录服务
#define MAX_NAME 20//名字的最大值
#define MAX_SEX 5//性别的最大值
#define MAX_TELE 12//电话的最大值
#define MAX_ADDR 30//地址的最大值

#define DEFAULT_SZ 3//开始通讯录空间大小
#define INC_SZ 2//开辟空间数值大小

//定义枚举,方便使用switch改变
enum OPTION
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,//3
	MODIFY,//4
	SHOW,//5
	SORT//6
};

//定义通讯录所包含的元素类型
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

//静态通讯录
//typedef struct Contact
//{
//	PeoInfo data[MAX];
//	int sz;
//}Contact;

//动态通讯录
typedef struct Contact
{
	PeoInfo* data;//指向了存放数据的空间
	int sz;//记录的当前放的有效元素的个数
	int capacity;//通讯录当前的最大容量
}Contact;

//函数声明

//初始化通讯录
void InitContact(Contact* pc);

//增加联系人
void AddContact(Contact* pc);

//显示所有联系人的信息
void ShowContact(const Contact* pc);

//删除指定联系人
void DelContact(Contact* pc);

//查找指定联系人
void SearchContact(const Contact* pc);

//修改指定联系人
void ModifyContact(Contact* pc);

//销毁通讯录
void DestroyContact(Contact* pc);

//保存通讯录信息到文件
void SaveContact(Contact* pc);

//排序
void SortContact(Contact* pc);

 💤test.c

#include"contact.h"

//续写菜单
void menu()
{
	printf("*******************************\n");
	printf("***** 1.add      2.del    *****\n");
	printf("***** 3.search   4.modify *****\n");
	printf("***** 5.show     6.sort   *****\n");
	printf("*****       0.exit        *****\n");
	printf("*******************************\n");
}

void test()
{
	//定义变量来实现输入
	int input = 0;
	
	//创建结构体
	Contact con;
	
	//初始化通讯录
	InitContact(&con);
	
	//循环
	do
	{
		//先打印菜单
		menu();

		printf("请选择->");
		scanf("%d", &input);

		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case EXIT:
			SaveContact(&con);
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误, 重新选择\n");
			break;
		}
	} while (input);
}

//主函数
int main()
{
	test();
	return 0;
}

 💤contact.c

#include"contact.h"

//静态版本
//void InitContact(Contact* pc)
//{
//	assert(pc);
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//}

//静态版本
//
//void AddContact(Contact* pc)
//{
//	assert(pc);
//	if (pc->sz == MAX)
//	{
//		printf("通讯录已满,无法添加\n");
//		return;
//	}
//
//	printf("请输入名字:>");
//	scanf("%s", pc->data[pc->sz].name);
//	printf("请输入年龄:>");
//	scanf("%d", &(pc->data[pc->sz].age));
//	printf("请输入性别:>");
//	scanf("%s", pc->data[pc->sz].sex);
//	printf("请输入电话:>");
//	scanf("%s", pc->data[pc->sz].tele);
//	printf("请输入地址:>");
//	scanf("%s", pc->data[pc->sz].addr);
//
//	pc->sz++;
//	printf("成功增加联系人\n");
//}

//是否需要扩容(声明函数)
int CheckCapacity(Contact* pc);

void LoadContact(Contact* pc)
{
	//打开文件
	FILE* pf = fopen("contact.dat", "rb");
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		if (0 == CheckCapacity(pc))
			return;
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

//初始化通讯录(动态)
void InitContact(Contact* pc)
{
	//判断pc是否为空
	assert(pc);
	//开辟空间
	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo));
	//判断是否为空
	if (pc->data == NULL)
	{
		perror("InitContact");
		return 0;
	}
	//初始化
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	//文件中保存的信息加载到通讯录中
	LoadContact(pc);
}

//是否需要扩容
int CheckCapacity(Contact* pc)
{
	//判断sz是否等于capacity
	if (pc->sz == pc->capacity)
	{
		//开辟空间
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
		//判断
		if (ptr == NULL)
		{
			perror("CheckCapacity");
			return;
		}
		else
		{
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("增容成功\n");
			return 1;
		}
	}
}

//增加联系人
void AddContact(Contact* pc)
{
	//断言
	assert(pc);
	//如果通讯录为空直接跳出循环
	if (CheckCapacity(pc) == 0)
	{
		return;
	}
	//输入
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);
	
	//CheckCapacity(pc);
	
	//指向下个元素
	pc->sz++;
	printf("成功增加联系人\n");
}

//显示所有联系人的信息
void ShowContact(const Contact* pc)
{
	//断言
	assert(pc);
	int i = 0;
	//打印列标题
	printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	//打印数据
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

//查找元素下标
static int FindByName(const Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到了
		}
	}
	return -1;//找不到
}

//删除指定联系人
void DelContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[MAX_NAME] = { 0 };
	assert(pc);
	//删除
	printf("请输入要删除的人名字:>");
	scanf("%s", name);

	//找到要删除的人
	int del = FindByName(pc, name);
	if (del == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	int i = 0;
	//删除坐标位del的联系人(向前覆盖)
	for (i = del; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	
	//要向后退一个元素
	pc->sz--;

	printf("成功删除联系人\n");
}

//查找指定联系人
void SearchContact(const Contact* pc)
{
	//断言
	assert(pc);

	char name[MAX_NAME] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
		printf("要查找的人不存在\n");
	else
	{
		printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		//打印数据
		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}

//修改指定联系人
void ModifyContact(Contact* pc)
{
	//断言
	assert(pc);

	char name[MAX_NAME] = { 0 };
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
		printf("要修改的人不存在\n");
	else
	{
		printf("请输入名字:>");
		scanf("%s", pc->data[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入性别:>");
		scanf("%s", pc->data[pos].sex);
		printf("请输入电话:>");
		scanf("%s", pc->data[pos].tele);
		printf("请输入地址:>");
		scanf("%s", pc->data[pos].addr);

		printf("修改成功\n");
	}
}

//销毁通讯录
void DestroyContact(Contact* pc)
{
	//释放
	free(pc->data);
	//置为空和0
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

//保存通讯录信息到文件
void SaveContact(Contact* pc)
{
	FILE* pf = fopen("contact.dat", "wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写数据
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

//排序
int cmp_s(const void* elem1, const void* elem2)
{
	return strcmp((char*)elem1, (char*)elem2);
}

void SortContact(Contact* pc)
{
	qsort(pc, pc->sz, sizeof(pc->data[0]), cmp_s);
	printf("%-10s\t%-5s\t%-10s\t%-5s\t%-10s\n", "姓名", "年龄", "电话", "性别", "地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-5d\t%-10s\t%-5s\t%-10s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].tele,
			pc->data[i].sex,
			pc->data[i].addr);
	}
}

🌟结束语

今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小说手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

 

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

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

相关文章

LED电子显示屏信号传输方式

LED电子显示屏广泛应用在休闲文化广场、繁华商贸中心、商业街、火车站、地铁、商场、等场所。由于其应用领域的多样性、复杂性&#xff0c;对音视频信号传输的稳定、可靠、流畅性也提出了更高的要求。单屏播放&#xff0c;亦或是组网联播等场合下全彩LED显示屏的信号采用的传输…

独立站SEO是什么意思?自主网站SEO的含义?

什么是独立站SEO优化&#xff1f;自建站搜索引擎优化是指什么&#xff1f; 独立站SEO&#xff0c;作为网络营销的重要一环&#xff0c;正在逐渐引起人们的关注。在当今数字化时代&#xff0c;独立站已经成为许多企业、个人宣传推广的首选平台之一。那么&#xff0c;究竟什么是…

C++对象模型实验(clang虚函数表结构)

摘要&#xff1a;本科期间有对比过msvc&#xff0c;gcc&#xff0c;clang的内存布局&#xff0c;距今已经6-7年了&#xff0c;当时还是使用的c11。时间过得比较久了&#xff0c;这部分内容特别是内存对齐似乎C17发生了一些变化&#xff0c;因此再实践下C类模型。本文描述了C不同…

docker优点简介和yum方式安装

一.docker简介 二.docker的优点 1.交付和部署速度快 2.高效虚拟化 3.迁移性和扩展性强 4.管理简单 三.docker的基本概念 1.镜像 2.容器 3.仓库 四.docker的安装部署 &#xff08;1&#xff09;点击容器 ​&#xff08;2&#xff09;选择docker-ce&#xff0c;根据相…

[C语言]分支语句和循环语句

[C语言]分支语句和循环语句 文章目录 [C语言]分支语句和循环语句C语言语句分类分支语句if语法结构else的匹配规则switch语句switch语句中的breakswitch语句中default 循环语句while循环while循环中的break和continuefor循环for循环中的break和continuefor循环的变种do while循环…

【腾讯云Cloud Studio实战训练营】用Vue+Vite快速构建完成交互式3D小故事

&#x1f440;前置了解&#xff1a;(官网 https://cloudstudio.net/) 什么是Cloud Studio&#xff1f; Cloud Studio 是基于浏览器的集成式开发环境&#xff08;IDE&#xff09;&#xff0c;为开发者提供了一个永不间断的云端工作站。用户在使用 Cloud Studio 时无需安装&#…

refresh大揽

注意在每一步大操作之前都有一个前期准备 prepareRefresh&#xff08;&#xff09; 设置spring启动的时间 设置spring关闭和开启的标志位 获取环境对象&#xff0c;并设置一些属性值&#xff0c;是系统环境的不是xml设置的 设置监听器&#xff0c;以及需要发布事件的集合。 Con…

浅析Java设计模式之四策略模式

title: 浅析Java设计模式之四策略模式 date: 2018-12-29 17:26:17 categories: 设计模式 description: 浅析Java设计模式之四策略模式 1. 目录 1. 目录2. 概念 2.1. 应用场景2.2. 优缺点 2.2.1. 优点2.2.2. 缺点 3. 模式结构4. 样例 4.1. 定义策略4.2. 定义具体策略4.3. 定义…

【自动电压调节器】无功功率控制的终端电压控制研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【IMX6ULL驱动开发学习】07.驱动程序分离的思想之平台总线设备驱动模型和设备树

一、驱动程序分离的思想 【IMX6ULL驱动开发学习】05.字符设备驱动开发模板&#xff08;包括读写函数、poll机制、异步通知、定时器、中断、自动创建设备节点和环形缓冲区&#xff09;_阿龙还在写代码的博客-CSDN博客 之前编写驱动程序的代码存在不少弊端&#xff1a;移植性差…

Redis从基础到进阶篇(一)

目录 一、了解NoSql 1.1 什么是Nosql 1.2 为什么要使用NoSql 1.3 NoSql数据库的优势 1.4 常见的NoSql产品 1.5 各产品的区别 二、Redis介绍 2.1什么是Redis 2.2 Redis优势 2.3 Redis应用场景 2.4 Redis下载 三、Linux下安装Redis 3.1 环境准备 3.2 Redis的…

广告牌安全传感器,实时监测事故隐患尽在掌握

在现代城市中&#xff0c;广告牌作为商业宣传的重要媒介&#xff0c;已然成为城市中一道独特的风景线。然而&#xff0c;随着城市迅速发展&#xff0c;广告牌的安全问题也引起了大众关注。广告招牌一般悬挂于建筑物高处&#xff0c;量大面大。由于设计、材料、施工方法的缺陷&a…

windows电脑系统自带的画图工具如何实现自由拼图

1.首先选中你要拼接的第一张图片&#xff0c;右键选着编辑&#xff0c;会自动打开自带的画图工具 然后就是打开第一张图片&#xff0c;如下图所示 接着就是将画布托大&#xff0c;如下图所示。 然后点击选择&#xff0c;选择下面的空白区域&#xff0c;选着区域的范围要比准备拼…

企微配置回调服务

1、企微配置可信域名 2、企微获取成员userID 3、企微获取用户敏感数据 4、企微配置回调服务 文章目录 一、简介1、概述2、相关文档地址 二、企微配置消息服务器1、配置消息接收参数2、参数解析3、参数拼接规则 三、代码编写—使用已有库1、代码下载2、代码修改3、服务代码编写 …

阿里云轻量应用服务器和云服务器有什么区别?2023更新

阿里云轻量应用服务器和云服务器ECS有什么区别&#xff1f;ECS是专业级云服务器&#xff0c;轻量应用服务器是轻量级服务器&#xff0c;轻量服务器使用门槛更低&#xff0c;适合个人开发者或中小企业新手使用&#xff0c;可视化运维&#xff0c;云服务器ECS适合集群类、高可用、…

gor工具http流量复制、流量回放,生产运维生气

gor是一款流量复制回放工具&#xff0c;gor工具的官网&#xff1a;https://goreplay.org/ 1、对某个端口的http流量进行打印 ./gor --input-raw :8000 --output-stdout 2、对流量实时转发&#xff0c;把81端口流量转发到192.168.3.221:80端口 ./gor --input-raw :81--output-ht…

Qt+Pyhton实现麒麟V10系统下word文档读写功能

目录 前言1.C调用python1.1 安装Python开发环境1.2 修改Qt工程配置1.3 初始化Python环境1.4 C 调用Python 函数1.5 常用的Python接口 2.python虚拟环境2.1Python虚拟环境简介2.2 virtualenv 安装及使用2.3 在C程序中配置virtualenv 虚拟环境 3.python-docx库的应用4.总结 前言 …

基于YOLOv8模型和PCB电子线路板缺陷目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8模型PCB电子线路板缺陷目标检测系统可用于日常生活中检测与定位PCB线路板瑕疵&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检…

panda3d加载模型复习和python面向对象编程属性学习

运行一个python示例&#xff1b;然后去除一些代码&#xff0c;只剩下加载模型相关&#xff0c;如下&#xff1b; from panda3d.core import loadPrcFileData # Configure the parallax mapping settings (these are just the defaults) loadPrcFileData("", "p…

Vue.js知识点学习的一点笔记

一、虚拟DOM 1、原生JS是命令式编程&#xff0c;当渲染在页面的数据发生一点点变化&#xff0c;需要整个重新渲染一编。vue.js渐进式框架有个虚拟DOM的概念&#xff0c;运用diff算法&#xff0c;比较新旧数据&#xff0c;相同的数据不变不重渲染&#xff0c;不同的部分新数据覆…