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,//0
	ADD,
	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官网

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Learning Discriminative Representations for Skeleton Based Action Recognition

标题&#xff1a;基于骨架的动作识别的学习判别性表示 原文链接&#xff1a;Learning Discriminative Representations for Skeleton Based Action Recognition (thecvf.com) 源码链接&#xff1a;https://github.com/zhysora/FR-Head 发表&#xff1a;CVPR 摘要 最近&…

【论文复现|智能算法改进】动态透镜成像学习人工兔优化算法及应用

目录 1.算法原理2.改进点3.结果展示4.参考文献 1.算法原理 【智能算法】人工兔优化算法&#xff08;ARO&#xff09;原理及实现 2.改进点 非线性递减能量因子&#xff1a; A ( t ) ( A max ⁡ − A min ⁡ ) ( 1 − sin ⁡ ( ( t T ) n π 2 ) (1) \begin{aligned}A\left…

李宏毅深度强化学习导论——当奖励是稀疏的

引言 这是李宏毅强化学习的笔记&#xff0c;主要介绍如何处理稀疏奖励问题。 稀疏奖励 当我们拿Actor和环境互动后可以得到很多奖励&#xff0c;整理之后可以得到分数 A A A&#xff0c;然后可以训练Actor。 但RL中有时会出现多数情况下奖励为零&#xff0c;此时我们不知道动…

Verilog基础【二】

3.1 Verilog 连续赋值 关键词&#xff1a;assign&#xff0c; 全加器 连续赋值语句是 Verilog 数据流建模的基本语句&#xff0c;用于对 wire 型变量进行赋值。&#xff1a; assign LHS_target RHS_expression &#xff1b;LHS&#xff08;left hand side&#xff09;…

卷积层+多个输入通道

卷积层多输入输出通道 在深度学习中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;通常用于处理具有多个输入通道的数据。当输入数据具有多个通道&#xff08;例如彩色图像的RGB通道&#xff09;时&#xff0c;卷积操作可以同时在每个通道上进行&#xff0c;并将各通道的…

软件测试-进阶篇

目录 测试的分类1 按测试对象划分1.1 界面测试1.2 可靠性测试1.3 容错性测试1.4 文档测试1.5 兼容性测试1.6 易用性测试1.7 安装卸载测试1.8 安装测试1.9 性能测试1.10 内存泄漏测试 2 按是否查看代码划分2.1 黑盒测试&#xff08;Black-box Testing&#xff09;2.2 白盒测试&a…

新闻管理系统(源码+文档)

新闻管理系统&#xff08;小程序、ios、安卓都可部署&#xff09; 文件包含内容程序简要说明含有功能项目截图客户端新闻详情新闻首页分类退出登录个人中心拨打客服热线注册界面个人资料新闻评论成功 管理端用户管理分类管理新闻管理 文件包含内容 1、搭建视频 2、流程图 3、开…

windows下部署llama.cpp

下载cmake 下载地址 解压&#xff0c;设置Path环境变量D:\CMake\bin 打开cmd输入cmake -version 安装mingw powershell下执行 Set-ExecutionPolicy RemoteSigned -Scope CurrentUser iex "& {$(irm get.scoop.sh)} -RunAsAdmin" scoop bucket add extras s…

Android获取本地文件目录

一、实现效果 一个简单的demo。点击按钮&#xff0c;获取本地文件目录&#xff0c;可以选择图片&#xff0c;展示选取的对应图片和展示存储路径。如图所示&#xff1a; 二、实现方式 1. 权限 AndroidManifest.xml文件里面添加权限 <uses-permission android:name"a…

【御控物联】JavaScript JSON结构转换(12):对象To数组——键值互换属性重组

文章目录 一、JSON结构转换是什么&#xff1f;二、核心构件之转换映射三、案例之《JSON对象 To JSON数组》四、代码实现五、在线转换工具六、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换…

