动态内存管理函数介绍及C语言实现通讯录管理系统2.0版(动态增长版本)

这篇具有很好参考价值的文章主要介绍了动态内存管理函数介绍及C语言实现通讯录管理系统2.0版(动态增长版本)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 前言

之前向大家介绍了C语言实现通讯录管理系统1.0版本,但该版本有明显的不足之处,比如:一开始就开辟了1000个date数组,如果联系人很少,那么就会造成严重的内存浪费,或者联系人超过了1000人,那么原数组就放不下了,所以今天我们考虑使用动态内存管理的办法来实现一个内存会随着联系人的增加而增加的通讯录动态增长版!
首先我们先来学习如何进行动态内存分配及动态内存函数的使用方法。

2. 动态内存函数

2.1 malloc函数

定义:void* malloc(size_t size);
功能:向内存申请一块连续可用的空间,并返回指向这块空间的指针。
注意事项:
size的单位是字节
如果开辟成功,则返回一个指向开辟好空间的指针。
如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
返回值的类型是void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定,使用前强制类型转换。
如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。

使用方法:

int main()
{
	//申请空间
	int* ptr = (int*)malloc(40);
	int* p = ptr;
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{

		*p = i;
		p++;
	}
	//释放空间
	free(ptr);
	ptr = NULL;
	return 0;
}

2.2 free函数

定义:void free(void* str);
功能:free函数用来释放动态开辟的内存。
注意事项:
如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。
如果参数ptr是NULL指针,则函数什么事都不做。
当我们不释放动态申请的内存的时候:
如果程序结束,动态申请的内存由操作系统自动回收。
但是如果程序不结束,动态内存是不会自动回收的,就会形成内存泄露的问题。
所以只要动态开辟了内存,使用完就需要用free函数释放。

2.3 calloc函数

定义:void* calloc(size_t num, size_t size);
功能:为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0。
注意事项:
与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0。

使用方法:

int main()
{
	//申请空间
	int* ptr = (int*)calloc(10, sizeof(int));
	int* p = ptr;
	if (p == NULL)
	{
		perror("calloc");
	}
	//使用空间

	//释放空间
	free(ptr);
	ptr = NULL;
	return 0;
}

2.4 realloc函数

定义:void* realloc(void* ptr, size_t size);
功能:realloc函数可以做到对动态开辟内存大小的调整。
注意事项:
ptr是要调整的内存地址。
size调整之后新大小。
返回值为调整之后的内存起始位置。
这个函数在调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

realloc在调整内存空间的是存在两种情况:
情况1:原有空间之后有足够大的空间
扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2:原有空间之后没有足够大的空间
扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
此时就要注意,如果整个堆区都没有一个合适大小的连续空间,就会申请失败。
所以使用完realloc函数应该先判断返回的地址是否为空,不为空就可以正常使用了。

使用方法:

int main()
{
	//申请空间
	int* ptr = (int*)malloc(40);
	if (ptr == NULL)
	{
		perror("malloc");
		return 1;
	}
	//使用空间
	int* p = ptr;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*p = i;
		p++;
	}
	//扩容空间
	int* p2 = (int*)realloc(ptr, 80);
	if (p2 == NULL)
	{
		perror("realloc");
	}
	p = p2;
	//使用空间

	//释放空间
	free(p);
	p = NULL;
	return 0;
}

3. 优化通讯录程序

学习完这些动态内存函数以后,我们就可以用动态内存分配来优化通讯录代码,避免内存浪费和内存不足的问题。

3.1 通讯录的优化

我们原来创建的通讯录是直接创建了1000个元素,而动态内存版本我们首先应该考虑如何修改通讯录,来满足我们的需求,这里我有两个想法:
1.通讯录初始只能存放3个联系人的信息。
2.当通讯录满的时候,每次增加2个人的空间。
这样修改的话,既避免了内存的浪费,也不会出现内存不够的情况。
具体修改方式如下:

//静态版本
//typedef struct contact
//{
//	people date[MAX];//1000人的信息
//	int count;//已保存的信息个数
//}contact;

//动态版本
typedef struct contact
{
	people* date;//1000人的信息
	int count;//已保存的信息个数
	int cap;//记录当前通讯录的最大容量
}contact;

3.2 初始化通讯录的优化

接下来就该初始化了,初始化通讯录的时候用malloc函数来开辟内存。

//静态版本
//void InitContact(contact* pc)
//{
//	assert(pc);
//	pc->count = 0;
//	memset(pc->date, 0, sizeof(pc->date));
//}

//动态版本
void InitContact(contact* pc)
{
	assert(pc);
	pc->count = 0;
	pc->cap = DEFAULT_SIZE;
	pc->date = (people*)malloc((pc->cap) * (sizeof(people)));
	if (pc->date == NULL)
	{
		perror("InitContact::malloc");
		return;
	}
	memset(pc->date, 0, (pc->cap) * (sizeof(people)));
}

当退出通讯录的时候,我们要释放动态开辟的内存,所以还应该添加一个销毁通讯录的函数。

void DestroyContact(contact* pc)
{
	free(pc->date);
	pc->date = NULL;
	pc->cap = 0;
	pc->count = 0;
	printf("销毁成功\n");
}

3.3 添加联系人的优化

接下来就是添加联系人的时候加入判断函数,判断此时通讯录是否为满,如果满了就再开辟2个联系人的内存,每次添加都应该判断一次。

void CheckCapacity(contact* pc)
{
	if (pc->count == pc->cap)
	{
		people* ptest = (people*)realloc(pc->date, ((pc->cap) + 2) * (sizeof(people)));
		if (ptest != NULL)
		{
			pc->date = ptest;
		}
		else
		{
			perror("CheckCapacity::realloc");
			return;
		}
		pc->cap += 2;
		printf("扩容成功\n");
	}
}

void AddPeople(contact* pc)
{
	assert(pc);
	//静态版本
	//if (pc->count == MAX)
	//{
	//	printf("通讯录已满,无法添加\n");
	//	return;
	//}

	//动态版本
	CheckCapacity(pc);

	printf("请输入姓名:\n");
	scanf("%s", pc->date[pc->count].name);
	printf("请输入性别:\n");
	scanf("%s", pc->date[pc->count].sex);
	printf("请输入年龄:\n");
	scanf("%d", &pc->date[pc->count].age);
	printf("请输入号码:\n");
	scanf("%s", pc->date[pc->count].tele);
	printf("请输入地址:\n");
	scanf("%s", pc->date[pc->count].address);
	pc->count++;
	printf("添加成功\n");
}

3.4 运行测试

我们来运行代码,观察结果
动态内存管理函数介绍及C语言实现通讯录管理系统2.0版(动态增长版本)
可以看出,这时候代码已经优化完成,初始只能保存3个联系人的信息,当继续存储时就会扩容。如果退出程序,就会销毁(释放)掉动态内存分配的空间,不会造成内存泄漏的问题。

4. 结尾

到这里,我们动态增长版本的通讯录管理系统2.0也就优化完成了,后续我还会对代码进行优化,敬请期待。文章来源地址https://www.toymoban.com/news/detail-403047.html

