欢迎来到代码驿站!

C代码

当前位置:首页 > 软件编程 > C代码

C语言之通讯录的模拟实现代码

时间:2021-08-26 08:11:43|栏目:C代码|点击:

  在C语言学习结束之际,谨以此篇文章来对C语言的学习告一段落。

纲要:

  • 通讯录的静态版本
  • 通讯录的动态版本
  • 通讯录的带文件版本

  因为三种实现方法除了储存形式不同,其他都基本相同,所以我们重点论述静态版本的实现,以及它们不同的储存方式。

一.通讯录的静态版本  

  为什么叫它为静态版本呢,因为在此部分的储存是以数组来储存的,那对于各种各样的信息,我们要拿什么数组来存放它呢?当然是结构体数组了,所以我们来定义一个结构体来表示个人信息:

//采用宏的目的是方便日后修改
#define NAME_MAX 20
#define SEX_MAX 5
#define PNUM_MAX 13
#define ADDR_MAX 20
#define MAX 10

//存放个人信息的结构体
typedef struct Data
{
  char name[NAME_MAX];//姓名
  int age;//年龄
  char sex[SEX_MAX];//性别
  char pnum[PNUM_MAX];//电话
  char addr[ADDR_MAX];//地址
} Data;

  现在有了个人信息的结构体,我们需要再来一个结构体来存放它的数组及数组内有效信息的个数,即:

//存放MAX个个人信息的通讯录
typedef struct Contact
{
  Data data[MAX];
  int size;
} Contact;

  那么,准备工作做好之后,我们就开始正式实现了,首先我们肯定是要先创建一个通讯录,这时我们再来想一想,我们就这样创建之后,我们是否可以直接使用呢?

  对此我们来看一张图片:

  我们发现,现在它里面都放着一些随机值,所以我们需要将其初始化一下,来方便我们的使用:

void ContactInit(Contact *p)
{
  //保证p不为NULL
  assert(p);
  //置零
  memset(p->data, 0, sizeof(p->data));
  p->size = 0;

}

  我们再来看一下结果:

  我们发现,现在它内部已经被我们置为了0;接着我们做的就是添加联系人了,不过在此之前,我们不妨先做一个菜单来显示我们都有一些什么功能:

void menu()
{
  //打印菜单
  printf("******************************************\n");
  printf("******   1.add    2.del    ******\n");
  printf("******   3.search  4.modify  ******\n");
  printf("******   5.show   6.sort   ******\n");
  printf("******   7.help   0.exit   ******\n");
  printf("******************************************\n");
}

  接着是我们的帮助选项:

//打印帮助信息
void ContactHelp(Contact *p)
{
  printf("*******************************************\n");
  printf("******   add ---- 添加联系人信息  ******\n");
  printf("******   del ---- 删除联系人信息  ******\n");
  printf("****** search ---- 查找联系人信息  ******\n");
  printf("****** modify ---- 修改联系人信息  ******\n");
  printf("******  show ---- 展示联系人信息  ******\n");
  printf("******  help ---- 帮助信息     ******\n");
  printf("******  sort ---- 排序联系人信息  ******\n");
  printf("******  exit ---- 退出通讯录    ******\n");
  printf("*******************************************\n");
}

  以及我们来用枚举来定义一些常量,方便在switch()结构中 来辨别它走了哪条路线:

//枚举来作为常量使得在看代码时比较清晰
enum choice
{
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT,
  HELP
};

  以及写出我们的选择结构:我们采用do-while循环

void test()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址

  //初始化
  ContactInit(p);
  int input = 0;
  do
  {
    menu();
    printf("请输入你的选择:> ");
    scanf("%d", &input);
    switch (input)
    {
      case ADD:
        ContactAdd(p);
        break;
      case DEL:
        ContactDel(p);
        break;
      case SEARCH:
        ContactSearch(p);
        break;
      case MODIFY:
        ContactModify(p);
        break;
      case SHOW:
        ContactShow(p);
        break;
      case SORT:
        ContactSort(p);
        break;
      case HELP:
        ContactHelp(p);
        break;
      case EXIT:
        ContactExit(p);
        break;
      default:
        printf("输入非法!");

    }

  } while (input);

}

  这样的好处是当用户输入0时循环便自己停止,不用我们再次去判断当用户输入0时我们要退出的问题,接下来我们就来填写我们函数的内容了:

  1.添加联系人

//添加联系人
void ContactAdd(Contact *p)
{
  //断言保证p不为NULL
  assert(p);
  //如果联系人容量已经等于最大容量了
  if(p->size==MAX)
  {
    printf("通讯录已满,请删除一些后继续添加!\n");
    return ;
  }
  Data person;//记录联系人信息
  printf("请输入联系人的姓名:>");
  scanf("%s", person.name);
  printf("请输入联系人的年龄:>");
  scanf("%d", &person.age);
  printf("请输入联系人的性别:>");
  scanf("%s", person.sex);
  printf("请输入联系人的电话:>");
  scanf("%s", person.pnum);
  printf("请输入联系人的住址:>");
  scanf("%s", person.addr);
  //将联系人信息存到通讯录中
  p->data[p->size] = person;
  p->size++;
}

  我们要是观察到我们输入的信息,最好就是把我们所输入的信息给打印出来:

  2.展示联系人

//展示联系人信息
void ContactShow(Contact *p)
{
  if (p->size == 0)
  {
    printf("通讯录中并无一人!\n");     return ; 
  }
  int i = 0;
  printf("  姓名\t性别\t 年龄\t  电话\t\t地址\n");
  for (i = 0; i < p->size; i++)
  {
    printf("  %-5s\t%s\t%d\t%s\t%s\n", p->data[i].name,
        p->data[i].sex,
        p->data[i].age,
        p->data[i].pnum,
        p->data[i].addr);

  }
}

  测试结果:

  接下来就是删除联系人了

  3.删除联系人

    首先删除联系人肯定需要查找信息,又因为后面的几个函数也要用到它,所以我们单独来写一个查找模块:

//查找模块
int ContactFind(Contact *p, char *FindData)
{
  assert(p);
  int i = 0;
  for (i = 0; i < p->size; i++)
  {
    if (strcmp(p->data[i].name, FindData) == 0)
    {
      return i;//找到就返回下标
    }
  }
  return -1;//找不到就返回-1
}

  删除:

