【c语言进阶】动态通讯录(上)

简介: 【c语言进阶】动态通讯录(上)

前言:


 在前面的学习中,我们写了静态通讯录:c语言实现静态通讯录


一、静态通讯录的弊端:


 对于简易版本的通讯录来说,我们是直接指定了通讯录的大小,那么此时我们会发现两个弊端:


弊端1:


 如果我们创建的通讯录空间过大,就会浪费空间;如果我们创建的通讯录太小又不够使用 。所以,此时我们就得优化通信录给定空间上的问题,不能再给其指定大小的空间,而是让其空间有灵活性,此时我们以动态增容的方式来给定通讯录的空间,就很好的规避了这一问题!


弊端2:


 我们知道程序运行起来我们输入的数据都是保存在内存上的,在简易版本中我们在运行通讯录之后添加的数据,在程序结束的时候都会被清除。当而我们既然要保存联系人的信息,就得做到数据持久化的保存,我们就得将数据保存到硬盘中,也就是文件当中,此时我们可以用文件操作的方式来实现持久化的保存联系人信息。


二、动态增容优化通讯录:


2.1.枚举类型的加入


 在前面我们学习了枚举类型的使用,我们在写menu菜单的switch函数时,常常会因为不知道数字对应的是哪一个功能而弄混。

 枚举类型中各成员的值为从零开始依次递增,于是我们可以再使用一个枚举类型来使我们的选项对应用户的选择:


enum OPTION
{
  Exit = 0,
  Add = 1,
  Del,
  Search,
  Modify,
  Print,
  sort
};


 这样一来,我们就可以把case后面的1,2,3等数据换成对应的功能名字。

如case 1:替换为case Add:


2.2.结构体的修改


 之前我们创建了两个结构体,第一个存放信息,第二个存放信息的数组和联系人数量,可是第二个存放的人信息的数组规定死了100个元素。所以我们将第二个结构体做一下改动即可:


//静态版本
//typedef struct contact
//{
//  PeoInfo data[MAX];
//  int sz;
//}contact;
//动态版本
typedef struct Contact
{
  PeoInfo* data;//指向存放人的信息的空间
  int sz;//当前已经放的信息的个数
  int capacity;//当前通讯录的最大容量
}contact;


 这里我们用sz记录联系人数量,用capacity指向当前通讯录的最大容量。在这里我们会发现结构体明显小了很多,因为存放人信息的空间我们还没有创建!


2.3.Initcontact函数的修改


 之前的初始化仅仅只是将所有的数据初始化为0,但是动态版本的通讯录还没有开辟联系人的空间。所有我们要在初始化函数里完成这个操作。


//静态版本:
//void Initcontact(contact* con)
//{
//  assert(con);
//  con->sz = 0;
//  memset(con->data, 0, sizeof(con->data));
//}
//动态版本:
void Initcontact(contact* con)
{
  assert(con);
  //DEFAULT_SZ是宏定义的3,在contact.h有添加!
  PeoInfo *ptr= (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
  if (ptr == NULL)
  {
  perror("InitContact::calloc");
  return;
  }
  con->sz = 0;
  con->capacity = DEFAULT_SZ;
  con->data = ptr;
//这里的Loadcontact函数在下面会提到!
  LoadContact(con);
}



 在这里大家就不用自己初始化联系人信息了!因为calloc本身就有这个功能!


2.4.Addcontact函数的修改


 之前静态通讯录的添加联系人只需要在不超过容量的基础上添加即可,超过容量就不能操作了。但是动态通讯录在发现容量不足时,要有自动增容的功能,这也是动态通讯录的有点所在!


//静态add
//void AddContact(contact* con)
//{
//  assert(con);
//  if (con->sz == 99)
//  {
//  printf("通讯录已经存满,请联系操作人员");
//  return;
//  }
//  printf("请输入联系人姓名:>");
//  scanf("%s", con->data[con->sz].name);
//  printf("请输入联系人性别:>");
//  scanf("%s",con->data[con->sz].sex);
//  printf("请输入联系人年龄:>");
//  scanf("%d", &(con->data[con->sz].age));
//  printf("请输入联系人联系方式:>");
//  scanf("%s", con->data[con->sz].tele);
//  printf("请输入联系人住址:>");
//  scanf("%s", con->data[con->sz].addr);
//  printf("联系人信息添加成功!\n");
//  con->sz++;
//}
// 
//判断容量是否够用!并且自动增容
void check_capacity(contact* con)
{
  assert(con);
  if (con->sz == con->capacity)
  {
  printf("内存已满,正在扩容——\n");
  Sleep(1000);
  PeoInfo* ptr = (PeoInfo*)realloc(con->data, (con->capacity + INC_SZ) * sizeof(PeoInfo));
  if (ptr==NULL)
  {
    perror("check_capacity::realloc");
    return;
  }
  con->capacity += INC_SZ;
  con->data = ptr;
  printf("扩容成功\n");
  }
}
//动态add
void AddContact(contact* con)
{
  assert(con);
  check_capacity(con);
  printf("请输入联系人姓名:>");
  scanf("%s", con->data[con->sz].name);
  printf("请输入联系人性别:>");
  scanf("%s", con->data[con->sz].sex);
  printf("请输入联系人年龄:>");
  scanf("%d", &(con->data[con->sz].age));
  printf("请输入联系人联系方式:>");
  scanf("%s", con->data[con->sz].tele);
  printf("请输入联系人住址:>");
  scanf("%s", con->data[con->sz].addr);
  printf("联系人信息添加成功!\n");
  con->sz++;
}


2.5.Desdrycontact函数的添加


 在使用完堆区的空间之后,最重要的事情是什么?当然是释放这块空间呀!


void DestroyContact(contact* con)
{
  free(con->data);
  con->data = NULL;
  con->sz = 0;
  con->capacity = 0;
  con = NULL;
}


目录
相关文章
|
8月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
4月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
51 2
|
4月前
|
存储 C语言
手把手教你用C语言实现通讯录管理系统
手把手教你用C语言实现通讯录管理系统
|
6月前
|
存储 搜索推荐 算法
【C语言】C语言—通讯录管理系统(源码)【独一无二】
【C语言】C语言—通讯录管理系统(源码)【独一无二】
109 2
|
6月前
|
存储 数据可视化 C语言
【C语言】C语言 手机通讯录系统的设计 (源码+数据+论文)【独一无二】
【C语言】C语言 手机通讯录系统的设计 (源码+数据+论文)【独一无二】
|
8月前
|
机器学习/深度学习 搜索推荐 程序员
C语言实现个人通讯录(功能优化)-2
C语言实现个人通讯录(功能优化)
|
8月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
65 0
|
8月前
|
存储 人机交互 C语言
【C语言项目实战】使用单链表实现通讯录
【C语言项目实战】使用单链表实现通讯录
|
8月前
|
存储 C语言 C++
【C语言刷题系列】水仙花数的打印及进阶
【C语言刷题系列】水仙花数的打印及进阶
|
23天前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
55 23

热门文章

最新文章