【基于动态内存+文件操作】通讯录管理系统

简介: 前言对于一个通讯录管理系统来说,较为重要的是清楚具体需要什么功能以及每一块功能的实现。下面,实现一个通讯录,该通讯录能够进行联系人的添加,删除,查找,修改,展示,排序,保存,销毁,等功能。我们知道,一个联系人有以下基本信息:联系人姓名,年龄,性别,电话,住址等。所以下面来实现功能时,按照每一个功能逐一实现即可。

前言

对于一个通讯录管理系统来说,较为重要的是清楚具体需要什么功能以及每一块功能的实现。

下面,实现一个通讯录,该通讯录能够进行联系人的添加,删除,查找,修改,展示,排序,保存,销毁,等功能。

我们知道,一个联系人有以下基本信息:联系人姓名,年龄,性别,电话,住址等。

所以下面来实现功能时,按照每一个功能逐一实现即可。

每一个项目文件的说明

该通讯录包含三个项目文件:

Contact.c文件
Contact.h文件
test.c文件

Contact.c文件是用来实现每个区域的功能。
Contact.h文件是用来声明函数,包含头文件的。
test.c文件是用来测试代码的(建议封装完一个函数,写完一个函数后就测试代码)

打印基本菜单,以供用户选择。

实现菜单较为简单,列出功能,共用户选择即可。

void menu(void)
{
  printf("*******************************\n");
  printf("******1.Add     2.Del    ******\n");
  printf("******3.Search  4.Modify ******\n");
  printf("******5.Show    6.Sort   ******\n");
  printf("******7.Clean   8.Save   ******\n");
  printf("******0.Exit             ******\n");
  printf("*******************************\n");
}

19f6900d35b74514b6623bcf5e8fd4f8.png

1.创建一个适合存放联系人信息的结构体

上面讲到,联系人的信息有姓名,年龄,性别,电话,地址等

#define MAX 100
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define CAPACITY_SIZE 3
//个人信息
typedef struct PeoInfo
{
  char name[NAME_MAX];
  int age;
  char sex[SEX_MAX];
  char tele[TELE_MAX];
  char addr[ADDR_MAX];
}PeoInfo;

基本联系人信息如上。

然而,这只是一个人的信息,一个通讯录有成百上千人,我们需要一块空间来存放联系人的信息,这就需要到一个结构体数组来存放每一个结构体联系人的信息,如下图:

d87fe12900b243bab9643b3595580b69.png

又有一个问题了,当存放了第一个人的信息后,怎么找到第二个人的空间来存放?第三个人呢?

由此可以联想到,需要用到一个存储下标的结构体变量,每存储一个人的信息,该下标变量就++。

04ef756e9be0443387bda36c24b72e7e.png

我们在一开始申请空间的时候,不适宜申请太多空间,申请多少空间,就用一个变量来记录,叫做capacity(容量),也就是结构体的申请的空间大小。

所以可以创建一个大空间存放每个人的信息,该空间也是一个结构体,包含一个数组和存储下标的变量和一个结构体的容量(能容纳多少个联系人)。

//整个通讯录信息
typedef struct Contact
{
  PeoInfo *data;
  int sz;
  int capacity;
}Contact;

2.初始化通讯录(加载上次的联系人,检查容量是否充足)

在初始化通讯录时,我们可以分装一个函数,专门实现该功能。

我们在写入联系人信息时,该信息会保存到本地的磁盘中,当我们再次进入通讯录时,应该加载上一次存放好的联系人的信息,防止用户重复存放等。

所以应该也需要封装一个加载信息的函数:

void LoadContact(Contact* ps)
{
  assert(ps);
  FILE* pfread = fopen("Contact.txt", "rb");//二进制形式读取
  PeoInfo tmp = { 0 };//把读取的联系人先放着,先判断容量够不够,再放进data里
  if (pfread == NULL)
  {
    printf("LoadContact:%s\n", strerror(errno));
  }
  else
  {
    while (fread(&tmp, sizeof(PeoInfo), 1, pfread))
    {
      CheckCapacity(ps);//判断容量够不够
      ps->data[ps->sz] = tmp;
      ps->sz++;
    }
  }
  fclose(pfread);
  pfread = NULL;
}

