基于C語言實(shí)現(xiàn)高級(jí)通訊錄的示例代碼
前言
前面已經(jīng)寫了一篇簡(jiǎn)易版本通訊錄的實(shí)現(xiàn),下面再來寫一篇功能比較齊全的,可增容,增容空間可自己掌控,也可將數(shù)據(jù)保存起來的,又添加了清空列表等一些功能的高級(jí)通訊錄!
為何要實(shí)現(xiàn)高級(jí)通訊錄
對(duì)于簡(jiǎn)易版本的通訊錄來說,我們是直接指定了通訊錄的大小,通訊錄的空間是直接給死了,那么此時(shí)我們會(huì)發(fā)現(xiàn)兩個(gè)弊端:
第一個(gè)弊端:
假設(shè)我們所添加的聯(lián)系人的個(gè)數(shù),小于,我們給定通訊錄的大小,此時(shí)多余的空間就被浪費(fèi)掉了!又假設(shè)我們添加聯(lián)系人的大小,大于,給定通訊錄的大小,此時(shí)我們發(fā)現(xiàn)通訊錄的空間不夠我們來封裝聯(lián)系人信息了! 此時(shí)我們就得優(yōu)化通信錄給定空間上的問題,不能再給其指定大小的空間,而是讓其空間有靈活性,此時(shí)我們以動(dòng)態(tài)增容的方式來給定通訊錄的空間,就很好的規(guī)避了這一問題!
第二個(gè)弊端:
我們知道程序運(yùn)行起來我們輸入的數(shù)據(jù)都是保存在內(nèi)存上的,在簡(jiǎn)易版本中我們?cè)谶\(yùn)行通訊錄之后添加的數(shù)據(jù),在程序結(jié)束的時(shí)候都會(huì)被清除。當(dāng)?shù)诙芜\(yùn)行起來的時(shí)候,這些數(shù)據(jù)都已經(jīng)不存在了,而我們既然要保存聯(lián)系人的信息,就得做到數(shù)據(jù)持久化的保存,才能真正保存聯(lián)系人信息,要做到持久化我們就得將數(shù)據(jù)保存到硬盤中,也就是文件當(dāng)中,此時(shí)我們可以用文件操作的方式來實(shí)現(xiàn)持久化的保存聯(lián)系人信息,就很好的規(guī)避了這一問題!
高級(jí)通訊錄實(shí)現(xiàn):
為了規(guī)避以上問題,我們?cè)賮韺?shí)現(xiàn)一個(gè)能增容能保存以及再完善一些功能的高級(jí)通訊錄!
創(chuàng)建通訊錄
我們先創(chuàng)建一個(gè)結(jié)構(gòu)體,用來封裝聯(lián)系人的:姓名、性別、年齡...等信息!再創(chuàng)建一個(gè)結(jié)構(gòu)體,用來:操控聯(lián)系人信息、記錄聯(lián)系人個(gè)數(shù)、記錄空間數(shù)....等!
具體實(shí)現(xiàn)看代碼:
#define NAME_SIZE 20 #define EAX_SIZE 6 #define PHONE_SIZE 15 //創(chuàng)建封裝通訊錄內(nèi)容的結(jié)構(gòu)體,并給其重命名 typedef struct information { char name[NAME_SIZE]; int age; char eax[EAX_SIZE]; char phone[PHONE_SIZE]; }information; //創(chuàng)建管理通訊錄的結(jié)構(gòu)體,并給其重命名 typedef struct contict { information* data;//結(jié)構(gòu)體指針 int sz;//聯(lián)系人個(gè)數(shù) int count;//增容的數(shù)量 }contict;
打印菜單
我們要?jiǎng)?chuàng)建一個(gè)菜單供用戶選擇,讓用戶選擇操作的功能,此時(shí)我們用do while循環(huán)里面嵌套Switch case語句來實(shí)現(xiàn)用戶對(duì)功能的選擇以及菜單的顯示!,
具體看代碼:
//定義所用到的常量 //因?yàn)槌A刻嘤妹杜e類型一次性定義 //讓這些常量代替我們對(duì)功能的選擇 enum Constant { EXIT, ADD, DEL, SEL, MODIFY, SHOW, SQRT, CLEAR }; //菜單 void menu(void) { printf("******************************\n"); printf("***** 1、add 2、del *****\n"); printf("***** 3、sel 4、modify *****\n"); printf("***** 5、show 6、sqrt *****\n"); printf("***** 7、clear 0、exit *****\n"); printf("******************************\n"); } int main() { //創(chuàng)建結(jié)構(gòu)體變量 contict con; //初始化通訊錄 init_contict(&con); int input = 0; do { //菜單 menu(); printf("請(qǐng)選擇-> "); scanf("%d", &input); switch (input) { case ADD: ADDcontict(&con);//添加聯(lián)系人 break; case DEL: DELcontict(&con);//刪除指定聯(lián)系人 break; case SEL: SELcontict(&con);//查詢指定聯(lián)系人 break; case MODIFY: MODIFYcontict(&con);//修改指定聯(lián)系人信息 break; case SHOW: SHOWcontict(&con);//顯示所有聯(lián)系人信息 break; case SQRT: SQRTcontict(&con);//排序聯(lián)系人 break; case CLEAR: CLEARcontict(&con);//清空通訊錄 break; case EXIT: SAVEcontictp(&con);//退出的時(shí)候保存通訊錄聯(lián)系人信息 FREEcontict(&con);//退出的時(shí)候釋放空間 printf("退出成功\n"); break; default: printf("選擇有誤請(qǐng)重新選擇-> \n"); break; } } while (input); return 0; }
先大致了解一下邏輯,而代碼里面的函數(shù)功能,我們下面一一實(shí)現(xiàn)與介紹!
初始化通訊錄
因?yàn)槭莿?dòng)態(tài)增容版本,我們?cè)诔跏蓟臅r(shí)候空間是由我們自行開辟的,而C語言里面給我們提供了動(dòng)態(tài)內(nèi)存開辟的函數(shù),我們按照這樣的思路來開辟空間,先開辟小一點(diǎn)的空間用,如果空間不夠用了我們?cè)僬{(diào)整空間,讓其變大!在初始化開辟空間的時(shí)候,我們使用calloc函數(shù)來申請(qǐng)空間,因?yàn)閏alloc函數(shù)在動(dòng)態(tài)空間申請(qǐng)的時(shí)候會(huì)將空間中的每個(gè)字節(jié)的內(nèi)容都初始化為0,然后我們?cè)賹⒂涗浡?lián)系人的個(gè)數(shù)的變量初始化為0,再將記錄空間數(shù)量的變量初始化為我們所開辟的聯(lián)系人空間的個(gè)數(shù)!
因?yàn)槭悄鼙4媛?lián)系人信息的通訊錄,為了用戶的后續(xù)使用和關(guān)閉,所以在初始化的時(shí)候,還得要調(diào)用一個(gè)功能,就是將保存在文件中的聯(lián)系人的信息讀到我們動(dòng)態(tài)申請(qǐng)的空間中,隨后繼續(xù)進(jìn)行操作,通俗點(diǎn)將就是將已經(jīng)存在的聯(lián)系人的信息拿到通訊錄里面!這個(gè)功能就是加載功能!
具體看代碼實(shí)現(xiàn):
//初始化通訊錄 #define IN 3 void init_contict(contict* pc) { assert(pc); //calloc函數(shù)在開辟空間的時(shí)候會(huì)將每個(gè)字節(jié)的內(nèi)容都初始化為0 information* p = (information*)calloc(IN, sizeof(information)); //判斷是否開辟成功 if (p == NULL) { perror("calloc"); return; } pc->data = p; pc->sz = 0; pc->count = IN; //加載文件信息到通訊錄中 read_contict(pc); //將原來存在的聯(lián)系人信息拿到通訊錄中 }
實(shí)現(xiàn)加載功能
就是將文件中的聯(lián)系人的信息,加載到通訊錄中,以便后續(xù)操作,完整的實(shí)現(xiàn)了持久化保存功能,比如說:但我們第一次使用通訊錄的時(shí)候會(huì)添加聯(lián)系人的信息,在最后關(guān)閉的時(shí)候,這些信息會(huì)被保存到文件中,當(dāng)我們第二次再進(jìn)行操作的時(shí)候,就將這些保存在文件中的聯(lián)系人信息加載到通訊錄中,以供我們操作,也更完整的實(shí)現(xiàn)了保存功能!具體點(diǎn)說就是對(duì)保存聯(lián)系人信息的文件進(jìn)行讀操作,將文件里的信息讀到通訊錄的空間里!
具體實(shí)現(xiàn)看代碼:
//加載文件信息到通訊錄中 void read_contict(contict* pc) { assert(pc); //打開文件 FILE* pf = fopen("AddressBook.txt", "rb"); //判斷是否打開成功 if (pf == NULL) { perror("fopen"); return; } //讀數(shù)據(jù) information tmp = { 0 }; int i = 0; while (fread(&tmp, sizeof(information), 1, pf)) { //讀取數(shù)據(jù)要考慮增容問題 Enhancement(pc); pc->data[i] = tmp; pc->sz++; i++; } //關(guān)閉文件 fclose(pf); pf = NULL; }
實(shí)現(xiàn)添加功能
添加聯(lián)系人的方式其實(shí)很簡(jiǎn)單,我們直接在通訊錄里面寫入值就行了,每寫入一個(gè)讓記錄聯(lián)系人個(gè)數(shù)的變量+1,再判斷一下空間的容量夠不夠是否需要增容?。ㄎ覀儗⒃鋈莘庋b成一個(gè)函數(shù),直接調(diào)用一下就行),增容的同時(shí)讓記錄空間的變量同樣變成增容之后空間的個(gè)數(shù)!
具體實(shí)現(xiàn)看代碼:
//添加聯(lián)系人 void ADDcontict(contict* pc) { assert(pc); //判斷是否要增容 Enhancement(pc);//增容功能后續(xù)實(shí)現(xiàn) printf("請(qǐng)輸入姓名-> "); scanf("%s", pc->data[pc->sz].name); printf("清輸入年齡-> "); scanf("%d", &(pc->data[pc->sz].age)); printf("請(qǐng)輸入性別-> "); scanf("%s", pc->data[pc->sz].eax); printf("請(qǐng)輸入電話-> "); scanf("%s", pc->data[pc->sz].phone); pc->sz++; printf("添加成功\n"); }
實(shí)現(xiàn)增容功能
在添加聯(lián)系以及后面我們從文件中讀取聯(lián)系人信息的時(shí)候,我們都可能遇到實(shí)現(xiàn)申請(qǐng)好的空間不夠用的情況,此時(shí)我們就要進(jìn)行調(diào)整空間的大小,讓空間變大也就是增容,我們知道C語言中,realloc函數(shù)(不懂可以看主要?jiǎng)討B(tài)內(nèi)存管理文章),可以調(diào)整申請(qǐng)好的動(dòng)態(tài)空間的大小,所以在實(shí)現(xiàn)增容這個(gè)功能的時(shí)候我們用,realloc函數(shù),來實(shí)現(xiàn)增容空間的功能!增容的同時(shí)我們也讓記錄空間個(gè)數(shù)的變量進(jìn)行增加!
具體實(shí)現(xiàn)看代碼:
//判斷是否要增容 #define IT 2 void Enhancement(contict* pc) { assert(pc); if (pc->sz == pc->count) { //增容 information* p = (information*)realloc(pc->data, (pc->count + IT) * sizeof(information)); if (p == NULL) { perror("realloc"); return; } pc->data = p; pc->count += IT; printf("增容成功\n"); } }
實(shí)現(xiàn)刪除功能
實(shí)現(xiàn)刪除指定聯(lián)系人,原理其實(shí)很簡(jiǎn)單,就是將要?jiǎng)h除的聯(lián)系人的信息,被其后面的聯(lián)系人覆蓋掉,以此類推從后往前一直覆蓋直到聯(lián)系人全部遍歷完,通俗點(diǎn)說就是讓其后面的每個(gè)聯(lián)系人都往前走一步!
畫圖簡(jiǎn)單明了:
具體實(shí)現(xiàn)看代碼:
//判斷該聯(lián)系人是否存在 There(char* name, contict* pc) { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(name, pc->data[i].name) == 0) { return i; } } return -1; } //刪除指定聯(lián)系人 void DELcontict(contict* pc) { assert(pc); //判斷聯(lián)系人列表是否為空 if (pc->sz == 0) { printf("聯(lián)系人列表為空 無法刪除\n"); return; } char name[NAME_SIZE]; printf("請(qǐng)輸入要?jiǎng)h除聯(lián)系人的姓名-> "); scanf("%s", name); //判斷該聯(lián)系人是否存在 int flag = There(name, pc);//因?yàn)楹罄m(xù)功能都要用到這一步,用一個(gè)函數(shù)來封裝! if (flag == -1) { printf("該聯(lián)系人不存在\n"); return; } //刪除聯(lián)系人 int i = 0; for (i = flag; i < pc->sz - 1; i++) { pc->data[i] = pc->data[i + 1]; } --pc->sz; printf("刪除成功\n"); }
實(shí)現(xiàn)查詢功能
查詢就指定聯(lián)系人就很簡(jiǎn)單了,就只是找到該聯(lián)系人,然后再將該聯(lián)系人的信息打印出來即可!
具體實(shí)現(xiàn)看代碼:
//判斷該聯(lián)系人是否存在 There(char* name, contict* pc) { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(name, pc->data[i].name) == 0) { return i; } } return -1; } //查找指定聯(lián)系人信息 void SELcontict(contict* pc) { assert(pc); if (pc->sz == 0) { printf("聯(lián)系人列表為空,無法查詢\n"); return; } char name[NAME_SIZE]; printf("請(qǐng)輸入要查詢聯(lián)系人的姓名-> "); scanf("%s", name); //判斷該聯(lián)系人是否存在 int flag = There(name, pc); if (flag == -1) { printf("該聯(lián)系人不存在\n"); return; } printf("%-10s %-5s %-5s %-13s\n", "姓名", "年齡", "性別", "電話"); printf("%-10s %-5d %-5s %-13s\n", pc->data[flag].name, pc->data[flag].age, pc->data[flag].eax, pc->data[flag].phone); printf("查詢成功\n"); }
實(shí)現(xiàn)修改功能
修改聯(lián)系人跟查詢聯(lián)系人一個(gè)思路,就是找到該聯(lián)系人的位置,然后將其信息修改掉,也就是用scanf函數(shù)重新給其輸入值即可!
具體實(shí)現(xiàn)看代碼:
//判斷該聯(lián)系人是否存在 There(char* name, contict* pc) { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(name, pc->data[i].name) == 0) { return i; } } return -1; } //修改指定聯(lián)系人信息 void MODIFYcontict(contict* pc) { assert(pc); if (pc->sz == 0) { printf("聯(lián)系人列表為空,無法修改\n"); return; } char name[NAME_SIZE]; printf("請(qǐng)輸入要修改聯(lián)系人的姓名-> "); scanf("%s", name); //判斷該聯(lián)系人是否存在 int flag = There(name, pc); if (flag == -1) { printf("該聯(lián)系人不存在\n"); return; } printf("請(qǐng)輸入姓名-> "); scanf("%s", pc->data[flag].name); printf("清輸入年齡-> "); scanf("%d", &(pc->data[flag].age)); printf("請(qǐng)輸入性別-> "); scanf("%s", pc->data[flag].eax); printf("請(qǐng)輸入電話-> "); scanf("%s", pc->data[flag].phone); printf("修改成功\n"); }
實(shí)現(xiàn)查詢所有聯(lián)系人功能
查詢所有聯(lián)系人信息,就是將所有聯(lián)系人信息都打印出來,我們只需要運(yùn)用一個(gè)for遍歷聯(lián)系人列表即可!
具體實(shí)現(xiàn)看代碼:
//顯示所有聯(lián)系人信息 void SHOWcontict(contict* pc) { assert(pc); if (pc->sz == 0) { printf("聯(lián)系人列表為空\(chéng)n"); return; } printf("%-10s %-5s %-5s %-13s\n", "姓名", "年齡", "性別", "電話"); int i = 0; for (i = 0; i < pc->sz; i++) { printf("%-10s %-5d %-5s %-13s\n", pc->data[i].name, pc->data[i].age, pc->data[i].eax, pc->data[i].phone); } }
實(shí)現(xiàn)排序功能
在排序的時(shí)候我們,給定兩種排序方法:按照年齡排序、按照姓名排序 供用戶選擇。用qsort函數(shù)(不了解的可以看主頁(yè)指針進(jìn)階里面有詳細(xì)介紹qsort)來分別實(shí)現(xiàn)兩種排序功能!
具體看代碼:
//排序聯(lián)系人信息 //按照年齡排序 int con_age(const void* e1, const void* e2) { //升序 return ((information*)e1)->age - ((information*)e2)->age; //降序 //return ((information*)e2)->age - ((information*)e1)->age; } //按照姓名排序 int con_name(const void* e1, const void* e2) { //升序 return strcmp(((information*)e1)->name, ((information*)e2)->name); //降序 //return strcmp(((information*)e2)->name, ((information*)e1)->name); } void SQRTcontict(contict* pc) { assert(pc); if (pc->sz == 0) { printf("聯(lián)系人列表為空,無法排序\n"); return; } int n = 0; printf("*********************\n"); printf("*** 1、按年齡排序 ***\n"); printf("*** 2、按姓名排序 ***\n"); printf("*********************\n"); printf("請(qǐng)選擇排序方式-> "); scanf("%d", &n); if (n == 1) { qsort(pc->data, pc->sz, sizeof(information), con_age); printf("按照年齡排序成功\n"); } else if (n == 2) { qsort(pc->data, pc->sz, sizeof(information), con_name); printf("按照姓名排序成功\n"); } else { printf("選擇排序無效\n"); } }
實(shí)現(xiàn)清空功能
要清空聯(lián)系人信息,就只需要將我們通訊錄申請(qǐng)的空間釋放掉,隨后再以讀的形式打開一下文件,打開之后什么都不干,讀的形式會(huì)將文件的內(nèi)容都覆蓋掉,會(huì)自動(dòng)清空文件里的內(nèi)容,再關(guān)閉文件,最后調(diào)用一下初始化函數(shù),讓它重新開辟一片空間!就完成清空功能了
具體實(shí)現(xiàn)看代碼:
//清空通訊錄信息 void CLEARcontict(contict* pc) { assert(pc); free(pc->data); pc->data = NULL; //打開文件 FILE* pf = fopen("AddressBook.txt", "wb");//wb在打開文件的時(shí)候會(huì)覆蓋前面的內(nèi)容! if (pf == NULL) { perror("fopen"); return; } //啥都不寫入直接關(guān)閉文件! //關(guān)閉文件 fclose(pf); pf = NULL; init_contict(pc); printf("清空成功\n"); }
實(shí)現(xiàn)保存功能
要讓聯(lián)系人信息持久化的保存,我們將其保存到文件中,進(jìn)行文件操作(不懂看主頁(yè)文件操作文章有詳細(xì)講解),只需要將每個(gè)聯(lián)系人的信息寫入文件中即可!
具體實(shí)現(xiàn)看代碼:
//退出的時(shí)候保存通訊錄聯(lián)系人信息 void SAVEcontictp(contict* pc) { assert(pc); //打開文件 FILE* pf = fopen("AddressBook.txt", "wb");//以二進(jìn)制的寫入形式打開 //判斷是否打開成功 if (pf == NULL) { perror("fopen"); return; } //開始寫數(shù)據(jù) int i = 0; for (i = 0; i < pc->sz; i++) { //一個(gè)一個(gè)的寫入數(shù)據(jù) fwrite(pc->data+i, sizeof(information),1, pf); } //關(guān)閉文件 fclose(pf); pf = NULL; printf("保存成功\n"); }
實(shí)現(xiàn)退出功能
在退出的時(shí)候,先將通訊錄里面聯(lián)系人的信息,保存到文件中,隨后再將動(dòng)態(tài)開辟的通訊錄的空間釋放就行,隨后將指針置為NULL,避免野指針。注意:先保存再釋放二者順序不可亂,不然會(huì)出錯(cuò)!
具體實(shí)現(xiàn)看代碼:
//退出的時(shí)候釋放空間 void FREEcontict(contict* pc) { assert(pc); free(pc->data); pc->data = NULL; pc->sz = 0; pc->count = 0; }
通訊錄總代碼
//動(dòng)態(tài)+可保存數(shù)據(jù)版本的通訊錄 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> //創(chuàng)建封裝通訊錄內(nèi)容的結(jié)構(gòu)體 #define NAME_SIZE 20 #define EAX_SIZE 6 #define PHONE_SIZE 15 typedef struct information { char name[NAME_SIZE]; int age; char eax[EAX_SIZE]; char phone[PHONE_SIZE]; }information; //創(chuàng)建管理通訊錄的結(jié)構(gòu)體 typedef struct contict { information* data;//結(jié)構(gòu)體指針 int sz;//聯(lián)系人個(gè)數(shù) int count;//增容的數(shù)量 }contict; //定義所用到的常量 //因?yàn)槌A刻嘤妹杜e類型一次性定義 //讓這些常量代替我們對(duì)功能的選擇 enum Constant { EXIT, ADD, DEL, SEL, MODIFY, SHOW, SQRT, CLEAR }; //菜單 void menu(void) { printf("******************************\n"); printf("***** 1、add 2、del *****\n"); printf("***** 3、sel 4、modify *****\n"); printf("***** 5、show 6、sqrt *****\n"); printf("***** 7、clear 0、exit *****\n"); printf("******************************\n"); } //判斷是否要增容 #define IT 2 void Enhancement(contict* pc) { assert(pc); if (pc->sz == pc->count) { //增容 information* p = (information*)realloc(pc->data, (pc->count + IT) * sizeof(information)); if (p == NULL) { perror("realloc"); return; } pc->data = p; pc->count += IT; printf("增容成功\n"); } } //加載文件信息到通訊錄中 void read_contict(contict* pc) { assert(pc); //打開文件 FILE* pf = fopen("AddressBook.txt", "rb"); //判斷是否打開成功 if (pf == NULL) { perror("fopen"); return; } //讀數(shù)據(jù) information tmp = { 0 }; int i = 0; while (fread(&tmp, sizeof(information), 1, pf)) { //讀取數(shù)據(jù)要考慮增容問題 Enhancement(pc); pc->data[i] = tmp; pc->sz++; i++; } //關(guān)閉文件 fclose(pf); pf = NULL; } //初始化通訊錄 #define IN 3 void init_contict(contict* pc) { assert(pc); //calloc函數(shù)在開辟空間的時(shí)候會(huì)將每個(gè)字節(jié)的內(nèi)容都初始化為0 information* p = (information*)calloc(IN, sizeof(information)); //判斷是否開辟成功 if (p == NULL) { perror("calloc"); return; } pc->data = p; pc->sz = 0; pc->count = IN; //加載文件信息到通訊錄中 read_contict(pc); //先不用管這個(gè)功能后續(xù)會(huì)慢慢了解 //主要了解上面初始化的代碼! } //添加聯(lián)系人 void ADDcontict(contict* pc) { assert(pc); //判斷是否要增容 Enhancement(pc); printf("請(qǐng)輸入姓名-> "); scanf("%s", pc->data[pc->sz].name); printf("清輸入年齡-> "); scanf("%d", &(pc->data[pc->sz].age)); printf("請(qǐng)輸入性別-> "); scanf("%s", pc->data[pc->sz].eax); printf("請(qǐng)輸入電話-> "); scanf("%s", pc->data[pc->sz].phone); pc->sz++; printf("添加成功\n"); } //判斷該聯(lián)系人是否存在 There(char* name, contict* pc) { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(name, pc->data[i].name) == 0) { return i; } } return -1; } //刪除指定聯(lián)系人 void DELcontict(contict* pc) { assert(pc); //判斷聯(lián)系人列表是否為空 if (pc->sz == 0) { printf("聯(lián)系人列表為空 無法刪除\n"); return; } char name[NAME_SIZE]; printf("請(qǐng)輸入要?jiǎng)h除聯(lián)系人的姓名-> "); scanf("%s", name); //判斷該聯(lián)系人是否存在 int flag = There(name, pc); if (flag == -1) { printf("該聯(lián)系人不存在\n"); return; } //刪除聯(lián)系人 int i = 0; for (i = flag; i < pc->sz - 1; i++) { pc->data[i] = pc->data[i + 1]; } --pc->sz; printf("刪除成功\n"); } //查找指定聯(lián)系人信息 void SELcontict(contict* pc) { assert(pc); if (pc->sz == 0) { printf("聯(lián)系人列表為空,無法查詢\n"); return; } char name[NAME_SIZE]; printf("請(qǐng)輸入要查詢聯(lián)系人的姓名-> "); scanf("%s", name); //判斷該聯(lián)系人是否存在 int flag = There(name, pc); if (flag == -1) { printf("該聯(lián)系人不存在\n"); return; } printf("%-10s %-5s %-5s %-13s\n", "姓名", "年齡", "性別", "電話"); printf("%-10s %-5d %-5s %-13s\n", pc->data[flag].name, pc->data[flag].age, pc->data[flag].eax, pc->data[flag].phone); printf("查詢成功\n"); } //修改指定聯(lián)系人信息 void MODIFYcontict(contict* pc) { assert(pc); if (pc->sz == 0) { printf("聯(lián)系人列表為空,無法修改\n"); return; } char name[NAME_SIZE]; printf("請(qǐng)輸入要修改聯(lián)系人的姓名-> "); scanf("%s", name); //判斷該聯(lián)系人是否存在 int flag = There(name, pc); if (flag == -1) { printf("該聯(lián)系人不存在\n"); return; } printf("請(qǐng)輸入姓名-> "); scanf("%s", pc->data[flag].name); printf("清輸入年齡-> "); scanf("%d", &(pc->data[flag].age)); printf("請(qǐng)輸入性別-> "); scanf("%s", pc->data[flag].eax); printf("請(qǐng)輸入電話-> "); scanf("%s", pc->data[flag].phone); printf("修改成功\n"); } //顯示所有聯(lián)系人信息 void SHOWcontict(contict* pc) { assert(pc); if (pc->sz == 0) { printf("聯(lián)系人列表為空\(chéng)n"); return; } printf("%-10s %-5s %-5s %-13s\n", "姓名", "年齡", "性別", "電話"); int i = 0; for (i = 0; i < pc->sz; i++) { printf("%-10s %-5d %-5s %-13s\n", pc->data[i].name, pc->data[i].age, pc->data[i].eax, pc->data[i].phone); } } //排序聯(lián)系人信息 //按照年齡排序 int con_age(const void* e1, const void* e2) { //升序 return ((information*)e1)->age - ((information*)e2)->age; //降序 //return ((information*)e2)->age - ((information*)e1)->age; } //按照姓名排序 int con_name(const void* e1, const void* e2) { //升序 return strcmp(((information*)e1)->name, ((information*)e2)->name); //降序 //return strcmp(((information*)e2)->name, ((information*)e1)->name); } void SQRTcontict(contict* pc) { assert(pc); if (pc->sz == 0) { printf("聯(lián)系人列表為空,無法排序\n"); return; } int n = 0; printf("*********************\n"); printf("*** 1、按年齡排序 ***\n"); printf("*** 2、按姓名排序 ***\n"); printf("*********************\n"); printf("請(qǐng)選擇排序方式-> "); scanf("%d", &n); if (n == 1) { qsort(pc->data, pc->sz, sizeof(information), con_age); printf("按照年齡排序成功\n"); } else if (n == 2) { qsort(pc->data, pc->sz, sizeof(information), con_name); printf("按照姓名排序成功\n"); } else { printf("選擇排序無效\n"); } } //清空通訊錄信息 void CLEARcontict(contict* pc) { assert(pc); free(pc->data); pc->data = NULL; //打開文件 FILE* pf = fopen("AddressBook.txt", "wb");//wb在打開文件的時(shí)候會(huì)覆蓋前面的內(nèi)容! if (pf == NULL) { perror("fopen"); return; } //啥都不寫入直接關(guān)閉文件! //關(guān)閉文件 fclose(pf); pf = NULL; init_contict(pc); printf("清空成功\n"); } //退出的時(shí)候釋放空間 void FREEcontict(contict* pc) { assert(pc); free(pc->data); pc->data = NULL; pc->sz = 0; pc->count = 0; } //退出的時(shí)候保存通訊錄聯(lián)系人信息 void SAVEcontictp(contict* pc) { assert(pc); //打開文件 FILE* pf = fopen("AddressBook.txt", "wb");//以二進(jìn)制的寫入形式打開 //判斷是否打開成功 if (pf == NULL) { perror("fopen"); return; } //開始寫數(shù)據(jù) int i = 0; for (i = 0; i < pc->sz; i++) { //一個(gè)一個(gè)的寫入數(shù)據(jù) fwrite(pc->data+i, sizeof(information),1, pf); } //關(guān)閉文件 fclose(pf); pf = NULL; printf("保存成功\n"); } //通訊錄 void Test(void) { //創(chuàng)建結(jié)構(gòu)體變量 contict con; //初始化通訊錄 init_contict(&con); int input = 0; do { //菜單 menu(); printf("請(qǐng)選擇-> "); scanf("%d", &input); switch (input) { case ADD: ADDcontict(&con);//添加聯(lián)系人 break; case DEL: DELcontict(&con);//刪除指定聯(lián)系人 break; case SEL: SELcontict(&con);//查詢指定聯(lián)系人 break; case MODIFY: MODIFYcontict(&con);//修改指定聯(lián)系人信息 break; case SHOW: SHOWcontict(&con);//顯示所有聯(lián)系人信息 break; case SQRT: SQRTcontict(&con);//排序聯(lián)系人 break; case CLEAR: CLEARcontict(&con);//清空通訊錄 break; case EXIT: SAVEcontictp(&con);//退出的時(shí)候保存通訊錄聯(lián)系人信息 FREEcontict(&con);//退出的時(shí)候釋放空間 printf("退出成功\n"); break; default: printf("選擇有誤請(qǐng)重新選擇-> \n"); break; } } while (input); } int main() { //測(cè)試通訊錄 Test(); return 0; }
以上就是基于C語言實(shí)現(xiàn)高級(jí)通訊錄的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于C語言高級(jí)通訊錄的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++基礎(chǔ)入門教程(一):基礎(chǔ)知識(shí)大雜燴
這篇文章主要介紹了C++基礎(chǔ)入門教程(一):基礎(chǔ)知識(shí)大雜燴,本文講解了注釋、頭文件、命名空間等內(nèi)容,需要的朋友可以參考下2014-11-11對(duì)一個(gè)數(shù)組進(jìn)行zig-zag重新排列
本文介紹了“對(duì)一個(gè)數(shù)組進(jìn)行zig-zag重新排列”,需要的朋友可以參考一下2013-03-03淺析棧區(qū)和堆區(qū)內(nèi)存分配的區(qū)別
以下是對(duì)棧區(qū)和堆區(qū)內(nèi)存分配的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-08-08C++應(yīng)用Eigen庫(kù)對(duì)應(yīng)實(shí)現(xiàn)matlab中部分函數(shù)問題
這篇文章主要介紹了C++應(yīng)用Eigen庫(kù)對(duì)應(yīng)實(shí)現(xiàn)matlab中部分函數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12C語言文件操作 fopen, fclose, mkdir詳解
本文給大家詳細(xì)介紹了下C語言的文件操作函數(shù)fopen, fclose, mkdir的用法及示例,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。2016-03-03C++ operator關(guān)鍵字(重載操作符)的用法詳解
下面小編就為大家?guī)硪黄狢++ operator關(guān)鍵字(重載操作符)的用法詳解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01C++實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01C語言驅(qū)動(dòng)開發(fā)之判斷自身是否加載成功詳解
在驅(qū)動(dòng)開發(fā)中我們有時(shí)需要得到驅(qū)動(dòng)自身是否被加載成功的狀態(tài),這個(gè)功能看似沒啥用實(shí)際上在某些特殊場(chǎng)景中還是需要的。本文將通過示例詳細(xì)講講這一功能的實(shí)現(xiàn)方法,需要的可以參考下2022-10-10