C语言动态内存讲解+通讯录2.0

文章目录

  • 前文
  • malloc和free
  • calloc
  • realloc
    • 枚举常量的简单说明及使用
  • 通讯录2.0
      • 动态开辟通讯录,满了就扩容
      • 保存数据和载入数据
    • 通讯录2.0演示
    • 推荐好用的软件

前文

本文主要介绍动态开辟的几个函数,以及改进之前的通讯录。

在这里插入图片描述

我们局部变量等是在栈区上开辟空间的,而我们动态开辟的空间在堆上面。

头文件: #include<stdlib.h>

函数介绍:
动态开辟空间的函数有以下四个,下面由我来一一介绍
malloc
calloc
realloc
free

malloc和free

malloc是开辟一块连续的空间

在这里插入图片描述

用法如下,需要注意的是,由于malloc是动态开辟内存的,所以我们需要判断是否开辟成功,如果是NULL就说明开辟失败了,malloc如果开辟失败了就会返回NULL;

free则是专门释放由动态开辟的空间的。

#include <stdlib.h>
int main()
{int* arr = (int*)malloc(INT_MAX);if (arr == NULL){perror("malloc arr");return 1;}int  i = 0;for (i = 0; i < 10; i++){arr[i] = i + 1;}for (i = 0; i < 10; i++){printf("%d ", arr[i]);}free(arr);arr = NULL;return 0;
}

在这里插入图片描述
下面我们通过调试来开一下free的过程
在这里插入图片描述

这里可以看到当我们malloc完后,arr就指向了一块有10个整型大小的连续空间

在这里插入图片描述
当我们free完之后发现虽然我们的空间已经被收回了,但是arr此时还是保留着那片空间的地址,此时arr就是野指针,不能继续使用,所以每当我们使用完动态开辟的空间free之后,我们都应该手动的把这块空间置为NULL

在这里插入图片描述
接下来验证以下malloc开辟失败的情况。
在这里插入图片描述
我们把malloc的参数设置为INT_MAX,INT_MAX表示整型所能容纳的最大整数,在x86的环境上,此时就是INT_MAX就是我们所拥有的最大空间,但不可能把所有的内存都给arr,所以开辟失败,此时arr指向NULL

calloc

calloc和malloc的区别就是calloc开辟的空间是初始化过了的。

在这里插入图片描述

同时calloc开辟的空间用完以后,也要free掉,同时置为NULL。

在这里插入图片描述

realloc

realloc是当空间大小不够的时候,可以在增加空间的大小,当然也可以减少空间

在这里插入图片描述
同时realloc开辟空间分两种情况如图:
在这里插入图片描述

#include <stdlib.h>int main()
{int* arr_malloc = (int*)malloc(40);if (arr_malloc == NULL){perror("malloc fail!");return 1;}int  i = 0;for (i = 0; i < 10; i++){arr_malloc[i] = i + 1;}int* ptr = (int*)realloc(arr_malloc, 80);if (ptr == NULL){perror("realloc fail!");return 1;}arr_malloc = ptr;for (i = 10; i < 20; i++){arr_malloc[i] = i + 1;}for (i = 0; i < 20; i++){printf("%d ", arr_malloc[i]);}free(arr_malloc);arr_malloc = NULL;return 0;
}

在这里插入图片描述
可以看到ptr直接拷贝了原空间的内容,此时后面的空间大小足够,所以直接在原空间后开辟。,用完不要忘记free和置NULL
在这里插入图片描述
此时来看一下如果后面空间不够是不是真的重新开辟了呢?
在这里插入图片描述
如图所示,当原空间后的空间不够的时候确实会重新开辟,并把原空间的内容拷贝过去。

到这里动态开辟的函数我们讲解就完毕了,前面我已经发过了文件的,接下来我们来对我们上次的通讯录进行改进

枚举常量的简单说明及使用

枚举顾名思义就是一一列举的意思,
把可能的值列举出来