初始化完通讯录后,就加载上一次的联系人信息出来。由于我们在进入通讯录时,申请的空间不多,有可能在本地磁盘中存储的联系人信息有多个,我们申请的空间只要少量,所以需要检查容量是否充足,如果容量不足,则需要再次申请空间。

//检查容量
void CheckCapacity(Contact* ps)
{
  assert(ps);
  if (ps->sz == ps->capacity)
  {
    //扩容
    PeoInfo* ptr = realloc(ps->data, sizeof(PeoInfo) * (2 + ps->capacity));//一次扩容两个
    if (ptr == NULL)
    {
      printf("%s\n", strerror(errno));
      printf("增容失败\n");
    }
    else
    {
      ps->data = ptr;
      ps->capacity += 2;
      printf("增容成功\n");
    }
  }
}


用上面的函数来检查容量。

void InitContact(Contact* ps)
{
  assert(ps);
  ps->data =(PeoInfo*)malloc(sizeof(PeoInfo) * CAPACITY_SIZE);
  if (ps->data == NULL)
  {
    printf("%s\n", strerror(errno));
  }
  ps->capacity = CAPACITY_SIZE;
  ps->sz = 0;
}

初始化完通讯录之后,就可以开始逐一实现每个函数的功能了。

枚举常量内部内容:

对于枚举来说,其成员的排序是从0开始的,即第一个成员的序号是0,第二个成员的序号是1…

enum
{
  Exit,//0
  Add,//1
  Del,//2
  Search,//3
  Modify,//4
  Show,//5
  Sort,//6
  Clean,//7
  Save//8
};

(1)增加联系人信息

再增加联系人之前,需要检查当前的容量是否足够,如果不够,也是一样需要增容。

增加联系人的信息,就需要输入姓名,年龄,性别,电话,住址等。

并且每次增加完之后,指向联系人的下标的变量就需要++,向前走。

void AddContact(Contact* ps)
{
  assert(ps);
  CheckCapacity(ps);
  检查容量是否充足
  printf("请输入姓名:>\n");
  scanf("%s", ps->data[ps->sz].name);
  printf("请输入年龄:>\n");
  scanf("%d", &ps->data[ps->sz].age);
  printf("请输入性别:>\n");
  scanf("%s", ps->data[ps->sz].sex);
  printf("请输入电话:>\n");
  scanf("%s", ps->data[ps->sz].tele);
  printf("请输入住址:>\n");
  scanf("%s", ps->data[ps->sz].addr);
  ps->sz++;
  printf("添加成功\n");
}

(2)删除联系人信息

实现代码之前,先想想,删除一个联系人,是不是要先找到该联系人?不然怎么删除呢?

而找该联系人,就是第三个功能:查找联系人。

而第四个功能:删除联系人,同理,必须先找到想修改的联系人的信息,才能修改。

所以,这三个功能都有相同点:先找到目标联系人

封装一个函数来实现:

static int FindByName(const Contact* ps)
{
  assert(ps);
  char name[NAME_MAX] = { 0 };
  scanf("%s", name);
  for (int i = 0; i < ps->sz; i++)
  {
    if (strcmp(ps->data[i].name, name) == 0)
    {
      return i;
    }
  }
  return -1;
}

以名字来查找。

有了这个函数,就可以删除目标联系人了。

所谓的删除,不过就是往前覆盖,进行下标再- -



0c9ea69d56264338b50201845b4f8427.gif

void DelContact(Contact* ps)
{
  assert(ps);
  printf("请输入要删除的人的名字:>\n");
  int pos = FindByName(ps);
  if (pos == -1)
  {
    printf("要删除的人不存在\n");
    return;
  }
  //删除也就是向前覆盖即可
  for (int i = pos; i < ps->sz - 1; i++)
  {
    ps->data[i] = ps->data[i + 1];
  }
  ps->sz--;
  printf("删除成功\n");
}

(3)查找联系人信息

查找联系人信息,然后打印出来。

void SearchContact(const Contact* ps)
{
  assert(ps);
  printf("请输入要查找的人的名字:>\n");
  int pos = FindByName(ps);
  if (pos == -1)
  {
    printf("要查找的人不存在\n");
    return;
  }
  printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话", "住址");
  printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n", ps->data[pos].name,
    ps->data[pos].age,
    ps->data[pos].sex,
    ps->data[pos].tele,
    ps->data[pos].addr);
}

