C语言 动态通讯录实现

简介: C语言 动态通讯录实现

前言:

上期博客写了静态通讯录并且答应给大家写一个动态版,这不,它来了:



1.动态版与静态版的区别


静态版的内存空间开辟大小是固定的,放了预期的最大值,并不会根据实际存放的数据而变化;

当需要存放的数据较少时,难免会出现内存的浪费,所以我们考虑申请动态内存开辟;


2.相关函数的介绍


2.1 malloc


开辟动态内存,最经典的就是 malloc 函数了:

c782dce7577cd3f9555ff5a639ea0ea0_088b4b881ff04dc09bdbb3d7caafc3bf.png

函数的作用是向内存申请一块连续可用的空间,并返回指向这块空间的指针

用它需要传递一个无符号整型的参数:需要开辟的动态内存的大小,单位是字节

如果开辟成功,函数返回指向开辟好空间的指针;

如果开辟失败,函数返回NULL指针;

因此 malloc 的返回值要做检查。


但是,动态内存嘛,向内存申请了还是要还的

还内存也方便,用一个 free 函数就可以:

7bad20359d8ee0d77e1428874114741a_e919fe67df804a21b126fdd2bf37b7ed.png


free 函数用来释放动态内存开辟的空间

如果 ptr 指向的空间不是动态内存开辟的,free 函数的行为未定义;

如果 ptr 是 NULL,函数不作为;


另外注意,指针释放后小心变野哦,释放的指针要赋个 NULL

开辟动态内存,养成好习惯:

free(ptr);
ptr = NULL;


2.2 calloc


228aa0b1957869b3d343c653db46d0c9_1c990103ee744d5b9e2f82b851d66582.png

calloc 函数的作用也是申请动态内存,只不过比 malloc 更灵活些;

它为 num 个大小为 size 的元素开辟一块空间,

并且把空间的每个字节初始化为 0。


2.3 realloc


33a6d787e37de99f03fc34d58feea56f_0f8f3a9851b44f2b8d75a0f433aeb156.png

realloc 函数的出现让动态内存管理更加灵活;

realloc 函数的作用是调整动态开辟内存的大小;

函数返回调整之后的内存起始位置

ptr 是要调整的内存地址

size 是调整之后的新大小


3.实现过程


做了以上铺垫,就可以开始正题了:

静态通讯录到动态通讯录,需要在哪动刀子呢?

多是在添加联系人信息时开辟动态内存:

我们先给存放联系人一个初始空间,再定义一个扩容空间,按需扩容。

给通讯录结构体改一 加一:

typedef struct Contact
{
  PeoInform data[MAX];//存放的联系人
  PeoInform* data;//指向存放人的信息空间
  int sz;//当前已经存放的联系人个数
  int capacity;//当前通讯录的容量
}Contact;

然后在原来的添加联系人的基础上加入检查是否扩容的函数:

void* check_capacity(Contact* pc)
{
  assert(pc);
  if (pc->sz == pc->capacity)
  {
    printf("通讯录已满,无法添加\n");
    return;
  }
  //扩容
  PeoInform* ptr = (PeoInform*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInform));
  if (ptr == NULL)
  {
    perror("check_capacity");
    return;
  }
  pc->data = ptr;
  pc->capacity += INC_SZ;
  printf("扩容成功\n");
}

初始化也要相应改变:

void Init_Contact(Contact* pc)
{
  assert(pc);
  pc->sz = 0;
    PeoInform* ptr = (PeoInform*)calloc(DEFAULT_SZ, sizeof(PeoInform));
  if (ptr == NULL)
  {
    perror("Init_Contact");
    return;
  }
  pc->data = ptr;
  pc->capacity = DEFAULT_SZ;
}

退出时要销毁通讯录:

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

到这里基本上就可以了,已经化为动态版。


总结:

静态版升级为动态版,实际上只是在申请内存上做了改动,重点是学会如何使用动态内存开辟。

目录
相关文章
|
3月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
44 2
|
3月前
|
存储 C语言
手把手教你用C语言实现通讯录管理系统
手把手教你用C语言实现通讯录管理系统
|
5月前
|
存储 搜索推荐 算法
【C语言】C语言—通讯录管理系统(源码)【独一无二】
【C语言】C语言—通讯录管理系统(源码)【独一无二】
|
5月前
|
存储 数据可视化 C语言
【C语言】C语言 手机通讯录系统的设计 (源码+数据+论文)【独一无二】
【C语言】C语言 手机通讯录系统的设计 (源码+数据+论文)【独一无二】
|
7月前
|
机器学习/深度学习 搜索推荐 程序员
C语言实现个人通讯录(功能优化)-2
C语言实现个人通讯录(功能优化)
|
7月前
|
存储 C语言 索引
C语言实现个人通讯录(功能优化)-1
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-1
|
7月前
|
C语言
C语言学习记录——通讯录(静态内存)
C语言学习记录——通讯录(静态内存)
38 2
|
8月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
84 1
|
8月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
102 1
|
7月前
|
存储 人机交互 C语言
【C语言项目实战】使用单链表实现通讯录
【C语言项目实战】使用单链表实现通讯录