【C进阶】通讯录2.0(文末附原码)

news2024/9/29 11:25:16

⭐博客主页:️CS semi主页
⭐欢迎关注:点赞收藏+留言
⭐系列专栏:C语言进阶
⭐代码仓库:C Advanced
家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们的支持是我创作最大的动力,欢迎友友们私信提问,家人们不要忘记点赞收藏+关注哦!!!

通讯录2.0

  • 前言
  • 一、枚举
  • 二、动态内存
    • (一)更改初始化
    • (二)更改ADD
    • (三)销毁内存空间
    • (四)修改qsort函数
  • 三、文件操作(用fread和fwrite改造)
    • (一)EXIT退出函数
    • (二)InitContact初始化函数
  • 四、结果
  • 五、原码
  • 总结


前言

前面我们写了简单的通讯录,接下来我们将写进阶的通讯录,里面包含枚举,动态内存和文件的操作,是包含了所有进阶的知识,所以,跟着我的脚步,出发!!!


一、枚举

枚举有点很多,比较大的优点是可读性好,当我们进行选择1,2,……后,我们对于这串代码的含义并不明确,而如果直接用枚举显示出来这些名称直接用,可读性非常强,另一个优点是它是有自己本身的类型的,是有类型检查的。更加严谨。
所以,只需要改test.c中的代码即可:
在这里插入图片描述
在这里插入图片描述


二、动态内存

(一)更改初始化

我们在进行存放联系人信息的时候,我现在有15个朋友,那我设立那么长的空间长时间不用是不是浪费了这么大的空间,那我们现在想的是设立一个动态数组,默认第一次的空间是3个,然后每当不够的时候加2个,空间不够就往上加2个……那我们改造一下:
我们创建动态内存是需要进行结构体声明的,是需要在contact.h里面替换掉原本的Contact的结构体而变成如下图所示(contact.h):
在这里插入图片描述

在这里插入图片描述

是data所指向的那段另开辟的动态内存空间,为了方便我们使用capcity的作用,我们进行宏定义,将初始化定义为3和将每次自增二定义为2,如下图(在contact.h中):在这里插入图片描述
进行定义完这个数组以后,我们需要来对初始化通讯录进行改造,这里就用到了动态数组开辟的方法,为data开辟一块空间(在contact.c中),如下图:
在这里插入图片描述

挨个解释解释:
制作一个新的ptr指针,用来存放动态开辟的数组,类型肯定要和pc->data是一样的,因为这样才能实现将ptr首元素指针传给pc,因为ptr是用来维护pc指针的,是要看是不是空指针,至于calloc函数,那就直接上链接,大家去直接看下面博客关于calloc的详细讲解:动态内存 那当然了,为了不影响速度,那就简单介绍一下calloc,它是能够将它所维护的空间初始化为0,然后我们将capcity初始化为3即可。

(二)更改ADD

这是在contact.c中的,上完代码就一步步解释。
在这里插入图片描述

我们将这个动态开辟内存封装成一个函数,在函数内部,我们需要判断的是已经满容量了以后,我们需要做的操作,要增容怎么办,realloc解决一切烦恼,大家也可以看博客,也可以听我先简单陈述:内存函数 realloc函数的解释是pc->data是所需增加的空间,后面的是总的数(增加的空间加上原本的空间)。和前面一样的道理,和王者荣耀里面的元歌一样,分身先往前走,前面安全了再让真身走,前面有危险,分身消失,真身保持不变。

(三)销毁内存空间

我们在学习动态数组开辟的时候,是有free这个函数的,是释放开辟的空间的函数,而在制作这套通讯录的动态数组中,我们同样也需要来一个销毁这个动态内存的空间的操作,那我们就定义一个Destory函数吧!
test.c
在这里插入图片描述
contact.h
在这里插入图片描述
contact.c
在这里插入图片描述
这串代码总体来讲就是将这些值全部变为空或者0。

(四)修改qsort函数

我发现如果qsort函数一直是保持这样不变的话,是肯定不正确的,我通过调试和各项参考发现如果还按照老版本的qsort函数发现数据都给我吞了,和Empty函数怎么一样了,当即我就慌了神,但是经过一段时间的思考,&con本来就是在结构体内开辟的一个数组,已经是被维护的数组,而con.data是指向某一个数组,因为我们创立的的data是指向某一个数组的,所以就不能是&con了,需要找到data的数组。
在这里插入图片描述
到这里先给个整体的代码,下面将进行文件的操作,有很多改编不需要文件的操作那就这里先放一下动态数组的版本吧!
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("*******  7.empty   0.exit    *******\n");
	printf("************************************\n");
}