//删除联系人
void ContactDel(Contact *p)
{
  assert(p);
  char DelName[NAME_MAX] = {0};
  printf("请输入你要删除的联系人姓名:>");
  scanf("%s", DelName);
  int ret = ContactFind(p, DelName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    int j = 0;
    for (j = ret; j < p->size; j++)
    {
      //从前往后依次挪动覆盖
      p->data[j] = p->data[j + 1];
    }
    //删除完成之后,联系人个数减一
    p->size--;
  }
}

  4.查找联系人信息

//查找联系人
void ContactSearch(Contact *p)
{
  assert(p);
  char SearchName[NAME_MAX];
  printf("请输入你要查找的联系人姓名:>\n");
  scanf("%s",SearchName);
  //查找有无此人
  int ret = ContactFind(p,SearchName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    printf("你所查找的联系人信息为:\n");
    printf("  姓名\t性别\t 年龄\t  电话\t\t地址\n");
    printf("  %-5s\t%s\t%d\t%s\t%s\n", p->data[ret].name,
        p->data[ret].sex,
        p->data[ret].age,
        p->data[ret].pnum,
        p->data[ret].addr);
  }
}

  5.修改联系人信息

//修改联系人信息
void ContactModify(Contact *p)
{
  assert(p);
  char ModifyName[NAME_MAX];
  printf("请输入你要修改的联系人姓名:>");
  scanf("%s",ModifyName);
  int ret = ContactFind(p,ModifyName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    Data person;//记录联系人信息
    printf("请输入联系人的姓名:>");
    scanf("%s", person.name);
    printf("请输入联系人的年龄:>");
    scanf("%d", &person.age);
    printf("请输入联系人的性别:>");
    scanf("%s", person.sex);
    printf("请输入联系人的电话:>");
    scanf("%s", person.pnum);
    printf("请输入联系人的住址:>");
    scanf("%s", person.addr);
    //将联系人信息存到通讯录中
    p->data[ret] = person;
  }
}

  6.排序联系人 --- 我们使用 qsort 来排序

enum sort_by
{
  NAME=1,
  SEX,
  AGE,
  PNUM,
  ADDR
};
void sort_menu()
{
  printf("      SORT_MENU     \n");
  printf("******************************\n");
  printf("****    1.name    ****\n");
  printf("****    2.sex     ****\n");
  printf("****    3.age     ****\n");
  printf("****    4.pnum    ****\n");
  printf("****    5.addr    ****\n");
  printf("******************************\n");
}

int sort_by_name(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->name, ((Data *) s2)->name);
}

int sort_by_sex(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->sex, ((Data *) s2)->sex);
}

int sort_by_age(const void *s1, const void *s2)
{
  return ((Data *) s1)->age - ((Data *) s2)->age;
}

int sort_by_pnum(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->pnum, ((Data *) s2)->pnum);
}

int sort_by_addr(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->addr, ((Data *) s2)->addr);
}


//排序联系人
void ContactSort(Contact *p)
{
  assert(p);
  int choice;
  sort_menu();
  printf("请选择排序的参考量:>");
  scanf("%d", &choice);
  switch (choice)
  {
    case NAME:
      qsort(p->data, p->size, sizeof(Data), sort_by_name);
      break;
    case SEX:
      qsort(p->data, p->size, sizeof(Data), sort_by_sex);
      break;
    case AGE:
      qsort(p->data, p->size, sizeof(Data), sort_by_age);
      break;
    case PNUM:
      qsort(p->data, p->size, sizeof(Data), sort_by_pnum);
      break;
    case ADDR:
      qsort(p->data, p->size, sizeof(Data), sort_by_addr);
      break;
    default:
      printf("输入有误,请检查输入!\n");
  }
}

到这,我们的静态通讯录就完了,但是我们仍可对用户操作优化一下,如:及时的清屏等,以及暂停:

例:

do
  {
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    system("cls");
    switch (input)
    {
      case QUIT:
        printf("退出通讯录!\n");
        break;
      case ADD:
        add(p);
        system("pause");
        system("cls");
        break;
      case DEL:
        del(p);
        system("pause");
        system("cls");
        break;
      case SEARCH:
        search(p);
        system("pause");
        system("cls");
        break;
      case MODIFY:
        modify(p);
        system("pause");
        system("cls");
        break;
      case SHOW:
        show(p);
        system("pause");
        system("cls");
        break;
      case SORT:
        sort(p);
        system("pause");
        system("cls");
        break;
      case HELP:
        help();
        system("pause");
        system("cls");
        break;
      default:
        printf("非法输入,请检查输入!\n");
        system("pause");
        system("cls");
        break;
    }
  } while (input);

  这样我们的界面看起来就干净多了,但是有没有发现,我们为了达到这个效果,我们写了很多重复的代码!

  那这样我们应该怎么办呢 --- 还记得我们之前所提到的函数指针数组吗?

void test2()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址
  //初始化
  ContactInit(p);
  //用一个函数指针数组来存放函数指针
  void (*fun[])(Contact *) ={ContactExit,
                ContactAdd,
                ContactDel,
                ContactSearch,
                ContactModify,
                ContactShow,
                ContactSort,
                ContactHelp};
  int input = 0;//存放用户选择的信息
  do{
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    system("cls");
    if(input>=0&&input<=sizeof(fun))
    {
      fun[input](p);
      system("cls");
    }
    else
    {
      system("cls");
      printf("输入非法,请检查输入!\n");
    }
  }while(input);
}

  这样是不是代码就少了很多!

所以完整代码如下:

Contact.h

//确保文件只包含一次
#ifndef CONTACT_CONTACT_H
#define CONTACT_CONTACT_H

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
//采用宏的目的是方便日后修改
#define NAME_MAX 20
#define SEX_MAX 8
#define PNUM_MAX 13
#define ADDR_MAX 20
#define MAX 10
//存放个人信息的结构体
typedef struct Data
{
  char name[NAME_MAX];//姓名
  int age;//年龄
  char sex[SEX_MAX];//性别
  char pnum[PNUM_MAX];//电话
  char addr[ADDR_MAX];//地址
} Data;
//存放MAX个个人信息的通讯录
typedef struct Contact
  Data data[MAX];
  int size;
} Contact;
//枚举来作为常量使得在看代码时比较清晰
enum choice
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT,
  HELP
};
enum sort_by
  NAME=1,
  SEX,
  AGE,
  PNUM,
  ADDR
