前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >抽丝剥茧C语言(高阶)动态+文件通讯录

抽丝剥茧C语言(高阶)动态+文件通讯录

作者头像
有礼貌的灰绅士
发布2023-03-28 15:28:38
7180
发布2023-03-28 15:28:38
举报

动态文件通讯录

导语

这一片博客我会改进上次的静态+文件通讯录,先分析哪里可以改,然后再下手,最后测试。 先从动态方面开始改。

动态改进

首先是储存联系人的潍坊可以更改,因为你写了100不一定能存上100个位置,这样容易浪费空间,或者是100个不够你还要手动去更改,很麻烦,我们可以让他刚开始分配一小块那日村,不够就一直扩容。 我们这里初始能放3个联系人,不够的话每次加2个。(数量少方便测试)

初始化通讯录与添加联系人的更改

首先,因为动态内存函数的性质,我们需要把结构体: contacts.h

代码语言:javascript
复制
typedef struct person
{
	char name[20];//名字
	int age;//年龄
	char sex[20];//性别
	char phone[20];//电话
	char location[20];//住址
}person;

typedef struct contacts
{
	person *data;//存放人信息的位置
	int count;//记录通讯录的人数
	int capacity;//记录当前通讯录有多少人
}contacts;

存放人信息的位置给更改成指针,然后需要一个变量来统计通讯录的容量。 首先改一下初始化通讯录的函数: contacts.c

代码语言:javascript
复制
int initialize(contacts* pc)
{
	assert(pc != NULL);
	pc->count = 0;//将计数的变量初始化为0
	pc->data = calloc(3,sizeof(person));//开辟一个动态内存,然后把地址传给data指针
	if (pc->data == NULL)
	{
		printf("initialize:%s",strerror(errno));
		return 1;
	}
	pc->capacity = 3;//一开始让通讯录只有三个人的容量
	return 0;
}

这次改添加联系人的地方 既然是无限扩容,就没有通讯录已满这一说,我们把判断人是不是满给改掉。 当然,把增容的内容封装成一个函数更容易维护: contacts.c

代码语言:javascript
复制
void capacity_increase(contacts* pc)//增容
{
	if (pc->count == pc->capacity)
	{
		person* str = (person*)realloc(pc->data, sizeof(person) * (pc->capacity + 2));
		if (str == NULL)
		{
			printf("addcontact:%s", strerror(errno));
			return 1;
		}
		else
		{
			pc->data = str;
			pc->capacity += 2;
		}
		printf("增容成功\n");
	}
}

int addcontact(contacts* pc)
{
	assert(pc != NULL);//断言pc指向的位置不是空指针
	capacity_increase(pc);//增容
	printf("姓名:");
	scanf("%s", pc->data[pc->count].name);
	printf("年龄:");
	scanf("%d", &(pc->data[pc->count].age));
	printf("性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("电话号:");
	scanf("%s", pc->data[pc->count].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[pc->count].location);
	pc->count++;
	printf("增加成功\n");
}
在这里插入图片描述
在这里插入图片描述

当然,退出程序的时候也要释放掉开辟的内存,所以写一个销毁内存的函数。

代码语言:javascript
复制
void destroycontact(contacts* pc)
{
	assert(pc != NULL);
	free(pc->data);
	pc->data = NULL;
}

动态通讯录的完全体

contacts.h

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#define MAX 100//通讯录最大人数
//定义的结构体
typedef struct person
{
	char name[20];//名字
	int age;//年龄
	char sex[20];//性别
	char phone[20];//电话
	char location[20];//住址
}person;

typedef struct contacts
{
	person* data;//存放人信息的位置
	int count;//记录通讯录的人数
	int capacity;//记录当前通讯录有多少人
}contacts;
//函数声明区
int initialize(contacts* pc);//初始化通讯录
int addcontact(contacts* pc);//输入联系人信息
void showcontact(const contacts* pc);//打印通讯录
int delcontact(contacts* pc);//删除联系人
int modifycontact(contacts* pc);//修改联系人信息
int findcontact(contacts* pc);//查找联系人
void sortcontact(contacts* pc);//排序通讯录
void destroycontact(contacts* pc);//动态内存销毁

contacts.c

代码语言:javascript
复制
#include "contacts.h"

int find_out(char* p1, contacts* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	int i = 0;
	for (i = 0; i < p2->count; i++)
	{
		if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
			return i;
	}
	return -1;
}
void capacity_increase(contacts* pc)//增容
{
	if (pc->count == pc->capacity)
	{
		person* str = (person*)realloc(pc->data, sizeof(person) * (pc->capacity + 2));
		if (str == NULL)
		{
			printf("addcontact:%s", strerror(errno));
			return 1;
		}
		else
		{
			pc->data = str;
			pc->capacity += 2;
		}
		printf("增容成功\n");
	}
}
int initialize(contacts* pc)
{
	assert(pc != NULL);
	pc->count = 0;//将计数的变量初始化为0
	pc->data = (person*)calloc(3,sizeof(person));
	if (pc->data == NULL)
	{
		printf("initialize:%s",strerror(errno));
		return 1;
	}
	pc->capacity = 3;
	return 0;
}

int addcontact(contacts* pc)
{
	assert(pc != NULL);//断言pc指向的位置不是空指针
	capacity_increase(pc);//增容
	printf("姓名:");
	scanf("%s", pc->data[pc->count].name);
	printf("年龄:");
	scanf("%d", &(pc->data[pc->count].age));
	printf("性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("电话号:");
	scanf("%s", pc->data[pc->count].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[pc->count].location);
	pc->count++;
	printf("增加成功\n");
}

void showcontact(const contacts* pc)
{
	assert(pc != NULL);
	int i = 0;
	printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].phone,
			pc->data[i].location);
	}
}

