C语言编程动态内存开辟实现升级版通讯录教程示例

目录
  • 前言
  • 一、存放联系人信息
  • 二、通讯录初始化
  • 三、增加联系人
  • 四、销毁通讯录
  • 后记

前言

所谓动态内存开辟的通讯录,就是我需要多少联系人,就给多少联系人,防止给定一个联系人上限,需要增加联系人无法扩容,而联系人没有上限那么多又会造成内存浪费。

本文继之前的静态通讯录作出改进,有兴趣的同学可以看看之前的文章:C语言实现静态通讯录

一、存放联系人信息

这里是用struct PeoInfodata结构体指针指向通讯录,而不再直接 struct PeoInfo data[Max]

用结构体数组定义通讯录容量大小,其他都和之前的静态通讯录一样

多种信息描述用结构体(struct PeoInfodata是动态,struct PeoInfo data[Max]是静态)

#define Name_max 20
#define Sex_max 5
#define Tele_max 12
#define Addr_max 30
#define Max 1000
//用#define定义是为了方便将来如果需要对数组大小增减,直接改#define这里的即可
struct PeoInfo
{
	char name[Name_max];//姓名
	int age;//年龄
	char sex[Sex_max];//性别
	char tele[Tele_max];//电话号码
	char addr[Addr_max];//地址
};//声明一个通讯录结构体类型
struct Contact
{
	struct PeoInfo*data;
	int sz;//记录已有联系人数目
	int capacity;//当前通讯录最大容量,将来如果不够可以自动扩容
};//struct Contact是一种结构体类型,它里面可以存放其他类型,而struct PoeInfo也是一种类型,自然是可以存放的

二、通讯录初始化

我们先来看一下,动态通讯录运行原理:

我们联系人结构体创建好之后data(结构体指针)这个成员是没有指向一块具体空间的,我们用初始化函数申请一块空间,然后让data指向那块空间,假设我们现在开辟三块空间
(开辟空间数由memset(pc->data, 0, Max * sizeof(struct PeoInfo));这句代码中的Max控制,比如我现在是开辟3块空间就把Max改成3即可)

(图片来自比特就业课)
开辟完空间后,capacity(当前通讯录最大容量)即是3,但是我们现在没有放有效联系人,所以sz(已有联系人数目)还是0

当你放入一个联系人张三的信息,sz变为1

再放入一个联系人李四的信息,sz变为2,然后再放入联系人王五的信息,sz变为3。后面的以此类推

代码如下(示例):

#define Default_sz 3//默认初始联系人容量为3
//这里#define定义是方便其他使用者将来如果不想初始容量为3,可以直接在#define这里修改
void InitContact(struct Contact*pc)
{
	pc->sz = 0;
	pc->data = (struct PeoInfo*)malloc(Default_sz * sizeof(struct PeoInfo));
	pc->capacity = Default_sz;
}

一个联系人结构体占用空间大小是sizeof(struct PeoInfo),我们这里是初始给3个联系人结构体大小空间(后面不够再自动扩),你也可以用其他数字代替,malloc开辟出空间后,是返回值类型为void*,我们需要的pc->data是struct PeoInfo*型,我们强制转换一下,然后开辟出来的空间会由struct PeoInfo *型的指针进行管理。

三、增加联系人

void AddContact(struct Contact*pc)//动态增加联系人
{
	if (pc->sz == pc->capacity)
	{
		//容量已达上限,如果增加联系人需扩容
		struct PeoInfo* ptr= (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2)*sizeof(struct PeoInfo));//追加空间函数,详情见笔者动态内存分配文章
		//realloc第二个参数是字节为单位,pc->capacity + 2是容量个数,sizeof(struct PeoInfo)是每个联系人结构体所占空间
		if (ptr != NULL)//realloc函数有可能开辟空间失败,失败会返回空指针
		{
			pc->data = ptr;
			pc->capacity += 2;//我们以每次增容+2为例,你也可以换其他数字
			printf("增容成功\n");
		}
		else//返回空指针说明开辟失败
		{
			return;//开辟失败就结束程序
		}
	}
	printf("请输入联系人姓名:\n");
	scanf("%s", pc->data[pc->sz].name);
	//pc->data是结构体指针,我们之前很多文字说过一个知识点,假设a是一个指针,*(a+n)=a[n]
	//pc->data[pc->sz]=*(pc->data+pc->sz)
	printf("请输入联系人年龄:\n");
	scanf("%d", &(pc->data[pc->sz].age));
	//这里年龄和前面的名字有什么区别?
	//name在结构体里是一个数组,数组单独出现可以看成数组首元素地址,age是一个整形,要&进行取地址操作
	printf("请输入联系人性别:\n");
	scanf("%d", (pc->data[pc->sz].sex));
	printf("请输入联系人电话:\n");
	scanf("%d", (pc->data[pc->sz].tele));
	printf("请输入联系人地址:\n");
	scanf("%d", (pc->data[pc->sz].addr));
	printf("该联系人已添加\n");
	pc->sz++;//添加完后,联系人数目+1
}

四、销毁通讯录