//初始化通讯录
void ContactInit(Contact *p);
//添加联系人
void ContactAdd(Contact* p);
//删除联系人
void ContactDel(Contact* p);
//查找联系人
void ContactSearch(Contact* p);
//修改联系人信息
void ContactModify(Contact* p);
//展示联系人信息
void ContactShow(Contact* p);
//排序联系人
void ContactSort(Contact* p);
//打印帮助
void ContactHelp(Contact* p);
//退出通讯录
void ContactExit(Contact* p);
#endif //CONTACT_CONTACT_H

Contact.c

#include "Contact.h"
// 强调!!!
//调试请加setbuf(stdout,NULL)!!!


//查找模块
int ContactFind(Contact *p, char *FindData)
{
  assert(p);
  int i = 0;
  for (i = 0; i < p->size; i++)
  {
    if (strcmp(p->data[i].name, FindData) == 0)
    {
      return i;//找到就返回下标
    }
  }
  return -1;//找不到就返回-1
}

void ContactInit(Contact *p)
{
  //保证p不为NULL
  assert(p);
  //置零
  memset(p->data, 0, sizeof(p->data));
  p->size = 0;

}


//添加联系人
void ContactAdd(Contact *p)
{
  //断言保证p不为NULL
  assert(p);
  //如果联系人容量已经等于最大容量了
  if (p->size == MAX)
  {
    printf("通讯录已满,请删除一些后继续添加!\n");
    return;
  }
  Data person;//记录联系人信息
  printf("请输入联系人的姓名:>");
  scanf("%s", person.name);
  printf("请输入联系人的年龄:>");
  scanf("%d", &person.age);
  printf("请输入联系人的性别:>");
  scanf("%s", person.sex);
  printf("请输入联系人的电话:>");
  scanf("%s", person.pnum);
  printf("请输入联系人的住址:>");
  scanf("%s", person.addr);
  //将联系人信息存到通讯录中
  p->data[p->size] = person;
  p->size++;
}

//删除联系人
void ContactDel(Contact *p)
{
  assert(p);
  char DelName[NAME_MAX] = {0};
  printf("请输入你要删除的联系人姓名:>");
  scanf("%s", DelName);
  int ret = ContactFind(p, DelName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    int j = 0;
    for (j = ret; j < p->size; j++)
    {
      //从前往后依次挪动覆盖
      p->data[j] = p->data[j + 1];
    }
    //删除完成之后,联系人个数减一
    p->size--;
  }
}

//查找联系人
void ContactSearch(Contact *p)
{
  assert(p);
  char SearchName[NAME_MAX];
  printf("请输入你要查找的联系人姓名:>");
  scanf("%s", SearchName);
  //查找有无此人
  int ret = ContactFind(p, SearchName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    printf("你所查找的联系人信息为:\n");
    printf("  姓名\t性别\t 年龄\t  电话\t\t地址\n");
    printf("  %-5s\t%s\t%d\t%s\t%s\n", p->data[ret].name,
        p->data[ret].sex,
        p->data[ret].age,
        p->data[ret].pnum,
        p->data[ret].addr);
  }
}

//修改联系人信息
void ContactModify(Contact *p)
{
  assert(p);
  char ModifyName[NAME_MAX];
  printf("请输入你要修改的联系人姓名:>");
  scanf("%s", ModifyName);
  int ret = ContactFind(p, ModifyName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    Data person;//记录联系人信息
    printf("请输入联系人的姓名:>");
    scanf("%s", person.name);
    printf("请输入联系人的年龄:>");
    scanf("%d", &person.age);
    printf("请输入联系人的性别:>");
    scanf("%s", person.sex);
    printf("请输入联系人的电话:>");
    scanf("%s", person.pnum);
    printf("请输入联系人的住址:>");
    scanf("%s", person.addr);
    //将联系人信息存到通讯录中
    p->data[ret] = person;
  }
}

//展示联系人信息
void ContactShow(Contact *p)
{
  if (p->size == 0)
  {
    printf("通讯录中并无一人!\n");
    return;
  }

  int i = 0;
  printf("  姓名\t性别\t 年龄\t  电话\t\t地址\n");
  for (i = 0; i < p->size; i++)
  {
    printf("  %-5s\t%s\t%d\t%s\t%s\n", p->data[i].name,
        p->data[i].sex,
        p->data[i].age,
        p->data[i].pnum,
        p->data[i].addr);

  }
}

void sort_menu()
{
  printf("      SORT_MENU     \n");
  printf("******************************\n");
  printf("****    1.name    ****\n");
  printf("****    2.sex     ****\n");
  printf("****    3.age     ****\n");
  printf("****    4.pnum    ****\n");
  printf("****    5.addr    ****\n");
  printf("******************************\n");
}

int sort_by_name(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->name, ((Data *) s2)->name);
}

int sort_by_sex(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->sex, ((Data *) s2)->sex);
}

int sort_by_age(const void *s1, const void *s2)
{
  return ((Data *) s1)->age - ((Data *) s2)->age;
}

int sort_by_pnum(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->pnum, ((Data *) s2)->pnum);
}

int sort_by_addr(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->addr, ((Data *) s2)->addr);
}


//排序联系人
void ContactSort(Contact *p)
{
  assert(p);
  int choice;
  sort_menu();
  printf("请选择排序的参考量:>");
  scanf("%d", &choice);
  switch (choice)
  {
    case NAME:
      qsort(p->data, p->size, sizeof(Data), sort_by_name);
      break;
    case SEX:
      qsort(p->data, p->size, sizeof(Data), sort_by_sex);
      break;
    case AGE:
      qsort(p->data, p->size, sizeof(Data), sort_by_age);
      break;
    case PNUM:
      qsort(p->data, p->size, sizeof(Data), sort_by_pnum);
      break;
    case ADDR:
      qsort(p->data, p->size, sizeof(Data), sort_by_addr);
      break;
    default:
      printf("输入有误,请检查输入!\n");
  }
}

//打印帮助信息
void ContactHelp(Contact *p)
{
  printf("*******************************************\n");
  printf("******   add ---- 添加联系人信息  ******\n");
  printf("******   del ---- 删除联系人信息  ******\n");
  printf("****** search ---- 查找联系人信息  ******\n");
  printf("****** modify ---- 修改联系人信息  ******\n");
  printf("******  show ---- 展示联系人信息  ******\n");
  printf("******  help ---- 帮助信息     ******\n");
  printf("******  sort ---- 排序联系人信息  ******\n");
  printf("******  exit ---- 退出通讯录    ******\n");
  printf("*******************************************\n");
}

