动态通讯录及程序保存在文件中

目录

一、结构体改造及增容函数

1.结构体部分

2.初始化函数及增容函数

二、信息添加及销毁和排序

1.信息添加函数(Add)

2.销毁函数(Destroy)

3.排序部分(qsort)

三、通讯录信息保存

1.保存在文件中(输出操作)

2.加载通讯录(输入操作)

四、整理通讯录

1.在菜单按0后退出程序

2.其他方式退出程序

3.打开程序就加载通讯录

4.完整通讯录代码


前言:这一次是在之前静态的通讯录基础上进行改造;变成动态通讯录,当空间不够时,可以完成自动增容,并且将通讯录中的信息保存在文件中,退出或关闭程序就不会再丢失数据。

先看静态通讯录的代码:

#define _CRT_SECURE_NO_WARNINGS 1

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

#define NAME_MAX 20
#define SEX_MAX 6
#define TELE_MAX 20
#define ADDR_MAX 20

#define MAX 100

typedef struct PeoInfo
{
	char name[NAME_MAX];//姓名
	char sex[SEX_MAX];//性别
	int age;//年龄
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//地址
}PeoInfo;

typedef struct contact
{
	PeoInfo data[MAX];//通讯录
	int sz;//记录通讯录的个数
}contact;

//函数的声明
//初始化
 void InitContact(contact* pc);

 //添加用户信息
 void AddContact(contact* pc);

 //打印通讯录
 void ShowContact(contact* pc);

 //删除联系人
 void DelContact(contact* pc);

 //查找某个联系人
 void SearchContact(contact* pc);

 //修改联系人
 void ModifyContact(contact* pc);

 //联系人排序
 void SortContact(contact* pc);

//函数功能的实现

void InitContact(contact* pc)
{
	assert(pc);
	memset(pc->data,0,sizeof(pc->data));
	pc->sz = 0;
}
void ShowContact(contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("%-10s %-5s %-10s %-15s %-10s\n","名字","性别","年龄","电话","住址");
	int i = 0;
	for (i=0;i<pc->sz;i++)
	{
		printf("%-10s %-5s %-10d %-15s %-10s\n",
			pc->data[i].name, pc->data[i].sex, pc->data[i].age,
			pc->data[i].tele, pc->data[i].addr);
	}
	printf("\n");
}

