文件版通讯录


  我们之前的通讯录在程序关闭后,联系人信息就销毁了,那我们如果想存储联系人信息该怎么办?

我们学习完文件操作之后,知道文件是保存在持久化存储设备(硬盘、U盘、光盘…)上的一段数据。那么我们可以在程序退出之前,把联系人信息存储到文件中,等我们再次运行程序时,需要先把联系人信息从文件中加载到程序中。

针对动态版的通讯录,我们来做一些改进。

1.程序退出时,将通讯录信息写入文件

void SaveContact(struct Contact* con)
{
	//打开文件
	FILE* fp = fopen("contact.txt","wb");
	if (fp == NULL)
	{
		perror("fopen");
		return;
	}

	//写数据
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		fwrite((con->data + i),sizeof(struct PeopleInfo),1,fp);
	}
	fclose(fp);
	fp = NULL;
}

2.程序运行起来,首先从文件中加载联系人信息

void CheckCapacity(struct Contact* con)
{
	if (con->sz == con->capacity)
	{
		//增容
		int newcapacity = con->capacity * 2;
		struct PeopleInfo* tmp = (struct PeopleInfo*)realloc(con->data,newcapacity * sizeof(struct PeopleInfo));
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		//增容成功
		con->data = tmp;
		con->capacity = newcapacity;
		printf("增容成功!\n");
	}
}

void LoadContact(struct Contact* con)
{
	//打开文件
	FILE* fp = fopen("contact.txt","rb");
	if (fp == NULL)
	{
		perror("loadcontatc:fopen");
		return;
	}

	//读文件
	struct PeopleInfo tmp = {0};
	while (fread(&tmp,sizeof(struct PeopleInfo),1, fp))
	{
		//检查空间是否满了
		CheckCapacity(con);
		con->data[con->sz] = tmp;
		con->sz++;
	}

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

//初始化通讯录 - 文件版
void InitContact(struct Contact* con)
{
	//没有联系人信息
	con->sz = 0;

	//动态开辟内存
	con->data = (struct PeopleInfo*)calloc(DEFAULT_SIZE, sizeof(struct PeopleInfo));

	if (con->data == NULL)
	{
		printf("开辟空间失败!\n");
		return -1;
	}
	con->capacity = DEFAULT_SIZE;

	//加载文件信息到通讯录中
	LoadContact(con);

}

完整代码:

/*contact.h*/
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DEFAULT_SIZE 3
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 15
#define ADDR_MAX 30
#define MAX 1000

//一个联系人的信息
struct PeopleInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
};

通讯录结构体-静态版
//struct Contact
//{
//	//1000个人的信息放在数组中
//	struct PeopleInfo data[MAX];
//
//	//当前通讯录联系人的个数
//	int sz;
//};


//动态版通讯录
struct Contact
{
	struct PeopleInfo* data;

	//通讯录中当前联系人个数
	int sz;

	//当前总容量
	int capacity;
};

void InitContact(struct Contact* con);

void AddContact(struct Contact* con);

void ShowContact(struct Contact* con);

int FindContact(const struct Contact* con, char name[]);

void DelContact(struct Contact* con);

void SearchContact(const struct Contact* con);

void ModifyContact(struct Contact* con);

void SortContact(struct Contact* con);

void ClearContact(struct Contact* con);

void DestoryContact(struct Contact* con);

void SaveContact(struct Contact* con);

void LoadContact(struct Contact* con);

void CheckCapacity(struct Contact* con);
/*contact.c*/
#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

void CheckCapacity(struct Contact* con)
{
	if (con->sz == con->capacity)
	{
		//增容
		int newcapacity = con->capacity * 2;
		struct PeopleInfo* tmp = (struct PeopleInfo*)realloc(con->data,newcapacity * sizeof(struct PeopleInfo));
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		//增容成功
		con->data = tmp;
		con->capacity = newcapacity;
		printf("增容成功!\n");
	}
}

void LoadContact(struct Contact* con)
{
	//打开文件
	FILE* fp = fopen("contact.txt","rb");
	if (fp == NULL)
	{
		perror("loadcontatc:fopen");
		return;
	}

	//读文件
	struct PeopleInfo tmp = {0};
	while (fread(&tmp,sizeof(struct PeopleInfo),1, fp))
	{
		//检查空间是否满了
		CheckCapacity(con);
		con->data[con->sz] = tmp;
		con->sz++;
	}

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

//初始化通讯录 - 文件版
void InitContact(struct Contact* con)
{
	//没有联系人信息
	con->sz = 0;

	//动态开辟内存
	con->data = (struct PeopleInfo*)calloc(DEFAULT_SIZE, sizeof(struct PeopleInfo));

	if (con->data == NULL)
	{
		printf("开辟空间失败!\n");
		return -1;
	}
	con->capacity = DEFAULT_SIZE;

	//加载文件信息到通讯录中
	LoadContact(con);

}


//文件版-增加联系人
void AddContact(struct Contact* con)
{
	//if (con->sz == con->capacity)
	//{
	//	//扩容
	//	struct PeopleInfo* ptr = (struct PeopleInfo*)realloc(con->data, 2 * (con->sz) * sizeof(struct PeopleInfo));
	//	if (ptr != NULL)
	//	{
	//		//扩容成功
	//		con->data = ptr;
	//		printf("增容成功!\n");
	//		con->capacity *= 2;
	//	}
	//	else
	//	{
	//		//扩容失败
	//		return;
	//	}
	//}


	CheckCapacity(con);

	//录入联系人信息
	printf("请输入姓名:>");
	scanf("%s", con->data[con->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(con->data[con->sz].age));
	printf("请输入性别:>");
	scanf("%s", con->data[con->sz].sex);
	printf("请输入电话:>");
	scanf("%s", con->data[con->sz].tele);
	printf("请输入地址:>");
	scanf("%s", con->data[con->sz].addr);

	printf("添加成功!\n");

	(con->sz)++;
}




//查看联系人
void ShowContact(struct Contact* con)
{
	//判断是否为空
	if (con->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}

	//打印标题
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n", "name", "age", "sex", "tele", "addr");

	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		/*printf("姓名:%s\n", con->data[i].name);
		printf("年龄:%d\n", con->data[i].age);
		printf("性别:%s\n", con->data[i].sex);
		printf("电话:%s\n", con->data[i].tele);
		printf("地址:%s\n", con->data[i].addr);*/
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n", con->data[i].name,
			con->data[i].age, con->data[i].sex, con->data[i].tele, con->data[i].addr);
	}
}