//退出通讯录
void ContactExit(Contact *p)
{
  printf("exit !\n");
}

main.c

#include "Contact.h"

void menu()
{
  //打印菜单
  printf("******************************************\n");
  printf("******   1.add    2.del    ******\n");
  printf("******   3.search  4.modify  ******\n");
  printf("******   5.show   6.sort   ******\n");
  printf("******   7.help   0.exit   ******\n");
  printf("******************************************\n");
}

void test()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址

  //初始化
  ContactInit(p);
  int input = 0;//存放用户选择的信息
  do
  {
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    switch (input)
    {
      case ADD:
        ContactAdd(p);
        break;
      case DEL:
        ContactDel(p);
        break;
      case SEARCH:
        ContactSearch(p);
        break;
      case MODIFY:
        ContactModify(p);
        break;
      case SHOW:
        ContactShow(p);
        break;
      case SORT:
        ContactSort(p);
        break;
      case HELP:
        ContactHelp(p);
        break;
      case EXIT:
        ContactExit(p);
        break;
      default:
        printf("输入非法!\n");
    }
  } while (input);

}

void test2()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址
  //初始化
  ContactInit(p);
  //用一个函数指针数组来存放函数指针
  void (*fun[])(Contact *) ={ContactExit,
                ContactAdd,
                ContactDel,
                ContactSearch,
                ContactModify,
                ContactShow,
                ContactSort,
                ContactHelp};
  int input = 0;//存放用户选择的信息
  do{
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    system("cls");
    if(input>=0&&input<=sizeof(fun))
    {
      fun[input](p);
      system("cls");
    }
    else
    {
      system("cls");
      printf("输入非法,请检查输入!\n");
    }
  }while(input);
}

int main()
{
  //test();
  test2();

  return 0;
}

二.动态通讯录

  动态实现的问题主要在于它的容量不再是一变不变的,而是可随着我们的数据量来变化的,所以在我们原来定义的Contact结构体就要微微改变一下了:

typedef struct Contact
{
  Data* data;//存放数据
  int size;//有效数据的个数
  int capacity;//容量的大小
} Contact;

  初始化函数也要改改:

//初始化 --- 动态
void ContactInit(Contact *p)
{
  assert(p);
  p->data=NULL;
  p->size=0;
  p->capacity=1;
}

  那么这样,添加函数也有一定的变化:

//检查容量函数
void CheckCapacity(Contact *p)
{
  assert(p);
  //如果联系人个数为0或与容量相同,就需要扩容
  if (p->size == 0 || p->size == p->capacity)
  {
    //动态内存开辟
    Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2);
    if (ptr == NULL)//开辟失败
    {
      //报错
      perror("CHECK CAPACITY ERROE !\n");
      exit(-1);
    }
    //开辟成功,重新赋值
    p->data = ptr;
    //扩容之后,容量也相应扩大
    p->capacity *= 2;
  }
  //反之什么都不需要干
}

//添加联系人 --- 动态
void ContactAdd(Contact *p)
{
  //断言保证p不为NULL
  assert(p);
  //如果联系人个数等于容量,或联系人个数等于0,这时我们就需要扩容了,我们来使用一个函数来干这事
  CheckCapacity(p);
  Data person;//记录联系人信息
  printf("请输入联系人的姓名:>");
  scanf("%s", person.name);
  printf("请输入联系人的年龄:>");
  scanf("%d", &person.age);
  printf("请输入联系人的性别:>");
  scanf("%s", person.sex);
  printf("请输入联系人的电话:>");
  scanf("%s", person.pnum);
  printf("请输入联系人的住址:>");
  scanf("%s", person.addr);
  //将联系人信息存到通讯录中
  p->data[p->size] = person;
  p->size++;
}

  最后我们还要记得释放我们开辟的内存 --- 退出

//退出通讯录 --- 动态
void ContactExit(Contact *p)
{
  //释放我们开辟的内存
  free(p->data);
  printf("exit !\n");
}

  动态通讯录的修改就只有这些:

  完整代码展示:

Contact.h

//确保文件只包含一次
#ifndef CONTACT_CONTACT_H
#define CONTACT_CONTACT_H
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
//采用宏的目的是方便日后修改
#define NAME_MAX 20
#define SEX_MAX 8
#define PNUM_MAX 13
#define ADDR_MAX 20
#define MAX 10
//存放个人信息的结构体
typedef struct Data
{
  char name[NAME_MAX];//姓名
  int age;//年龄
  char sex[SEX_MAX];//性别
  char pnum[PNUM_MAX];//电话
  char addr[ADDR_MAX];//地址
} Data;
/*
//存放MAX个个人信息的通讯录 --- 静态
typedef struct Contact
{
  Data data[MAX];
  int size;
} Contact;
*/
//存放MAX个个人信息的通讯录 --- 动态
typedef struct Contact
{
  Data* data;//存放数据
  int size;//有效数据的个数
  int capacity;//容量的大小
} Contact;
//枚举来作为常量使得在看代码时比较清晰
enum choice
{
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT,
  HELP
};
enum sort_by
{
  NAME=1,
  SEX,
  AGE,
  PNUM,
  ADDR
};
//初始化通讯录
void ContactInit(Contact *p);
//添加联系人
void ContactAdd(Contact* p);
//删除联系人
void ContactDel(Contact* p);
//查找联系人
void ContactSearch(Contact* p);
//修改联系人信息
void ContactModify(Contact* p);
//展示联系人信息
void ContactShow(Contact* p);
//排序联系人
void ContactSort(Contact* p);
//打印帮助
void ContactHelp(Contact* p);
//退出通讯录
void ContactExit(Contact* p);
#endif //CONTACT_CONTACT_H

Contact.c

#include "Contact.h"
// 强调!!!
//调试请加setbuf(stdout,NULL)!!!


//查找模块
int ContactFind(Contact *p, char *FindData)
{
  assert(p);
  int i = 0;
  for (i = 0; i < p->size; i++)
  {
    if (strcmp(p->data[i].name, FindData) == 0)
    {
      return i;//找到就返回下标
    }
  }
  return -1;//找不到就返回-1
}

/*
//初始化 --- 静态
void ContactInit(Contact *p)
{
  //保证p不为NULL
  assert(p);
  //置零
  memset(p->data, 0, sizeof(p->data));
  p->size = 0;

}
*/

