【C语言】通讯录动态版和文件版

通讯录动态版

  • 通讯录的静态版本:一旦确认了通讯的大小,后面就不可以在更改
    如果空间填写的太大,会浪费空间,如果太小,满足不了需求
  • 动态版本:通讯录的大小是可变的,如果需求不够可以进行扩容,这就解决了静态版本的缺陷
  • 动态版本的实现思路:
    最开始通讯录的空间默认能存放 3 个人的信息,如果空间不够,就增加空间,每次增加2个人的信息
    动态版本和静态版本的代码差不多,只需要修改 通讯录的初始化和增加信息

动态版本的初始化

// 静态版本
//创建通讯录空间
typedef struct Contact
{
	PeoInfo ds[MAX];
	int count;
}Contact;
//初始化
void InitContact(Contact* ps)
{
	assert(ps); //判断
	ps->count = 0;
	memset(ps, 0, sizeof(ps->ds));
}
-------------------------------------------------
//动态版本
typedef struct Contact
{
	PeoInfo* ds;//存放信息
	int count;       // 记录通讯录的成员个数
	int capacity;    //当前通讯录的容量
}Contact;
//初始化
int InitContact(Contact * ps)
{
	assert(ps); //判断
	ps->count = 0;
	ps->ds = (PeoInfo*)calloc(DEFAULT_sz,sizeof(PeoInfo));
	if (ps->ds == NULL)
	{
		printf("InitContact:%s\n",perror);
		return 1;
	}
	ps->capacity = DEFAULT_sz;
	return 0;
}
  • 动态版本开辟就不能是数组了,要改成指针,就可以使用动态内存函数
  • count 记录当前人的信息是不用修改,但是还需要一个变量来记录当前空间的容量capacity
  • 初始化函数里的DEFAULT_sz,是用define 定义的全局变量 是 3

动态版本的增加信息

// 静态版本
void AddContact(Contact* ps)
{
	assert(ps);
	if (ps->ds == MAX)
	{
		printf("通讯录已满\n");
		return;
	}
}
-----------------------------------------
void AddContact(Contact* ps)
{
    assert(ps);
	if (ps->count == ps->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(ps->ds, (ps->capacity + INC_sz) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			printf("AddContact:%s\n", strerror(errno));
			return;
		}
		else
		{
			ps->ds = ptr;
		}
		ps->capacity += INC_sz;
		printf("增容成功\n");
	}
	...........
}
  • 静态版本通讯录满了是直接返回的,而动态版的满了是进行扩容的
  • 增加函数里的INT_sz,是用define 定义的全局变量 是 2,扩容的数量
  • 后面的代码就和静态版的都是一样的了

源代码

test.c