enum Option {
	EXIT,//0
	ADD, //1
	DEL, //2
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	EMPTY
};

int main()
{
	int input = 0;
	//创建通讯录
	Contact con;
	//初始化通讯录
	InitContact(&con);

	do {
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			Sleep(1000);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			Sleep(500);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT://&con
			qsort(con.data, con.sz, sizeof(con.data[0]), ContactSortName);
			printf("排序成功\n");
			Sleep(1000);
			break;
		case EMPTY:
			EmptyContact(&con);
			printf("已全部清空\n");
			Sleep(1000);
			break;
		case EXIT:
			Destory(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

contact.h

#define MAX 1000
#define NAMEMAX 20
#define SEWXMAX 5
#define ADDRMAX 30
#define TELEMAX 12

#define DEFAULTSZ 3
#define INCSZ 2

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

//人的信息
typedef struct PeoInfo {
	char name[NAMEMAX];
	int age;
	char sex[SEWXMAX];
	char addr[ADDRMAX];
	char tele[TELEMAX];
}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);

//排序
int ContactSortName(void* e1, void* e2);

//清空
void EmptyContact(Contact* pc);

//销毁通讯录内存
void Destory(Contact* pc);

contact.c

//负责实现声明

#include"contact.h"

静态版本
实现初始化通讯录
//void InitContact(Contact* pc) {
//	assert(pc);
//	pc->sz = 0;
//	memset(pc->data, 0, sizeof(pc->data));//传过来的是地址,根据地址找到了data数组,算的是data数组的总大小
//}

//动态版本
//实现初始化通讯录
void InitContact(Contact* pc) {
	assert(pc);
	pc->sz = 0;
	PeoInfo* ptr = (PeoInfo*)calloc(DEFAULTSZ,sizeof(PeoInfo) );
	if (ptr == NULL) {
		perror("calloc::InitContact");
		return;
	}
	pc->data = ptr;
	pc->capacity = DEFAULTSZ;
}

静态版本
增加联系人
//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].addr);
//	printf("请输入电话>");
//	scanf("%s", pc->data[pc->sz].tele);
//	pc->sz++;
//}

//动态版本
//增加联系人
void check_capacity(Contact* pc) {
	if (pc->sz == pc->capacity) {
		//增容
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + INCSZ));
		if (ptr == NULL) {
			perror("realloc::check_capacity");
			return;
		}
		pc->data = ptr;
		pc->capacity += INCSZ;
	}
}
void AddContact(Contact* pc) {
	assert(pc);
	check_capacity(pc);

	//增加一个人信息
	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].addr);
	printf("请输入电话>");
	scanf("%s", pc->data[pc->sz].tele);
	pc->sz++;
}


//显示通讯录里的信息
void ShowContact(const Contact* pc) {
	assert(pc);
	int i = 0;
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "name", "age", "sex", "address", "telephone");
	for (i = 0; i < pc->sz; i++) {
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].addr,
			pc->data[i].tele);
	}
}


int FindByName(const Contact* pc, char name[]) {
	assert(pc);
	int i = 0;
	int pos = 0;
	for (i = 0; i < pc->sz; i++) {
		if (strcmp(pc->data[i].name, name) == 0) {
			pos = i;
			return i;
		}
	}
	return -1;
}
//删除联系人
void DelContact(Contact* pc) {
	assert(pc);
	char name[NAMEMAX] = { 0 };
	//没有联系人不删除
	if (pc->sz == 0) {
		printf("通讯录为空,无法删除\n");
		return;
	}
	//删除联系人
	//找到要删除的人
	printf("请输入要删除的人的名字:>");
	scanf("%s", name);
	//查找
	int ret = FindByName(pc, name);
	if (-1 == ret) {
		printf("查无此人\n");
		return;
	}
	else {
		//删除
		int i = 0;
		for (i = ret; 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[NAMEMAX] = { 0 };
	printf("请输入要查找人的名字>");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (-1 == ret) {
		printf("查无此人\n");
		return;
	}
	else {
		//打印信息
		printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "name", "age", "sex", "address", "telephone");
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[ret].name,
			pc->data[ret].age,
			pc->data[ret].sex,
			pc->data[ret].addr,
			pc->data[ret].tele);
	}
}