牛客2024年愚人节比赛(A-K)

比赛链接 毕竟是娱乐场&#xff0c;放平心态打吧。。。 只有A一个考了数学期望&#xff0c;其他的基本都是acmer特有的脑筋急转弯&#xff0c;看个乐呵即可。 A 我是欧皇&#xff0c;赚到盆满钵满&#xff01; 思路&#xff1a; 我们有 p 1 p_1 p1​ 的概率直接拿到一件实…

Oracle Solaris 11.3开工失败问题处理记录

1、故障现像 起初是我这有套RAC有点问题&#xff0c;我想重启1个节点&#xff0c;结果发现重启后该节点的IP能PING通&#xff0c;但SSH连不上去&#xff0c;对应的RAC服务也没有自动启动。 操作系统是solaris 11.3。由于该IP对应的主机是LDOM&#xff0c;于是我去主域上telnet…

html基础:颜色的 5 种表示方法(最全!)

你好&#xff0c;我是云桃桃。一个希望帮助更多朋友快速入门 WEB 前端的程序媛&#xff0c;大专生&#xff0c;2年时间从1800到月入过万&#xff0c;工作5年买房。 分享成长心得。 HTML 颜色在网页设计中扮演着重要角色&#xff0c;给网页增加颜色可以增强用户体验&#xff0c;…

MySQL看这一篇就够了

目录 MySQL安装&#xff08;Linux&#xff09; 1、仓库安装 2、本地安装 3、容器安装 MySQL体系结构 连接层 SQL层 存储引擎层 MySQL存储引擎的介绍 常用存储引擎的特性比对 InnoDB的逻辑存储结构 系统文件层 MySQL库表操作 库操作 表操作 创建表 查看表 删除…

snmp服务

双击 安装snmputil和MIB Browser getSwitchStatus.cpp&#xff1a; #include <iostream> #include <stdio.h> #include <net-snmp/net-snmp-config.h> #include <net-snmp/net-snmp-includes.h>using namespace std;int main() {init_snmp("getS…

算法学习——LeetCode力扣补充篇3(143. 重排链表、141. 环形链表、205. 同构字符串、1002. 查找共用字符、925. 长按键入)

算法学习——LeetCode力扣补充篇3 143. 重排链表 143. 重排链表 - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为&#xff1a; L0 → Ln → …

给三分钟热度学习Python的同学的一条建议

最近公司来了一个实习生妹子&#xff0c;在读商科硕士&#xff0c;平时我会让她做做数据清洗的工作&#xff0c;她工作倒是贼认真&#xff0c;但对计算机属于一窍不通&#xff0c;不会写SQL&#xff0c;Ecxel也很菜&#xff0c;对于很简单的取数往往会花很多的时间。 她向我倒…

halcon图像腐蚀

1、原理 使用结构元素在图像上移动&#xff0c;只有结构元素上的所有像素点都属于图像中时&#xff0c;才保留结构元素中心点所在的像素&#xff0c;常用于分离连接的两个物体、消除噪声。 2、halcon代码 dev_open_file_dialog (read_image, default, default, Selection) r…

<Linux> Linux环境开发工具

一、Linux软件包管理器 - yum 什么是软件包&#xff1a; 在Linux 下安装软件 , 一个通常的办法是下载到程序的源代码 , 并进行编译 , 得到可执行程序 . 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好 , 做成软件包 ( 可以理解成 windows 上的安装程序) 放在一…

AI融合细分场景,突破未来家的想象,萤石2024春季新品发布会圆满举办

3月31日&#xff0c;“AI无界 萤未来”2024萤石春季新品发布会暨渠道合作伙伴大会于杭州正式举办。萤石重磅发布视频通话摄像机S10、超级夜景室外云台H8x系列、TAMO看护摄像机、AI三摄全自动人脸视频锁DL60FVX Pro以及家庭助理机器人RK3等多款新品&#xff0c;以创新、前沿的AI…