【c语言进阶】动态通讯录
创始人
2024-05-22 00:35:07
0

在这里插入图片描述

🚀write in front🚀
📜所属专栏: c语言学习
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

文章目录

  • 前言:
  • 一、静态通讯录的弊端:
  • 二、动态增容优化通讯录:
    • 2.1.枚举类型的加入
    • 2.2.结构体的修改
    • 2.3.Initcontact函数的修改
    • 2.4.Addcontact函数的修改
    • 2.5.Desdrycontact函数的添加
  • 三、文件操作优化通讯录:
    • 3.1.Savecontact函数的添加(通讯录信息保存)
    • 3.2.Loadcontact函数的添加(导入通讯录信息)
  • 四、完整代码展示:
    • contact.h:
    • test.c
    • contact.c
  • 总结:

前言:

  在前面的学习中,我们写了静态通讯录:c语言实现静态通讯录

一、静态通讯录的弊端:

  对于简易版本的通讯录来说,我们是直接指定了通讯录的大小,那么此时我们会发现两个弊端:

弊端1:

  如果我们创建的通讯录空间过大,就会浪费空间;如果我们创建的通讯录太小又不够使用 。所以,此时我们就得优化通信录给定空间上的问题,不能再给其指定大小的空间,而是让其空间有灵活性此时我们以动态增容的方式来给定通讯录的空间,就很好的规避了这一问题!

弊端2:

  我们知道程序运行起来我们输入的数据都是保存在内存上的,在简易版本中我们在运行通讯录之后添加的数据,在程序结束的时候都会被清除。当而我们既然要保存联系人的信息,就得做到数据持久化的保存,我们就得将数据保存到硬盘中,也就是文件当中,此时我们可以用文件操作的方式来实现持久化的保存联系人信息。

二、动态增容优化通讯录:

2.1.枚举类型的加入

  在前面我们学习了枚举类型的使用,我们在写menu菜单的switch函数时,常常会因为不知道数字对应的是哪一个功能而弄混。
  枚举类型中各成员的从零开始依次递增,于是我们可以再使用一个枚举类型来使我们的选项对应用户的选择:

enum OPTION
{Exit = 0,Add = 1,Del,Search,Modify,Print,sort
};

  这样一来,我们就可以把case后面的1,2,3等数据换成对应的功能名字。
case 1:替换为case Add:

2.2.结构体的修改

  之前我们创建了两个结构体,第一个存放信息,第二个存放信息的数组和联系人数量,可是第二个存放的人信息的数组规定死了100个元素。所以我们将第二个结构体做一下改动即可:

//静态版本
//typedef struct contact
//{
//	PeoInfo data[MAX];
//	int sz;
//}contact;//动态版本
typedef struct Contact
{PeoInfo* data;//指向存放人的信息的空间int sz;//当前已经放的信息的个数int capacity;//当前通讯录的最大容量
}contact;

  这里我们用sz记录联系人数量,用capacity指向当前通讯录的最大容量。在这里我们会发现结构体明显小了很多,因为存放人信息的空间我们还没有创建!

2.3.Initcontact函数的修改

  之前的初始化仅仅只是将所有的数据初始化为0,但是动态版本的通讯录还没有开辟联系人的空间。所有我们要在初始化函数里完成这个操作。

//静态版本:
//void Initcontact(contact* con)
//{
//	assert(con);
//	con->sz = 0;
//	memset(con->data, 0, sizeof(con->data));
//}//动态版本:
void Initcontact(contact* con)
{assert(con);//DEFAULT_SZ是宏定义的3,在contact.h有添加!PeoInfo *ptr= (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));if (ptr == NULL){perror("InitContact::calloc");return;}con->sz = 0;con->capacity = DEFAULT_SZ;con->data = ptr;//这里的Loadcontact函数在下面会提到!LoadContact(con);
}

  在这里大家就不用自己初始化联系人信息了!因为calloc本身就有这个功能!

2.4.Addcontact函数的修改

  之前静态通讯录的添加联系人只需要在不超过容量的基础上添加即可,超过容量就不能操作了。但是动态通讯录在发现容量不足时要有自动增容的功能,这也是动态通讯录的有点所在!

