【文件版&动态版通讯录】

简介: 【文件版&动态版通讯录】

今天我们再改进一下之前的通讯录,现在可以把通讯录的信息保存在文件当中;

一、测试部分

本次保存和读取通讯录的内容都是以二进制的形式保存和读取;

对于测试部分,改动的地方在于销毁通讯录之前,需要把通讯录的内容保存到文件中,所以在销毁通讯录的函数前加了一个SaveContact函数保存通讯录;函数的具体实现看函数实现部分;

#include "C_File Dynamic Contact.h"
    void menu()
    {
      printf("******      1.Add         2.Del     ***********\n");
      printf("******      3.Search      4.Modify  ***********\n");
      printf("******      5.Show        6.Sort    ***********\n");
      printf("******             0.exit           ***********\n");
      printf("***********************************************\n");
    }
    enum Option
    {
      EXIT,
      ADD,
      DEL,
      SEARCH,
      MODIFY,
      SHOW,
      SORT,
    };
    int main()
    {
      int input = 0;
      Contact con;
      InitContact(&con);
      do
      {
        menu();
        printf("请选择:\n");
        scanf("%d", &input);
        switch (input)
        {
        case ADD:
          AddContact(&con);
          break;
        case DEL:
          DelContact(&con);
          break;
        case SEARCH:
          SearchContact(&con);
          break;
        case MODIFY:
          ModifyContact(&con);
          break;
        case SHOW:
          ShowContact(&con);
          break;
        case SORT:
          SortContact(&con);
          break;
        case EXIT:
          SaveContact(&con);
          DestoryContact(&con);
          printf("退出通讯录\n");
          break;
        default:
          printf("输入错误。请重新输入:\n");
          break;
        }
      } while (input);
      return 0;
    }

二、函数实现部分

现在我们在销毁通讯录前加了保存通讯录函数SaveContact,并实现了;

但是在保存之后的通讯录,我们在下一次打开时,是不是也最好可以把通讯录中的内容读取出来呢,所以我们在初始化通讯录函数中加了这么个函数-LoadContact,加载通讯录的内容,函数的具体实现如下;

#include "C_File Dynamic Contact.h"
    void CheakCapacity(Contact* pc);
    //加载文件的信息到通讯录
    void LoadContact(Contact* pc)
    {
      //以二进制的形式读取
      FILE* pf = fopen("Contact.txt", "rb");
      assert(pf);
      //读文件,创建一个临时变量储存读到的信息
      PeoInfo tmp = { 0 };
      //将读到的信息放在tmp中
      while (fread(&tmp, sizeof(PeoInfo), 1, pf))
      {
        //每次读取前判断容量是否够,不够就扩容
        CheakCapacity(pc);
        //将tmp中的信息放到内存中
        pc->data[pc->sz] = tmp;
        pc->sz++;
      }
      fclose(pf);
      pf = NULL;
    }
    //动态版本初始化通讯录
    void InitContact(Contact* pc)
    {
      pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
      assert(pc->data);
      pc->sz = 0;
      pc->Capacity = DEFAULT_SZ;
      //加载通讯录信息
      LoadContact(pc);
    }
    //查找函数
    //加static修饰这个函数是为了这个函数只能在这个.c文件内用,出了这个文件就用不了
    static int FindByName(Contact* pc, char* name)
    {
      int i = 0;
      for (i = 0; i < pc->sz; i++)
      {
        //如果找到了就返回这个下标
        if (strcmp(pc->data[i].name, name) == 0)
        {
          return i;
        }
      }
      return -1;
    }
    //打印通讯录
    void ShowContact(Contact* pc)
    {
      int i = 0;
      //打印标题
      printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
      for (i = 0; i < pc->sz; i++)
      {
        printf("%-10s %-4d %-5s %-12s %-30s\n",
          pc->data[i].name,
          pc->data[i].age,
          pc->data[i].sex,
          pc->data[i].tele,
          pc->data[i].addr);
      }
      printf("\n");
    }
    //检查Capacity的容量是否满
    void CheakCapacity(Contact* pc)
    {
      if (pc->Capacity == pc->sz)
      {
        PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->Capacity + INC_SZ) * sizeof(PeoInfo));
        assert(ptr);
        pc->Capacity += INC_SZ;
        pc->data = ptr;
        printf("增容成功!\n");
      }
    }
    //增加指定联系人
    void AddContact(Contact* pc)
    {
      CheakCapacity(pc);
      printf("请输入名字:");
      scanf("%s", pc->data[pc->sz].name);
      printf("请输入年龄:");
      scanf("%d", &(pc->data[pc->sz].age));
      printf("请输入性别:");
      scanf("%s", pc->data[pc->sz].sex);
      printf("请输入电话:");
      scanf("%s", pc->data[pc->sz].tele);
      printf("请输入地址:");
      scanf("%s", pc->data[pc->sz].addr);
      //添加完sz的长度++
      pc->sz++;
      printf("添加成功\n");
    }
    //删除指定联系人
    void DelContact(Contact* pc)
    {
      //通讯录为空
      if (pc->sz == 0)
      {
        printf("通讯录为空,无法删除\n");
        return;
      }
      //不为空,删除
      char name[MAX_NAME];
      printf("请输入名字:");
      scanf("%s", &name);
      //一个查找函数,因为查找功能重复,所以写一个查找函数更好
      int pos = FindByName(pc, name);
      if (pos == -1)
      {
        printf("要删除的不存在\n");
        return;
      }
      int i = 0;
      //将后面的数据往前挪
      for (i = pos; i < pc->sz; i++)
      {
        pc->data[i] = pc->data[i + 1];
      }
      //挪完后有效数据的长度--
      pc->sz--;
      printf("删除成功\n");
    }
    //在通讯录查找指定的人
    void SearchContact(Contact* pc)
    {
      printf("请输入要查找的人的名字:");
      char name[MAX_NAME];
      scanf("%s", &name);
      int pos = FindByName(pc, name);
      if (pos == -1)
      {
        printf("要查找的人不存在\n");
        return;
      }
      printf("查找成功!\n\n");
      printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
      //找到了打印数据
      printf("%-10s %-4d %-5s %-12s %-30s\n",
        pc->data[pos].name,
        pc->data[pos].age,
        pc->data[pos].sex,
        pc->data[pos].tele,
        pc->data[pos].addr);
      printf("\n");
    }
    //修改通讯录的数据
    void ModifyContact(Contact* pc)
    {
      printf("请输入需要修改的人的名字:");
      char name[MAX_NAME];
      scanf("%s", &name);
      int pos = FindByName(pc, name);
      if (pos == -1)
      {
        printf("不存在此人\n");
        return;
      }
      //找到了就修改pos下标的数据
      printf("请重新输入TA的数据\n");
      printf("请输入名字:");
      scanf("%s", pc->data[pos].name);
      printf("请输入年龄:");
      scanf("%d", &(pc->data[pos].age));
      printf("请输入性别:");
      scanf("%s", pc->data[pos].sex);
      printf("请输入电话:");
      scanf("%s", pc->data[pos].tele);
      printf("请输入地址:");
      scanf("%s", pc->data[pos].addr);
      printf("修改成功\n");
    }
    //按照名字排序
    int cmp_by_name(void* e1, void* e2)
    {
      //强转成PeoInfo*类型
      return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
    }
    void SortContact(Contact* pc)
    {
      printf("按照名字排列:\n");
      qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
      printf("排序成功\n\n");
    }
    //保存通讯录
    void SaveContact(Contact* pc)
    {
      //以二进制形式打开并写进去
      FILE* pf = fopen("Contact.txt", "wb");
      assert(pf);
      for (int i = 0; i < pc->sz; i++)
      {
        fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
      }
      fclose(pf);
      pf = NULL;
    }
    //销毁通讯录
    void DestoryContact(Contact* pc)
    {
      free(pc->data);
      pc->data = NULL;
      pc->Capacity = 0;
      pc->sz = 0;
      printf("释放内存\n");
    }