比如在生活中有星期一~星期天,可以一一列举

在这里插入图片描述
枚举和结构体的用法类似,不过枚举里面成员变量使用逗号隔开的。同时枚举里面如果你不规定的话,第一个默认为0,而且你枚举出来的值是可以直接使用的,不需要像结构体一样通过.或着->去访问成员。

通讯录2.0

通讯录1.0版本地址

1.0版本问题:
1.没办法对数据进行保存
2.空间大小固定了,不能修改

解决方案:
1.每次退出程序的时候把数据保存到文件中,初始化的时候导入数据到内存中
2.空间动态开辟,同时给一个容量,每次满了,就扩容。

同时这个的switch选项我们可以使用枚举美观一下
在这里插入图片描述

enum
{EXIT,//0ADD,DEL,SEARCH,MODIFY,SHOW,SORT//6
};

在这里插入图片描述

动态开辟通讯录,满了就扩容

在这里插入图片描述
此时我们应该把上面的data改成指针形式而不是数组,同时定义每次扩容扩充几个

//定义容量
#define INC_SZ 3
//通讯录
typedef struct Contact
{int count;//表示当前人数PeoInfor* data;int capacity;}Contact;

接下来就是改变初始化函数了。
原函数
在这里插入图片描述
改完之后

//初始化通讯录
void InitialPeoInfor(Contact* pc)
{assert(pc);pc->count = 0;pc->capacity = INC_SZ;//我这里把容量初始化为INC_SZ,写几个都可以看你自己pc->data = (PeoInfor*)malloc(pc->capacity * sizeof(PeoInfor));if (pc->data == NULL){perror("malloc fail!");return;}
}

接下来就是扩容的问题了,扩容我们写在添加联系人这个函数里面

//检查容量
void check_capacity(Contact* pc)
{//当我们通讯录的人数跟容量相同了,就说明满了,此时需要扩容if (pc->count == pc->capacity){PeoInfor* ptr = (PeoInfor*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfor));if (ptr == NULL){perror("realloc fail!");return;}pc->data = ptr;pc->capacity += INC_SZ;//扩容后把容量加上扩容的数量printf("扩容成功\n");}
}

此时运行可以发现当我们输完3个人再想输入的时候会提示扩容成功。
在这里插入图片描述

既然我们的通讯录是通过动态开辟来的,那么我们肯定要free掉,所以我们再写一个销毁数据的函数。

//销毁数据
void DesTory(Contact* pc)
{assert(pc);free(pc->data);pc->data = NULL;
}

在这里插入图片描述

保存数据和载入数据

保存数据是当我们程序退出的时候保存,这里我们写一个SaveData()函数来实现保存数据

这里的数据我们以二进制的形式写入,这样就可以对数据进行一定的保护。
既然二进制的形式写入,我们来复习以下fwritefread这两个函数吧。
在这里插入图片描述

//保存数据
void SaveData(Contact* pc)
{assert(pc);//                           wb表示以二进制形式写入FILE* pf = fopen("data.txt", "wb");if (pf == NULL){perror("fopen fail!");return;}int i = 0;for (i = 0; i < pc->count; i++){fwrite(pc->data + i, sizeof(PeoInfor), 1, pf);}printf("保存成功\n");
}

同时载入数据的时候我们要对容量进行检查
在这里插入图片描述

//载入数据
void LoadPeoInfor(Contact* pc)
{FILE* pf = fopen("data.txt", "rb");if (pf == NULL){perror("Read data fopen");return;}PeoInfor tmp = { 0 };while (fread(&tmp, sizeof(PeoInfor), 1, pf) == 1)//每次读一个{check_capacity(pc);pc->data[pc->count] = tmp;pc->count++;}
}//初始化通讯录
void InitialPeoInfor(Contact* pc)
{assert(pc);pc->count = 0;pc->capacity = INC_SZ;pc->data = (PeoInfor*)malloc(pc->capacity * sizeof(PeoInfor));if (pc->data == NULL){perror("malloc fail!");return;}LoadPeoInfor(pc);
}

通讯录2.0演示

在这里插入图片描述

推荐好用的软件

这里推荐两款软件,一个就是我这个鼠标,他的图标变成了羽毛,还是挺方便找鼠标指针的。
第二个就是这个gif录制软件了,ScreenTOGif,真的挺好用的。
安装包放在文章顶部啦~。

鼠标那个我上传上去了,好像只能上传一个,gif录制我直接给下载链接吧。
ScreenTOGif官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/785668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新model开发记录

模型使用 -- 用blender导出为 fbx &#xff0c;修改渲染方式&#xff08;点击模型->Materials->Extract Materials(将材质从fbx中 单独提取出来了)->Materials 选择 Shader -> SimpleURPToonLitExample 点开脸的材质&#xff0c;勾选第一条&#xff09; 解决角色…

力扣-python-故障键盘

题解&#xff1a; from collections import dequeclass Solution:def finalString(self, s: str) -> str:# 创建一个双端队列用于存储字符q deque()# 定义一个标志位&#xff0c;用于标记当前字符应该添加到队列的哪一端head False# 遍历输入的字符串s的每一个字符for ch…

C++刷题篇——05静态扫描

一、题目 二、解题思路 注意&#xff1a;注意理解题目&#xff0c;缓存的前提是先扫描一次 1、使用两个map&#xff0c;两个map的key相同&#xff0c;map1&#xff1a;key为文件标识&#xff0c;value为文件出现的次数&#xff1b;map2&#xff1a;key为文件标识&#xff0c;va…

CTF wed安全(攻防世界)练习题

一、Training-WWW-Robots 进入网站如图&#xff1a; 翻译&#xff1a;在这个小小的挑战训练中&#xff0c;你将学习Robots exclusion standard。网络爬虫使用robots.txt文件来检查它们是否被允许抓取和索引您的网站或只是其中的一部分。 有时这些文件会暴露目录结构&#xff0c…

【数据结构】优先级队列——堆

&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;个人主页&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388; &#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;数据结构专栏&#x1f388;&#x1f388;&#x1f388;&…

C++11:右值引用

C11&#xff1a;右值引用 右值与左值右值引用语法右值引用底层移动语义引用折叠完美转发 传统的C语法中就有引用的语法&#xff0c;而C11中新增了的右值引用语法特性&#xff0c;所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用&#xff0c;都是给对…

VR全景赋能智慧农业,打造沉浸式种植体验平台

随着人口的增长&#xff0c;传统农业也正在面临着不一样的挑战&#xff0c;加上很多人对农业的固有印象&#xff0c;很少有年轻人愿意下到农田里&#xff0c;那么该如何提高产量、降低成本以及引导年轻人深刻感受现代农业成为了急需解决的问题。 随着城市化脚步的推进&#xff…

数码管时钟--LABVIEW编程

一、程序的前面板 1.获取系统时钟&#xff0c;年月日&#xff0c;时分秒&#xff0c;用14个数码管显示。 2.闹钟设定小时和分钟。 二、程序的后面板 三、程序运行图 四、程序源码 源程序可以在百度网盘自行下载&#xff0c;地址链接见下方。 链接&#xff1a;https://pan.b…

LeetCode-54. 螺旋矩阵【数组 矩阵 模拟】

LeetCode-54. 螺旋矩阵【数组 矩阵 模拟】 题目描述&#xff1a;解题思路一&#xff1a;定义上下左右四个边界&#xff0c;进行模拟。解题思路二&#xff1a;5行 Python zip函数图一乐解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xf…

SketchUp Pro中文---3D建模与设计领域的专业选手

SketchUp Pro是一款功能强大的3D建模软件&#xff0c;广泛应用于建筑、城市规划、室内设计等领域。它拥有用户友好的界面和丰富的建模工具&#xff0c;支持实时查看、高 级扩展以及智能提示等功能&#xff0c;使得建模过程更加直观、灵活和高效。SketchUp Pro还支持自定义插件&…

1033 To Fill or Not to Fill

是否有能到达的站点 无&#xff0c;输出当前距离&#xff08;最后一个到达站点距离满油箱状态下行走距离&#xff09;有 有价格更低的站点 如果油量不足以到达新站点&#xff0c;加刚好到达该站点的油量&#xff08;只加可到达范围内最便宜的油&#xff09;有价格更高的站点 在…

论文速览 | IEEE TCI, 2022 | 单光子级非视距成像:估计强度与优化重建

注1:本文系"计算成像最新论文速览"系列之一,致力于简洁清晰地介绍、解读非视距成像领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, SIGGRAPH, TPAMI; Light‑Science & Applications, Optica 等)。 本次介绍的论文是:<2…