(4)修改联系人信息

void ModifyContact(Contact* ps)
{
  assert(ps);
  printf("请输入要修改的人的名字:>\n");
  int pos = FindByName(ps);
  if (pos == -1)
  {
    printf("要修改的人不存在\n");
    return;
  }
  printf("请输入姓名:>\n");
  scanf("%s", ps->data[pos].name);
  printf("请输入年龄:>\n");
  scanf("%d", &ps->data[pos].age);
  printf("请输入性别:>\n");
  scanf("%s", ps->data[pos].sex);
  printf("请输入电话:>\n");
  scanf("%s", ps->data[pos].tele);
  printf("请输入住址:>\n");
  scanf("%s", ps->data[pos].addr);
  printf("修改成功\n");
}

(5)展示联系人信息

void ShowContact(const Contact* ps)
{
  assert(ps);
  if (ps->sz == 0)
  {
    printf("通讯录为空\n");
    return;
  }
  printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名","年龄","性别", "电话","住址");
  for (int i = 0; i < ps->sz; i++)
  {
    printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n", ps->data[i].name, 
      ps->data[i].age, 
      ps->data[i].sex,
      ps->data[i].tele, 
      ps->data[i].addr);
  }
}

(6)对联系人信息进行排序

提供的排序种类有:姓名,年龄,性别,电话,住址

int cmp_name(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
int cmp_age(const void* e1, const void* e2)
{
  return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age ;
}
int cmp_sex(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->sex, ((PeoInfo*)e2)->sex);
}
int cmp_tele(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->tele, ((PeoInfo*)e2)->tele);
}
int cmp_addr(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->addr, ((PeoInfo*)e2)->addr);
}
void SortContact(Contact* ps)
{
  assert(ps);
  char tmp[5] = { 0 };
  printf("请输入要排序的种类:>\n");
  printf("(姓名,年龄,性别,电话,住址)\n");
  scanf("%s", tmp);
  char* arr[5] = { "姓名","年龄","性别","电话","住址" };
  if (strcmp(arr[0], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_name);
  }
  if (strcmp(arr[1], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_age);
  }
  if (strcmp(arr[2], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_sex);
  }
  if (strcmp(arr[3], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_tele);
  }
  if (strcmp(arr[4], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_addr);
  }
  printf("排序成功\n");
}
void CleanContact(Contact* ps)
{
  if (ps->sz == 0)
  {
    printf("通讯录已为空,无需清除\n");
    return;
  }
  memset(ps->data, 0, ps->sz);
  ps->sz = 0;
  printf("清除成功\n");
} 

7)清空联系人列表

void CleanContact(Contact* ps)
{
  if (ps->sz == 0)
  {
    printf("通讯录已为空,无需清除\n");
    return;
  }
  memset(ps->data, 0, ps->sz);
  ps->sz = 0;
  printf("清除成功\n");
} 


(8)保存当前的联系人信息到本地磁盘中

保存信息也就是写入文件。

void SaveContact(Contact* ps)
{
  assert(ps);
  size_t count = 0;
  if (ps->sz == 0)
  {
    printf("无要保存的联系人\n");
    return;
  }
  FILE* pfwrite = fopen("Contact.txt", "wb");//以二进制形式写入
  if (pfwrite == NULL)
  {
    printf("SaveContact:%s\n", strerror(errno));
  }
  for (int i = 0; i < ps->sz; i++)
  {
    count = fwrite(&(ps->data[i]), sizeof(ps->data[0]), 1, pfwrite);
    //size_t fwrite(const void* buffer, size_t size, size_t count, FILE * stream);
  }
  if (ps->sz == (int)count)
  {
    printf("所有联系人全部保存成功\n");
  }
  else
  {
    printf("保存了%zd个联系人", count);
  }
  fclose(pfwrite);
  pfwrite = NULL;
}

所有函数的声明

//初始化通讯录
void InitContact(Contact* ps);
//增加联系人信息
void AddContact(Contact *ps);
//展示联系人信息
void ShowContact(const Contact*ps);
//删除联系人信息
void DelContact(Contact* ps);
//搜索联系人信息
void SearchContact(const Contact *ps);
//修改联系人信息
void ModifyContact(Contact *ps);
//对联系人进行排序
void SortContact(Contact* ps);
//清空联系人
void CleanContact(Contact*ps);
//退出时销毁通讯录
void DestroyContact(Contact *ps);
//保存通讯录信息
void SaveContact(Contact* ps);