int delcontact(contacts* pc)
{
	assert(pc != NULL);
	char name[20] = { 0 };
	printf("输入此人姓名\n");
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	pc->count = pc->count - 1;
	while (i < pc->count)
	{
		pc->data[i] = pc->data[i + 1];
		i++;
	}
	printf("删除成功\n");
}

int modifycontact(contacts* pc)
{
	assert(pc != NULL);
	printf("输入此人姓名\n");
	char name[20] = { 0 };
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	printf("请输入要修改的信息\n");
	printf("姓名:");
	scanf("%s", pc->data[i].name);
	printf("年龄:");
	scanf("%d", &(pc->data[i].age));
	printf("性别:");
	scanf("%s", pc->data[i].sex);
	printf("电话号:");
	scanf("%s", pc->data[i].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[i].location);
	printf("修改成功\n");
}

int findcontact(contacts* pc)
{
	assert(pc != NULL);
	printf("输入此人姓名\n");
	char name[20] = { 0 };
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
	printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
		pc->data[i].name,
		pc->data[i].age,
		pc->data[i].sex,
		pc->data[i].phone,
		pc->data[i].location);
}
int estimate(const void* p1, const void* p2)
{
	return strcmp(((person*)p1)->name, ((person*)p2)->name);
}
void sortcontact(contacts* pc)
{
	assert(pc != NULL);
	qsort(pc->data, pc->count, sizeof(person), estimate);
	printf("排序成功\n");
}

void destroycontact(contacts* pc)
{
	assert(pc != NULL);
	free(pc->data);
	pc->data = NULL;
}

test.c

代码语言:javascript
复制
#include "contacts.h"
enum list
{
	EXIT,
	ADD,
	DEL,
	MODIFY,
	FIND,
	SHOW,
	SORT
};
void catalogue()
{
	printf("*********************************\n");
	printf("***   1.add        2.del      ***\n");
	printf("***   3.modify     4.find     ***\n");
	printf("***   5.show       6.sort     ***\n");
	printf("***   0.exit                  ***\n");
	printf("*********************************\n");
}
int main()
{
	int n = 0;
	contacts con;//通讯录
	initialize(&con);//初始换通讯录
	do
	{
		catalogue();//通讯录菜单
		printf("请选择>");
		scanf("%d", &n);//选择要做什么
		switch (n)
		{
		case EXIT://退出程序
			destroycontact(&con);
			printf("退出通讯录\n");
			break;
		case ADD://添加联系人
			addcontact(&con);
			break;
		case DEL://删除联系人
			delcontact(&con);
			break;
		case FIND://查找联系人
			findcontact(&con);
			break;
		case MODIFY://修改联系人信息
			modifycontact(&con);
			break;
		case SHOW://展示联系人
			showcontact(&con);
			break;
		case SORT://排序通讯录
			sortcontact(&con);
			break;
		default:
			printf("输入错误请重新输入\n");
		}
	} while (n);
	return 0;
}

动态文件通讯录

无论是静态通讯录还是动态的通讯录其实都是在内存里面,第二次打开后之前的数据就全都没有了,那么这次我们让数据储存到文件里。 contacts.c