//修改指定联系人
void ModifyContact(Contact* pc) {
	assert(pc);
	//先找这个联系人
	char name[NAMEMAX] = { 0 };
	printf("请输入要修改人的名字>");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (-1 == ret) {
		printf("查无此人\n");
		return;
	}
	else {
		//信息重新录入
		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].addr);
		printf("请输入电话>");
		scanf("%s", pc->data[ret].tele);
		printf("修改完成\n");
	}
}

//排序
int ContactSortName(void* e1, void* e2) {
	assert(e1 && e2);
	return strcmp((Contact*)e1, (Contact*)e2);
}

//清空
void EmptyContact(Contact* pc) {
	assert(pc);
	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));
}

//销毁通讯录内存
void Destory(Contact* pc) {
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
	pc = NULL;
}

三、文件操作(用fread和fwrite改造)

(一)EXIT退出函数

既然我们要大刀阔斧地朝向代码进行改编,势必要把它放到文件里面,那就我文件执行完我再放吧,这毕竟我立马存到文件里面万一之后要删删改改呢?所以我们在EXIT函数进行增加添加文件项:
test.c:
在这里插入图片描述

contact.c:
首先我们需要在相对应的文件夹中创立一个好取名字的文件名并在contact.c文件中进行引用,这里选择的是fwrite,是因为在计算机中写的是二进制的“流”,更加的好用。
在这里插入图片描述
在这里插入图片描述

这里是需要认清楚fwrite函数的用法,大家可以看下面这篇博客:
文件操作简单而言就是找到数组地址,字节长度,元素个数,文件流。

(二)InitContact初始化函数

contact.c:
在这里插入图片描述
我们读到文件里面需要加载文件信息到通讯录,我们直接封装一个函数进行操作(还在contact.c):

在这里插入图片描述
这里形式有些许复杂,我们需要了解清楚fread函数的具体作用,再根据增容的变化值进行读数据。


四、结果

这是添加完的操作:
在这里插入图片描述
这是退出通讯录,保存完文件的操作:
在这里插入图片描述
这是再次打开调试台显示数据被保存的操作:
在这里插入图片描述

五、原码

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("*******  7.empty   0.exit    *******\n");
	printf("************************************\n");
}

enum Option {
	EXIT,//0
	ADD, //1
	DEL, //2
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	EMPTY
};

int main()
{
	int input = 0;
	//创建通讯录
	Contact con;
	//初始化通讯录
	InitContact(&con);

	do {
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			Sleep(1000);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			Sleep(500);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT://&con
			qsort(con.data, con.sz, sizeof(con.data[0]), ContactSortName);
			printf("排序成功\n");
			Sleep(1000);
			break;
		case EMPTY:
			EmptyContact(&con);
			printf("已全部清空\n");
			Sleep(1000);
			break;
		case EXIT:
			//保存通讯录信息到文件中
			SaveContact(&con);
			Destory(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

contact.h

#define MAX 1000
#define NAMEMAX 20
#define SEWXMAX 5
#define ADDRMAX 30
#define TELEMAX 12

#define DEFAULTSZ 3
#define INCSZ 2

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

//人的信息
typedef struct PeoInfo {
	char name[NAMEMAX];
	int age;
	char sex[SEWXMAX];
	char addr[ADDRMAX];
	char tele[TELEMAX];
}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);

//排序
int ContactSortName(void* e1, void* e2);

//清空
void EmptyContact(Contact* pc);

//销毁通讯录内存
void Destory(Contact* pc);

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

//加载文件信息到通讯录
void LoadContact(Contact* pc);

contact.c

//负责实现声明

#include"contact.h"

静态版本
实现初始化通讯录
//void InitContact(Contact* pc) {
//	assert(pc);
//	pc->sz = 0;
//	memset(pc->data, 0, sizeof(pc->data));//传过来的是地址,根据地址找到了data数组,算的是data数组的总大小
//}

//动态版本
//实现初始化通讯录
void InitContact(Contact* pc) {
	assert(pc);
	pc->sz = 0;
	PeoInfo* ptr = (PeoInfo*)calloc(DEFAULTSZ, sizeof(PeoInfo));
	if (ptr == NULL) {
		perror("calloc::InitContact");
		return;
	}
	pc->data = ptr;
	pc->capacity = DEFAULTSZ;

	//加载文件信息到通讯录
	LoadContact(pc);
}

静态版本
增加联系人
//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].addr);
//	printf("请输入电话>");
//	scanf("%s", pc->data[pc->sz].tele);
//	pc->sz++;
//}

//动态版本
//增加联系人
void check_capacity(Contact* pc) {
	if (pc->sz == pc->capacity) {
		//增容
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + INCSZ));
		if (ptr == NULL) {
			perror("realloc::check_capacity");
			return;
		}
		pc->data = ptr;
		pc->capacity += INCSZ;
	}
}
void AddContact(Contact* pc) {
	assert(pc);
	check_capacity(pc);

	//增加一个人信息
	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].addr);
	printf("请输入电话>");
	scanf("%s", pc->data[pc->sz].tele);
	pc->sz++;
}