void AddContact(contact* pc)
{
	assert(pc);
	int adds;
		back:
		if (pc->sz == MAX)
		{
			printf("通讯录已满,存入信息失败\n");
			return;
		}

		printf("请输入姓名>:");
		scanf("%s", pc->data[pc->sz].name);
		printf("请输入性别>:");
		scanf("%s", pc->data[pc->sz].sex);
		printf("请输入年龄>:");
		scanf("%d", &(pc->data[pc->sz].age));
		printf("请输入电话>:");
		scanf("%s", pc->data[pc->sz].tele);
		printf("请输入住址>:");
		scanf("%s", pc->data[pc->sz].addr);
		pc->sz++;
		printf("信息添加成功\n");

		printf("是否继续添加联系人信息1/0:");
		scanf("%d",&adds);
		if (adds == 1)
			goto back;
		else
		{
			return;
		}
}
//查看某个联系人是否存在
static int FindContact(contact* pc,char name[])
{
	assert(pc);
	int i = 0;
	for (i=0;i<pc->sz;i++)
	{
		if (strcmp(name, pc->data[i].name) == 0)
			return i;
	}
	return -1;
}
//删除联系人
void DelContact(contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,删除失败\n");
		return;
	}
	printf("请输入你要删除的联系人:");
	char name[NAME_MAX];
	scanf("%s",name);
	int ret = FindContact(pc,name);
	if (ret == -1)
	{
		printf("联系人不存在,删除失败\n");
		return;
	}
	int i = 0;
	for (i=ret;i<pc->sz-1;i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功\n");
}
//查找联系人
void SearchContact(contact* pc)
{
	assert(pc);
	printf("请输入你要查找联系人的名字:");
		char name[NAME_MAX];
	scanf("%s", name);
	int ret = FindContact(pc, name);
	if (ret == -1)
	{
		printf("联系人不存在,查找失败\n");
		return;
	}
	printf("查找成功:\n");
	printf("%-10s %-5s %-10s %-15s %-10s\n", "名字", "性别", "年龄", "电话", "住址");
	printf("%-10s %-5s %-10d %-15s %-10s\n",
		pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age,
		pc->data[ret].tele, pc->data[ret].addr);
}
//修改联系人
void ModifyContact(contact* pc)
{
	assert(pc);
	printf("请输入你要查找联系人的名字:");
	char name[NAME_MAX];
	scanf("%s", name);
	int ret = FindContact(pc, name);
	if (ret == -1)
	{
		printf("联系人不存在,修改失败\n");
		return;
	}
	printf("联系人存在:");
	printf("%-10s %-5s %-10d %-15s %-10s\n",
		pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age,
		pc->data[ret].tele, pc->data[ret].addr);
	printf("请修改姓名>:");
	scanf("%s", pc->data[ret].name);
	printf("请修改性别>:");
	scanf("%s", pc->data[ret].sex);
	printf("请修改年龄>:");
	scanf("%d", &(pc->data[ret].age));
	printf("请修改电话>:");
	scanf("%s", pc->data[ret].tele);
	printf("请修改住址>:");
	scanf("%s", pc->data[ret].addr);
	printf("\n修改成功");
}
//分类菜单
void menu2()
{
	printf("*************************\n");
	printf("**** 1.名字   2.年龄 ****\n");
	printf("*************************\n");

}
//名字排序
int qsort_cmp_name(const void* e1,const void* e2)
{
	return strcmp((((contact*)e1)->data)->name, (((contact*)e2)->data)->name);
}
//年龄排序
int qsort_cmp_age(const void* e1,const void* e2)
{
	return (((contact*)e1)->data)->age - (((contact*)e2)->data)->age;
}
//联系人排序
void SortContact(contact* pc)
{
	int input2;
	menu2();
	printf("请选择排序方式:");
	scanf("%d",&input2);
	switch (input2)
	{
	case 1:qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_name);
	case 2:qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_age);
	defualt:printf("选择错误\n");
		break;
	}
}

//主函数及菜单
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");
}
enum Option
{
EXIT,//退出
ADD,//增加
DEL,//删除联系人
SEARCH,//查找联系人
MODIFY,//修改指定联系人
SHOW,//打印联系人
SORT,//分类
};
int main()
{
	contact con;
	InitContact(&con);
	int input;
	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:printf("你已选择退出程序\n");
			break;
		default:printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

我们将对其进行改造。

一、结构体改造及增容函数

1.结构体部分

typedef struct PeoInfo
{
	char name[NAME_MAX];//姓名
	char sex[SEX_MAX];//性别
	int age;//年龄
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//地址
}PeoInfo;
typedef struct contact
{
	PeoInfo* data;//通讯录指针
	int capacity;//通讯录最大容量
	int sz;//记录通讯录的个数
}contact;

(1)通讯录的内容不需要修改。

(2)因为数组是不可能动态变化大小,所以改成指针,可以指向一块空间,就可以使用realloc进行增容。

2.初始化函数及增容函数

(1)初始化函数

#define INCAPA 3//capacity初始容量

//动态初始化版本
void InitContact(contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capacity = INCAPA;
	pc->data = calloc(pc->capacity, sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return 1;
	}
}

(1)sz刚开始是0,capacity开始的容量我们赋值INCAPA,也就是3

(2)使用calloc将开辟好的一块空间赋值给data

(2)增容函数 

//增容函数
void CheckCapacity(contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* str = (PeoInfo*)realloc(pc->data, (pc->capacity + 5) * sizeof(PeoInfo));
		if (str != NULL)
		{
			pc->data = str;
			pc->capacity += 5;
			printf("增容成功\n");
		}
		else
		{
			perror("CheckCapacity->realloc");
			return;
		}
	}
}

(1)该函数用来扩容

(2)sz==capacity说明通讯录已满需要扩容,每次增加5个空间

二、信息添加及销毁和排序

1.信息添加函数(Add)