//初始化 --- 动态
void ContactInit(Contact *p)
{
  assert(p);
  p->data = NULL;
  p->size = 0;
  p->capacity = 1;
}

/*//添加联系人 --- 静态
void ContactAdd(Contact *p)
{
  //断言保证p不为NULL
  assert(p);
  //如果联系人容量已经等于最大容量了
  if (p->size == MAX)
  {
    printf("通讯录已满,请删除一些后继续添加!\n");
    return;
  }
  Data person;//记录联系人信息
  printf("请输入联系人的姓名:>");
  scanf("%s", person.name);
  printf("请输入联系人的年龄:>");
  scanf("%d", &person.age);
  printf("请输入联系人的性别:>");
  scanf("%s", person.sex);
  printf("请输入联系人的电话:>");
  scanf("%s", person.pnum);
  printf("请输入联系人的住址:>");
  scanf("%s", person.addr);
  //将联系人信息存到通讯录中
  p->data[p->size] = person;
  p->size++;
}*/

//检查容量函数
void CheckCapacity(Contact *p)
{
  assert(p);
  //如果联系人个数为0或与容量相同,就需要扩容
  if (p->size == 0 || p->size == p->capacity)
  {
    //动态内存开辟
    Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2);
    if (ptr == NULL)//开辟失败
    {
      //报错
      perror("CHECK CAPACITY ERROE !\n");
      exit(-1);
    }
    //开辟成功,重新赋值
    p->data = ptr;
    //扩容之后,容量也相应扩大
    p->capacity *= 2;
  }
  //反之什么都不需要干
}

//添加联系人 --- 动态
void ContactAdd(Contact *p)
{
  //断言保证p不为NULL
  assert(p);
  //如果联系人个数等于容量,或联系人个数等于0,这时我们就需要扩容了,我们来使用一个函数来干这事
  CheckCapacity(p);
  Data person;//记录联系人信息
  printf("请输入联系人的姓名:>");
  scanf("%s", person.name);
  printf("请输入联系人的年龄:>");
  scanf("%d", &person.age);
  printf("请输入联系人的性别:>");
  scanf("%s", person.sex);
  printf("请输入联系人的电话:>");
  scanf("%s", person.pnum);
  printf("请输入联系人的住址:>");
  scanf("%s", person.addr);
  //将联系人信息存到通讯录中
  p->data[p->size] = person;
  p->size++;
}

//删除联系人
void ContactDel(Contact *p)
{
  assert(p);
  char DelName[NAME_MAX] = {0};
  printf("请输入你要删除的联系人姓名:>");
  scanf("%s", DelName);
  int ret = ContactFind(p, DelName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    int j = 0;
    for (j = ret; j < p->size; j++)
    {
      //从前往后依次挪动覆盖
      p->data[j] = p->data[j + 1];
    }
    //删除完成之后,联系人个数减一
    p->size--;
  }
}

//查找联系人
void ContactSearch(Contact *p)
{
  assert(p);
  char SearchName[NAME_MAX];
  printf("请输入你要查找的联系人姓名:>");
  scanf("%s", SearchName);
  //查找有无此人
  int ret = ContactFind(p, SearchName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    printf("你所查找的联系人信息为:\n");
    printf("  姓名\t性别\t 年龄\t  电话\t\t地址\n");
    printf("  %-5s\t%s\t%d\t%s\t%s\n", p->data[ret].name,
        p->data[ret].sex,
        p->data[ret].age,
        p->data[ret].pnum,
        p->data[ret].addr);
  }
}

//修改联系人信息
void ContactModify(Contact *p)
{
  assert(p);
  char ModifyName[NAME_MAX];
  printf("请输入你要修改的联系人姓名:>");
  scanf("%s", ModifyName);
  int ret = ContactFind(p, ModifyName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    Data person;//记录联系人信息
    printf("请输入联系人的姓名:>");
    scanf("%s", person.name);
    printf("请输入联系人的年龄:>");
    scanf("%d", &person.age);
    printf("请输入联系人的性别:>");
    scanf("%s", person.sex);
    printf("请输入联系人的电话:>");
    scanf("%s", person.pnum);
    printf("请输入联系人的住址:>");
    scanf("%s", person.addr);
    //将联系人信息存到通讯录中
    p->data[ret] = person;
  }
}

//展示联系人信息
void ContactShow(Contact *p)
{
  if (p->size == 0)
  {
    printf("通讯录中并无一人!\n");
    return;
  }

  int i = 0;
  printf("  姓名\t性别\t 年龄\t  电话\t\t地址\n");
  for (i = 0; i < p->size; i++)
  {
    printf("  %-5s\t%s\t%d\t%s\t%s\n", p->data[i].name,
        p->data[i].sex,
        p->data[i].age,
        p->data[i].pnum,
        p->data[i].addr);

  }
}

void sort_menu()
{
  printf("      SORT_MENU     \n");
  printf("******************************\n");
  printf("****    1.name    ****\n");
  printf("****    2.sex     ****\n");
  printf("****    3.age     ****\n");
  printf("****    4.pnum    ****\n");
  printf("****    5.addr    ****\n");
  printf("******************************\n");
}

int sort_by_name(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->name, ((Data *) s2)->name);
}

int sort_by_sex(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->sex, ((Data *) s2)->sex);
}

int sort_by_age(const void *s1, const void *s2)
{
  return ((Data *) s1)->age - ((Data *) s2)->age;
}

int sort_by_pnum(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->pnum, ((Data *) s2)->pnum);
}

int sort_by_addr(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->addr, ((Data *) s2)->addr);
}


//排序联系人
void ContactSort(Contact *p)
{
  assert(p);
  int choice;
  sort_menu();
  printf("请选择排序的参考量:>");
  scanf("%d", &choice);
  switch (choice)
  {
    case NAME:
      qsort(p->data, p->size, sizeof(Data), sort_by_name);
      break;
    case SEX:
      qsort(p->data, p->size, sizeof(Data), sort_by_sex);
      break;
    case AGE:
      qsort(p->data, p->size, sizeof(Data), sort_by_age);
      break;
    case PNUM:
      qsort(p->data, p->size, sizeof(Data), sort_by_pnum);
      break;
    case ADDR:
      qsort(p->data, p->size, sizeof(Data), sort_by_addr);
      break;
    default:
      printf("输入有误,请检查输入!\n");
  }
}

