在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
#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"); }
#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"); }
動態通信錄的修改就只有這些:
完整代碼展現:
//確保文件只包含一次 #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
#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"); }
#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"); }
除此以外,其餘都與動態通信錄相同
完整代碼:
//確保文件只包含一次 #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
#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"); }
#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語言也就告一段落了!
之後的路咱們依然任重而道遠!