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!
推薦閱讀:
- None Found