//显示通讯录里的信息
void ShowContact(const Contact* pc) {
	assert(pc);
	int i = 0;
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "name", "age", "sex", "address", "telephone");
	for (i = 0; i < pc->sz; i++) {
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].addr,
			pc->data[i].tele);
	}
}


int FindByName(const Contact* pc, char name[]) {
	assert(pc);
	int i = 0;
	int pos = 0;
	for (i = 0; i < pc->sz; i++) {
		if (strcmp(pc->data[i].name, name) == 0) {
			pos = i;
			return i;
		}
	}
	return -1;
}
//删除联系人
void DelContact(Contact* pc) {
	assert(pc);
	char name[NAMEMAX] = { 0 };
	//没有联系人不删除
	if (pc->sz == 0) {
		printf("通讯录为空,无法删除\n");
		return;
	}
	//删除联系人
	//找到要删除的人
	printf("请输入要删除的人的名字:>");
	scanf("%s", name);
	//查找
	int ret = FindByName(pc, name);
	if (-1 == ret) {
		printf("查无此人\n");
		return;
	}
	else {
		//删除
		int i = 0;
		for (i = ret; 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[NAMEMAX] = { 0 };
	printf("请输入要查找人的名字>");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (-1 == ret) {
		printf("查无此人\n");
		return;
	}
	else {
		//打印信息
		printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "name", "age", "sex", "address", "telephone");
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[ret].name,
			pc->data[ret].age,
			pc->data[ret].sex,
			pc->data[ret].addr,
			pc->data[ret].tele);
	}
}

//修改指定联系人
void ModifyContact(Contact* pc) {
	assert(pc);
	//先找这个联系人
	char name[NAMEMAX] = { 0 };
	printf("请输入要修改人的名字>");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (-1 == ret) {
		printf("查无此人\n");
		return;
	}
	else {
		//信息重新录入
		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].addr);
		printf("请输入电话>");
		scanf("%s", pc->data[ret].tele);
		printf("修改完成\n");
	}
}

//排序
int ContactSortName(void* e1, void* e2) {
	assert(e1 && e2);
	return strcmp((Contact*)e1, (Contact*)e2);
}

//清空
void EmptyContact(Contact* pc) {
	assert(pc);
	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));
}

//销毁通讯录内存
void Destory(Contact* pc) {
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
	pc = NULL;
}

//保存通讯录中的信息到文件中
void SaveContact(Contact* pc) {
	assert(pc);
	//写数据
	//打开文件
	FILE* pf = fopen("D:\\GITTE chuantimu\\test_1_24(【C进阶】文件操作3)\\contact.txt", "wb");
	if (NULL == pf) {
		perror("SaveContact::fopen");
		return;
	}
	else {
		//写数据
		int i = 0;
		for (i = 0; i < pc->sz; i++) {
			fwrite(&(pc->data[i]), sizeof(PeoInfo), 1, pf);
		}
		//关闭文件
		fclose(pf);
		pf = NULL;
		printf("保存数据成功\n");
	}
}

//加载文件信息到通讯录
void LoadContact(Contact* pc) {
	assert(pc);
	//读数据
	//1.打开文件
	FILE* pf = fopen("D:\\GITTE chuantimu\\test_1_24(【C进阶】文件操作3)\\contact.txt", "rb");
	if (pf == NULL) {
		perror("LoadContact::fopen");
		return;
	}
	else {
		//2.读数据
		PeoInfo tmp = { 0 };
		int i = 0;
		while (fread(&tmp, sizeof(PeoInfo), 1, pf)) {
			//增容
			check_capacity(pc);
			pc->data[i] = tmp;
			pc->sz++;
			i++;
		}
		fclose(pf);
		pf = NULL;
	}
}

