C語言之通信錄的模擬實現

C語言之通信錄的模擬實現

  在C語言學習結束之際,謹以此篇文章來對C語言的學習告一段落。數組

 

綱要:ide

  • 通信錄的靜態版本
  • 通信錄的動態版本
  • 通信錄的帶文件版本

 

  由於三種實現方法除了儲存形式不一樣,其餘都基本相同,因此咱們重點論述靜態版本的實現,以及它們不一樣的儲存方式。函數

 


一.通信錄的靜態版本  

  爲何叫它爲靜態版本呢,由於在此部分的儲存是以數組來儲存的,那對於各類各樣的信息,咱們要拿什麼數組來存放它呢?固然是結構體數組了,因此咱們來定義一個結構體來表示我的信息:學習

//採用宏的目的是方便往後修改
#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;

  那麼,準備工做作好以後,咱們就開始正式實現了,首先咱們確定是要先建立一個通信錄,這時咱們再來想想,咱們就這樣建立以後,咱們是否能夠直接使用呢?優化

  對此咱們來看一張圖片:spa

 

 

   咱們發現,如今它裏面都放着一些隨機值,因此咱們須要將其初始化一下,來方便咱們的使用:指針

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

}

  咱們再來看一下結果:調試

 

 

   咱們發現,如今它內部已經被咱們置爲了0;接着咱們作的就是添加聯繫人了,不過在此以前,咱們不妨先作一個菜單來顯示咱們都有一些什麼功能:code

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

  這樣是否是代碼就少了不少!

 

因此完整代碼以下:

//確保文件只包含一次
#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.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[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");
}
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[input](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[p->size] = 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[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.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[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");
}
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[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;
}
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[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");
}

  除此以外,其餘都與動態通信錄相同

  完整代碼:

//確保文件只包含一次
#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.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[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");
}
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[input](p);

        }
        else
        {
            system("cls");
            printf("輸入非法,請檢查輸入!\n");
        }
    }while(input);
}

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

    return 0;
}
main.c

 

 

 

 

 


 

|---------------------------------------------------------------------------------------------------

到此,咱們的C語言也就告一段落了!

之後的路咱們依然任重而道遠!

相關文章
相關標籤/搜索