基于C語(yǔ)言實(shí)現(xiàn)高級(jí)通訊錄的示例代碼
前言
前面已經(jīng)寫了一篇簡(jiǎn)易版本通訊錄的實(shí)現(xiàn),下面再來(lái)寫一篇功能比較齊全的,可增容,增容空間可自己掌控,也可將數(shù)據(jù)保存起來(lái)的,又添加了清空列表等一些功能的高級(jí)通訊錄!
為何要實(shí)現(xiàn)高級(jí)通訊錄
對(duì)于簡(jiǎn)易版本的通訊錄來(lái)說(shuō),我們是直接指定了通訊錄的大小,通訊錄的空間是直接給死了,那么此時(shí)我們會(huì)發(fā)現(xiàn)兩個(gè)弊端:
第一個(gè)弊端:
假設(shè)我們所添加的聯(lián)系人的個(gè)數(shù),小于,我們給定通訊錄的大小,此時(shí)多余的空間就被浪費(fèi)掉了!又假設(shè)我們添加聯(lián)系人的大小,大于,給定通訊錄的大小,此時(shí)我們發(fā)現(xiàn)通訊錄的空間不夠我們來(lái)封裝聯(lián)系人信息了! 此時(shí)我們就得優(yōu)化通信錄給定空間上的問(wèn)題,不能再給其指定大小的空間,而是讓其空間有靈活性,此時(shí)我們以動(dòng)態(tài)增容的方式來(lái)給定通訊錄的空間,就很好的規(guī)避了這一問(wèn)題!
第二個(gè)弊端:
我們知道程序運(yùn)行起來(lái)我們輸入的數(shù)據(jù)都是保存在內(nèi)存上的,在簡(jiǎn)易版本中我們?cè)谶\(yùn)行通訊錄之后添加的數(shù)據(jù),在程序結(jié)束的時(shí)候都會(huì)被清除。當(dāng)?shù)诙芜\(yùn)行起來(lái)的時(shí)候,這些數(shù)據(jù)都已經(jīng)不存在了,而我們既然要保存聯(lián)系人的信息,就得做到數(shù)據(jù)持久化的保存,才能真正保存聯(lián)系人信息,要做到持久化我們就得將數(shù)據(jù)保存到硬盤中,也就是文件當(dāng)中,此時(shí)我們可以用文件操作的方式來(lái)實(shí)現(xiàn)持久化的保存聯(lián)系人信息,就很好的規(guī)避了這一問(wèn)題!
高級(jí)通訊錄實(shí)現(xiàn):
為了規(guī)避以上問(wèn)題,我們?cè)賮?lái)實(shí)現(xiàn)一個(gè)能增容能保存以及再完善一些功能的高級(jí)通訊錄!
創(chuàng)建通訊錄
我們先創(chuàng)建一個(gè)結(jié)構(gòu)體,用來(lái)封裝聯(lián)系人的:姓名、性別、年齡...等信息!再創(chuàng)建一個(gè)結(jié)構(gòu)體,用來(lái):操控聯(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語(yǔ)句來(lái)實(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語(yǔ)言里面給我們提供了動(dòng)態(tài)內(nèi)存開辟的函數(shù),我們按照這樣的思路來(lái)開辟空間,先開辟小一點(diǎn)的空間用,如果空間不夠用了我們?cè)僬{(diào)整空間,讓其變大!在初始化開辟空間的時(shí)候,我們使用calloc函數(shù)來(lái)申請(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);
//將原來(lái)存在的聯(lián)系人信息拿到通訊錄中
}實(shí)現(xiàn)加載功能
就是將文件中的聯(lián)系人的信息,加載到通訊錄中,以便后續(xù)操作,完整的實(shí)現(xiàn)了持久化保存功能,比如說(shuō):但我們第一次使用通訊錄的時(shí)候會(huì)添加聯(lián)系人的信息,在最后關(guān)閉的時(shí)候,這些信息會(huì)被保存到文件中,當(dāng)我們第二次再進(jìn)行操作的時(shí)候,就將這些保存在文件中的聯(lián)系人信息加載到通訊錄中,以供我們操作,也更完整的實(shí)現(xiàn)了保存功能!具體點(diǎn)說(shuō)就是對(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ù)要考慮增容問(wèn)題
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語(yǔ)言中,realloc函數(shù)(不懂可以看主要?jiǎng)討B(tài)內(nèi)存管理文章),可以調(diào)整申請(qǐng)好的動(dòng)態(tài)空間的大小,所以在實(shí)現(xiàn)增容這個(gè)功能的時(shí)候我們用,realloc函數(shù),來(lái)實(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)說(shuō)就是讓其后面的每個(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)系人列表為空 無(wú)法刪除\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ù)來(lái)封裝!
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)系人的信息打印出來(lái)即可!
具體實(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)系人列表為空,無(wú)法查詢\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)系人列表為空,無(wú)法修改\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)系人信息都打印出來(lái),我們只需要運(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)來(lái)分別實(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)系人列表為空,無(wú)法排序\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("選擇排序無(wú)效\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ù)要考慮增容問(wèn)題
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)系人列表為空 無(wú)法刪除\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)系人列表為空,無(wú)法查詢\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)系人列表為空,無(wú)法修改\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)系人列表為空,無(wú)法排序\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("選擇排序無(wú)效\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語(yǔ)言實(shí)現(xiàn)高級(jí)通訊錄的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言高級(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ì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下2013-08-08
C++應(yīng)用Eigen庫(kù)對(duì)應(yīng)實(shí)現(xiàn)matlab中部分函數(shù)問(wèn)題
這篇文章主要介紹了C++應(yīng)用Eigen庫(kù)對(duì)應(yīng)實(shí)現(xiàn)matlab中部分函數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
C語(yǔ)言文件操作 fopen, fclose, mkdir詳解
本文給大家詳細(xì)介紹了下C語(yǔ)言的文件操作函數(shù)fopen, fclose, mkdir的用法及示例,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。2016-03-03
C++ operator關(guān)鍵字(重載操作符)的用法詳解
下面小編就為大家?guī)?lái)一篇C++ operator關(guān)鍵字(重載操作符)的用法詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01
C++實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
C語(yǔ)言驅(qū)動(dòng)開發(fā)之判斷自身是否加載成功詳解
在驅(qū)動(dòng)開發(fā)中我們有時(shí)需要得到驅(qū)動(dòng)自身是否被加載成功的狀態(tài),這個(gè)功能看似沒(méi)啥用實(shí)際上在某些特殊場(chǎng)景中還是需要的。本文將通過(guò)示例詳細(xì)講講這一功能的實(shí)現(xiàn)方法,需要的可以參考下2022-10-10