总结

这次的改编算是比较完美了,但肯定还有美中不足的地方,就是排列可以更加多元化一些,如果仅仅是qsort排序是很方便但也需要体验不同的排序方式,总而言之,这就是最终的通讯录版本了~~


客官,来个三连支持一下吧!!!

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

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

相关文章

webpack搭建的React脚手架项目与vite进行兼容化开发

React项目兼容vite开发 问题描述 前言&#xff1a;之前在做Vue开发项目的过程中&#xff0c;是使用vite搭建的项目&#xff0c;不论是启动速度还是热更新&#xff0c;都非常的丝滑&#xff0c;可以极大弥补我电脑的短板&#xff0c;也提升了我的开发体验&#xff01;。 由于…

马帮对接打通金蝶云星空订单

马帮对接打通金蝶云星空获取订单列表接口与销售出库新增接口接入系统&#xff1a;马帮马帮ERP旗下有马帮ERP3.0、马帮ERP亚马逊专用版、马帮WMS仓储管理系统、马帮云仓、马帮TMS、跨境分销、马帮供应链SCM管理系统等产品&#xff0c;为跨境电商卖家提供高效管理方法和解决方案&…

【操作系统】—— 如何使用VMware虚拟机(带你快速了解)

&#x1f4dc; “作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴。 &#x1f341; 操作系统【带你快速了解】对于电脑来说&#xff0c;如果说…

java多态/类的组合2022023

多态 Java引用变量有两个类型&#xff1a;一个是编译时类型&#xff0c;一个是运行时类型。编译时类型由声明该变量时使用的类型决定&#xff0c;运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致&#xff0c;就可能出现所谓的多态&#xff08;Polymor…

LeetCode刷题复盘笔记—一文搞懂贪心算法之55. 跳跃游戏问题(贪心算法系列第四篇)

今日主要总结一下可以使用贪心算法解决的一道题目&#xff0c;55. 跳跃游戏 题目&#xff1a;55. 跳跃游戏 Leetcode题目地址 题目描述&#xff1a; 给定一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃的最大长…

Python流程控制语句之选择语句

前言 在生活中&#xff0c;我们总是要做出许多选择&#xff0c;程序也是一样。比如下面的例子&#xff1a; 如果输入的用户名和密码正确&#xff0c;提示登录成功&#xff0c;否则&#xff0c;提示登录失败。如果考试成绩大于等于60分&#xff0c;则及格&#xff0c;否则不及…

在甲骨文云容器实例(Container Instances)上部署firefox

甲骨文云推出了容器实例&#xff0c;这是一项无服务器计算服务&#xff0c;可以即时运行容器&#xff0c;而无需管理任何服务器。 今天我们尝试一下通过容器实例部署firefox。 Step1. 创建容器实例 在甲骨文容器实例页面&#xff0c;单击"创建容器实例"&#xff0c…

[漏洞分析] CVE-2022-2602 io_uring UAF内核提权详细解析

本文首发于华为安全应急响应中心公众号&#xff1a; https://mp.weixin.qq.com/s/w_u0FoiFdU0KM397UXJojw 文章目录漏洞简介环境搭建漏洞原理文件引用计数与飞行计数引用计数飞行计数发送过程scm_send接收过程unix_gc垃圾处理机制io_uring原理(仅限漏洞)io_uring_setupio_urin…

零基础学JavaWeb开发(十六)之 mybatis(2)

5、MyBatis - 映射文件标签 5.1、映射文件的顶级元素 select&#xff1a;映射查询语句 insert&#xff1a;映射插入语句 update&#xff1a;映射更新语句 delete&#xff1a;映射删除语句 sql&#xff1a;可以重用的 sql 代码块 resultMap&#xff1a;最复杂&#xff0c…

11. 集合set类型详解

python3 set类型的使用 1. 基础知识 &#xff08;1&#xff09; 集合&#xff08;set&#xff09;是由一个或数个形态各异的大小整体组成的&#xff0c;构成集合的事物或对象称作元素或是成员。集合是一个无序的不重复元素序列。 &#xff08;2&#xff09;基本功能是进行成员…

