盛夏的果实 发表于 2021-8-10 15:04:22

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;//姓名
    int age;//年龄
    char sex;//性别
    char pnum;//电话
    char addr;//地址
} Data;
现在有了个人信息的结构体,我们需要再来一个结构体来存放它的数组及数组内有效信息的个数,即:
//存放MAX个个人信息的通讯录
typedef struct Contact
{
    Data data;
    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 = 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.name,
               p->data.sex,
               p->data.age,
               p->data.pnum,
               p->data.addr);

    }
}测试结果:


接下来就是删除联系人了
3.删除联系人
首先删除联系人肯定需要查找信息,又因为后面的几个函数也要用到它,所以我们单独来写一个查找模块:
//查找模块
int ContactFind(Contact *p, char *FindData)
{
    assert(p);
    int i = 0;
    for (i = 0; i < p->size; i++)
    {
      if (strcmp(p->data.name, FindData) == 0)
      {
            return i;//找到就返回下标
      }
    }
    return -1;//找不到就返回-1
}删除:
//删除联系人
void ContactDel(Contact *p)
{
    assert(p);
    char DelName = {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 = p->data;
      }
      //删除完成之后,联系人个数减一
      p->size--;
    }
}


4.查找联系人信息
//查找联系人
void ContactSearch(Contact *p)
{
    assert(p);
    char SearchName;
    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.name,
               p->data.sex,
               p->data.age,
               p->data.pnum,
               p->data.addr);
    }
}

5.修改联系人信息
//修改联系人信息
void ContactModify(Contact *p)
{
    assert(p);
    char ModifyName;
    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 = 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(p);
            system("cls");
      }
      else
      {
            system("cls");
            printf("输入非法,请检查输入!\n");
      }
    }while(input);
}这样是不是代码就少了很多!
所以完整代码如下:

//确保文件只包含一次
#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;//姓名
    int age;//年龄
    char sex;//性别
    char pnum;//电话
    char addr;//地址
} Data;

//存放MAX个个人信息的通讯录
typedef struct Contact
{
    Data data;
    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_HContact.h

#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.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 = person;
    p->size++;
}

//删除联系人
void ContactDel(Contact *p)
{
    assert(p);
    char DelName = {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 = p->data;
      }
      //删除完成之后,联系人个数减一
      p->size--;
    }
}

//查找联系人
void ContactSearch(Contact *p)
{
    assert(p);
    char SearchName;
    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.name,
               p->data.sex,
               p->data.age,
               p->data.pnum,
               p->data.addr);
    }
}

//修改联系人信息
void ContactModify(Contact *p)
{
    assert(p);
    char ModifyName;
    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 = 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.name,
               p->data.sex,
               p->data.age,
               p->data.pnum,
               p->data.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");
}Contact.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(p);
            system("cls");
      }
      else
      {
            system("cls");
            printf("输入非法,请检查输入!\n");
      }
    }while(input);
}

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

    return 0;
}main.c

二.动态通讯录
动态实现的问题主要在于它的容量不再是一变不变的,而是可随着我们的数据量来变化的,所以在我们原来定义的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 = person;
    p->size++;
}最后我们还要记得释放我们开辟的内存 --- 退出
//退出通讯录 --- 动态
void ContactExit(Contact *p)
{
    //释放我们开辟的内存
    free(p->data);
    printf("exit !\n");
}动态通讯录的修改就只有这些:
完整代码展示:

//确保文件只包含一次
#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;//姓名
    int age;//年龄
    char sex;//性别
    char pnum;//电话
    char addr;//地址
} Data;

/*
//存放MAX个个人信息的通讯录 --- 静态
typedef struct Contact
{
    Data data;
    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_HContact.h

#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.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 = 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 = person;
    p->size++;
}

//删除联系人
void ContactDel(Contact *p)
{
    assert(p);
    char DelName = {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 = p->data;
      }
      //删除完成之后,联系人个数减一
      p->size--;
    }
}

//查找联系人
void ContactSearch(Contact *p)
{
    assert(p);
    char SearchName;
    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.name,
               p->data.sex,
               p->data.age,
               p->data.pnum,
               p->data.addr);
    }
}

//修改联系人信息
void ContactModify(Contact *p)
{
    assert(p);
    char ModifyName;
    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 = 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.name,
               p->data.sex,
               p->data.age,
               p->data.pnum,
               p->data.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");
}Contact.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(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(p);

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

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

    return 0;
}main.c



三.带文件的动态通讯录
在这个里面,我们只需在初始化时进行文件的读取及关闭时文件的保存:
初始化:
//从文件载入信息
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=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");
}除此之外,其他都与动态通讯录相同
完整代码:

//确保文件只包含一次
#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;//姓名
    int age;//年龄
    char sex;//性别
    char pnum;//电话
    char addr;//地址
} Data;

/*
//存放MAX个个人信息的通讯录 --- 静态
typedef struct Contact
{
    Data data;
    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_HContact.h

#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.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=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 = 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 = person;
    p->size++;
}

//删除联系人
void ContactDel(Contact *p)
{
    assert(p);
    char DelName = {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 = p->data;
      }
      //删除完成之后,联系人个数减一
      p->size--;
    }
}

//查找联系人
void ContactSearch(Contact *p)
{
    assert(p);
    char SearchName;
    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.name,
               p->data.sex,
               p->data.age,
               p->data.pnum,
               p->data.addr);
    }
}

//修改联系人信息
void ContactModify(Contact *p)
{
    assert(p);
    char ModifyName;
    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 = 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.name,
               p->data.sex,
               p->data.age,
               p->data.pnum,
               p->data.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");
}Contact.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(p);

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

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

    return 0;
}main.c
|---------------------------------------------------------------------------------------------------
到此,我们的C语言也就告一段落了!
以后的路我们依然任重而道远!

转载声明:
作者:HighLight_FanYa
由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。
本文版权归作者和博客共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


文档来源:51CTO技术博客https://blog.51cto.com/guguguhuha/3335922
页: [1]
查看完整版本: C语言之通讯录的模拟实现