Dimitra:基于区块链、AI 等前沿技术重塑传统农业

根据 2023 年联合国粮食及农业组织&#xff08;FAO&#xff09;、国际农业发展基金&#xff08;IFAD&#xff09;等组织联合发布的《世界粮食安全和营养状况》报告显示&#xff0c;目前全球约有 7.35 亿饥饿人口&#xff0c;远高于 2019 年的 6.13 亿&#xff0c;这意味着农业仍…

为什么跟着高手还是亏损?fpmarkets10秒解答

各位投资者&#xff0c;不知道你们有没有遇见这样的情况&#xff1f;不管是别人能够持续盈利的技术指标&#xff0c;还是业内知名的行业专家&#xff0c;只要是我们这些普通的投资者一旦使用持续盈利的技术指标&#xff0c;或者跟随专家顾问的信号同时在同一个方向建仓&#xf…

python怎么处理txt

导入文件处理模块 import os 检测路径是否存在&#xff0c;存在则返回True&#xff0c;不存在则返回False os.path.exists("demo.txt") 如果你要创建一个文件并要写入内容 #如果demo.txt文件存在则会覆盖&#xff0c;并且demo.txt文件里面的内容被清空&#xff0c;如…

Machine Learning机器学习之文本分析的词法分析、句法分析、语义分析(详细讲解)