void DestoryContact(struct Contact*pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

因为我们通讯录是用结构体指针malloc出来的嘛,不再需要通讯录我们就用free函数把那块空间还给操作系统,然后要记得把指针置为空指针(就比如你去宾馆,退房要把钥匙还给宾馆)

后记

对于静态通讯录改动态通讯录也就是改一下它的初始化、增加联系人(类比静态通讯录没有上限,也避免浪费空间),还有通讯录销毁的一些小改动,对于完整通讯录还有查找、删除、修改、显示联系人等操作函数,但由于和静态没有改动,读者可自行查看笔者以前的通讯录文章 。

以上就是C语言编程动态内存开辟实现升级版通讯录教程示例的详细内容,更多关于C语言实现通讯录的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言实现静态链表

    本文实例为大家分享了C语言实现静态链表的具体代码,供大家参考,具体内容如下 注意事项: 1.这里用k申请空间,i遍历空间. 2.静态链表是利用游标来模拟指针,把固定分配的内存分成备用链表和链表两大块,在利用自制的malloc和free函数申请释放备用空间时,实现离散存储. 3.基本操作和动态链表实际上差不多,不过一个是利用p = p->next一个是使用i = L[i].cur来实现指针的后移. 4.初始化链表时,链表只有最后一个空间的cur是0, 意味是头指针,并没有任何分配的空间.备用链表的

  • C语言编程内存分配通讯录静态实现示例代码教程

    实现一个通讯录: 通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名.性别.年龄.电话.住址 提供方法: 1. 添加联系人信息 2. 删除指定联系人信息 3. 查找指定联系人信息 4. 修改指定联系人信息 5. 显示所有联系人信息 6. 清空所有联系人 7. 以名字排序所有联系人 首先我们采用顺序表的方式来实现一个通讯录,顺序表就是一种静态的模式.但是呢,静态的方式存在着一些明显的弊端,比如说:(1)信息少了存在空间浪费现象,信息多了存在空间不足的现象:(2)无法对信息进行保存,没有实

  • C语言实现静态顺序表的实例详解

    C语言实现静态顺序表的实例详解 线性表 定义一张顺序表也就是在内存中开辟一段连续的存储空间,并给它一个名字进行标识.只有定义了一个顺序表,才能利用该顺序表存放数据元素,也才能对该顺序表进行各种操作. 接下来看看静态的顺序表,直接上代码: SeqList.h #define _CRT_SECURE_NO_WARNINGS 1 #ifndef __SEQLIST_H__ #define __SEQLIST_H__ #include <stdio.h> #include <stdlib.h&g

  • C语言之通讯录的模拟实现代码

    在C语言学习结束之际,谨以此篇文章来对C语言的学习告一段落. 纲要: 通讯录的静态版本 通讯录的动态版本 通讯录的带文件版本 因为三种实现方法除了储存形式不同,其他都基本相同,所以我们重点论述静态版本的实现,以及它们不同的储存方式. 一.通讯录的静态版本 为什么叫它为静态版本呢,因为在此部分的储存是以数组来储存的,那对于各种各样的信息,我们要拿什么数组来存放它呢?当然是结构体数组了,所以我们来定义一个结构体来表示个人信息: //采用宏的目的是方便日后修改 #define NAME_MAX 20

  • C语言模拟实现动态通讯录

    目录 1.模拟实现通讯录总体架构一览图 2.文件执行任务 3.分模块实现 测试模块 test.c 头文件 功能函数声明 contact.h 功能函数逐一实现 1.模拟实现通讯录总体架构一览图 2.文件执行任务 3.分模块实现 测试模块 test.c 1.为了更好地展示,制作一个菜单,在菜单中有 添加,删除,查找,修改,排序,清空,退出的选项. 2.因为起先要进入程序一趟,所以用do····while循环(输入选项来看具体操作,退出还是其他操作) #include "contact.h"

  • C语言编程动态内存开辟实现升级版通讯录教程示例

    目录 前言 一.存放联系人信息 二.通讯录初始化 三.增加联系人 四.销毁通讯录 后记 前言 所谓动态内存开辟的通讯录,就是我需要多少联系人,就给多少联系人,防止给定一个联系人上限,需要增加联系人无法扩容,而联系人没有上限那么多又会造成内存浪费. 本文继之前的静态通讯录作出改进,有兴趣的同学可以看看之前的文章:C语言实现静态通讯录 一.存放联系人信息 这里是用struct PeoInfodata结构体指针指向通讯录,而不再直接 struct PeoInfo data[Max] 用结构体数组定义通

  • C语言编程动态内存分配常见错误全面分析

    目录 前言:为什么存在动态内存分配? 一.动态内存函数 1.malloc和free函数 2.calloc函数 3.realloc函数 二.常见错误 1.对NULL指针解引用 2.对动态开辟空间的越界访问 3.对非动态开辟使用free函数 4.使用free释放一块动态内存开辟内存的一部分 5.对同一块空间多次释放 6.动态开辟内存忘记释放 总结 前言:为什么存在动态内存分配? 我们已经掌握的内存开辟方式如下 int a=10;//在栈空间上开辟4字节 char arr[10]={0};//在栈空间

  • C语言 动态内存开辟常见问题解决与分析流程

    目录 前言 一.动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.使用free释放非动态开辟的空间 4.使用free释放动态内存中的一部分 5.对同一块动态内存动态开辟的空间多次释放 6.动态开辟的空间忘记释放(容易造成内存泄露,比较严重) 二.动态内存错误面试题分析 1.NULL指针传参不取地址传的也是一份临时拷贝 2.局部变量和形式参数存在于栈上 3.动态内存开的空间记得free释放掉 4.非法访问内存 总结: 前言 当我们用动态内存分配函数来编写程序时,在编写

  • C语言初识动态内存管理malloc calloc realloc free函数

    目录 一.为什么存在动态内存分配 二.动态内存函数的使用 1.malloc函数 (1)malloc的定义 (2)malloc函数的注意事项 (3)malloc函数的使用 2.calloc函数 (1)calloc函数的定义 (2)calloc函数的注意事项 (3)calloc函数的使用 3.realloc函数 (1)realloc函数的定义 (2)realloc函数的注意事项 (3)realloc函数的使用 总结 一.为什么存在动态内存分配 在c语言中我们目前掌握的内存开辟方式有: int val

  • 详细谈谈C语言中动态内存

    目录 前言 1.关于动态内存的函数 1.1malloc和free函数 1.2calloc函数 1.3realloc函数 2.常见的动态内存错误 2.1对NULL指针解引用 2.2对动态内存开辟的空间越界访问 2.3 对非动态开辟内存使用free释放 2.4 使用free释放一块动态开辟内存的一部分 2.5对同一块动态内存多次释放 2.6内存泄漏 补充:为什么要引入动态内存分配 总结 前言 关于动态内存管理,可能有学习过的小伙伴,也有没有听说过的.没有听说过的小伙伴会觉得很奇怪啊,为什么要动态开辟

  • C语言中动态内存分配malloc、calloc和realloc函数解析

    目录 前言 free函数 malloc函数 calloc函数 realloc函数 扩充 malloc/calloc/realloc区别总结 总结 前言 有时候我们需要的空间大小不确定,需要随着程序需要的空间而变化, 那以数组开辟的固定大小的空间就不适用了, 这时候我们就需要动态分配开辟空间了.当空间不够时就扩容.动态开辟是在堆区开辟一块连续可用空间,并返回这块空间的地址.有三种函数malloc, calloc和realloc.我们动态内存分配就在堆区开辟空间 上面的四个区只有堆区的空间是需要手动

  • C语言中动态内存管理图文详解

    目录 1.动态内存开辟的原因 2.动态内存函数的介绍 2.1malloc和free 2.2calloc 2.3realloc 3.常见的动态内存错误 3.1对NULL指针的解引用操作 3.2对动态开辟空间的越界访问 3.3对非动态开辟内存使用free 3.4使用释放一块动态开辟内存的一部分 3.5对同一块动态内存多次释放 3.6动态开辟内存忘记释放(内存泄漏) 4.练习 4.1练习1 4.1练习2 4.3练习3 4.4练习4 5.C/C++程序的内存开辟 总结 1.动态内存开辟的原因 常见的内存

  • 深入了解C语言的动态内存管理

    目录 一.为什么会存在动态内存 二.动态内存函数 1.malloc和free 2.calloc 3.realloc 三.动态内存函数常见错误 2.对NULL指针进行解引用操作 3.使用free释放一块动态开辟内存的一部分 4.对静态内存进行free释放 5.对同一内存空间多次释放 6.动态开辟空间忘记释放 四.经典笔试题 1.笔试1 2.笔试2 3.笔试3 总结 一.为什么会存在动态内存 int data=20;//在栈空间上开辟4个字节空间 char ch[5]={0};//在栈开辟5个字节连

  • 详解C语言中动态内存管理及柔性数组的使用

    目录 一.malloc 二.free 三.calloc 四.realloc 1.realloc在扩容时的情况 2.realloc也能实现malloc功能 五.使用动态内存的常见错误 1.free空指针 2.对动态开辟的空间越界访问 3.对非动态开辟内容free 4.只free动态开辟空间的一部分 5.对同一块内存多次free 6.动态内存空间忘记释放(内存泄漏) 六.柔性数组 1.柔性数组的概念 2.柔性数组的特点 3.柔性数组的使用场景 4.柔性数组的优点 一.malloc 这个函数向堆区申请

  • 详解C语言之动态内存管理

    目录 开辟动态内存的函数 释放开辟的动态内存空间的函数 错误信息函数 具体使用例: 常见的动态内存错误 总结 先来了解一下动态管理内存所需用到的函数 开辟动态内存的函数 1.malloc函数:void* malloc(size_t size); 功能:开辟一块大小为size单位为字节的动态空间.若开辟成功返回函数开辟空间的无类型指针,若开辟失败则返回空指针NULL 2.calloc函数: void* calloc(size_t num, size_t size); 功能:开辟一块能容纳下num个

随机推荐