//静态add
//void AddContact(contact* con)
//{
//	assert(con);
//	if (con->sz == 99)
//	{
//		printf("通讯录已经存满,请联系操作人员");
//		return;
//	}
//	printf("请输入联系人姓名:>");
//	scanf("%s", con->data[con->sz].name);
//	printf("请输入联系人性别:>");
//	scanf("%s",con->data[con->sz].sex);
//	printf("请输入联系人年龄:>");
//	scanf("%d", &(con->data[con->sz].age));
//	printf("请输入联系人联系方式:>");
//	scanf("%s", con->data[con->sz].tele);
//	printf("请输入联系人住址:>");
//	scanf("%s", con->data[con->sz].addr);
//	printf("联系人信息添加成功!\n");
//	con->sz++;
//}
// 
//判断容量是否够用!并且自动增容
void check_capacity(contact* con)
{assert(con);if (con->sz == con->capacity){printf("内存已满,正在扩容——\n");Sleep(1000);PeoInfo* ptr = (PeoInfo*)realloc(con->data, (con->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr==NULL){perror("check_capacity::realloc");return;}con->capacity += INC_SZ;con->data = ptr;printf("扩容成功\n");}
}
//动态add
void AddContact(contact* con)
{assert(con);check_capacity(con);printf("请输入联系人姓名:>");scanf("%s", con->data[con->sz].name);printf("请输入联系人性别:>");scanf("%s", con->data[con->sz].sex);printf("请输入联系人年龄:>");scanf("%d", &(con->data[con->sz].age));printf("请输入联系人联系方式:>");scanf("%s", con->data[con->sz].tele);printf("请输入联系人住址:>");scanf("%s", con->data[con->sz].addr);printf("联系人信息添加成功!\n");con->sz++;
}

2.5.Desdrycontact函数的添加

  在使用完堆区的空间之后,最重要的事情是什么?当然是释放这块空间呀!

void DestroyContact(contact* con)
{free(con->data);con->data = NULL;con->sz = 0;con->capacity = 0;con = NULL;
}

三、文件操作优化通讯录:

3.1.Savecontact函数的添加(通讯录信息保存)

  为了在保存内存中操作完成后的所有联系人信息,我们在程序退出之前将联系人信息以2进制的方式写进文件里面

void SaveContact(contact* con)
{FILE* fp = fopen("contact.txt", "wb");if (fp==NULL){perror("SaveContact");}else{ printf("正在保存\n");Sleep(1000);for (int i = 0; i < con->sz; i++)fwrite(con->data + i, sizeof(PeoInfo), 1, fp);fclose(fp);fp = NULL;printf("保存成功\n");}
}

3.2.Loadcontact函数的添加(导入通讯录信息)

  在我们对于通讯录进行修改时,要将之前文件中存好的信息导入内存中去,这个步骤也应该在初始化函数中进行,我们将他分装为函数,代码如下:

void LoadContact(contact* con)
{FILE* fp = fopen("contact.txt", "rb");PeoInfo str={ 0 };if (fp==NULL){perror("LoadContact");}else{printf("正在加载>>>\n");Sleep(1000);int i = 0;while (fread(&str, sizeof(PeoInfo), 1, fp)){check_capacity(con);con->data[i] = str;con->sz++;i++;}}fclose(fp);fp = NULL;printf("加载成功!\n");
}

四、完整代码展示:

contact.h:


#pragma once
#include
#include
#include
#include#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 20#define DEFAULT_SZ 3
#define INC_SZ 2enum OPTION
{Exit = 0,Add = 1,Del,Search,Modify,Print,sort
};typedef struct PeoInfo
{char name[MAX_NAME];char sex[MAX_SEX];int age;char addr[MAX_ADDR];char tele[MAX_TELE];
}PeoInfo;//静态版本
//typedef struct contact
//{
//	PeoInfo data[MAX];
//	int sz;
//}contact;//动态版本
typedef struct Contact
{PeoInfo* data;//指向存放人的信息的空间int sz;//当前已经放的信息的个数int capacity;//当前通讯录的最大容量
}contact;//初始化消息
void Initcontact(contact *con);//增加消息
void AddContact(contact *con);//删除信息
void DelContact(contact *con);//查找个别人消息
void SeachContact(contact *con);//修改个别人消息
void ModifyContact(contact* con);//打印全部通讯录
void PrintContact(contact* con);//排序通讯录
void sortContact(contact* con);//保存通讯录中的信息到文件中
void SaveContact(contact* con);//加载文件信息到通讯录
void LoadContact(contact* con);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"void menu()
{printf("**********************************\n");printf("**********************************\n");printf("******** 欢迎使用本通讯录 ********\n");printf("**********************************\n");printf("***** 本通讯录现提供以下功能 *****\n");printf("************ 1.Add ***************\n");printf("************ 2.Del ***************\n");printf("************ 3.Search ************\n");printf("************ 4.Modify ************\n");printf("************ 5.Print *************\n");printf("************ 6.sort **************\n");printf("************ 0.exit**************\n");printf("**********************************\n");
}
void Contact()
{int input = 0;contact con;Initcontact(&con);do{menu();printf("请选择>");scanf("%d", &input);switch (input){case Add:AddContact(&con);break;case Del:DelContact(&con);break;case Search:SeachContact(&con);break;case Modify:ModifyContact(&con);break;case Print:PrintContact(&con);break;case sort:sortContact(&con);break;case Exit:SaveContact(&con);DestroyContact(&con);printf("已成功退出");break;default:printf("输入错误,请重新输入\n");break;}} while (input);}
int main()
{Contact();return 0;
}

contact.c

#define _CRT_SECURE_NO_WARNINGS 1#include "contact.h"int FindByName(contact* con, char name[])
{assert(con);int i = 0;for (i = 0; i < con->sz; i++){if (strcmp(con->data[i].name,name) == 0){return i;}}return -1;
}
//静态版本:
//void Initcontact(contact* con)
//{
//	assert(con);
//	con->sz = 0;
//	memset(con->data, 0, sizeof(con->data));
//}//动态版本:
void Initcontact(contact* con)
{assert(con);PeoInfo *ptr= (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));if (ptr == NULL){perror("InitContact::calloc");return;}con->sz = 0;con->capacity = DEFAULT_SZ;con->data = ptr;LoadContact(con);
}void DestroyContact(contact* con)
{free(con->data);con->data = NULL;con->sz = 0;con->capacity = 0;con = NULL;//??}
//静态add
//void AddContact(contact* con)
//{
//	assert(con);
//	if (con->sz == 99)
//	{
//		printf("通讯录已经存满,请联系操作人员");
//		return;
//	}
//	printf("请输入联系人姓名:>");
//	scanf("%s", con->data[con->sz].name);
//	printf("请输入联系人性别:>");
//	scanf("%s",con->data[con->sz].sex);
//	printf("请输入联系人年龄:>");
//	scanf("%d", &(con->data[con->sz].age));
//	printf("请输入联系人联系方式:>");
//	scanf("%s", con->data[con->sz].tele);
//	printf("请输入联系人住址:>");
//	scanf("%s", con->data[con->sz].addr);
//	printf("联系人信息添加成功!\n");
//	con->sz++;
//}
// void check_capacity(contact* con)
{assert(con);if (con->sz == con->capacity){printf("内存已满,正在扩容——\n");Sleep(1000);PeoInfo* ptr = (PeoInfo*)realloc(con->data, (con->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr==NULL){perror("check_capacity::realloc");return;}con->capacity += INC_SZ;con->data = ptr;printf("扩容成功\n");}
}
//动态add
void AddContact(contact* con)
{assert(con);check_capacity(con);printf("请输入联系人姓名:>");scanf("%s", con->data[con->sz].name);printf("请输入联系人性别:>");scanf("%s", con->data[con->sz].sex);printf("请输入联系人年龄:>");scanf("%d", &(con->data[con->sz].age));printf("请输入联系人联系方式:>");scanf("%s", con->data[con->sz].tele);printf("请输入联系人住址:>");scanf("%s", con->data[con->sz].addr);printf("联系人信息添加成功!\n");con->sz++;
}
void DelContact(contact* con)
{assert(con);char name[100];if (con->sz == 0){printf("通讯录为空,无法删除\n");return;}printf("请输入要删除人名字:>");scanf("%s", name);int ret = FindByName(con, name);int i = 0;if (-1 == ret){printf("没有找到此人\n");return;}else{for (i = ret; i < con->sz-1; i++){con->data[i] = con->data[i + 1];}con->sz--;memset(&con->data[i], 0, sizeof(con->data[i]));printf("删除成功!\n");}
}void SeachContact(contact* con)
{assert(con);char name[MAX_NAME];if (con->sz == 0){printf("通讯录为空,无法输入\n");return;}printf("请输入查找人名字");scanf("%s", name);int ret = FindByName(con, name);if (ret == -1){printf("您查找的人不存在!\n");return;}printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", con->data[ret].name, con->data[ret].age, con->data[ret].sex, con->data[ret].addr, con->data[ret].tele);
}void ModifyContact(contact* con)
{assert(con);char name[MAX_NAME] = { 0 };if (con->sz == 0){printf("通讯录为空,无法修改\n");return;}printf("请输入查找人名字");scanf("%s", name);int ret = FindByName(con, name);if (-1 == ret){printf("您要修改的人不存在\n");return;}printf("请输入联系人姓名:>");scanf("%s", con->data[ret].name);printf("请输入联系人性别:>");scanf("%s", con->data[ret].sex);printf("请输入联系人年龄:>");scanf("%d", &(con->data[ret].age));printf("请输入联系人住址:>");scanf("%s", con->data[ret].addr);printf("请输入联系人联系方式:>");scanf("%s", con->data[ret].tele);printf("联系人信息修改成功!\n");
}void PrintContact(contact* con)
{printf("%-10s\t%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n","联系人", "姓名", "年龄", "性别", "地址", "电话");for (int i = 0; i < con->sz; i++){printf("%-10d\t%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n",i+1, con->data[i].name,con->data[i].age,con->data[i].sex,con->data[i].addr,con->data[i].tele);}
}int cmp_con_by_name(const void* e1, const void* e2)
{return (strcmp(((PeoInfo *)e1)->name, ((PeoInfo*)e2)->name));
}
void sortContact(contact* con)
{assert(con);if (0 == con->sz){printf("通讯录为空,无法排序\n");return;}qsort(con->data, con->sz, sizeof(con->data[0]), cmp_con_by_name);printf("排序成功\n");
}void SaveContact(contact* con)
{FILE* fp = fopen("contact.txt", "wb");if (fp==NULL){perror("SaveContact");}else{ printf("正在保持\n");Sleep(1000);for (int i = 0; i < con->sz; i++)fwrite(con->data + i, sizeof(PeoInfo), 1, fp);fclose(fp);fp = NULL;printf("保存成功\n");}
}void LoadContact(contact* con)
{FILE* fp = fopen("contact.txt", "rb");PeoInfo str={ 0 };if (fp==NULL){perror("LoadContact");}else{printf("正在加载>>>\n");Sleep(1000);int i = 0;while (fread(&str, sizeof(PeoInfo), 1, fp)){check_capacity(con);con->data[i] = str;con->sz++;i++;}}fclose(fp);fp = NULL;printf("加载成功!\n");
}

总结:

  我们通过文件操作的知识和动态内存空间管理的知识终于完善了动态通讯录的编写!相信大家在自己真正写出来之后都会感觉学有所成!
  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
c语言学习
算法
智力题
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

相关内容

热门资讯

圣诞节活动主持词节目串词 圣诞节活动主持词节目串词3篇  根据活动对象的不同,需要设置不同的主持词。在人们积极参与各种活动的今...
生日华诞主持词 生日华诞主持词范文各位领导,各位朋友,各位来宾,女士们,先生们:  中午好。  今天是个喜庆的日子,...
学术会议主持词 学术会议主持词  什么是主持词  由主持人于节目进行过程中串联节目的串联词。如今的各种演出活动和集会...
订婚仪式及主持词 订婚仪式及主持词范文(通用3篇)  活动对象的不同,主持词的写作风格也会大不一样。在现在的社会生活中...
古剑奇谭欧阳少恭经典台词参考 古剑奇谭欧阳少恭经典台词参考  大型古装玄幻剧《古剑奇谭》正在湖南卫视热播,剧中,乔振宇饰演温文尔雅...
幼儿园晨会主持词 幼儿园晨会主持词  美好的一天从早上开始,从晨会开始,从大家的好的状态开始,从最好的开始。以下是小编...
诗文诵读展示主持词 诗文诵读展示主持词  主持词没有固定的格式,他的最大特点就是富有个性。在当今不断发展的世界,很多晚会...
大学生毕业典礼的主持词 大学生毕业典礼的主持词(精选5篇)  活动对象的不同,主持词的写作风格也会大不一样。在当下的社会中,...
婚礼的主持词 婚礼的主持词  婚礼的主持词(精选21篇)  主持词的写作要突出活动的主旨并贯穿始终。随着社会一步步...
主婚人致辞 主婚人致辞(精选6篇)  在生活、工作和学习中,大家都写过致辞吧,致辞具有很强的实用性和针对性。还在...
促销活动主持词 促销活动主持词  利用在中国拥有几千年文化的诗词能够有效提高主持词的感染力。在现今人们越来越重视活动...
小品活动的主持词 小品活动的主持词  【篇一】  各位亲爱的老师,同学们,大家下午好!  欢迎来到天津师范大学新闻传播...
森林报好词好句 森林报好词好句  好词:  小巧玲珑 飞云流雾 红日西垂 霞光四射 层峦叠嶂 水天相接  轻歌曼舞 ...
早会主持稿 早会主持稿(精选5篇)  在现在社会,我们可以使用主持稿的机会越来越多,主持稿是主持人为节目进行过程...
优秀员工颁奖词 优秀员工颁奖词大全  在平时的学习、工作或生活中,大家都经常接触到颁奖词吧,颁奖词是在某一主题的颁奖...
女儿出阁司仪主持词 女儿出阁司仪主持词范文  主持词要把握好吸引观众、导入主题、创设情境等环节以吸引观众。在当下的中国社...
歌颂祖国串词 歌颂祖国串词一。各位领导 各位来宾,大家晚上好。今天我们这里篷壁生辉,喜气洋溢,是因为有您们的光临,...
小学生庆元旦联欢会主持词 小学生庆元旦联欢会主持词范文(精选5篇)  主持词要注意活动对象,针对活动对象写相应的主持词。在现今...