目录 前言 词法分析&#xff1a; 词义消歧&#xff1a; 句法分析&#xff1a; 语义分析&#xff1a; 文本分析应用 1、文本分类&#xff1a; 设计过程&#xff1a; 代码实现&#xff1a; 完整代码&#xff1a; 2、情感分析&#xff1a; 总结 博主介绍&#xff1a;✌专注于前后…

【Go】四、包名、访问范围控制、标识符、运算符

文章目录 1、_2、包名3、命名大小影响可访问范围4、运算符5、获取终端输入 1、_ 下划线"_"本身在Go中是一个特殊的标识符&#xff0c;称为空标识符用于忽略某个值 1&#xff09;忽略导入的没使用的包 2&#xff09;忽略某个返回值 2、包名 main包是程序的入口包&a…

关于 HEAP CORRUPTION DETECTED:after Normal block 错误的原因及解析

目录 一、HEAP CORRUPTION DETECTED:after Normal block 出现的报错情况&#xff1a; 二、问题原因&#xff08;重要&#xff09;&#xff1a; 三、举例 1.错误代码如下&#xff1a; 2.错误原因及分析&#xff08;重要&#xff09;&#xff1a; 3.解决方法 ​编辑 4.正…

【Linux C | 多线程编程】线程的连接、分离,资源销毁情况

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;2024-04-01 1…

SSM框架学习——MyBatis关联映射

MyBatis关联映射 为什么要关联映射 实际开发中&#xff0c;对数据库操作常常会涉及多张表&#xff0c;所以在OOP中就涉及对象与对象的关联关系。针对多表操作&#xff0c;MyBatis提供关联映射。 关联关系概述 一对一&#xff1a;A类中定义B类的属性b&#xff0c;B类中定义A…