到了这里,关于动态内存管理函数介绍及C语言实现通讯录管理系统2.0版(动态增长版本)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】——动态内存管理与文件操作,后面加一个通讯录福利,万字解读,看完你会有一个全新认识

    目录 一.动态内存管理 1.为什么有动态内存管理 2.malloc和free  2.calloc和realloc 3.柔性数组 二.文件操作 1.为什么使用文件  2.二进制文件和文本文件  3.文件的打开和关闭 4.文件的顺序读写 5.文件缓冲区 三.通讯录  1.预处理  2.基本框架 3.初始化函数 4.增加联系人  5.显示联系人

    2024年03月13日
    浏览(26)
  • 文件操作介绍及C语言实现通讯录管理系统3.0最终版(文件操作版本)

    上一篇文章我们学习了动态内存开辟的相关知识点,并用动态内存函数优化了我们的通讯录,但通讯录还有需要改进的地方,比如,正常情况下的通讯录,应该可以一直保存联系人信息,而不是退出就清空了,这就需要我们实实在在的保存下来一个通讯录。 接下来我会给大家

    2023年04月08日
    浏览(40)
  • 动态通讯录实现(C语言)

    目录 前言: 一:单个节点的设计和主逻辑  结点设计 主逻辑 二:接口实现 (1)生成一个新的结点 (2)增加信息 (3)打印信息 (4)查找  (5)删除信息 (6)修改信息 (7)排序  插入排序 快速排序 (8)已有数据读取 (9)更新数据录入 三:全部代码 contact.h(声明) contact.c(接口) test.c(主逻辑) 本

    2024年02月05日
    浏览(32)
  • 【C语言】实现通讯录(动态+文件)

    在之前三子棋和扫雷的基础上,本篇文章博主将给大家逐步分析实现通讯录,介绍通讯录的每个功能( 动态增长和文件保存 )。 —————————————————————— test.c - 测试通讯录 Contact.c - 函数的实现 Contact.h - 函数和类型的声明 以多文件的形式分模块写的

    2024年02月13日
    浏览(36)
  • 【C语言】实现动态版通讯录

    💌内容专栏:【C语言】进阶部分 💌本文概括: 结合自定义类型、动态内存管理知识,对静态版本的通讯录进行优化。 💌本文作者:花 碟 💌发布时间:2023.4.2   目录 前言: 一、静态版本代码实现: 二、动态通讯录  三、代码整理  前面我们学过了结构体、枚举等自定义

    2024年02月02日
    浏览(22)
  • C语言实现通讯录--动态版

    实现一个通讯录,联系人的数量可多可少 1.在静态版本的基础上改用动态的方法: (1)默认能够存放三个人的信息 (2)不够的话,每次增加两个人的信息 2.其他功能不变 建立三个文件: test.c 用于测试通讯录的相关功能 contsct.c 通讯录的实现模块(用函数实现功能) conta

    2024年02月15日
    浏览(23)
  • C语言之通讯录的实现(静态版,动态版,文件版)

    个人主页(找往期文章包括但不限于本期文章中不懂的知识点): 我要学编程(ಥ_ಥ)-CSDN博客 目录 静态通讯录的实现逻辑  test.c:通讯录的逻辑实现 Contact.h:函数的声明与头文件的包含 Contact.c:函数的实现  通讯录源码:  test.c: Contact.c: Contect.h: 动态版通讯录  test.c: Co

    2024年04月13日
    浏览(27)
  • 【C语言】实现通讯录管理系统

    大家好,我是苏貝,本篇博客带大家实现通讯录,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 本文将使用C语言来实现通讯录管理系统,该通讯录包括若干联系人,和每个联系人的姓名、年龄、性别、电话、地址。此通讯录的功能包括:增加联系人信息,

    2024年02月08日
    浏览(29)
  • 【进阶C语言】动态版通讯录的实现(详细讲解+全部码源)

    前言 📕作者简介: 热爱跑步的恒川 ,致力于 C/C++、Java、Python 等多编程语言,热爱跑步,喜爱音乐的一位博主。 📗本文收录于 C语言进阶 系列,本专栏主要内容为数据的存储、指针的进阶、字符串和内存函数的介绍、自定义类型结构、动态内存管理、文件操作等,持续更

    2024年02月01日
    浏览(33)
  • C语言用链表实现通讯录管理系统

    目录 总体思路 具体代码 编译通过 总体代码 一、创建一个结构体保存通讯录信息。 二、构建链表,并存于文件中。 三、实现链表结点的增加、删除、查询、输出。 一、创建一个结构体,保存信息。 二、用尾插法创建一个链表,并让用户选择是否输入数据。 三、将链表数据

    2024年02月02日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包