//打印帮助信息
void ContactHelp(Contact *p)
{
  printf("*******************************************\n");
  printf("******   add ---- 添加联系人信息  ******\n");
  printf("******   del ---- 删除联系人信息  ******\n");
  printf("****** search ---- 查找联系人信息  ******\n");
  printf("****** modify ---- 修改联系人信息  ******\n");
  printf("******  show ---- 展示联系人信息  ******\n");
  printf("******  help ---- 帮助信息     ******\n");
  printf("******  sort ---- 排序联系人信息  ******\n");
  printf("******  exit ---- 退出通讯录    ******\n");
  printf("*******************************************\n");
}

/*//退出通讯录
void ContactExit(Contact *p)
{
  printf("exit !\n");
}*/

//退出通讯录 --- 动态
void ContactExit(Contact *p)
{
  //释放我们开辟的内存
  free(p->data);
  printf("exit !\n");
}

main.c

#include "Contact.h"

void menu()
{
  //打印菜单
  printf("******************************************\n");
  printf("******   1.add    2.del    ******\n");
  printf("******   3.search  4.modify  ******\n");
  printf("******   5.show   6.sort   ******\n");
  printf("******   7.help   0.exit   ******\n");
  printf("******************************************\n");
}

void test()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址

  //初始化
  ContactInit(p);
  int input = 0;//存放用户选择的信息
  do
  {
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    switch (input)
    {
      case ADD:
        ContactAdd(p);
        break;
      case DEL:
        ContactDel(p);
        break;
      case SEARCH:
        ContactSearch(p);
        break;
      case MODIFY:
        ContactModify(p);
        break;
      case SHOW:
        ContactShow(p);
        break;
      case SORT:
        ContactSort(p);
        break;
      case HELP:
        ContactHelp(p);
        break;
      case EXIT:
        ContactExit(p);
        break;
      default:
        printf("输入非法!\n");
    }
  } while (input);

}

void test2()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址
  //初始化
  ContactInit(p);
  //用一个函数指针数组来存放函数指针
  void (*fun[])(Contact *) ={ContactExit,
                ContactAdd,
                ContactDel,
                ContactSearch,
                ContactModify,
                ContactShow,
                ContactSort,
                ContactHelp};
  int input = 0;//存放用户选择的信息
  do{
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    if(input>=0&&input<=sizeof(fun))
    {
      //system("cls");
      fun[input](p);

    }
    else
    {
      system("cls");
      printf("输入非法,请检查输入!\n");
    }
  }while(input);
}

int main()
{
  //test();
  test2();

  return 0;
}

#include "Contact.h"

void menu()
{
  //打印菜单
  printf("******************************************\n");
  printf("******   1.add    2.del    ******\n");
  printf("******   3.search  4.modify  ******\n");
  printf("******   5.show   6.sort   ******\n");
  printf("******   7.help   0.exit   ******\n");
  printf("******************************************\n");
}

void test()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址

  //初始化
  ContactInit(p);
  int input = 0;//存放用户选择的信息
  do
  {
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    switch (input)
    {
      case ADD:
        ContactAdd(p);
        break;
      case DEL:
        ContactDel(p);
        break;
      case SEARCH:
        ContactSearch(p);
        break;
      case MODIFY:
        ContactModify(p);
        break;
      case SHOW:
        ContactShow(p);
        break;
      case SORT:
        ContactSort(p);
        break;
      case HELP:
        ContactHelp(p);
        break;
      case EXIT:
        ContactExit(p);
        break;
      default:
        printf("输入非法!\n");
    }
  } while (input);

}

void test2()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址
  //初始化
  ContactInit(p);
  //用一个函数指针数组来存放函数指针
  void (*fun[])(Contact *) ={ContactExit,
                ContactAdd,
                ContactDel,
                ContactSearch,
                ContactModify,
                ContactShow,
                ContactSort,
                ContactHelp};
  int input = 0;//存放用户选择的信息
  do{
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    if(input>=0&&input<=sizeof(fun))
    {
      //system("cls");
      fun[input](p);

    }
    else
    {
      system("cls");
      printf("输入非法,请检查输入!\n");
    }
  }while(input);
}

int main()
{
  //test();
  test2();

  return 0;
}

三.带文件的动态通讯录

  在这个里面,我们只需在初始化时进行文件的读取及关闭时文件的保存:

  初始化:

//从文件载入信息
void Lodging(Contact *p)
{
  assert(p);
  //打开一文件
  FILE *fp = fopen("../Contact.dat", "ab");//如果不存在就创建,存在就追加
  if (fp == NULL)
  {
    perror("FILE: Ab");
    exit(-1);
  }
  fclose(fp);//关闭文件,我们这一步只是为了确保文件存在
  //打开一文件
  fp=fopen("../Contact.dat","rb");
  if (fp == NULL)
  {
    perror("FILE: Rb");
    exit(-1);
  }
  Data temp;//将读入的信息存入temp中
  while(fread(&temp, sizeof(Data),1,fp))
  {
    //检查容量
    CheckCapacity(p);
    //赋值
    p->data[p->size]=temp;
    p->size++;
  }
  fclose(fp);//关闭文件
}


//初始化 --- 带文件
void ContactInit(Contact *p)
{
  assert(p);
  p->data = NULL;
  p->size = 0;
  p->capacity = 1;
  Lodging(p);
}

  结束时保存:

void Save(Contact* p)
{
  assert(p);
  FILE* fp =fopen("../Contact.dat","wb");
  int i =0;
  for(i=0;i<p->size;i++)
  {
    fwrite(p->data+i, sizeof(Data),1,fp);
  }
  fclose(fp);
}

//退出通讯录 --- 带文件
void ContactExit(Contact *p)
{
  //保存置文件
  Save(p);
  //释放我们开辟的内存
  free(p->data);
  printf("exit !\n");
}

  除此之外,其他都与动态通讯录相同

  完整代码:

Contact.h

//确保文件只包含一次
#ifndef CONTACT_CONTACT_H
#define CONTACT_CONTACT_H

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

//采用宏的目的是方便日后修改
#define NAME_MAX 20
#define SEX_MAX 8
#define PNUM_MAX 13
#define ADDR_MAX 20
#define MAX 10

//存放个人信息的结构体
typedef struct Data
{
  char name[NAME_MAX];//姓名
  int age;//年龄
  char sex[SEX_MAX];//性别
  char pnum[PNUM_MAX];//电话
  char addr[ADDR_MAX];//地址
} Data;