//动态版本
void AddContact(contact* pc)
{
	assert(pc);
	CheckCapacity(pc);//检查通讯录是否满
	int adds;
back:
	printf("请输入姓名>:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入性别>:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄>:");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入电话>:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址>:");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
	printf("信息添加成功\n");

	printf("是否继续添加联系人信息1/0:");
	scanf("%d", &adds);
	if (adds == 1)
		goto back;
	else
	{
		return;
	}
}

(1)在添加信息的时候,检查容量是否已满,满则扩容

2.销毁函数(Destroy)

//销毁通讯录
void DestroyContact(contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

calloc和realloc开辟的内存为动态内存,程序结束需要及时释放

3.排序部分(qsort)

void menu2()
{
	printf("*************************\n");
	printf("**** 1.名字   2.年龄 ****\n");
	printf("*************************\n");
}
//动态排序
//名字排序
int qsort_cmp_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
//年龄排序
int qsort_cmp_age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//联系人排序
void SortContact(contact* pc)
{
	int input2;
	menu2();
	printf("请选择排序方式:");
	scanf("%d", &input2);
	switch (input2)
	{
	case 1:qsort(pc->data, pc->sz, sizeof(PeoInfo), qsort_cmp_name); break;
	case 2:qsort(pc->data, pc->sz, sizeof(PeoInfo), qsort_cmp_age); break;
	defualt:printf("选择错误\n");
		break;
	}
}

这个排序代码同样适用于静态通讯录。

三、通讯录信息保存

1.保存在文件中(输出操作)

为了将通讯录中的信息保存下来,所以我们需要将程序写入文件中,从而可以达到保存数据的目的,下面是文件保存的代码:

//通讯录信息保存
void SaveContact(contact* pc)
{
	assert(pc);
	//打开文件
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return 1;
	}
	//写文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);//fwrite写文件更方便
	}

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

(1)我们利用fwrite函数以二进制的形式将数据写入contact.txt的文本中、

(2)每一次写一个人的信息

2.加载通讯录(输入操作)

单单将数据保存到文件中还不行,下次再将程序运行起来,还是一个空的通讯录,因为上次的数据在文件中,所以我们需要将文件中的数据输入程序中,这就是读文件的操作:

//加载通讯录
void LoadContact(contact* pc)
{
	assert(pc);
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact");
		return 1;
	}
	PeoInfo tmp = { 0 };//用来存放fread读写的信息
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		//检查容量
		CheckCapacity(pc);
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}

	fclose(pf);
	pf = NULL;
}

(1)我们将文件中的通讯录信息加载出来,需要考虑通讯录的空间是否足够,否则需要增容

(2)然后同理将通讯录的信息一个个输出出来

四、整理通讯录

上述已经写好了文件保存的程序,接下来就需要调用,当程序退出时就可以及时保存到文件中。

退出的情况有很多种:

1.在菜单按0后退出程序

下面的代码是正常退出程序时的操作:

case EXIT:SaveContact(&con);//将通讯录保存于文件中
			DestroyContact(&con);
			printf("你已选择退出程序\n");
			break;

2.其他方式退出程序

暴力退出,如:直接叉掉程序、直接关掉软件(VS),这些也需要单独考虑

(1)增加信息后暴力退出

那我们就在增加信息函数后面加上一个文件保存函数,每次调用增容函数后就及时保存

case ADD:AddContact(&con);
			SaveContact(&con);
			break;

(2)删除信息后暴力退出

删除信息后不及时保存,然后暴力退出依旧达不到删除信息的目的,所以也需要在调用删除函数后面补上文件保存函数。

case DEL:DelContact(&con);
			SaveContact(&con);
			break;

(3)排序后暴力退出

排序同理,排完序就及时保存。

case SORT:SortContact(&con);
			SaveContact(&con);
			break;

(4)修改信息后暴力退出

修改同理,修改后及时保存信息 

case MODIFY:ModifyContact(&con);
			SaveContact(&con);
			break;

3.打开程序就加载通讯录

当每次把程序运行起来之后,就希望已经将文件中的信息加载到程序中了,所以需要在初始化函数处进行改造,加上加载文件的函数接口即可