代码语言:javascript
复制
void stockpilecontact(contacts* pc)
{
	assert(pc != NULL);
	FILE* p1 = fopen("contacts.txt", "wb");//打开文件,以二进制方式写
	if (p1 == NULL)
	{
		perror("SaveContact");
		return;
	}
	int i = 0;
	for (i = 0; i < pc->count; i++)//输入通讯录中的成员信息
	{
		fwrite(pc->data + i, sizeof(person), 1, p1);

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

运行之后我们添加三个人的信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

然后打开我们的文件目录来看看:

在这里插入图片描述
在这里插入图片描述

这个就是我们刚刚生成的文件,里面有我们输入三个联系人的信息:

在这里插入图片描述
在这里插入图片描述

有些地方是乱码看不懂是因为这是以二进制形式输入。 现在我们想办法让这个通讯录读取这些联系人。 打开文件的地方当然要在初始化通讯录的时候读取文件内容。 读取要注意,我们把读取的联系人存在内存时,要先判断能不能放的下,放不下就要增容。 contacts.c

代码语言:javascript
复制
void capacity_increase(contacts* pc)//增容
{
	if (pc->count == pc->capacity)
	{
		person* str = (person*)realloc(pc->data, sizeof(person) * (pc->capacity + 2));
		if (str == NULL)
		{
			printf("addcontact:%s", strerror(errno));
			return 1;
		}
		else
		{
			pc->data = str;
			pc->capacity += 2;
		}
		printf("增容成功\n");
	}
}
void uploadcontacts(contacts* pc)//读取联系人函数
{
	FILE* p2 = fopen("contacts.txt", "rb");//打开文件二进制方式读
	if (p2 == NULL)
	{
		perror("OpenContacts");
		return 1;
	}
	person arr = { 0 };//文件读取数据的储存位置
	while (fread(&arr, sizeof(person), 1, p2))
	{
		capacity_increase(pc);//判断是否需要增容
		pc->data[pc->count] = arr;//存入内存中
		pc->count++;
	}
	fclose(p2);//关闭文件
	p2=NULL;
}
int initialize(contacts* pc)
{
	assert(pc != NULL);
	pc->count = 0;//将计数的变量初始化为0
	pc->data = (person*)calloc(3,sizeof(person));
	if (pc->data == NULL)
	{
		printf("initialize:%s",strerror(errno));
		return 1;
	}
	pc->capacity = 3;
	uploadcontacts(pc);// 读取通讯录
	return 0;
}

运行一下看看:

在这里插入图片描述
在这里插入图片描述

有上次输入的联系人。 我又添加了一个联系人,之后退出,再次打开然后展示:

在这里插入图片描述
在这里插入图片描述

完整版代码

contacts.h

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#define MAX 100//通讯录最大人数
//定义的结构体
typedef struct person
{
	char name[20];//名字
	int age;//年龄
	char sex[20];//性别
	char phone[20];//电话
	char location[20];//住址
}person;

typedef struct contacts
{
	person* data;//存放人信息的位置
	int count;//记录通讯录的人数
	int capacity;//记录当前通讯录有多少人
}contacts;
//函数声明区
int initialize(contacts* pc);//初始化通讯录
int addcontact(contacts* pc);//输入联系人信息
void showcontact(const contacts* pc);//打印通讯录
int delcontact(contacts* pc);//删除联系人
int modifycontact(contacts* pc);//修改联系人信息
int findcontact(contacts* pc);//查找联系人
void sortcontact(contacts* pc);//排序通讯录
void destroycontact(contacts* pc);//动态内存销毁
void stockpilecontact(contacts* pc);//储存到文件里
void uploadcontacts(contacts* pc);//读取文件

contacts.c

代码语言:javascript
复制
#include "contacts.h"

int find_out(char* p1, contacts* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	int i = 0;
	for (i = 0; i < p2->count; i++)
	{
		if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
			return i;
	}
	return -1;
}
void capacity_increase(contacts* pc)//增容
{
	if (pc->count == pc->capacity)
	{
		person* str = (person*)realloc(pc->data, sizeof(person) * (pc->capacity + 2));
		if (str == NULL)
		{
			printf("addcontact:%s", strerror(errno));
			return 1;
		}
		else
		{
			pc->data = str;
			pc->capacity += 2;
		}
		printf("增容成功\n");
	}
}
void uploadcontacts(contacts* pc)//读取联系人函数
{
	FILE* p2 = fopen("contacts.txt", "rb");//打开文件二进制方式读
	if (p2 == NULL)
	{
		perror("OpenContacts");
		return 1;
	}
	person arr = { 0 };
	
	while (fread(&arr, sizeof(person), 1, p2))
	{
		capacity_increase(pc);//判断是否需要增容
		pc->data[pc->count] = arr;
		pc->count++;
	}
	fclose(p2);//关闭文件
	p2 = NULL;
}
int initialize(contacts* pc)
{
	assert(pc != NULL);
	pc->count = 0;//将计数的变量初始化为0
	pc->data = (person*)calloc(3,sizeof(person));
	if (pc->data == NULL)
	{
		printf("initialize:%s",strerror(errno));
		return 1;
	}
	pc->capacity = 3;
	uploadcontacts(pc);// 读取通讯录
	return 0;
}

int addcontact(contacts* pc)
{
	assert(pc != NULL);//断言pc指向的位置不是空指针
	capacity_increase(pc);//增容
	printf("姓名:");
	scanf("%s", pc->data[pc->count].name);
	printf("年龄:");
	scanf("%d", &(pc->data[pc->count].age));
	printf("性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("电话号:");
	scanf("%s", pc->data[pc->count].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[pc->count].location);
	pc->count++;
	printf("增加成功\n");
}

void showcontact(const contacts* pc)
{
	assert(pc != NULL);
	int i = 0;
	printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].phone,
			pc->data[i].location);
	}
}