/*
//存放MAX个个人信息的通讯录 --- 静态
typedef struct Contact
{
  Data data[MAX];
  int size;
} Contact;
*/
//存放MAX个个人信息的通讯录 --- 动态
typedef struct Contact
{
  Data* data;//存放数据
  int size;//有效数据的个数
  int capacity;//容量的大小
} Contact;

//枚举来作为常量使得在看代码时比较清晰
enum choice
{
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT,
  HELP
};

enum sort_by
{
  NAME=1,
  SEX,
  AGE,
  PNUM,
  ADDR
};


//初始化通讯录
void ContactInit(Contact *p);

//添加联系人
void ContactAdd(Contact* p);

//删除联系人
void ContactDel(Contact* p);

//查找联系人
void ContactSearch(Contact* p);

//修改联系人信息
void ContactModify(Contact* p);

//展示联系人信息
void ContactShow(Contact* p);

//排序联系人
void ContactSort(Contact* p);

//打印帮助
void ContactHelp(Contact* p);

//退出通讯录
void ContactExit(Contact* p);

//检查容量函数
void CheckCapacity(Contact *p);


#endif //CONTACT_CONTACT_H

Contact.c

#include "Contact.h"
// 强调!!!
//调试请加setbuf(stdout,NULL)!!!


//查找模块
int ContactFind(Contact *p, char *FindData)
{
  assert(p);
  int i = 0;
  for (i = 0; i < p->size; i++)
  {
    if (strcmp(p->data[i].name, FindData) == 0)
    {
      return i;//找到就返回下标
    }
  }
  return -1;//找不到就返回-1
}

/*
//初始化 --- 静态
void ContactInit(Contact *p)
{
  //保证p不为NULL
  assert(p);
  //置零
  memset(p->data, 0, sizeof(p->data));
  p->size = 0;

}
*/

/*
//初始化 --- 动态
void ContactInit(Contact *p)
{
  assert(p);
  p->data = NULL;
  p->size = 0;
  p->capacity = 1;
}
*/

//从文件载入信息
void Lodging(Contact *p)
{
  assert(p);
  //打开一文件
  FILE *fp = fopen("../Contact.dat", "ab");//如果不存在就创建,存在就追加
  if (fp == NULL)
  {
    perror("FILE: Ab");
    exit(-1);
  }
  fclose(fp);//关闭文件,我们这一步只是为了确保文件存在
  //打开一文件
  fp=fopen("../Contact.dat","rb");
  if (fp == NULL)
  {
    perror("FILE: Rb");
    exit(-1);
  }
  Data temp;//将读入的信息存入temp中
  while(fread(&temp, sizeof(Data),1,fp))
  {
    //检查容量
    CheckCapacity(p);
    //赋值
    p->data[p->size]=temp;
    p->size++;
  }
  fclose(fp);//关闭文件
}


//初始化 --- 带文件
void ContactInit(Contact *p)
{
  assert(p);
  p->data = NULL;
  p->size = 0;
  p->capacity = 1;
  Lodging(p);
}


/*//添加联系人 --- 静态
void ContactAdd(Contact *p)
{
  //断言保证p不为NULL
  assert(p);
  //如果联系人容量已经等于最大容量了
  if (p->size == MAX)
  {
    printf("通讯录已满,请删除一些后继续添加!\n");
    return;
  }
  Data person;//记录联系人信息
  printf("请输入联系人的姓名:>");
  scanf("%s", person.name);
  printf("请输入联系人的年龄:>");
  scanf("%d", &person.age);
  printf("请输入联系人的性别:>");
  scanf("%s", person.sex);
  printf("请输入联系人的电话:>");
  scanf("%s", person.pnum);
  printf("请输入联系人的住址:>");
  scanf("%s", person.addr);
  //将联系人信息存到通讯录中
  p->data[p->size] = person;
  p->size++;
}*/

//检查容量函数
void CheckCapacity(Contact *p)
{
  assert(p);
  //如果联系人个数为0或与容量相同,就需要扩容
  if (p->size == 0 || p->size == p->capacity)
  {
    //动态内存开辟
    Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2);
    if (ptr == NULL)//开辟失败
    {
      //报错
      perror("CHECK CAPACITY ERROE !\n");
      exit(-1);
    }
    //开辟成功,重新赋值
    p->data = ptr;
    //扩容之后,容量也相应扩大
    p->capacity *= 2;
  }
  //反之什么都不需要干
}

//添加联系人 --- 动态
void ContactAdd(Contact *p)
{
  //断言保证p不为NULL
  assert(p);
  //如果联系人个数等于容量,或联系人个数等于0,这时我们就需要扩容了,我们来使用一个函数来干这事
  CheckCapacity(p);
  Data person;//记录联系人信息
  printf("请输入联系人的姓名:>");
  scanf("%s", person.name);
  printf("请输入联系人的年龄:>");
  scanf("%d", &person.age);
  printf("请输入联系人的性别:>");
  scanf("%s", person.sex);
  printf("请输入联系人的电话:>");
  scanf("%s", person.pnum);
  printf("请输入联系人的住址:>");
  scanf("%s", person.addr);
  //将联系人信息存到通讯录中
  p->data[p->size] = person;
  p->size++;
}

//删除联系人
void ContactDel(Contact *p)
{
  assert(p);
  char DelName[NAME_MAX] = {0};
  printf("请输入你要删除的联系人姓名:>");
  scanf("%s", DelName);
  int ret = ContactFind(p, DelName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    int j = 0;
    for (j = ret; j < p->size; j++)
    {
      //从前往后依次挪动覆盖
      p->data[j] = p->data[j + 1];
    }
    //删除完成之后,联系人个数减一
    p->size--;
  }
}

//查找联系人
void ContactSearch(Contact *p)
{
  assert(p);
  char SearchName[NAME_MAX];
  printf("请输入你要查找的联系人姓名:>");
  scanf("%s", SearchName);
  //查找有无此人
  int ret = ContactFind(p, SearchName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    printf("你所查找的联系人信息为:\n");
    printf("  姓名\t性别\t 年龄\t  电话\t\t地址\n");
    printf("  %-5s\t%s\t%d\t%s\t%s\n", p->data[ret].name,
        p->data[ret].sex,
        p->data[ret].age,
        p->data[ret].pnum,
        p->data[ret].addr);
  }
}