#include "Contact.h"
void meun()
{
	printf("*****************************************\n");
	printf("********* 1.增加          2.删除 *********\n");
	printf("********* 3.查找          4.修改 *********\n");
	printf("********* 5.显示          6.排序 *********\n");
	printf("********* 0.退出                 *********\n");
	printf("*****************************************\n");
}
int main()
{
	int input = 0;
	Contact con;

	InitContact(&con);
	do
	{
		meun();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			SearchContact(&con);
			break;
		case 4:
			ModifyContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			SortContact(&con);
			break;
		case 0:
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
		return 0;
}

Contact.h

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

#define MAX 100     //静态版数组的大小
#define MAX_NAME 20 //名字的大小
#define MAX_SEX 10  //性别的大小
#define MAX_TELE 12  // 电话大大小
#define MAX_ADDR 10  //地址的大小

#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 struct Contact
{
	PeoInfo* ds;//存放信息
	int count;       // 记录通讯录的成员个数
	int capacity;    //当前通讯录的容量
}Contact;

//初始化
int InitContact(Contact* ps);
//增加信息
void AddContact(Contact* ps);
//显示联系人信息
void ShowContact(Contact* ps);
//删除联系人
void DelContact(Contact* ps);
//查找联系人
void SearchContact(Contact* ps);
//修改联系人信息
void ModifyContact(Contact* ps);
//排序
void SortContact(Contact* ps);

Contact.c

//初始化
int InitContact(Contact * ps)
{
	assert(ps); //判断
	ps->count = 0;
	ps->ds = (PeoInfo*)calloc(DEFAULT_sz,sizeof(PeoInfo));
	if (ps->ds == NULL)
	{
		printf("InitContact:%s\n",perror);
		return 1;
	}
	ps->capacity = DEFAULT_sz;
	return 0;
}

// 扩容的函数
void CheckCapacity(Contact* ps)
{
	if (ps->count == ps->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(ps->ds, (ps->capacity + INC_sz) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			printf("AddContact:%s\n", strerror(errno));
			return;
		}
		else
		{
			ps->ds = ptr;
		}
		ps->capacity += INC_sz;
		printf("增容成功\n");

	}
}
//增加联系人信息
void AddContact(Contact* ps)
{
	assert(ps);
	CheckCapacity(ps);
	
	printf("请输入联系人的名字:");
	scanf("%s", ps->ds[ps->count].name);
	printf("请输入联系人的年龄:");
	scanf("%d", &(ps->ds[ps->count].age));
	printf("请输入联系人的性别:");
	scanf("%s", ps->ds[ps->count].sex);
	printf("请输入联系人的电话:");
	scanf("%s", ps->ds[ps->count].tele);
	printf("请输入联系人的地址:");
	scanf("%s", ps->ds[ps->count].addr);

	ps->count++;
	printf("增加成功\n");
}

//显示联系人信息
void ShowContact(Contact* ps)
{
	assert(ps);
	int i = 0;
	if (ps->count == 0)
	{
		printf("通讯录为空,没有联系人\n");
		return;
	}
	printf("%-5s %-5s %-5s %-5s %-10s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < ps->count; i++)
	{
		printf("%-5s %-5d %-5s %-5s %-10s\n", ps->ds[i].name,
			ps->ds[i].age,
			ps->ds[i].sex,
			ps->ds[i].tele,
			ps->ds[i].addr);
	}
}

int FindByName(Contact* ps, char name[])
{
	int i = 0;
	for (i = 0; i < ps->count; i++)
	{
		if (strcmp(ps->ds[i].name, name) == 0)
			return i;
	}
	return -1;
}

//删除联系人
void DelContact(Contact* ps)
{
	assert(ps);
	char name[MAX_NAME] = { 0 };
	if (ps->count == 0)
	{
		printf("通讯录为空,没有联系人\n");
		return;
	}
	printf("请输入要删除的联系人名字:");
	scanf("%s", name);
	//查找联系人是否存在
	int ret = FindByName(ps, name);
	if (ret == -1)
	{
		printf("没有这个联系人\n");
	}

	//删除
	int i = 0;
	for (i = ret; i < ps->count-1; i++)
	{
		ps->ds[i] = ps->ds[i + 1];
	}
	ps->count--;
	printf("删除成功\n");
}

//查找联系人
void SearchContact(Contact* ps)
{
	assert(ps);
	char name[MAX_NAME] = { 0 };
	printf("请输入查找的联系人:");
	scanf("%s", &name);
	//查找联系人是否存在
	int ret = FindByName(ps, name);
	if (ret == -1)
	{
		printf("没有这个联系人\n");
		return;
	}

	printf("%-5s %-5s %-5s %-5s %-10s\n", "名字", "年龄", "性别", "电话", "地址");
	printf("%-5s %-5d %-5s %-5s %-10s\n", ps->ds[ret].name,
			ps->ds[ret].age,
			ps->ds[ret].sex,
			ps->ds[ret].tele,
			ps->ds[ret].addr);
}

//修改联系人信息
void ModifyContact(Contact* ps)
{
	assert(ps);
	char name[MAX_NAME] = { 0 };
	printf("请输入修改的联系人:");
	scanf("%s", &name);
	//查找联系人是否存在
	int ret = FindByName(ps, name);
	if (ret == -1)
	{
		printf("没有这个联系人\n");
		return;
	}
	printf("请填写修改信息\n");
	printf("请输入联系人的名字:");
	scanf("%s", ps->ds[ret].name);
	printf("请输入联系人的年龄:");
	scanf("%d", &(ps->ds[ret].age));
	printf("请输入联系人的性别:");
	scanf("%s", ps->ds[ret].sex);
	printf("请输入联系人的电话:");
	scanf("%s", ps->ds[ret].tele);
	printf("请输入联系人的地址:");
	scanf("%s", ps->ds[ret].addr);

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

int age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e2)->age - ((PeoInfo*)e1)->age;
}
//排序
void SortContact(Contact* ps)
{
	assert(ps);
	qsort(ps->ds, ps->count, sizeof(ps->ds[0]), age);
	printf("排序成功\n");
}

通讯录文件版

通讯录文件版是为了填写的数据在退出的时候能够保存下来
下一次打开还能找到上一次的数据
文件版添加的功能和修改:

  1. 在退出的时候,写了一个函数进行保存信息(SaveContact)
  2. 重新进入程序,在进行初始化的时候,把信息加载进来

文件退出时保存信息

在退出的时候,添加了一个函数进行保存信息(SaveContact)
代码的实现:

void SaveContact(Contact* ps)
{
	assert(ps);
	FILE* pf = fopen("Contact.txt", "wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写文件 - 二进制的方式
	int i = 0;
	for (i = 0; i < ps->count; i++)
	{
		fwrite(ps->ds+i, sizeof(PeoInfo), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}
  • 首先是打开通讯录代码所在的文件,是以“wb” 的方式进行打开,进行保存
  • 第二步就是进行保存信息,用fwrite函数每次保存一个信息到 pf
  • 第三步就是关闭文件退出

信息加载

重新进入程序时,在进行初始化的时候,要把信息先加载进来

void LodaContact(Contact* ps)
{
	FILE* pf = fopen("Contact.txt", "rb");
	if (pf == NULL)
	{
		perror("odaContact");
		return;
	}
	//文件数据填充
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf) == 1)
	{
		CheckCapacity(ps);
		ps->ds[ps->count] = tmp;
		ps->count++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}
  • 第一步:打开存放数据的文件,以“rb” 的形式打开文件
  • 第二步:进行数据填充进程序中,用 fread 函数,每次填充 1 个成员,每个成员大小是PeoInfo
    填充到 tmp 变量中,这是为了防止通讯录放不下,如果放不小就要先进行扩容
    最后就是关闭文件

源文件

text.c

#include "Contact.h"

void meun()
{
	printf("*****************************************\n");
	printf("********* 1.增加          2.删除 *********\n");
	printf("********* 3.查找          4.修改 *********\n");
	printf("********* 5.显示          6.排序 *********\n");
	printf("********* 0.退出                 *********\n");
	printf("*****************************************\n");
}
int main()
{
	int input = 0;
	Contact con;

	InitContact(&con);
	do
	{
		meun();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			SearchContact(&con);
			break;
		case 4:
			ModifyContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			SortContact(&con);
			break;
		case 0:
			SaveContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
		return 0;
}

Contact.h

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

#define MAX 100     //静态版数组的大小
#define MAX_NAME 20 //名字的大小
#define MAX_SEX 10  //性别的大小
#define MAX_TELE 12  // 电话大大小
#define MAX_ADDR 10  //地址的大小

#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 struct Contact
{
	PeoInfo* ds;//存放信息
	int count;       // 记录通讯录的成员个数
	int capacity;    //当前通讯录的容量
}Contact;


//初始化
int InitContact(Contact* ps);
//增加信息
void AddContact(Contact* ps);
//显示联系人信息
void ShowContact(Contact* ps);
//删除联系人
void DelContact(Contact* ps);
//查找联系人
void SearchContact(Contact* ps);
//修改联系人信息
void ModifyContact(Contact* ps);
//排序
void SortContact(Contact* ps);
//保存通讯录信息
void SaveContact(const Contact* ps);
//加载文件信息到通讯录中
void LodaContact(Contact* ps);

Contact.c

#include "Contact.h"
// 扩容空间
void CheckCapacity(Contact* ps)
{
	if (ps->count == ps->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(ps->ds, (ps->capacity + INC_sz) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			printf("AddContact:%s\n", strerror(errno));
			return;
		}
		else
		{
			ps->ds = ptr;
		}
		ps->capacity += INC_sz;
		printf("增容成功\n");

	}
}
 //填充信息
void LodaContact(Contact* ps)
{
	FILE* pf = fopen("Contact.txt", "rb");
	if (pf == NULL)
	{
		perror("odaContact");
		return;
	}
	//
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf) == 1)
	{
		CheckCapacity(ps);
		ps->ds[ps->count] = tmp;
		ps->count++;
	}

	fclose(pf);
	pf = NULL;
}
//动态版本
int InitContact(Contact * ps)
{
	assert(ps); //判断
	ps->count = 0;
	ps->ds = (PeoInfo*)calloc(DEFAULT_sz,sizeof(PeoInfo));
	if (ps->ds == NULL)
	{
		printf("InitContact:%s\n",perror);
		return 1;
	}
	ps->capacity = DEFAULT_sz;
	//加载通讯录信息中
	LodaContact(ps);
	return 0;
}


//增加联系人信息
void AddContact(Contact* ps)
{
	assert(ps);
	/*if (ps->ds == MAX)
	{
		printf("通讯录已满\n");
		return;
	}*/
	CheckCapacity(ps);
	
	printf("请输入联系人的名字:");
	scanf("%s", ps->ds[ps->count].name);
	printf("请输入联系人的年龄:");
	scanf("%d", &(ps->ds[ps->count].age));
	printf("请输入联系人的性别:");
	scanf("%s", ps->ds[ps->count].sex);
	printf("请输入联系人的电话:");
	scanf("%s", ps->ds[ps->count].tele);
	printf("请输入联系人的地址:");
	scanf("%s", ps->ds[ps->count].addr);

	ps->count++;
	printf("增加成功\n");
}

//显示联系人信息
void ShowContact(Contact* ps)
{
	assert(ps);
	int i = 0;
	if (ps->count == 0)
	{
		printf("通讯录为空,没有联系人\n");
		return;
	}
	printf("%-5s %-5s %-5s %-5s %-10s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < ps->count; i++)
	{
		printf("%-5s %-5d %-5s %-5s %-10s\n", ps->ds[i].name,
			ps->ds[i].age,
			ps->ds[i].sex,
			ps->ds[i].tele,
			ps->ds[i].addr);
	}
}

int FindByName(Contact* ps, char name[])
{
	int i = 0;
	for (i = 0; i < ps->count; i++)
	{
		if (strcmp(ps->ds[i].name, name) == 0)
			return i;
	}
	return -1;
}

//删除联系人
void DelContact(Contact* ps)
{
	assert(ps);
	char name[MAX_NAME] = { 0 };
	if (ps->count == 0)
	{
		printf("通讯录为空,没有联系人\n");
		return;
	}
	printf("请输入要删除的联系人名字:");
	scanf("%s", name);
	//查找联系人是否存在
	int ret = FindByName(ps, name);
	if (ret == -1)
	{
		printf("没有这个联系人\n");
	}

	//删除
	int i = 0;
	for (i = ret; i < ps->count-1; i++)
	{
		ps->ds[i] = ps->ds[i + 1];
	}
	ps->count--;
	printf("删除成功\n");
}

//查找联系人
void SearchContact(Contact* ps)
{
	assert(ps);
	char name[MAX_NAME] = { 0 };
	printf("请输入查找的联系人:");
	scanf("%s", &name);
	//查找联系人是否存在
	int ret = FindByName(ps, name);
	if (ret == -1)
	{
		printf("没有这个联系人\n");
		return;
	}

	printf("%-5s %-5s %-5s %-5s %-10s\n", "名字", "年龄", "性别", "电话", "地址");
	printf("%-5s %-5d %-5s %-5s %-10s\n", ps->ds[ret].name,
			ps->ds[ret].age,
			ps->ds[ret].sex,
			ps->ds[ret].tele,
			ps->ds[ret].addr);
}

//修改联系人信息
void ModifyContact(Contact* ps)
{
	assert(ps);
	char name[MAX_NAME] = { 0 };
	printf("请输入修改的联系人:");
	scanf("%s", &name);
	//查找联系人是否存在
	int ret = FindByName(ps, name);
	if (ret == -1)
	{
		printf("没有这个联系人\n");
		return;
	}
	printf("请填写修改信息\n");
	printf("请输入联系人的名字:");
	scanf("%s", ps->ds[ret].name);
	printf("请输入联系人的年龄:");
	scanf("%d", &(ps->ds[ret].age));
	printf("请输入联系人的性别:");
	scanf("%s", ps->ds[ret].sex);
	printf("请输入联系人的电话:");
	scanf("%s", ps->ds[ret].tele);
	printf("请输入联系人的地址:");
	scanf("%s", ps->ds[ret].addr);

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

int age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e2)->age - ((PeoInfo*)e1)->age;
}
//排序
void SortContact(Contact* ps)
{
	assert(ps);
	qsort(ps->ds, ps->count, sizeof(ps->ds[0]), age);
	printf("排序成功\n");
}

//保存信息到文件中
void SaveContact(Contact* ps)
{
	assert(ps);
	FILE* pf = fopen("Contact.txt", "wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写文件 - 二进制
	int i = 0;
	for (i = 0; i < ps->count; i++)
	{
		fwrite(ps->ds+i, sizeof(PeoInfo), 1, pf);
	}

	fclose(pf);
	pf = NULL;
}

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值