三、函数声明部分

#include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <assert.h>
    #define MAX_NAME 20
    #define MAX_SEX 5
    #define MAX_TELE 12
    #define MAX_ADDR 30
    //定义开始默认通讯录开辟空间的大小
    #define DEFAULT_SZ 3
    //定义每次
    #define INC_SZ 2
    //表示一个人的信息
    typedef struct PeoInfo
    {
      char name[MAX_NAME];
      int age;
      char sex[MAX_SEX];
      char tele[MAX_TELE];
      char addr[MAX_ADDR];
    }PeoInfo;
    //定义另外一个结构体,存放第一个结构体的数据和记录通讯录中有效信息的个数
    typedef struct Contact
    {
      PeoInfo* data;//data指向了存放数据的空间
      int sz;//记录通讯录中有效信息的个数
      int Capacity;//通讯录当前的容量
    }Contact;
    //初始化通讯录
    void InitContact(Contact* pc);
    //打印通讯录
    void ShowContact(Contact* pc);
    //增加指定联系人
    void AddContact(Contact* pc);
    //删除指定联系人
    void DelContact(Contact* pc);
    //在通讯录查找指定的人
    void SearchContact(Contact* pc);
    //修改通讯录的数据
    void ModifyContact(Contact* pc);
    //排序通讯录
    void SortContact(Contact* pc);
    //保存通讯录
    void SaveContact(Contact* pc);
    //销毁通讯录
    void DestoryContact(Contact* pc);
目录
相关文章
|
7月前
|
存储
通讯录(动态实现与文件优化版)
通讯录(动态实现与文件优化版)
55 1
【动态通讯录】
【动态通讯录】
48 0
|
7月前
|
C++
动态通讯录及程序保存在文件中
动态通讯录及程序保存在文件中
54 0
动态通讯录及程序保存在文件中
|
7月前
|
存储 编译器 C语言
通讯录详解(静态版,动态版,文件版)
通讯录详解(静态版,动态版,文件版)
113 0
|
存储
【静态通讯录】
【静态通讯录】
42 0
|
存储
通讯录(静态版)
通讯录(静态版)
110 0
|
C语言
C/【静态通讯录】
C/【静态通讯录】
静态通讯录
C语言学习——教你学会静态通讯录的实现(保姆级教程哦~)