升级版通讯录(C语言版)

一、使用动态开辟内存

在低版本中,我们使用固定长度的数组存放通讯录信息,但是数据信息过多就会出现越界错误,如果数据信息过少,又会造成极大的内存浪费,故我们可以采用动态内存开辟来很好地解决。

我们首先需要改变初始化函数,先利用malloc开辟一定的空间。

void initContact(struct Contact* connect)
{
	assert(connect);
	connect->size = 0;
	connect->capacity = FAULT_SZ;
	 connect->data= (struct PeoInfo*)malloc(FAULT_SZ * sizeof(struct PeoInfo));
	memset(connect->data, 0, sizeof(struct PeoInfo) * connect->capacity);
}

接下来在添加元素时,可能会出现空间不足的情况,所以我们首先应该判断size是否等于capacity,如果容量不足,我们就需要利用realloc函数进行扩容。 

int check_is_full( struct Contact* connect)
{
	if (connect->size == connect->capacity)
	{
		struct PeoInfo* p = (struct PeoInfo*)realloc(connect->data, (connect->capacity+EXPAND_SZ) * sizeof(struct PeoInfo));
		if (p != NULL)
		{
			connect->data = p;
			connect->capacity += EXPAND_SZ;
			printf("扩容成功!\n");
			p = NULL;
			return 1;
		}
		else
		{
			printf("扩容失败,无法再继续添加!");
			return 0;
		}
		
	}
	else
	{
		return 1;
	}
}

那么,我们添加元素的函数就会变成如下所示:

void addContact(struct Contact* connect)
{
	assert(connect);
	int flag = check_is_full(connect);
	if (flag)
	{
			printf("姓名:");
			scanf("%s", connect->data[connect->size].name);
			printf("性别:");
			scanf("%s", connect->data[connect->size].sex);
			printf("年龄:");
			scanf("%d", &(connect->data[connect->size].age));
			printf("电话号码:");
			scanf("%s", connect->data[connect->size].tele);
			printf("地址:");
			scanf("%s", connect->data[connect->size].adder);
			connect->size++;
			printf("添加成功!\n");
	}
	else
	{
		return;
	}
	
}

但是在退出程序时,我们需要对开辟的内存进行释放,那么我们就需要再增加一个函数来释放空间。

void destoryContact(struct Contact* connect)
{
	free(connect->data);
	connect->data = NULL;
	connect->capacity = 0;
	connect->size = 0;
}

 二、对通讯录信息进行文件存储

我们通常使用的通讯录是能够保存信息的,这时就需要在函数退出时,并将信息保存到一个文件上。

void saveContact(struct Contact* connect)
{
	FILE* fpw =fopen("contact.txt", "wb");
	if (fpw == NULL)
	{
		perror("fopen");
		return;
	}
	for (int i = 0; i < connect->size; i++)
	{
		fwrite(connect->data + i, sizeof(struct PeoInfo), 1, fpw);
	}
//fwrite(connect->data, sizeof(struct PeoInfo), connect->size, fpw);
//这样写也没问题
	fclose(fpw);
	fpw = NULL;
}

那么在进行初始化的时候,我们就应该将存储到文件的通讯录信息初始到Contact对象中去,以便能更好地进行排序、删除、查找等操作。 并且在这个函数中我们还需要调用是否需要扩容的那个函数。

void loadContact(struct Contact* connect)
{
	FILE* fpr = fopen("contact.txt", "rb");
	if (fpr == NULL)
	{
		perror("fopen");
		return;
	}
	struct PeoInfo temp = { 0 };
	while (fread(&temp, sizeof(struct PeoInfo), 1, fpr))
	{
		check_is_full(connect);
		connect->data[connect->size] = temp;
		connect->size++;
	}
	fclose(fpr);
	fpr = NULL;
}

那么,初始化函数就会变为:

void initContact(struct Contact* connect)
{
	assert(connect);
	connect->size = 0;
	connect->capacity = FAULT_SZ;
	 connect->data= (struct PeoInfo*)malloc(FAULT_SZ * sizeof(struct PeoInfo));
	memset(connect->data, 0, sizeof(struct PeoInfo) * connect->capacity);
	loadContact(connect);
}

 这样我们的信息就会保存在文件中去了。

在升级版通讯录中,我们其余函数是保持不变的,我们的主函数做了略微修改:

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
enum Option
{
	quit,
	add,
	delete,
	search,
	modify,
	sort,
	list,
	empty
};
void menu()
{
	printf("--------------------------------------------------------------------\n");
	printf("-----------1.add                  2.delete--------------------------\n");
	printf("-----------3.search               4.modify--------------------------\n");
	printf("-----------5.sort                 6.list----------------------------\n");
	printf("-----------7.empty                0.exit----------------------------\n");
	printf("--------------------------------------------------------------------\n");
}
int main()
{
	enum Option option;
	struct Contact connect;
	initContact(&connect);
	do
	{
		menu();
		printf("请输入您要进行的操作:");
		scanf("%d", &option);
		switch (option)
		{
		case add:
			addContact(&connect);
			break;
		case delete:
			deleteContact(&connect);
			break;
		case search:
			searchContact(&connect);
			break;
		case modify:
			modifyContact(&connect);
			break;
		case sort:
			sortContact(&connect);
			break;
		case list:
			listContact(&connect);
			break;
		case empty:
			emptyContact(&connect);
			break;
		case quit:
			saveContact(&connect);
			destoryContact(&connect);
			printf("保存成功!\n");
			printf("退出成功!\n");
			break;
		default:
			printf("您的输入有误!");
			break;
		}

	} while (option);

	return 0;
}

注意在contact.h进行函数声明的更新! 

你可能感兴趣的:(projects,c语言,数据结构,算法)