void InitContact(contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capacity = INCAPA;
	pc->data = calloc(pc->capacity, sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return 1;
	}
	//每次初始化前可以先打开之前的通讯录
	LoadContact(pc);
}

4.完整通讯录代码

#define _CRT_SECURE_NO_WARNINGS 1

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

#define NAME_MAX 20
#define SEX_MAX 6
#define TELE_MAX 20
#define ADDR_MAX 30


#define MAX 100

#define INCAPA 3//capacity初始容量

typedef struct PeoInfo
{
	char name[NAME_MAX];//姓名
	char sex[SEX_MAX];//性别
	int age;//年龄
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//地址
}PeoInfo;

//静态的通讯录
//typedef struct contact
//{
//	PeoInfo data[MAX];//通讯录
//	int sz;//记录通讯录的个数
//}contact;

//动态版本
typedef struct contact
{
	PeoInfo* data;//通讯录
	int capacity;//通讯录最大容量
	int sz;//记录通讯录的个数
}contact;

//初始化
void InitContact(contact* pc);

//添加用户信息
void AddContact(contact* pc);

//打印通讯录
void ShowContact(contact* pc);

//删除联系人
void DelContact(contact* pc);

//查找某个联系人
void SearchContact(contact* pc);

//修改联系人
void ModifyContact(contact* pc);

//联系人分类
void SortContact(contact* pc);

//增容函数
void CheckCapacity(contact* pc);

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

//文件保存函数
void SaveContact(contact* pc);

//加载通讯录
void LoadContact(contact* pc);

#define _CRT_SECURE_NO_WARNINGS 1


//静态初始化
//void InitContact(contact* pc)
//{
//	assert(pc);
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//}
//动态初始化版本
void InitContact(contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capacity = INCAPA;
	pc->data = calloc(pc->capacity, sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return 1;
	}
	//每次初始化前可以先打开之前的通讯录
	LoadContact(pc);
}

//加载通讯录
void LoadContact(contact* pc)
{
	assert(pc);
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact");
		return 1;
	}
	PeoInfo tmp = { 0 };//用来存放fread读写的信息
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		//检查容量
		CheckCapacity(pc);
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}

	fclose(pf);
	pf = NULL;
}

//销毁通讯录
void DestroyContact(contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

void ShowContact(contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("%-10s %-5s %-10s %-15s %-10s\n", "名字", "性别", "年龄", "电话", "住址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s %-5s %-10d %-15s %-10s\n",
			pc->data[i].name, pc->data[i].sex, pc->data[i].age,
			pc->data[i].tele, pc->data[i].addr);
	}
	printf("\n");
}
//静态版本
//void AddContact(contact* pc)
//{
//	assert(pc);
//	int adds;
//back:
//	if (pc->sz == MAX)
//	{
//		printf("通讯录已满,存入信息失败\n");
//		return;
//	}
//
//	printf("请输入姓名>:");
//	scanf("%s", pc->data[pc->sz].name);
//	printf("请输入性别>:");
//	scanf("%s", pc->data[pc->sz].sex);
//	printf("请输入年龄>:");
//	scanf("%d", &(pc->data[pc->sz].age));
//	printf("请输入电话>:");
//	scanf("%s", pc->data[pc->sz].tele);
//	printf("请输入住址>:");
//	scanf("%s", pc->data[pc->sz].addr);
//	pc->sz++;
//	printf("信息添加成功\n");
//
//	printf("是否继续添加联系人信息1/0:");
//	scanf("%d", &adds);
//	if (adds == 1)
//		goto back;
//	else
//	{
//		return;
//	}
//}

//增容函数
void CheckCapacity(contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* str = (PeoInfo*)realloc(pc->data, (pc->capacity + 5) * sizeof(PeoInfo));
		if (str != NULL)
		{
			pc->data = str;
			pc->capacity += 5;
			printf("增容成功\n");
		}
		else
		{
			perror("CheckCapacity->realloc");
			return;
		}
	}
}

