C语言实现通讯录【二】

在C语言实现通讯录【一】的基础上进行优化,主要实现两大模块:

  • 动态内存开辟

  • 文件数据存储

动态内存开辟:

考虑到通讯录的大小无法固定,在C语言实现通讯录【一】版本上定义一个足够大的结构体数组进行通讯录信息存储,设置数组大小为固定大小1000,很明显造成了内存空间浪费,也存在超出存储空间的情况,对此,固定大小的数组存储就显得有点太low了,为何不试试动态内存开辟?

  • 通讯录初始化

首先修改通讯录结构体,将原有存放信息的结构体数组改为结构体指针,存放地址,方便指向malloc新开辟内存

同时,增加变量capacity  记录当前通讯录最大容量

//typedef struct contact//通讯录结构体  方便维护通讯录
//{
//  peoinfo data[MAX_PEOPLE];
//  int sz;//记录当前通讯录人数
//}contact;//****************************************************
typedef struct contact//通讯录结构体  方便维护通讯录
{peoinfo *data;//定义结构体指针 存放地址  方便内存开辟int sz;//记录当前通讯录人数int capacity;//通讯录当前最大容量 可根据当前容量来决定是否需要扩充
}contact;

在初始化过程中,利用malloc开辟一个默认存储容量的空间,设置默认容量大小为3  即初始开辟记录信息大小为3的空间

void Initcontact(contact* pc)
{pc->sz = 0;pc->capacity = DEFAULT_CAPCITY;pc->data = (peoinfo*)malloc(DEFAULT_CAPCITY * sizeof(peoinfo));if (pc->data == NULL){perror("Initcontact::malloc");return;}load_contact(pc);//通过文件写入数据初始化通讯录
}
  • 通讯录增容

在添加数据信息的过程中,如果用户添加的信息达到默认容量仍继续添加,需要扩容处理

首先判断,当前通讯录信息数目与默认容量的大小,达到默认容量后进行增容  每次增容大小设置为2