//修改联系人信息
void ContactModify(Contact *p)
{
  assert(p);
  char ModifyName[NAME_MAX];
  printf("请输入你要修改的联系人姓名:>");
  scanf("%s", ModifyName);
  int ret = ContactFind(p, ModifyName);
  if (ret == -1)
  {
    printf("通讯录中并无此人,请重新检查输入!\n");
  } else
  {
    Data person;//记录联系人信息
    printf("请输入联系人的姓名:>");
    scanf("%s", person.name);
    printf("请输入联系人的年龄:>");
    scanf("%d", &person.age);
    printf("请输入联系人的性别:>");
    scanf("%s", person.sex);
    printf("请输入联系人的电话:>");
    scanf("%s", person.pnum);
    printf("请输入联系人的住址:>");
    scanf("%s", person.addr);
    //将联系人信息存到通讯录中
    p->data[ret] = person;
  }
}

//展示联系人信息
void ContactShow(Contact *p)
{
  assert(p);
  if (p->size == 0)
  {
    printf("通讯录中并无一人!\n");
    return;
  }

  int i = 0;
  printf("  姓名\t性别\t 年龄\t  电话\t\t地址\n");
  for (i = 0; i < p->size; i++)
  {
    printf("  %-5s\t%s\t%d\t%s\t%s\n", p->data[i].name,
        p->data[i].sex,
        p->data[i].age,
        p->data[i].pnum,
        p->data[i].addr);

  }
}

void sort_menu()
{
  printf("      SORT_MENU     \n");
  printf("******************************\n");
  printf("****    1.name    ****\n");
  printf("****    2.sex     ****\n");
  printf("****    3.age     ****\n");
  printf("****    4.pnum    ****\n");
  printf("****    5.addr    ****\n");
  printf("******************************\n");
}

int sort_by_name(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->name, ((Data *) s2)->name);
}

int sort_by_sex(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->sex, ((Data *) s2)->sex);
}

int sort_by_age(const void *s1, const void *s2)
{
  return ((Data *) s1)->age - ((Data *) s2)->age;
}

int sort_by_pnum(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->pnum, ((Data *) s2)->pnum);
}

int sort_by_addr(const void *s1, const void *s2)
{
  return strcmp(((Data *) s1)->addr, ((Data *) s2)->addr);
}


//排序联系人
void ContactSort(Contact *p)
{
  assert(p);
  int choice;
  sort_menu();
  printf("请选择排序的参考量:>");
  scanf("%d", &choice);
  switch (choice)
  {
    case NAME:
      qsort(p->data, p->size, sizeof(Data), sort_by_name);
      break;
    case SEX:
      qsort(p->data, p->size, sizeof(Data), sort_by_sex);
      break;
    case AGE:
      qsort(p->data, p->size, sizeof(Data), sort_by_age);
      break;
    case PNUM:
      qsort(p->data, p->size, sizeof(Data), sort_by_pnum);
      break;
    case ADDR:
      qsort(p->data, p->size, sizeof(Data), sort_by_addr);
      break;
    default:
      printf("输入有误,请检查输入!\n");
  }
}

//打印帮助信息
void ContactHelp(Contact *p)
{
  printf("*******************************************\n");
  printf("******   add ---- 添加联系人信息  ******\n");
  printf("******   del ---- 删除联系人信息  ******\n");
  printf("****** search ---- 查找联系人信息  ******\n");
  printf("****** modify ---- 修改联系人信息  ******\n");
  printf("******  show ---- 展示联系人信息  ******\n");
  printf("******  help ---- 帮助信息     ******\n");
  printf("******  sort ---- 排序联系人信息  ******\n");
  printf("******  exit ---- 退出通讯录    ******\n");
  printf("*******************************************\n");
}

/*//退出通讯录
void ContactExit(Contact *p)
{
  printf("exit !\n");
}*/

/*
//退出通讯录 --- 动态
void ContactExit(Contact *p)
{
  //释放我们开辟的内存
  free(p->data);
  printf("exit !\n");
}*/

void Save(Contact* p)
{
  assert(p);
  FILE* fp =fopen("../Contact.dat","wb");
  int i =0;
  for(i=0;i<p->size;i++)
  {
    fwrite(p->data+i, sizeof(Data),1,fp);
  }
  fclose(fp);
}

//退出通讯录 --- 带文件
void ContactExit(Contact *p)
{
  //保存置文件
  Save(p);
  //释放我们开辟的内存
  free(p->data);
  printf("exit !\n");
}

main.c

#include "Contact.h"

void menu()
{
  //打印菜单
  printf("******************************************\n");
  printf("******   1.add    2.del    ******\n");
  printf("******   3.search  4.modify  ******\n");
  printf("******   5.show   6.sort   ******\n");
  printf("******   7.help   0.exit   ******\n");
  printf("******************************************\n");
}

void test()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址

  //初始化
  ContactInit(p);
  int input = 0;//存放用户选择的信息
  do
  {
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    switch (input)
    {
      case ADD:
        ContactAdd(p);
        break;
      case DEL:
        ContactDel(p);
        break;
      case SEARCH:
        ContactSearch(p);
        break;
      case MODIFY:
        ContactModify(p);
        break;
      case SHOW:
        ContactShow(p);
        break;
      case SORT:
        ContactSort(p);
        break;
      case HELP:
        ContactHelp(p);
        break;
      case EXIT:
        ContactExit(p);
        break;
      default:
        printf("输入非法!\n");
    }
  } while (input);

}

void test2()
{
  Contact list;//定义一个通讯录
  Contact *p = &list;//赋址
  //初始化
  ContactInit(p);
  //用一个函数指针数组来存放函数指针
  void (*fun[])(Contact *) ={ContactExit,
                ContactAdd,
                ContactDel,
                ContactSearch,
                ContactModify,
                ContactShow,
                ContactSort,
                ContactHelp};
  int input = 0;//存放用户选择的信息
  do{
    menu();
    printf("请输入你的选择:>");
    scanf("%d", &input);
    if(input>=0&&input<=sizeof(fun))
    {
      //system("cls");
      fun[input](p);

    }
    else
    {
      system("cls");
      printf("输入非法,请检查输入!\n");
    }
  }while(input);
}

int main()
{
  //test();
  test2();

  return 0;
}

上一篇:深入学习C++智能指针之shared_ptr与右值引用的方法

栏    目:C代码

下一篇:纯C语言:贪心Prim算法生成树问题源码分享

本文标题:C语言之通讯录的模拟实现代码

本文地址:http://www.codeinn.net/misctech/169921.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有