头文件如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<errno.h>


完整代码如下:

Contact.h项目文件

#define _CRT_SECURE_NO_WAR#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<errno.h>
#define MAX 100
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define CAPACITY_SIZE 3
//个人信息
typedef struct PeoInfo
{
  char name[NAME_MAX];
  int age;
  char sex[SEX_MAX];
  char tele[TELE_MAX];
  char addr[ADDR_MAX];
}PeoInfo;
//整个通讯录信息
typedef struct Contact
{
  PeoInfo *data;
  int sz;
  int capacity;
}Contact;
//初始化通讯录
void InitContact(Contact* ps);
//增加联系人信息
void AddContact(Contact *ps);
//展示联系人信息
void ShowContact(const Contact*ps);
//删除联系人信息
void DelContact(Contact* ps);
//搜索联系人信息
void SearchContact(const Contact *ps);
//修改联系人信息
void ModifyContact(Contact *ps);
//对联系人进行排序
void SortContact(Contact* ps);
//清空联系人
void CleanContact(Contact*ps);
//退出时销毁通讯录
void DestroyContact(Contact *ps);
//保存通讯录信息
void SaveContact(Contact* ps);
enum
{
  Exit,//0
  Add,//1
  Del,//2
  Search,//3
  Modify,//4
  Show,//5
  Sort,//6
  Clean,//7
  Save//8
};


Contact.c项目文件如下:

#include"Contact.h"
//检查容量
void CheckCapacity(Contact* ps)
{
  assert(ps);
  if (ps->sz == ps->capacity)
  {
    //扩容
    PeoInfo* ptr = realloc(ps->data, sizeof(PeoInfo) * (2 + ps->capacity));//一次扩容两个
    if (ptr == NULL)
    {
      printf("%s\n", strerror(errno));
      printf("增容失败\n");
    }
    else
    {
      ps->data = ptr;
      ps->capacity += 2;
      printf("增容成功\n");
    }
  }
}
//加载联系人信息
void LoadContact(Contact* ps)
{
  assert(ps);
  FILE* pfread = fopen("Contact.txt", "rb");//二进制形式读取
  PeoInfo tmp = { 0 };//把读取的联系人先放着,先判断容量够不够,再放进data里
  if (pfread == NULL)
  {
    printf("LoadContact:%s\n", strerror(errno));
  }
  else
  {
    //size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
    while (fread(&tmp, sizeof(PeoInfo), 1, pfread))
    {
      CheckCapacity(ps);//判断容量够不够
      ps->data[ps->sz] = tmp;
      ps->sz++;
    }
  }
  fclose(pfread);
  pfread = NULL;
}
//初始化通讯录
void InitContact(Contact* ps)
{
  assert(ps);
  ps->data =(PeoInfo*)malloc(sizeof(PeoInfo) * CAPACITY_SIZE);
  if (ps->data == NULL)
  {
    printf("%s\n", strerror(errno));
  }
  ps->capacity = CAPACITY_SIZE;
  ps->sz = 0;
  LoadContact(ps);//从上次保存的文件中加载联系人信息出来
  //memset(ps->data, 0, sizeof(ps->data));
  //ps->sz = 0;
}
void AddContact(Contact* ps)
{
  assert(ps);
  CheckCapacity(ps);
  printf("请输入姓名:>\n");
  scanf("%s", ps->data[ps->sz].name);
  printf("请输入年龄:>\n");
  scanf("%d", &ps->data[ps->sz].age);
  printf("请输入性别:>\n");
  scanf("%s", ps->data[ps->sz].sex);
  printf("请输入电话:>\n");
  scanf("%s", ps->data[ps->sz].tele);
  printf("请输入住址:>\n");
  scanf("%s", ps->data[ps->sz].addr);
  ps->sz++;
  printf("添加成功\n");
}
static int FindByName(const Contact* ps)
{
  assert(ps);
  char name[NAME_MAX] = { 0 };
  scanf("%s", name);
  for (int i = 0; i < ps->sz; i++)
  {
    if (strcmp(ps->data[i].name, name) == 0)
    {
      return i;
    }
  }
  return -1;
}
void DelContact(Contact* ps)
{
  assert(ps);
  printf("请输入要删除的人的名字:>\n");
  int pos = FindByName(ps);
  if (pos == -1)
  {
    printf("要删除的人不存在\n");
    return;
  }
  //删除也就是向前覆盖即可
  for (int i = pos; i < ps->sz - 1; i++)
  {
    ps->data[i] = ps->data[i + 1];
  }
  ps->sz--;
  printf("删除成功\n");
}
void SearchContact(const Contact* ps)
{
  assert(ps);
  printf("请输入要查找的人的名字:>\n");
  int pos = FindByName(ps);
  if (pos == -1)
  {
    printf("要查找的人不存在\n");
    return;
  }
  printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话", "住址");
  printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n", ps->data[pos].name,
    ps->data[pos].age,
    ps->data[pos].sex,
    ps->data[pos].tele,
    ps->data[pos].addr);
}
void ModifyContact(Contact* ps)
{
  assert(ps);
  printf("请输入要修改的人的名字:>\n");
  int pos = FindByName(ps);
  if (pos == -1)
  {
    printf("要修改的人不存在\n");
    return;
  }
  printf("请输入姓名:>\n");
  scanf("%s", ps->data[pos].name);
  printf("请输入年龄:>\n");
  scanf("%d", &ps->data[pos].age);
  printf("请输入性别:>\n");
  scanf("%s", ps->data[pos].sex);
  printf("请输入电话:>\n");
  scanf("%s", ps->data[pos].tele);
  printf("请输入住址:>\n");
  scanf("%s", ps->data[pos].addr);
  printf("修改成功\n");
}
void ShowContact(const Contact* ps)
{
  assert(ps);
  if (ps->sz == 0)
  {
    printf("通讯录为空\n");
    return;
  }
  printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名","年龄","性别", "电话","住址");
  for (int i = 0; i < ps->sz; i++)
  {
    printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n", ps->data[i].name, 
      ps->data[i].age, 
      ps->data[i].sex,
      ps->data[i].tele, 
      ps->data[i].addr);
  }
}
int cmp_name(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
int cmp_age(const void* e1, const void* e2)
{
  return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age ;
}
int cmp_sex(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->sex, ((PeoInfo*)e2)->sex);
}
int cmp_tele(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->tele, ((PeoInfo*)e2)->tele);
}
int cmp_addr(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->addr, ((PeoInfo*)e2)->addr);
}
void SortContact(Contact* ps)
{
  assert(ps);
  char tmp[5] = { 0 };
  printf("请输入要排序的种类:>\n");
  printf("(姓名,年龄,性别,电话,住址)\n");
  scanf("%s", tmp);
  char* arr[5] = { "姓名","年龄","性别","电话","住址" };
  if (strcmp(arr[0], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_name);
  }
  if (strcmp(arr[1], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_age);
  }
  if (strcmp(arr[2], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_sex);
  }
  if (strcmp(arr[3], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_tele);
  }
  if (strcmp(arr[4], tmp) == 0)
  {
    //起始地址,排序个数,每个元素大小,比较方法
    qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_addr);
  }
  printf("排序成功\n");
}
void CleanContact(Contact* ps)
{
  if (ps->sz == 0)
  {
    printf("通讯录已为空,无需清除\n");
    return;
  }
  memset(ps->data, 0, ps->sz);
  ps->sz = 0;
  printf("清除成功\n");
} 
void DestroyContact(Contact* ps)
{
  free(ps->data);
  ps->data = NULL;
  printf("销毁成功\n");
}
void SaveContact(Contact* ps)
{
  assert(ps);
  size_t count = 0;
  if (ps->sz == 0)
  {
    printf("无要保存的联系人\n");
    return;
  }
  FILE* pfwrite = fopen("Contact.txt", "wb");//以二进制形式写入
  if (pfwrite == NULL)
  {
    printf("SaveContact:%s\n", strerror(errno));
  }
  for (int i = 0; i < ps->sz; i++)
  {
    count = fwrite(&(ps->data[i]), sizeof(ps->data[0]), 1, pfwrite);
    //size_t fwrite(const void* buffer, size_t size, size_t count, FILE * stream);
  }
  if (ps->sz == (int)count)
  {
    printf("所有联系人全部保存成功\n");
  }
  else
  {
    printf("保存了%zd个联系人", count);
  }
  fclose(pfwrite);
  pfwrite = NULL;
}