//动态版本
void AddContact(contact* pc)
{
	assert(pc);
	CheckCapacity(pc);//检查通讯录是否满
	int adds;
back:
	printf("请输入姓名>:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入性别>:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄>:");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入电话>:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址>:");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
	printf("信息添加成功\n");

	printf("是否继续添加联系人信息1/0:");
	scanf("%d", &adds);
	if (adds == 1)
		goto back;
	else
	{
		return;
	}
}
//通讯录信息保存
void SaveContact(contact* pc)
{
	assert(pc);
	//打开文件
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return 1;
	}
	//写文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);//fwrite写文件更方便
	}

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


//查看某个联系人是否存在
static int FindContact(contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(name, pc->data[i].name) == 0)
			return i;
	}
	return -1;
}
//删除联系人
void DelContact(contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,删除失败\n");
		return;
	}
	printf("请输入你要删除的联系人:");
	char name[NAME_MAX];
	scanf("%s", name);
	int ret = FindContact(pc, name);
	if (ret == -1)
	{
		printf("联系人不存在,删除失败\n");
		return;
	}
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功\n");
}
//查找联系人
void SearchContact(contact* pc)
{
	assert(pc);
	printf("请输入你要查找联系人的名字:");
	char name[NAME_MAX];
	scanf("%s", name);
	int ret = FindContact(pc, name);
	if (ret == -1)
	{
		printf("联系人不存在,查找失败\n");
		return;
	}
	printf("查找成功:\n");
	printf("%-10s %-5s %-10s %-15s %-10s\n", "名字", "性别", "年龄", "电话", "住址");
	printf("%-10s %-5s %-10d %-15s %-10s\n",
		pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age,
		pc->data[ret].tele, pc->data[ret].addr);
}
//修改联系人
void ModifyContact(contact* pc)
{
	assert(pc);
	printf("请输入你要查找联系人的名字:");
	char name[NAME_MAX];
	scanf("%s", name);
	int ret = FindContact(pc, name);
	if (ret == -1)
	{
		printf("联系人不存在,修改失败\n");
		return;
	}
	printf("联系人存在:");
	printf("%-10s %-5s %-10d %-15s %-10s\n",
		pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age,
		pc->data[ret].tele, pc->data[ret].addr);
	printf("请修改姓名>:");
	scanf("%s", pc->data[ret].name);
	printf("请修改性别>:");
	scanf("%s", pc->data[ret].sex);
	printf("请修改年龄>:");
	scanf("%d", &(pc->data[ret].age));
	printf("请修改电话>:");
	scanf("%s", pc->data[ret].tele);
	printf("请修改住址>:");
	scanf("%s", pc->data[ret].addr);
	printf("\n修改成功\n");
}
//分类菜单
void menu2()
{
	printf("*************************\n");
	printf("**** 1.名字   2.年龄 ****\n");
	printf("*************************\n");

}
//静态排序
//名字排序
//int qsort_cmp_name(const void* e1, const void* e2)
//{
//	return strcmp((((contact*)e1)->data)->name, (((contact*)e2)->data)->name);
//}
年龄排序
//int qsort_cmp_age(const void* e1, const void* e2)
//{
//	return (((contact*)e1)->data)->age - (((contact*)e2)->data)->age;
//}
联系人排序
//void SortContact(contact* pc)
//{
//	int input2;
//	menu2();
//	printf("请选择排序方式:");
//	scanf("%d", &input2);
//	switch (input2)
//	{
//	case 1:qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_name); break;
//	case 2:qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_age); break;
//	defualt:printf("选择错误\n");
//		break;
//	}
//}