int FindContact(const struct Contact* con, char name[])
{
	//遍历data数组
	int i = 0;
	for (i = 0; i < (con->sz); i++)
	{
		if (strcmp(con->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}


//删除指定联系人
void DelContact(struct Contact* con)
{
	//通讯录为空
	if (con->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}


	printf("请输入要删除的联系人姓名:>");
	char name[NAME_MAX] = { 0 };
	scanf("%s", name);

	//查找是否存在该联系人
	int ret = FindContact(con, name);

	if (ret == -1)
	{
		printf("该联系人不存在!\n");
	}
	else
	{
		//删除联系人
		//后面的联系人前移
		int i = 0;
		for (i = ret; i < con->sz - 1; i++)
		{
			/*strcpy(con->data[i].name,con->data[i + 1].name);
			con->data[i].age = con->data[i + 1].age;
			strcpy(con->data[i].sex,con->data[i + 1].sex);
			strcpy(con->data[i].tele ,con->data[i + 1].tele);
			strcpy(con->data[i].addr ,con->data[i + 1].addr);*/
			con->data[i] = con->data[i + 1];
		}
		printf("删除成功!\n");
		con->sz--;
	}

}


void SearchContact(const struct Contact* con)
{
	char name[NAME_MAX] = { 0 };
	printf("请输入要查找的联系人的姓名:>");
	scanf("%s", name);

	int ret = FindContact(con, name);
	if (ret == -1)
	{
		printf("没有该联系人!\n");
		return;
	}
	else
	{
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n", "name", "age", "sex", "tele", "addr");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n", con->data[ret].name,
			con->data[ret].age, con->data[ret].sex, con->data[ret].tele, con->data[ret].addr);
	}

}

void ModifyContact(struct Contact* con)
{
	if (con->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}

	printf("输入要修改的联系人的姓名:>");
	char name[NAME_MAX] = { 0 };

	scanf("%s", name);

	int ret = FindContact(con, name);
	if (ret == -1)
	{
		printf("该联系人不存在!\n");
	}
	else
	{
		printf("请输入姓名:>");
		scanf("%s", con->data[ret].name);

		printf("请输入年龄:>");
		scanf("%d", &(con->data[ret].age));

		printf("请输入性别:>");
		scanf("%s", con->data[ret].sex);

		printf("请输入电话:>");
		scanf("%s", con->data[ret].tele);

		printf("请输入地址:>");
		scanf("%s", con->data[ret].addr);

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

int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct PeopleInfo*)e1)->name, ((struct PeopleInfo*)e2)->name);
}


void SortContact(struct Contact* con)
{
	qsort(con->data, con->sz, sizeof(con->data[0]), cmp_by_name);
}



//清空通讯录
void ClearContact(struct Contact* con)
{
	//使用memset函数
	memset(con->data, 0, con->sz * sizeof(struct PeopleInfo));
	con->sz = 0;
}


void DestoryContact(struct Contact* con)
{
	//释放动态开辟的空间
	free(con->data);
	con->data = NULL;
	con->sz = 0;
	con->capacity = 0;
}

void SaveContact(struct Contact* con)
{
	//打开文件
	FILE* fp = fopen("contact.txt","wb");
	if (fp == NULL)
	{
		perror("fopen");
		return;
	}

	//写数据
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		fwrite((con->data + i),sizeof(struct PeopleInfo),1,fp);
	}
	fclose(fp);
	fp = NULL;
}
/*test.c*/
#define _CRT_SECURE_NO_WARNINGS 1
#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.clear      0.exit   **************\n");
	printf("*********************************************\n");
}


enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	CLEAR
};
int main()
{
	int input = 0;

	//创建一个通讯录
	struct 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 CLEAR:
			//清空所有联系人
			ClearContact(&con);
			break;
		case EXIT:
			//保存通讯录
			SaveContact(&con);
			
			//销毁通讯录
			DestoryContact(&con);
			printf("退出通讯录!\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}


//do
//{
//	menu();
//	printf("请选择:>");
//	scanf("%d", &input);
//
//	//使用函数指针数组
//	//void InitContact(struct Contact* con);
//
//	void (*funparr[7])(struct Contact*) = { 0,AddContact,DelContact,
//	SearchContact,ModifyContact,ShowContact,SortContact };
//
//	if (input >= 1 && input <= 6)
//	{
//		funparr[input](&con);
//	}
//	else if (input == 0)
//	{
//		printf("退出通讯录!\n");
//	}
//	else
//	{
//		printf("输入有误!\n");
//	}
//} while (input);

本章完。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值