基于C語言實(shí)現(xiàn)高級通訊錄的示例代碼
前言
前面已經(jīng)寫了一篇簡易版本通訊錄的實(shí)現(xiàn),下面再來寫一篇功能比較齊全的,可增容,增容空間可自己掌控,也可將數(shù)據(jù)保存起來的,又添加了清空列表等一些功能的高級通訊錄!
為何要實(shí)現(xiàn)高級通訊錄
對于簡易版本的通訊錄來說,我們是直接指定了通訊錄的大小,通訊錄的空間是直接給死了,那么此時我們會發(fā)現(xiàn)兩個弊端:
第一個弊端:
假設(shè)我們所添加的聯(lián)系人的個數(shù),小于,我們給定通訊錄的大小,此時多余的空間就被浪費(fèi)掉了!又假設(shè)我們添加聯(lián)系人的大小,大于,給定通訊錄的大小,此時我們發(fā)現(xiàn)通訊錄的空間不夠我們來封裝聯(lián)系人信息了! 此時我們就得優(yōu)化通信錄給定空間上的問題,不能再給其指定大小的空間,而是讓其空間有靈活性,此時我們以動態(tài)增容的方式來給定通訊錄的空間,就很好的規(guī)避了這一問題!
第二個弊端:
我們知道程序運(yùn)行起來我們輸入的數(shù)據(jù)都是保存在內(nèi)存上的,在簡易版本中我們在運(yùn)行通訊錄之后添加的數(shù)據(jù),在程序結(jié)束的時候都會被清除。當(dāng)?shù)诙芜\(yùn)行起來的時候,這些數(shù)據(jù)都已經(jīng)不存在了,而我們既然要保存聯(lián)系人的信息,就得做到數(shù)據(jù)持久化的保存,才能真正保存聯(lián)系人信息,要做到持久化我們就得將數(shù)據(jù)保存到硬盤中,也就是文件當(dāng)中,此時我們可以用文件操作的方式來實(shí)現(xiàn)持久化的保存聯(lián)系人信息,就很好的規(guī)避了這一問題!
高級通訊錄實(shí)現(xiàn):
為了規(guī)避以上問題,我們再來實(shí)現(xiàn)一個能增容能保存以及再完善一些功能的高級通訊錄!
創(chuàng)建通訊錄
我們先創(chuàng)建一個結(jié)構(gòu)體,用來封裝聯(lián)系人的:姓名、性別、年齡...等信息!再創(chuàng)建一個結(jié)構(gòu)體,用來:操控聯(lián)系人信息、記錄聯(lián)系人個數(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)系人個數(shù)
int count;//增容的數(shù)量
}contict;打印菜單
我們要創(chuàng)建一個菜單供用戶選擇,讓用戶選擇操作的功能,此時我們用do while循環(huán)里面嵌套Switch case語句來實(shí)現(xiàn)用戶對功能的選擇以及菜單的顯示!,
具體看代碼:
//定義所用到的常量
//因為常量太多用枚舉類型一次性定義
//讓這些常量代替我們對功能的選擇
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("請選擇-> ");
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);//退出的時候保存通訊錄聯(lián)系人信息
FREEcontict(&con);//退出的時候釋放空間
printf("退出成功\n");
break;
default:
printf("選擇有誤請重新選擇-> \n");
break;
}
} while (input);
return 0;
}先大致了解一下邏輯,而代碼里面的函數(shù)功能,我們下面一一實(shí)現(xiàn)與介紹!
初始化通訊錄
因為是動態(tài)增容版本,我們在初始化的時候空間是由我們自行開辟的,而C語言里面給我們提供了動態(tài)內(nèi)存開辟的函數(shù),我們按照這樣的思路來開辟空間,先開辟小一點(diǎn)的空間用,如果空間不夠用了我們再調(diào)整空間,讓其變大!在初始化開辟空間的時候,我們使用calloc函數(shù)來申請空間,因為calloc函數(shù)在動態(tài)空間申請的時候會將空間中的每個字節(jié)的內(nèi)容都初始化為0,然后我們再將記錄聯(lián)系人的個數(shù)的變量初始化為0,再將記錄空間數(shù)量的變量初始化為我們所開辟的聯(lián)系人空間的個數(shù)!
因為是能保存聯(lián)系人信息的通訊錄,為了用戶的后續(xù)使用和關(guān)閉,所以在初始化的時候,還得要調(diào)用一個功能,就是將保存在文件中的聯(lián)系人的信息讀到我們動態(tài)申請的空間中,隨后繼續(xù)進(jìn)行操作,通俗點(diǎn)將就是將已經(jīng)存在的聯(lián)系人的信息拿到通訊錄里面!這個功能就是加載功能!
具體看代碼實(shí)現(xiàn):
//初始化通訊錄
#define IN 3
void init_contict(contict* pc)
{
assert(pc);
//calloc函數(shù)在開辟空間的時候會將每個字節(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)了持久化保存功能,比如說:但我們第一次使用通訊錄的時候會添加聯(lián)系人的信息,在最后關(guān)閉的時候,這些信息會被保存到文件中,當(dāng)我們第二次再進(jìn)行操作的時候,就將這些保存在文件中的聯(lián)系人信息加載到通訊錄中,以供我們操作,也更完整的實(shí)現(xiàn)了保存功能!具體點(diǎn)說就是對保存聯(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í)很簡單,我們直接在通訊錄里面寫入值就行了,每寫入一個讓記錄聯(lián)系人個數(shù)的變量+1,再判斷一下空間的容量夠不夠是否需要增容?。ㄎ覀儗⒃鋈莘庋b成一個函數(shù),直接調(diào)用一下就行),增容的同時讓記錄空間的變量同樣變成增容之后空間的個數(shù)!
具體實(shí)現(xiàn)看代碼:
//添加聯(lián)系人
void ADDcontict(contict* pc)
{
assert(pc);
//判斷是否要增容
Enhancement(pc);//增容功能后續(xù)實(shí)現(xiàn)
printf("請輸入姓名-> ");
scanf("%s", pc->data[pc->sz].name);
printf("清輸入年齡-> ");
scanf("%d", &(pc->data[pc->sz].age));
printf("請輸入性別-> ");
scanf("%s", pc->data[pc->sz].eax);
printf("請輸入電話-> ");
scanf("%s", pc->data[pc->sz].phone);
pc->sz++;
printf("添加成功\n");
}實(shí)現(xiàn)增容功能
在添加聯(lián)系以及后面我們從文件中讀取聯(lián)系人信息的時候,我們都可能遇到實(shí)現(xiàn)申請好的空間不夠用的情況,此時我們就要進(jìn)行調(diào)整空間的大小,讓空間變大也就是增容,我們知道C語言中,realloc函數(shù)(不懂可以看主要動態(tài)內(nèi)存管理文章),可以調(diào)整申請好的動態(tài)空間的大小,所以在實(shí)現(xiàn)增容這個功能的時候我們用,realloc函數(shù),來實(shí)現(xiàn)增容空間的功能!增容的同時我們也讓記錄空間個數(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í)很簡單,就是將要刪除的聯(lián)系人的信息,被其后面的聯(lián)系人覆蓋掉,以此類推從后往前一直覆蓋直到聯(lián)系人全部遍歷完,通俗點(diǎ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 DELcontict(contict* pc)
{
assert(pc);
//判斷聯(lián)系人列表是否為空
if (pc->sz == 0)
{
printf("聯(lián)系人列表為空 無法刪除\n");
return;
}
char name[NAME_SIZE];
printf("請輸入要刪除聯(lián)系人的姓名-> ");
scanf("%s", name);
//判斷該聯(lián)系人是否存在
int flag = There(name, pc);//因為后續(xù)功能都要用到這一步,用一個函數(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)系人就很簡單了,就只是找到該聯(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("請輸入要查詢聯(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)系人一個思路,就是找到該聯(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("請輸入要修改聯(lián)系人的姓名-> ");
scanf("%s", name);
//判斷該聯(lián)系人是否存在
int flag = There(name, pc);
if (flag == -1)
{
printf("該聯(lián)系人不存在\n");
return;
}
printf("請輸入姓名-> ");
scanf("%s", pc->data[flag].name);
printf("清輸入年齡-> ");
scanf("%d", &(pc->data[flag].age));
printf("請輸入性別-> ");
scanf("%s", pc->data[flag].eax);
printf("請輸入電話-> ");
scanf("%s", pc->data[flag].phone);
printf("修改成功\n");
}實(shí)現(xiàn)查詢所有聯(lián)系人功能
查詢所有聯(lián)系人信息,就是將所有聯(lián)系人信息都打印出來,我們只需要運(yùn)用一個for遍歷聯(lián)系人列表即可!
具體實(shí)現(xiàn)看代碼:
//顯示所有聯(lián)系人信息
void SHOWcontict(contict* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("聯(lián)系人列表為空\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)排序功能
在排序的時候我們,給定兩種排序方法:按照年齡排序、按照姓名排序 供用戶選擇。用qsort函數(shù)(不了解的可以看主頁指針進(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("請選擇排序方式-> ");
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)系人信息,就只需要將我們通訊錄申請的空間釋放掉,隨后再以讀的形式打開一下文件,打開之后什么都不干,讀的形式會將文件的內(nèi)容都覆蓋掉,會自動清空文件里的內(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在打開文件的時候會覆蓋前面的內(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)行文件操作(不懂看主頁文件操作文章有詳細(xì)講解),只需要將每個聯(lián)系人的信息寫入文件中即可!
具體實(shí)現(xiàn)看代碼:
//退出的時候保存通訊錄聯(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++)
{
//一個一個的寫入數(shù)據(jù)
fwrite(pc->data+i, sizeof(information),1, pf);
}
//關(guān)閉文件
fclose(pf);
pf = NULL;
printf("保存成功\n");
}實(shí)現(xiàn)退出功能
在退出的時候,先將通訊錄里面聯(lián)系人的信息,保存到文件中,隨后再將動態(tài)開辟的通訊錄的空間釋放就行,隨后將指針置為NULL,避免野指針。注意:先保存再釋放二者順序不可亂,不然會出錯!
具體實(shí)現(xiàn)看代碼:
//退出的時候釋放空間
void FREEcontict(contict* pc)
{
assert(pc);
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->count = 0;
}通訊錄總代碼
//動態(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)系人個數(shù)
int count;//增容的數(shù)量
}contict;
//定義所用到的常量
//因為常量太多用枚舉類型一次性定義
//讓這些常量代替我們對功能的選擇
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ù)在開辟空間的時候會將每個字節(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);
//先不用管這個功能后續(xù)會慢慢了解
//主要了解上面初始化的代碼!
}
//添加聯(lián)系人
void ADDcontict(contict* pc)
{
assert(pc);
//判斷是否要增容
Enhancement(pc);
printf("請輸入姓名-> ");
scanf("%s", pc->data[pc->sz].name);
printf("清輸入年齡-> ");
scanf("%d", &(pc->data[pc->sz].age));
printf("請輸入性別-> ");
scanf("%s", pc->data[pc->sz].eax);
printf("請輸入電話-> ");
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("請輸入要刪除聯(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("請輸入要查詢聯(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("請輸入要修改聯(lián)系人的姓名-> ");
scanf("%s", name);
//判斷該聯(lián)系人是否存在
int flag = There(name, pc);
if (flag == -1)
{
printf("該聯(lián)系人不存在\n");
return;
}
printf("請輸入姓名-> ");
scanf("%s", pc->data[flag].name);
printf("清輸入年齡-> ");
scanf("%d", &(pc->data[flag].age));
printf("請輸入性別-> ");
scanf("%s", pc->data[flag].eax);
printf("請輸入電話-> ");
scanf("%s", pc->data[flag].phone);
printf("修改成功\n");
}
//顯示所有聯(lián)系人信息
void SHOWcontict(contict* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("聯(lián)系人列表為空\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("請選擇排序方式-> ");
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在打開文件的時候會覆蓋前面的內(nèi)容!
if (pf == NULL)
{
perror("fopen");
return;
}
//啥都不寫入直接關(guān)閉文件!
//關(guān)閉文件
fclose(pf);
pf = NULL;
init_contict(pc);
printf("清空成功\n");
}
//退出的時候釋放空間
void FREEcontict(contict* pc)
{
assert(pc);
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->count = 0;
}
//退出的時候保存通訊錄聯(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++)
{
//一個一個的寫入數(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("請選擇-> ");
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);//退出的時候保存通訊錄聯(lián)系人信息
FREEcontict(&con);//退出的時候釋放空間
printf("退出成功\n");
break;
default:
printf("選擇有誤請重新選擇-> \n");
break;
}
} while (input);
}
int main()
{
//測試通訊錄
Test();
return 0;
}以上就是基于C語言實(shí)現(xiàn)高級通訊錄的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于C語言高級通訊錄的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
VScode配置C++運(yùn)行環(huán)境的完整步驟
這篇文章主要給大家介紹了關(guān)于VScode配置C++運(yùn)行環(huán)境的完整步驟,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
C語言字符串函數(shù)操作(strlen,strcpy,strcat,strcmp)詳解
大家好,本篇文章主要講的是C語言字符串函數(shù)操作(strlen,strcpy,strcat,strcmp)詳解,感興趣的同學(xué)趕快來看一看吧2021-12-12
C++實(shí)現(xiàn)簡單學(xué)生成績管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡單學(xué)生成績管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
C++實(shí)現(xiàn)高校人員信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)高校人員信息管理系統(tǒng)項,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-06-06
Qt6實(shí)現(xiàn)調(diào)用攝像頭并顯示畫面
這篇文章主要為大家詳細(xì)介紹了Qt6如何實(shí)現(xiàn)調(diào)用攝像頭并顯示畫面的效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的可以參考一下2023-02-02

