通讯录(文件版本)

简介: 通讯录(文件版本)

无论是上面的静态版本的通讯录或者是动态版本的通讯录,在程序运行结束之后都会被销毁掉,就是保存的联系人的数据也会丢失,这显然不符合我们对通讯录的需求,我们正常需要的是能够在下一次打开通讯录的时候找到以前保存过的联系人的信息,这样才是有意义的通讯录,那我们可以把以上两个版本的通讯录进行改造,使它变成文件版本的通讯录,即把每次存进去的信息在程序关闭之前保存到文件当中,在下一次打开程序的时候自动加载到程序当中,这样才是符合我们需求的通讯录。


其实我们只需要增加两个函数即可,即退出程序前保存数据和运行程序时加载数据的函数:


//新增函数
//保存通讯录信息到文件中
void SaveContact(Contact* con)
{
  assert(con);
  //以二进制写的形式打开文件“wb”
  FILE* pf = fopen("contact.txt", "wb");
  if (pf == NULL)
  {
    perror("SaveContact");
    return;
  }
  int i = 0;
  //遍历把数据逐一写到文件中
  for (i = 0; i < con->sz; i++)
  {
      //参数意义:1.待写入数据的地址,2.结构体大小
      //3.一次写入的数据的数量,逐一写入,4.存放数据的地址
    fwrite(con->data + i, sizeof(peo_info), 1, pf);
  }
  fclose(pf);//关闭文件
  pf = NULL;
  printf("保存成功!\n");
}


void check_capacity(Contact* con)
{
  assert(con);
  if (con->capacity == con->sz)
  {
    peo_info* p = (peo_info*)realloc(con->data, sizeof(peo_info) * (con->capacity + 2));
    if (p == NULL)
    {
      perror("realloc");
      return;
    }
    else
    {
      con->data = p;
      con->capacity += 2;
      printf("增容成功!\n");
    }
  }
}
//新增函数
void LoadContact(Contact* con)
{
  assert(con);
  //由于保存数据时是用二进制的形式写进文件中
  //所以需要用二进制读的形式打开文件
  FILE* pf = fopen("contact.txt", "rb");
  if (pf == NULL)
  {
    perror("LoadContact");
    return;
  }
  //读数据,需要创建一个临时变量
  peo_info tmp = { 0 };
  int i = 0;
  //fread函数读到一个数据返回1,读不到数据返回返回0
  //循环就停止
  while (fread(&tmp, sizeof(peo_info), 1, pf))
  {
    //读到一个数据需要先检查是否需要增容
    check_capacity(con);
    con->data[i] = tmp;//对应位置进行结构体赋值即可
    i++;
    con->sz++;//每加载一个数据数量sz+1
  }
  printf("加载成功!\n");
  fclose(pf);//关闭文件
  pf = NULL;
}
void InitContact(Contact* con)
{
  assert(con);
  peo_info* p = (peo_info*)calloc(2, sizeof(peo_info));
  if (p == NULL)
  {
    perror("InitContact");
    return;
  }
  con->data = p;
  con->sz = 0;
  con->capacity = 2;
  //新增函数,初始化完成后加载数据到程序中
  //加载文件信息到通讯录
  LoadContact(con);
}



SaveContact函数保存数据在Destroy之前调用即可。


以上就是通讯录文件版本新增的两个函数,这个就是符合我们需求的通讯录的最终版本哦。你学会了吗?

相关文章
|
存储 算法 数据可视化
深入解析力扣161题:相隔为 1 的编辑距离(逐字符比较与动态规划详解)
深入解析力扣161题:相隔为 1 的编辑距离(逐字符比较与动态规划详解)
|
8月前
|
机器学习/深度学习 自然语言处理 安全
《鸿蒙微内核与人工智能算法协同,开启智能系统新时代》
鸿蒙系统凭借独特的微内核架构与人工智能算法的深度融合,引领操作系统智能化新潮流。微内核将核心功能模块化,提升系统的精简性、稳定性和安全性,同时增强可扩展性和维护性。人工智能算法涵盖机器学习、自然语言处理等领域,应用于语音助手、图像识别及资源管理,优化系统性能。两者高效协同,实现资源共享、任务调度和数据安全,显著提升系统性能和智能化水平,为用户带来流畅、智能的使用体验。
121 13
|
存储 Java 分布式数据库
【分布式计算框架】HBase数据库编程实践
【分布式计算框架】HBase数据库编程实践
305 1
|
5G 调度 芯片
5G 帧结构 |带你读《5G空口特性与关键技术》之七
虽然在较高的载波频率下通常不使用较小的子载波间隔,但是参数集可以独立于频段进行选择。不同子载波间隔可用于不同的场景下。如对于室外宏覆盖和微小区,可以采用 30kHz 子载波间隔;而室内站则可以采用 60kHz 子载波间隔;对于毫米波,则可以采用更大的子载波间隔,如 120kHz。
12514 2
5G 帧结构 |带你读《5G空口特性与关键技术》之七
|
前端开发 JavaScript API
|
JavaScript 前端开发 安全
深入探究iframe:网页嵌入的魔法盒子(上)
深入探究iframe:网页嵌入的魔法盒子(上)
|
druid 关系型数据库 MySQL
高并发下 MySQL Statement Cancellation Timer 的线程数暴涨
高并发下 MySQL Statement Cancellation Timer 的线程数暴涨
|
安全 前端开发 Java
SpringBoot整合Spring Security,使用短信验证码方式进行登录(七)
该类和图片验证码差不多,只是多个手机号判断,需要注意的是,这里拦截的是/smslogin接口,该接口为短信登录的接口,该接口不像/login接口由security提供,需要我们自己实现。
890 0
|
安全 AndFix 区块链
区块链3D元宇宙游戏系统开发规则玩法/步骤指南/源码项目
Developing a blockchain metaverse 3D game system is a complex and innovative process that requires comprehensive consideration of blockchain technology, game design and development, and virtual reality (VR). The following is the general process for developing the system:
|
存储 SQL 弹性计算
阿里DDD四弹拜读
阿里殷浩大牛写了DDD系统文章,现在已经更新到每四篇,有很多异于常规的地方,收获良多,总结一下
1882 0
阿里DDD四弹拜读