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語言通訊錄內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!