c/c++语言开发共享C语言之通讯录的模拟实现代码

在c语言学习结束之际,谨以此篇文章来对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;

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

  对此我们来看一张图片:

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

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

  void contactinit(contact *p)  {    //保证p不为null    assert(p);    //置零    memset(p->data, 0, sizeof(p->data));    p->size = 0;    }

  我们再来看一下结果:

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

  我们发现,现在它内部已经被我们置为了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++;  }

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

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

  2.展示联系人

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

  测试结果:

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

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

  接下来就是删除联系人了

  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--;    }  }

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

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

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

  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  电话tt地址n");      printf("  %-5st%st%dt%st%sn", p->data[ret].name,          p->data[ret].sex,          p->data[ret].age,          p->data[ret].pnum,          p->data[ret].addr);    }  }

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

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

  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;    }  }

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

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

  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");    }  }

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

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

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

例:

  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  电话tt地址n");      printf("  %-5st%st%dt%st%sn", 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  电话tt地址n");    for (i = 0; i < p->size; i++)    {      printf("  %-5st%st%dt%st%sn", 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  电话tt地址n");      printf("  %-5st%st%dt%st%sn", 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  电话tt地址n");    for (i = 0; i < p->size; i++)    {      printf("  %-5st%st%dt%st%sn", 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  电话tt地址n");      printf("  %-5st%st%dt%st%sn", 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  电话tt地址n");    for (i = 0; i < p->size; i++)    {      printf("  %-5st%st%dt%st%sn", 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语言通讯录内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/595791.html

(0)
上一篇 2021年5月8日
下一篇 2021年5月8日

精彩推荐