C语言实现通讯录【二】(动态内存开辟,文件数据存储)
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语言实现通讯录【二】(动态内存开辟,文件数据存储)相关推荐
- 简陋版C语言仿真通讯录之动态内存开辟版本
简陋版C语言仿真通讯录 https://blog.csdn.net/csdn_kou/article/details/80287640 简陋版C语言仿真通讯录之动态内存开辟版本 给Contact结构体 ...
- 【C语言】动态内存开辟
目录 一.动态内存开辟的原因 二.动态内存开辟函数 1.malloc函数 2.free函数 3.calloc 4.realloc 总结 三.C/C++内存开辟 四.柔性数组 1.柔性数组定义 2.柔性 ...
- C/C++动态内存开辟详解(含常见错误以及经典面试题)
动态内存开辟 1.四个重要的内存函数 1.1 malloc和free 1.2 calloc 1.3 realloc 2.常见错误 2.1 对NULL指针进行解引用操作 2.2 对动态开辟内存的越界访问 ...
- C语言动态内存开辟详解(malloc,calloc,realloc,free,柔型数组)
目录 一.概述 二.相关库函数的使用 1.malloc 2.calloc malloc vs. calloc 异同 3.free的使用 4.realloc 三.易错点 四.C\C++程序的内存开辟规则 ...
- C语言之动态内存开辟之malloc
说到动态内存开辟,就不得不谈malloc.calloc.realloc以及free,所以接下来分别谈一下这四个函数. 1.malloc(开辟动态内存空间) 头文件:#include<stdlib ...
- C语言提高篇之——动态内存管理
目录 1. 动态内存分配存在的意义 2.动态内存函数介绍 2.1 malloc 2.2 free 2.3 calloc 2.4 realloc 3.常见的动态内存错误 3.1 对空指针解引用 3.2 ...
- 【c语言】通讯录【动态完整版有排序和文件操作】
一.通讯录是什么 二.通讯录的实现 一.通讯录是什么 通讯录 1.我假设这个通讯录能够存放每个学生的信息 每个人信息:名字+年龄+性别+电话+地址 我的目的是创建通讯录.实现对应功能,为了数据持久化放 ...
- 梓益C语言学习笔记之链表&动态内存&文件
梓益C语言学习笔记之链表&动态内存&文件 一.定义: 链表是一种物理存储上非连续,通过指针链接次序,实现的一种线性存储结构. 二.特点: 链表由一系列节点(链表中每一个元素称为节点)组 ...
- 通讯录(柔性数组,动态内存,文件读取、TXT)-C-20220120
C语言建立txt版通讯录(柔性数组,动态内存,文件读取) txt中包含了标题行和序号这些不需要录入结构体的内容,搞得函数很复杂,仔细考虑完善了一些异常情况,很多地方加了注释,代码有些繁杂没时间去进一步 ...
最新文章
- python字典默认输出键还是值_说说在 Python 字典中如何在读取不存在的键时得到一个默认值...
- Obejctive-C 中定义可变参函数
- UOJ#454-[UER #8]打雪仗【通信题】
- oracle去掉默认值sql,如何在T-SQL中删除默认值或类似约束?
- Linux内核访问外设I/O--动态映射(ioremap)和静态映射(map_desc) (转载)
- 电脑可以登微信但是登不上网页
- CHI到底是干嘛的 保证cache一致性 2.3 snoop
- 织梦模板建站必须学会的基本代码
- Java中Json解析
- 三种方式实现echarts树图的背景图片设置
- 你还在用二分法求2个鸡蛋100层楼的问题吗?
- ps水花飞溅效果制作
- windows计算机锁屏的快捷键是什么,电脑锁屏快捷键是什么
- “2020学术公众号100强”重磅发布,“年度学术公众号Top10”开启投票
- 【小程序实现五星好评功能】
- 试题 算法提高 编程求一元二次方程的根
- ltspice语言中文_ltspice-一简介(中文教程教本)新.pdf
- 软件测试面试英文自我介绍,软件测试英文自我介绍
- 16进制编码与字符编码的相互转化
- 百度统计js-api
热门文章
- 服务器系统重装后anaconda3安装以及环境配置
- 约瑟夫问题与魔术(六)——《自我匹配的奇迹》魔术赏析
- php出现NaN,【整理】PHP中的NaN是什么意思
- 215.	数组中的第 K个最大元素
- 耳机接口规则_耳机母座接口定义及使用注意事项
- c语言小游戏吧,【图片】C语言小游戏~贪吃蛇【c语言吧】_百度贴吧
- 李涛ps高手之路笔记2
- react 引入轮播插件_简单实现 babelpluginimport 插件
- ubuntu 搭建mysql环境_docker 搭建ubuntu+mysql环境教程
- html5调用封装库jar,H5项目如何调用aar、jar包资源(HBuilder离线打包实践)