void check_capcity(contact* pc)
{if (pc->sz == pc->capacity){peoinfo* ptr = (peoinfo*)realloc(pc->data, (pc->capacity + CAP_V) * sizeof(peoinfo));if (ptr != NULL){pc->data = ptr;//realloc 修改容量  返回地址给data指针维护pc->capacity += CAP_V;printf("扩容成功\n");}else{perror("add_contact::realloc");}}
}

在进行添加功能前都需要进行容量判断,调用check_capcity()函数,进行是否需要增容操作

void add_contact(contact* pc)
{check_capcity(pc);printf("请输入姓名:");scanf("%s", pc->data[pc->sz].name);printf("请输入电话:");scanf("%s", pc->data[pc->sz].tele);printf("请输入地址:");scanf("%s", pc->data[pc->sz].addr);printf("请输入QQ:");scanf("%s", pc->data[pc->sz].qq);printf("请输入性别:");scanf("%s", pc->data[pc->sz].sex);printf("请输入年龄:");scanf("%hd", &(pc->data[pc->sz].age));pc->sz++;printf("添加成功");
}
  • 空间释放

注意!!!动态内存开辟一定要记得释放空间,在退出通讯录的时候必须释放所开辟的空间,以免内存泄漏

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

文件数据存储

  • 退出数据保存

引入文件流操作,以二进制写入,调用fwrite函数实现

void save_contact(contact* pc)
{//创建文件写入数据FILE* fpwrite = fopen("contact.dat", "wb");//二进制写入if (fpwrite == NULL){perror("open file for writing");return;}//创建成功 后写入for (int i = 0; i < pc->sz; i++){fwrite(pc->data+i,sizeof(peoinfo),1,fpwrite);}fclose(fpwrite);fpwrite = NULL;
}
  • 加载数据写入

在初始化通讯录函数中添加load_contact函数  通过读取文件数据初始化通讯录

读取过程中,利用fread特性逐条读取,其返回值为读取到信息的个数,每次读取为1条信息,返回为1,读取结束,返回为0

此时需要注意,是不是要一直读取直至文件所有信息都读取到进行初始化呢?我们通讯录的容量是否足够呢?

所以每读取到一条信息就需要一次容量判断,不足就进行增容操作

void load_contact(contact* pc)
{peoinfo tmp = { 0 };FILE* fpread = fopen("contact.dat","rb");if (fpread == NULL){perror("open file for reading");return;}while (fread(&tmp,sizeof(peoinfo),1,fpread)){check_capcity(pc);pc->data[pc->sz] = tmp;pc->sz++;}fclose(fpread);fpread = NULL;
}void Initcontact(contact* pc)
{pc->sz = 0;pc->capacity = DEFAULT_CAPCITY;pc->data = (peoinfo*)malloc(DEFAULT_CAPCITY * sizeof(peoinfo));if (pc->data == NULL){perror("Initcontact::malloc");return;}load_contact(pc);//通过文件写入数据初始化通讯录
}

C语言实现通讯录【二】(动态内存开辟,文件数据存储)相关推荐

  1. 简陋版C语言仿真通讯录之动态内存开辟版本

    简陋版C语言仿真通讯录 https://blog.csdn.net/csdn_kou/article/details/80287640 简陋版C语言仿真通讯录之动态内存开辟版本 给Contact结构体 ...

  2. 【C语言】动态内存开辟

    目录 一.动态内存开辟的原因 二.动态内存开辟函数 1.malloc函数 2.free函数 3.calloc 4.realloc 总结 三.C/C++内存开辟 四.柔性数组 1.柔性数组定义 2.柔性 ...

  3. C/C++动态内存开辟详解(含常见错误以及经典面试题)

    动态内存开辟 1.四个重要的内存函数 1.1 malloc和free 1.2 calloc 1.3 realloc 2.常见错误 2.1 对NULL指针进行解引用操作 2.2 对动态开辟内存的越界访问 ...

  4. C语言动态内存开辟详解(malloc,calloc,realloc,free,柔型数组)

    目录 一.概述 二.相关库函数的使用 1.malloc 2.calloc malloc vs. calloc 异同 3.free的使用 4.realloc 三.易错点 四.C\C++程序的内存开辟规则 ...

  5. C语言之动态内存开辟之malloc

    说到动态内存开辟,就不得不谈malloc.calloc.realloc以及free,所以接下来分别谈一下这四个函数. 1.malloc(开辟动态内存空间) 头文件:#include<stdlib ...

  6. C语言提高篇之——动态内存管理

    目录 1. 动态内存分配存在的意义 2.动态内存函数介绍 2.1 malloc 2.2 free 2.3 calloc 2.4 realloc 3.常见的动态内存错误 3.1 对空指针解引用 3.2 ...

  7. 【c语言】通讯录【动态完整版有排序和文件操作】

    一.通讯录是什么 二.通讯录的实现 一.通讯录是什么 通讯录 1.我假设这个通讯录能够存放每个学生的信息 每个人信息:名字+年龄+性别+电话+地址 我的目的是创建通讯录.实现对应功能,为了数据持久化放 ...

  8. 梓益C语言学习笔记之链表&动态内存&文件

    梓益C语言学习笔记之链表&动态内存&文件 一.定义: 链表是一种物理存储上非连续,通过指针链接次序,实现的一种线性存储结构. 二.特点: 链表由一系列节点(链表中每一个元素称为节点)组 ...

  9. 通讯录(柔性数组,动态内存,文件读取、TXT)-C-20220120

    C语言建立txt版通讯录(柔性数组,动态内存,文件读取) txt中包含了标题行和序号这些不需要录入结构体的内容,搞得函数很复杂,仔细考虑完善了一些异常情况,很多地方加了注释,代码有些繁杂没时间去进一步 ...

最新文章

  1. python字典默认输出键还是值_说说在 Python 字典中如何在读取不存在的键时得到一个默认值...
  2. Obejctive-C 中定义可变参函数
  3. UOJ#454-[UER #8]打雪仗【通信题】
  4. oracle去掉默认值sql,如何在T-SQL中删除默认值或类似约束?
  5. Linux内核访问外设I/O--动态映射(ioremap)和静态映射(map_desc) (转载)
  6. 电脑可以登微信但是登不上网页
  7. CHI到底是干嘛的 保证cache一致性 2.3 snoop
  8. 织梦模板建站必须学会的基本代码
  9. Java中Json解析
  10. 三种方式实现echarts树图的背景图片设置
  11. 你还在用二分法求2个鸡蛋100层楼的问题吗?
  12. ps水花飞溅效果制作
  13. windows计算机锁屏的快捷键是什么,电脑锁屏快捷键是什么
  14. “2020学术公众号100强”重磅发布,“年度学术公众号Top10”开启投票
  15. 【小程序实现五星好评功能】
  16. 试题 算法提高 编程求一元二次方程的根
  17. ltspice语言中文_ltspice-一简介(中文教程教本)新.pdf
  18. 软件测试面试英文自我介绍,软件测试英文自我介绍
  19. 16进制编码与字符编码的相互转化
  20. 百度统计js-api

热门文章

  1. 服务器系统重装后anaconda3安装以及环境配置
  2. 约瑟夫问题与魔术(六)——《自我匹配的奇迹》魔术赏析
  3. php出现NaN,【整理】PHP中的NaN是什么意思
  4. 215. 数组中的第 K个最大元素
  5. 耳机接口规则_耳机母座接口定义及使用注意事项
  6. c语言小游戏吧,【图片】C语言小游戏~贪吃蛇【c语言吧】_百度贴吧
  7. 李涛ps高手之路笔记2
  8. react 引入轮播插件_简单实现 babelpluginimport 插件
  9. ubuntu 搭建mysql环境_docker 搭建ubuntu+mysql环境教程
  10. html5调用封装库jar,H5项目如何调用aar、jar包资源(HBuilder离线打包实践)