int delcontact(contacts* pc)
{
	assert(pc != NULL);
	char name[20] = { 0 };
	printf("输入此人姓名\n");
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	pc->count = pc->count - 1;
	while (i < pc->count)
	{
		pc->data[i] = pc->data[i + 1];
		i++;
	}
	printf("删除成功\n");
}

int modifycontact(contacts* pc)
{
	assert(pc != NULL);
	printf("输入此人姓名\n");
	char name[20] = { 0 };
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	printf("请输入要修改的信息\n");
	printf("姓名:");
	scanf("%s", pc->data[i].name);
	printf("年龄:");
	scanf("%d", &(pc->data[i].age));
	printf("性别:");
	scanf("%s", pc->data[i].sex);
	printf("电话号:");
	scanf("%s", pc->data[i].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[i].location);
	printf("修改成功\n");
}

int findcontact(contacts* pc)
{
	assert(pc != NULL);
	printf("输入此人姓名\n");
	char name[20] = { 0 };
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
	printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
		pc->data[i].name,
		pc->data[i].age,
		pc->data[i].sex,
		pc->data[i].phone,
		pc->data[i].location);
}
int estimate(const void* p1, const void* p2)
{
	return strcmp(((person*)p1)->name, ((person*)p2)->name);
}
void sortcontact(contacts* pc)
{
	assert(pc != NULL);
	qsort(pc->data, pc->count, sizeof(person), estimate);
	printf("排序成功\n");
}

void destroycontact(contacts* pc)
{
	assert(pc != NULL);
	free(pc->data);
	pc->data = NULL;
}
void stockpilecontact(contacts* pc)
{
	assert(pc != NULL);
	FILE* p1 = fopen("contacts.txt", "wb");//打开文件,以二进制方式写
	if (p1 == NULL)
	{
		perror("SaveContact");
		return;
	}
	int i = 0;
	for (i = 0; i < pc->count; i++)//输入通讯录中的成员信息
	{
		fwrite(pc->data + i, sizeof(person), 1, p1);

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

test.c

代码语言:javascript
复制
#include "contacts.h"
enum list
{
	EXIT,
	ADD,
	DEL,
	MODIFY,
	FIND,
	SHOW,
	SORT
};
void catalogue()
{
	printf("*********************************\n");
	printf("***   1.add        2.del      ***\n");
	printf("***   3.modify     4.find     ***\n");
	printf("***   5.show       6.sort     ***\n");
	printf("***   0.exit                  ***\n");
	printf("*********************************\n");
}
int main()
{
	int n = 0;
	contacts con;//通讯录
	initialize(&con);//初始换通讯录
	do
	{
		catalogue();//通讯录菜单
		printf("请选择>");
		scanf("%d", &n);//选择要做什么
		switch (n)
		{
		case EXIT://退出程序
			stockpilecontact(&con);
			destroycontact(&con);
			printf("退出通讯录\n");
			break;
		case ADD://添加联系人
			addcontact(&con);
			break;
		case DEL://删除联系人
			delcontact(&con);
			break;
		case FIND://查找联系人
			findcontact(&con);
			break;
		case MODIFY://修改联系人信息
			modifycontact(&con);
			break;
		case SHOW://展示联系人
			showcontact(&con);
			break;
		case SORT://排序通讯录
			sortcontact(&con);
			break;
		default:
			printf("输入错误请重新输入\n");
		}
	} while (n);
	return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 动态文件通讯录
  • 导语
  • 动态改进
    • 初始化通讯录与添加联系人的更改
      • 动态通讯录的完全体
      • 动态文件通讯录
      • 完整版代码
      相关产品与服务
      腾讯云服务器利旧
      云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档