test.c项目文件如下:

#include"Contact.h"
void menu(void)
{
  printf("*******************************\n");
  printf("******1.Add     2.Del    ******\n");
  printf("******3.Search  4.Modify ******\n");
  printf("******5.Show    6.Sort   ******\n");
  printf("******7.Clean   8.Save   ******\n");
  printf("******0.Exit             ******\n");
  printf("*******************************\n");
}
int main()
{
  int input = 0;
  //创建通讯录
  Contact con;
  //初始化通讯录
  InitContact(&con);
  do
  {
    menu();
    printf("请选择:>\n");
    scanf("%d", &input);
    switch (input)
    {
    case Exit:
      SaveContact(&con);//退出时自动保存
      printf("在您退出通讯录时,已自动为您保存\n");
      DestroyContact(&con);//退出时销毁通讯录
      printf("退出通讯录\n");
      break;
    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 Clean:
      CleanContact(&con);
      break;
    case Save:
      SaveContact(&con);
      break;
    default:
      printf("选择错误,请重新选择:>\n");
      break;
    }
  } while (input);
  return 0;
}

小编想说的话

在实现通讯录的功能时,还有诸多不够完善的地方,以上通讯录系统是小编花好些时间一点点封装出来的,如有bug,欢迎在评论区指正!谢谢呀。


相关文章
|
1月前
|
XML Ubuntu Linux
部署08---扩展-Win10配置WSL(Ubuntu)环境,WSL系统是什么意思,是Windows系统上的一个子系统, xml的一大特点是直链系统,直接链接你的CPU,硬盘和内存,如何用 WSL部署
部署08---扩展-Win10配置WSL(Ubuntu)环境,WSL系统是什么意思,是Windows系统上的一个子系统, xml的一大特点是直链系统,直接链接你的CPU,硬盘和内存,如何用 WSL部署
|
1月前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
35 1
|
1月前
|
监控 Python
paramiko 模块 ---Python脚本监控当前系统的CPU、内存、根目录、IP地址等信息
paramiko 模块 ---Python脚本监控当前系统的CPU、内存、根目录、IP地址等信息
|
1月前
|
存储 缓存 算法
操作系统的内存管理机制及其对系统性能的影响
本文深入探讨了操作系统中内存管理的关键技术和策略,以及它们如何影响计算机系统的整体性能。通过分析不同的内存分配算法、虚拟内存技术、以及缓存策略,本文旨在揭示这些机制对于提高资源利用效率、减少延迟和优化用户体验的重要性。结合最新的研究成果和实际案例,本文为读者提供了对操作系统内存管理深度理解的视角,并讨论了未来可能的发展趋势。
|
1月前
|
设计模式 存储 缓存
Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
36 0
|
1月前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
33 0
|
1月前
|
设计模式 存储 缓存
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
21 0
|
2月前
|
存储 消息中间件 缓存
Redis:内存数据存储与缓存系统的技术探索
**Redis 概述与最佳实践** Redis,全称Remote Dictionary Server,是流行的内存数据结构存储系统,常用于数据库、缓存和消息中介。它支持字符串、哈希、列表等数据结构,并具备持久化、主从复制、集群部署及发布/订阅功能。Redis适用于缓存系统、计数器、消息队列、分布式锁和实时系统等场景。最佳实践包括选择合适的数据结构、优化缓存策略、监控调优、主从复制与集群部署以及确保安全配置。
47 3
|
2月前
|
C语言
C语言学习记录——通讯录(静态内存)
C语言学习记录——通讯录(静态内存)
21 2
|
3月前
|
缓存 算法 安全
深入理解操作系统内存管理:分页系统的优势与挑战
【5月更文挑战第31天】 在现代操作系统中,内存管理是核心功能之一。分页系统作为内存管理的一种流行技术,其设计哲学基于时间和空间的局部性原理,旨在提高内存利用率和系统性能。本文将探讨分页系统的关键优势及其面临的挑战,包括页面置换算法、内存碎片问题以及虚拟到物理地址转换的复杂性。通过对分页机制的深入分析,我们揭示了它在多任务处理环境中如何允许多个进程共享主存资源,并保证了操作系统的稳定性与高效性。