大年初四,Flutter Forward 中国社区直播活动与你不见不散

之前我们预告过&#xff0c;2023 年 1 月 25 日 (年初四)&#xff0c;Flutter 团队将在肯尼亚首都内罗毕举办 Flutter Forward 大会&#xff0c;并同时开启线上直播。本次活动将为展示最新的 Flutter 技术更新&#xff0c;包括一个主题演讲&#xff0c;以及多个技术演讲和线上问…

【兔年之兔子走迷宫】 用一个小游戏对回溯法进行实现 | C++

第六章 回溯法 目录 第六章 回溯法 ●前言 ●一、回溯法是什么&#xff1f; 1.简要介绍 ●二、回溯法经典案例——兔子走迷宫游戏 1.具体情况 2.代码展示&#xff08;C&#xff09; 3.结果展示 ●总结 前言 简单的来说&#xff0c;算法就是用计算机程序代码来实…

性能监控和工具使用

1、jvm 内存模型 程序计数器 Program Counter Register&#xff1a;  记录的是正在执行的虚拟机字节码指令的地址&#xff0c;  此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemoryError的区 域  虚拟机&#xff1a;VM Stack  描述的是 JAVA 方法执行的内…

Delphi 中.dproj 文件解析(二、详细解析)

上一篇 介绍了Delphi 的各个版本&#xff0c;本文开始分析.dproj文件。.dproj是一个XML文件&#xff0c;里边包含了我们在Delphi开发环境中对项目设置的所有参数&#xff08;位于IDE&#xff1a;Project -> Options 中&#xff09;&#xff0c;包括并不限于&#xff1a;版本…

LabVIEW查找范例VI

LabVIEW查找范例VILabVIEW拥有数百个范例VI&#xff0c;用户可搜索需要的范例VI并将其整合到自己创建的VI中。除LabVIEW内置的范例VI之外&#xff0c;在ni.com技术支持页中可查看更多的范例VI。用户可根据应用程序的需要对范例进行修改&#xff0c;也可复制并粘贴一个或多个范例…

LC-1824. 最少侧跳次(动态规划)

1824. 最少侧跳次数 难度中等49 给你一个长度为 n 的 3 跑道道路 &#xff0c;它总共包含 n 1 个 点 &#xff0c;编号为 0 到 n 。一只青蛙从 0 号点第二条跑道 出发 &#xff0c;它想要跳到点 n 处。然而道路上可能有一些障碍。 给你一个长度为 n 1 的数组 obstacles &a…

【FPGA】Verilog 实践:狄摩根定律 | 布尔方程 | 1bit 比较器

写在前面&#xff1a;为了解狄摩根定理和布尔函数的行为&#xff0c;我们使用 Verilog 实现狄摩根定律和布尔函数的行为。生成输入信号后&#xff0c;验证通过仿真实现的结果。 Ⅰ. 前置知识 0x00 离散结构&#xff1a;否定量词的狄摩根定律 否定量词的狄摩根定律是&#xf…

基于自适应降噪的深度神经网络对抗图像检测【论文阅读】

近年来&#xff0c;许多研究表明&#xff0c;深度神经网络(DNN)分类器可能会被对抗性示例所欺骗&#xff0c;这种对抗性示例是通过对原始样本引入一些扰动来设计的。据此&#xff0c;提出了一些强大的防御技术。然而&#xff0c;现有的防御技术往往需要修改目标模型或依赖于攻击…

针对容器场景的多功能渗透工具

介绍 CDK是一款为容器环境定制的渗透测试工具&#xff0c;在已攻陷的容器内部提供零依赖的常用命令及PoC/EXP。集成Docker/K8s场景特有的 逃逸、横向移动、持久化利用方式&#xff0c;插件化管理。 下载/植入 将可执行文件投递到已攻入的容器内部开始使用 https://github.c…

浏览器打不开某些网站是什么原因导致,试试用这些方法来解决

不少小伙伴使用一些浏览器浏览网页的时候&#xff0c;发现打不开某些网站&#xff0c;这是什么原因导致的呢?本文讲汇总几个常见的原因&#xff0c;我们可以通过以下几个原因排查&#xff0c;并且使用下文的解决方法可以试试能否打开网站。打不开网站的原因1、浏览器限制如果用…