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语言之通讯录的模拟实现代码的文章就介绍到这了,更多相关C语言通讯录内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言实现个人通讯录管理系统

    如何用c语言制作简易的个人通讯录管理系统?想必这是每一位初步学习c语言的同学需要解决的一个大问题.如何将这些数据类型不完全相同的数据元素存储并访问呢?采用结构体便能轻松解决这个问题! #include<stdio.h> #include<string.h> #include<stdlib.h> #include<windows.h> struct stu //第一部分:声明结构体类型struct stu { char name[100];//姓名为字符串型

  • C语言通讯录管理系统完整版

    C语言实现了通讯录的录入信息.保存信息.插入.删除.排序.查找.单个显示等功能.. 完整的代码如下: #include <stdio.h> #include <malloc.h> //得到指向大小为Size的内存区域的首字节的指针// #include <string.h> #include <stdlib.h> //标准库函数// #define NULL 0 #define LEN sizeof(struct address_list) //计算字节//

  • C语言实现通讯录系统

    C语言通讯录系统实现,供大家参考,具体内容如下 需求分析: 利用文件读,写的方法 实现增加通讯录联系人信息 实现删除通讯录联系人信息 实现查找通讯录联系人信息 实现修改通讯录联系人信息 实现查看现有通讯录联系人信息 代码实现: // main.c // C语言通讯录实现 // // Created by Brisinga on 15/10/14. // Copyright © 2015年 yan. All rights reserved. // #include <stdio.h> #incl

  • 用C语言实现简易通讯录

    C语言实现一个通讯录,通讯录可以用来存储1000个人的信息,每个人的信息包括: 姓名.性别.年龄.电话.住址 **提供方法: 1. 添加联系人信息 2. 删除指定联系人信息 3. 查找指定联系人信息 4. 修改指定联系人信息 5. 显示所有联系人信息 6. 清空所有联系人 7. 以名字排序所有联系人** 思路分析: 首先我们可以分三个模块来解决这个问题,第一个模块我们需要一个头文件,这个头文件里可以包含一些相应信息,当实现文件和测试文件包含自己定义的头文件时便可以获得一些相关的信息.所以头文件里

  • C语言实现通讯录功能

    本文实例为大家分享了C语言实现通讯录功能的具体代码,供大家参考,具体内容如下 先定义头文件 #ifndef __CONTACT_H__ #define __CONTACT_H__ #define NAME_LEN 10 #define SEX_LEN 6 #define TELE_LEN 12 #define ADDR_LEN 20 #define MAX_PEO 1000 typedef struct PEO { char name[NAME_LEN]; int age; char sex[S

  • C语言通讯录管理系统课程设计

    本文实例为大家分享了C语言通讯录管理系统课程设计,供大家参考,具体内容如下 #include <stdio.h> #include <stdlib.h> #include <windows.h> struct Sign{ char name[8]; char sex[4]; char birthday[12]; char phone[11]; char postcode[7]; char addr[30]; struct Sign *next; }pe; char Ph

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

    在C语言学习结束之际,谨以此篇文章来对C语言的学习告一段落. 纲要: 通讯录的静态版本 通讯录的动态版本 通讯录的带文件版本 因为三种实现方法除了储存形式不同,其他都基本相同,所以我们重点论述静态版本的实现,以及它们不同的储存方式. 一.通讯录的静态版本 为什么叫它为静态版本呢,因为在此部分的储存是以数组来储存的,那对于各种各样的信息,我们要拿什么数组来存放它呢?当然是结构体数组了,所以我们来定义一个结构体来表示个人信息: //采用宏的目的是方便日后修改 #define NAME_MAX 20

  • C语言数据结构实现银行模拟

    C语言数据结构实现银行模拟 实现代码: #include <stdio.h> #include <stdlib.h> #include <windows.h> #define MAX_WIN 20 #define MAX_STAY 100 typedef struct customer *link; struct customer { int stay; link next; }; link GUY(int stay, link next) { link c = mal

  • C语言实现通讯录管理系统

    本文实例为大家分享了C语言实现通讯录管理系统的具体代码,供大家参考,具体内容如下 工具:Visual C++6.0 说明: 本系统基于C语言实现班级通讯录管理系统,为大一时学习C语言刚入门所做的课程设计.功能包括增.删.查.改等,非常适合初学者练手.通讯录包括的个人信息有姓名.学号.性别.籍贯.政治面貌.手机号.QQ号.宿舍等.主要用到了指针.结构体.遍历链表.文件读取等知识点. 运行效果: 代码: #include<stdio.h> #include<string.h> #inc

  • C语言实现通讯录小项目

    本文实例为大家分享了C语言实现通讯录小项目的具体代码,供大家参考,具体内容如下 编写程序实现通讯录的基本功能,可以做到增,删,查,改,打印通讯录,等等功能 test.c #include <stdio.h> #include "contact.h" void menu() { printf("*********************************************\n"); printf("****** 1. add 2.de

  • C语言实现通讯录小功能

    本文实例为大家分享了C语言实现通讯录功能的具体代码,供大家参考,具体内容如下 头文件contact.h #pragma once #define _CRT_SECURE_NO_WARNINGS 1 //#define max 1000 #define fault 3 #define max_name 20 #define max_telephone 12 #define max_sex 5 #define max_address 30 #include<stdio.h> #include<

  • C语言实现通讯录程序

    本文实例为大家分享了C语言实现通讯录程序的具体代码,供大家参考,具体内容如下 设计要求: 可以存放1000个人的信息,每个人的信息包括姓名.年龄.性别.电话.住址 通讯录功能包括: 1.增加联系人 2.删除指定联系人 3.查找指定联系人 4.修改指定联系人 5.显示所有联系人 6.退出通讯录 思路分析: 首先我们需要创建3个文件,分别是源文件(test.c).通讯录文件(contact.c).通讯录头文件(contact.h),其中头文件用来包含头文件.声名信息.结构体.创建全局变量以及宏. 我

  • C语言简易通讯录的实现代码

    本文实例为大家分享了C语言简易通讯录的具体代码,供大家参考,具体内容如下 通讯录的实现: 一.介绍: 运用C语言的数组.指针.结构体等相关知识:实现一个简易的通讯录: 此通讯录的大概内容为: 通讯录可存储1000个人的信息: 每个人的基本信息有:名字+ 年龄+性别 +  电话+ QQ + 地址 此通讯录所具有的功能:增加+ 删除 +  查询 + 修改 +  排序 + 退出 此通讯录在设计时:总共设计了三个文件: contact.h: 类型的声明和函数的声明 contact.c:函数功能的具体实现

  • C语言编程内存分配通讯录静态实现示例代码教程

    实现一个通讯录: 通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名.性别.年龄.电话.住址 提供方法: 1. 添加联系人信息 2. 删除指定联系人信息 3. 查找指定联系人信息 4. 修改指定联系人信息 5. 显示所有联系人信息 6. 清空所有联系人 7. 以名字排序所有联系人 首先我们采用顺序表的方式来实现一个通讯录,顺序表就是一种静态的模式.但是呢,静态的方式存在着一些明显的弊端,比如说:(1)信息少了存在空间浪费现象,信息多了存在空间不足的现象:(2)无法对信息进行保存,没有实

  • C语言实现通讯录的详细代码

    目录 (一)实现思路 1.通讯录功能 2.模块化实现各方面的功能 3.代码实现 (二)源代码 A.test.c B.Contact.h C.Contact.c (一)实现思路 1.通讯录功能 添加好友,删除好友,查找好友,修改好友信息,对好友进行排序 2.模块化实现各方面的功能 a. test.c 测试通讯录功能 b. Contact.c 实现通讯录功能 c. Contact.h 包含通讯录实现的头文件 3.代码实现 (二)源代码 A.test.c #define _CRT_SECURE_NO_

随机推荐