//动态排序
//名字排序
int qsort_cmp_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
//年龄排序
int qsort_cmp_age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//联系人排序
void SortContact(contact* pc)
{
	int input2;
	menu2();
	printf("请选择排序方式:");
	scanf("%d", &input2);
	switch (input2)
	{
	case 1:qsort(pc->data, pc->sz, sizeof(PeoInfo), qsort_cmp_name); break;
	case 2:qsort(pc->data, pc->sz, sizeof(PeoInfo), qsort_cmp_age); break;
	defualt:printf("选择错误\n");
		break;
	}
}


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");
}
enum Option
{
	EXIT,//退出
	ADD,//增加
	DEL,//删除联系人
	SEARCH,//查找联系人
	MODIFY,//修改指定联系人
	SHOW,//打印联系人
	SORT,//分类
};
int main()
{
	contact con;
	InitContact(&con);
	int input=0;
	do
	{
		menu();
		printf("请输入你的选择>:");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:AddContact(&con);
			SaveContact(&con);
			break;
		case DEL:DelContact(&con);
			SaveContact(&con);
			break;
		case SEARCH:SearchContact(&con);
			break;
		case MODIFY:ModifyContact(&con);
			SaveContact(&con);
			break;
		case SHOW:ShowContact(&con);
			break;
		case SORT:SortContact(&con);
			SaveContact(&con);
			break;
		case EXIT:SaveContact(&con);//将通讯录保存于文件中
			DestroyContact(&con);
			printf("你已选择退出程序\n");
			break;
		default:printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

运行结果:

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

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

相关文章

【华为数通HCIP | 网络工程师】821-BGP 组播高频题与解析(1)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

在线直线度测量仪为什么在轧钢行业越来越受欢迎!

在线直线度测量仪是利用光电检测原理及直线法进行直线度尺寸精密检测的。其测量方法是前后两台测量仪测量的数据拟合一条直线&#xff0c;中间的测量仪所测数值与直径做对比&#xff0c;即可得到被测物的直线度尺寸。 在线直线度测量仪的优点 在线直线度测量仪是一种三台小测…

Vue生命周期全解析:从工厂岗位到任务执行,一览无遗!

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 ⭐ 专栏简介 &#x1f4d8; 文章引言 一、生…

Bean的循环依赖问题

2023.11.10 通俗来讲&#xff0c;循环依赖指的是一个实例或多个实例存在相互依赖的关系&#xff08;类之间循环嵌套引用&#xff09;。比如&#xff1a;丈夫类Husband&#xff0c;妻子类Wife。Husband中有Wife的引用。Wife中有Husband的引用。 正常调用这两对象不会出现问题&am…

python实现全向轮EKF_SLAM

python实现全向轮EKF_SLAM 代码地址及效果运动预测观测修正参考算法 代码地址及效果 代码地址 运动预测 简化控制量 u t u_t ut​ 分别定义为 v x Δ t v_x \Delta t vx​Δt&#xff0c; v y Δ t v_y \Delta t vy​Δt&#xff0c;和 ω z Δ t \omega_z \Delta t ωz…

解压游戏资源,导出游戏模型

游戏中有很多好看的角色&#xff0c;地图等等资源。 你有没有想过&#xff0c;把他们导出到自己的游戏中进行魔改又或则玩换肤等操作呢&#xff1f; 相信很多同学都喜欢拳皇中的角色&#xff0c; 那么我们今天就拿拳皇15举例子&#xff0c;导出他的资源。 首先要先安装好这个…

通过商品ID获取到京东商品详情页面数据,京东商品详情官方开放平台API接口,京东APP详情接口,可以拿到sku价格,销售价演示案例

淘宝SKU详情接口是指&#xff0c;获取指定商品的SKU的详细信息。SKU是指提供不同的商品参数组合的一个机制&#xff0c;通过不同的SKU来标识商品的不同组合形式&#xff0c;如颜色、尺寸等。SKU详情接口可以帮助开发者获取指定商品的SKU列表&#xff0c;以及每个SKU的属性、库存…

算法:穷举,暴搜,深搜,回溯,剪枝

文章目录 算法基本思路例题全排列子集全排列II电话号码和字母组合括号生成组合目标和组合总和优美的排列N皇后有效的数独解数独单词搜索黄金矿工不同路径III 总结 算法基本思路 穷举–枚举 画出决策树设计代码 在设计代码的过程中&#xff0c;重点要关心到全局变量&#xff…

ChatGPT风潮再起!最新国内产品一网打尽,畅游指南曝光!

一、国内类chatgpt产品 在人工智能领域&#xff0c;自然语言处理&#xff08;NLP&#xff09;是一个重要的方向&#xff0c;涉及到语音识别、文本生成、机器翻译、问答系统等多个应用场景。近年来&#xff0c;随着深度学习技术的发展&#xff0c;NLP也取得了突破性的进展&#…

React向组件内部动态传入带内容的结构--props

children props&#xff1a;通过组件标签体传入结构 <A><B>xxx</B> </A> {this.props.children}render props&#xff1a;通过组件标签属性传入结构&#xff0c;一般用render函数属性 <A render{data> <C data{data}></C>}></…

super() 和 super(props) 有什么区别?

一、ES6 类 在 ES6 中&#xff0c;通过 extends 关键字实现类的继承&#xff0c;方式如下&#xff1a; class sup { constructor(name) { this.name name; } printName() { console.log(this.name); }}class sub extends sup { constructor(name, age) { …

二十二、W5100S/W5500+RP2040树莓派Pico<SMTP发送邮件>

文章目录 1 前言2 简介2 .1 什么是SMTP&#xff1f;2.2 SMTP是如何工作的&#xff1f;2.3 SMTP、IMAP和POP32.4 SMTP应用场景 3 WIZnet以太网芯片4 SMTP发送邮件示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前…

常见产品结构四大类型 优劣势比较

一般&#xff0c;我们通过产品架构来构建用户体验&#xff0c;这样可以提供更清晰的导航和组织、优化用户流程和交互、增强产品的可扩展性和可维护性&#xff0c;提升用户的满意度和忠诚度。如果没有明确的产品结构&#xff0c;可能会导致功能冗余或功能缺失、交互流程混乱等问…

「Verilog学习笔记」使用generate…for语句简化代码

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 generate…for语句是Verilog HDL语言特有的语句&#xff0c;使用循环结构编写可综合的多个形式相近的代码&#xff0c;循环变量必须由特定关键字genvar声明。 timesca…

VSD Viewer v6.16.1(Visio绘图文件阅读器)

VSD Viewer是一款可以打开和查看Microsoft Visio文件的工具&#xff0c;适用于Windows和macOS操作系统。它具有以下优点&#xff1a; 直观易用&#xff1a;VSD Viewer的用户界面非常简单直观&#xff0c;易于使用。支持多种文件格式&#xff1a;VSD Viewer支持多种Visio文件格…

二维码解码器怎么用?快速分解二维码图片的方法

现在很多人会将链接网址生成二维码之后来使用&#xff0c;这种方式能够让别人更快的获取链接的内容&#xff0c;而且扫码访问内容的方式也更适合大家的使用习惯。那么如果想要获取二维码中的链接时&#xff0c;一般会使用二维码解码器来处理&#xff0c;那么具体该怎么使用呢&a…

驱动基石之_tasklet中断下半部_工作队列_中断线程化处理

tasklet中断下半部 linux的中断分为两个部分&#xff1a; 1.中断上半部&#xff1a;在中断上半部期间&#xff0c;不允许被其他中断打断&#xff0c;直到中断上半部的服务函数执行完。 2.中断下半部&#xff1a;中断下半部&#xff0c;在执行中断下半部服务函数的期间&#xf…

断点续传-http中Header参数Range(分段请求基础)

文章目录 Range请求头信息介绍RangeIf-Range 响应头Content-RangeAccept-Ranges 需要用到几个http头 rangeif-rangecontent-rangeaccept-range 断点续传的优缺点 好处&#xff1a;防止大文件下载过程出现网络异常&#xff0c;而前功尽弃。缺点&#xff1a;要发起多次请求&…

echarts 圆环图 高亮事件 切换 中心文字

createEcharts() {let chartDom this.$refs.echartsthis.Echarts echarts.init(chartDom)let option {title: {text: 128, //主标题文本subtext: 总数, //副标题文本left: center,top: 32%,textStyle: {fontFamily: Montserrat-MediumItalic,fontSize: 30,color: #fff,align…

构建全面预算体系,加强企业风险管理

全面预算管理体系是帮助企业实现其战略目标的重要手段。随着预算管理理念备受重视&#xff0c;这种新型的企业管理模式通过高效科学的方式和工具&#xff0c;在我国新时代背景下&#xff0c;逐渐成为了企业经营运作过程中针对挑战的有效措施。通常情况下&#xff0c;企业将全面…