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

news2024/11/28 10:36:16

文章目录

  • 前文
  • 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官网

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

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

相关文章

Python学习笔记 - 如何在google Colab中显示图像?

这里是使用的opencv进行图片的读取&#xff0c;自然也是想使用opencv的imshow方法来显示图像&#xff0c;但是在google Colab中不可以使用&#xff0c;所以寻找了一下变通的显示方法。 方法1&#xff1a;使用matplotlib 使用plt需要交换一下r、b通道&#xff0c;否则显示不正常…

conda使用记录

linux 使用conda创建新一个新的python环境过程 conda create -n recommendation_env python3.8.18 # 指定python版本 conda env list # 查看所有的环境 conda activate recommendation_env # 激活创建的新环境 pip install flask # 安装依赖 或者 pip install flask版本号 或者…

鸿蒙(HarmonyOS)ArkTs语言基础教程开发准备

本文档适用于HarmonyOS应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用&#xff08;如下图所示&#xff09;&#xff0c;快速了解工程目录的主要文件&#xff0c;熟悉HarmonyOS应用开发流程。 在开始之前&#xff0c;您需要了解有关HarmonyOS应用的一些基本概…

Intel FPGA (4):状态机

Intel FPGA (4)&#xff1a;状态机 前提摘要 个人说明&#xff1a; 限于时间紧迫以及作者水平有限&#xff0c;本文错误、疏漏之处恐不在少数&#xff0c;恳请读者批评指正。意见请留言或者发送邮件至&#xff1a;“Email:noahpanzzzgmail.com”。本博客的工程文件均存放在&am…

学习Linux推荐的书籍

我记得有人曾经说过&#xff0c;征服一个男人最好的途径就是抓住他的胃。 ‍‍‍‍ 学习Linux&#xff0c;最重要的就是要先搞懂Linux是啥&#xff0c;有啥&#xff0c;为啥&#xff1f;‍‍‍‍‍‍‍‍‍‍‍‍‍ 所以&#xff0c;我推荐的第一本书就是-《Unix编程艺术》。…

力扣热题100_链表_142_环形链表 II

文章目录 题目链接解题思路解题代码 题目链接 142. 环形链表 II 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中…

深度学习_NLP常用库报错问题解决

1、SpaCy can‘t find model ‘zh_core_web_sm‘. It doesn‘t seem to be a python package or a valid path to a data 或者 can‘t find model ‘en_core_web_sm‘. It doesn‘t seem to be a python package or a valid path to a data 安装最新的版本&#xff1a; en_…

PE 系统收集 (下一次何至于慌忙乱)

简介 介绍一些PE系统, 还有就是多种烧录PE到U盘方式。 PE 1. Hikari PE Hikari PE 官网说明 当电脑无法制作启动盘时可以使用Android收集制作

家庭网络防御系统搭建-配置流量镜像到NDR系统

由于需要将家庭网络中的全部流量送到NDR分析系统进行分析&#xff0c;因此需要一个具备流量镜像功能的交换机或者路由器。在前面文章所提及的家庭网络架构中&#xff0c;需要一台交换机即可拷贝东西向流量以及南北向流量。当然如果家庭中的路由器或者其他设备具备交换机镜像功能…

OpenCV 4.9使用通用内部函数对代码进行矢量化

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV使用通用内部函数对代码进行矢量化 下一篇&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; ​ 目标 本教程的目标是提供使用通用内部函数功…

VSCode必备插件,创建运行JS、Html

这里介绍如何用vscode来创建一下.js文件和.html文件&#xff0c;然后正确的运行他们 一、首先安装两个插件 第一个插件 open in browser (就是我们运行.html文件,把html通过浏览器给它打开) 第二个插件 Code Runner (就是我们运行.js文件&#xff0c;就是直接运行.js文件…

咪咕打造体育元宇宙

9月23日20点&#xff0c;第19届亚运会在杭州开幕。主火炬点燃环节&#xff0c;超过1亿的「数字火炬手」汇聚成具象的数字火炬手&#xff0c;从钱塘江踏着浪花一步步来到「大莲花」上空&#xff0c;和线下的六棒火炬手共同点燃主火炬。 云上观众通过咪咕视频的AR交互界面&#…

Oracle+11g+笔记(1)-SQL语言基础

Oracle11g笔记(1)-SQL语言基础 1、SQL语言基础 1.1 SQL语言的功能 数据定义功能&#xff1a;DDL(CREATE、DROP、ALERT)。 数据查询功能&#xff1a;DQL(Select)。 数据操作功能&#xff1a;DML(INDERT、UPDATE、DELETE)。 数据控制功能&#xff1a;DCL(GRANT、REVOKE、COM…

基于SSM的校园订餐系统

一、功能实现 前台模块 前台主要功能有&#xff1a;用户注册、用户登录、我的购物车、我的订单、商品评论、校园资讯后台模块 后台主要功能有&#xff1a;用户管理、商品管理、订单管理、评论管理、资讯管理等 二、技术选型 2.1 后台技术选型 SpringBoot(Spring、SpringMVC…

ssm015基于java的健身房管理系统的设计与实现+vue

健身房管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本健身房管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间…

win11下,RTMP流媒体服务器保姆级教程

本片博客将详细介绍如何搭建一个RTMP流媒体服务器,包含源码下载&#xff0c;编译常见问题解决方法以及流媒体测试&#xff0c;最后讲解了如何利用obs软件实现推流。 服务器&#xff1a;SRS 3.0(Simple Realtime Server&#xff0c;支持RTMP、HTTP-FLV、HLS、WebRTC) 推流端&…

蓝桥杯刷题day13——自助餐【算法赛】

一、问题描述 食堂最近推出了自助取餐功能&#xff0c;可以通过盘子的形状自动计算费用。你参与到自助计算价格的项目工作中。视觉组的同学已经帮你通过图像识别把盘子图片转换为了字符串&#xff0c;你只需要计算具体的价格即可。 餐盘的费用如下表所示: 你将会得到n 个字符…

【css】文本过长溢出一行不换行普通css以及antd实现

.text-box { white-space: nowrap; /* 防止文字换行 */ overflow: hidden; /* 隐藏超出div的内容 */ text-overflow: ellipsis; /* 当内容超出时&#xff0c;显示省略号 */ max-width: calc(100% - 80px); /* 假设按钮宽度为80px&#xff0c;则设置div的最大宽度为容器宽度…

强化基础-Java-集合

这块的知识点比较零碎也是看到了就过来记录一点&#xff0c;可能是之前没有特别注意的&#xff0c;会持续补充 集合 1 通用实现 ListSetSortedSet&#xff08;如果表达是有序的,返回签名使用有序set来表达&#xff09;NavigableSet(since 1.6)Queue (since 1.5)Deque(since …

2024 年最值得阅读的 ChatGPT 书籍

自ChatGPT问市以来&#xff0c;其全球风靡之势标志着生成式人工智能新纪元的到来。尽管在ChatGPT之前&#xff0c;大型语言模型(LLM)已存在&#xff0c;但其便捷访问和用户友好界面无疑将LLM的应用推向了新高度。至2024年&#xff0c;ChatGPT持续作为热门话题&#xff0c;本文旨…