C語言之通訊錄的模擬實(shí)現(xiàn)代碼
在C語言學(xué)習(xí)結(jié)束之際,謹(jǐn)以此篇文章來對(duì)C語言的學(xué)習(xí)告一段落。
綱要:
- 通訊錄的靜態(tài)版本
- 通訊錄的動(dòng)態(tài)版本
- 通訊錄的帶文件版本
因?yàn)槿N實(shí)現(xiàn)方法除了儲(chǔ)存形式不同,其他都基本相同,所以我們重點(diǎn)論述靜態(tài)版本的實(shí)現(xiàn),以及它們不同的儲(chǔ)存方式。
一.通訊錄的靜態(tài)版本
為什么叫它為靜態(tài)版本呢,因?yàn)樵诖瞬糠值膬?chǔ)存是以數(shù)組來儲(chǔ)存的,那對(duì)于各種各樣的信息,我們要拿什么數(shù)組來存放它呢?當(dāng)然是結(jié)構(gòu)體數(shù)組了,所以我們來定義一個(gè)結(jié)構(gòu)體來表示個(gè)人信息:
//采用宏的目的是方便日后修改
#define NAME_MAX 20
#define SEX_MAX 5
#define PNUM_MAX 13
#define ADDR_MAX 20
#define MAX 10
//存放個(gè)人信息的結(jié)構(gòu)體
typedef struct Data
{
char name[NAME_MAX];//姓名
int age;//年齡
char sex[SEX_MAX];//性別
char pnum[PNUM_MAX];//電話
char addr[ADDR_MAX];//地址
} Data;
現(xiàn)在有了個(gè)人信息的結(jié)構(gòu)體,我們需要再來一個(gè)結(jié)構(gòu)體來存放它的數(shù)組及數(shù)組內(nèi)有效信息的個(gè)數(shù),即:
//存放MAX個(gè)個(gè)人信息的通訊錄
typedef struct Contact
{
Data data[MAX];
int size;
} Contact;
那么,準(zhǔn)備工作做好之后,我們就開始正式實(shí)現(xiàn)了,首先我們肯定是要先創(chuàng)建一個(gè)通訊錄,這時(shí)我們?cè)賮硐胍幌?,我們就這樣創(chuàng)建之后,我們是否可以直接使用呢?
對(duì)此我們來看一張圖片:

我們發(fā)現(xiàn),現(xiàn)在它里面都放著一些隨機(jī)值,所以我們需要將其初始化一下,來方便我們的使用:
void ContactInit(Contact *p)
{
//保證p不為NULL
assert(p);
//置零
memset(p->data, 0, sizeof(p->data));
p->size = 0;
}
我們?cè)賮砜匆幌陆Y(jié)果:

我們發(fā)現(xiàn),現(xiàn)在它內(nèi)部已經(jīng)被我們置為了0;接著我們做的就是添加聯(lián)系人了,不過在此之前,我們不妨先做一個(gè)菜單來顯示我們都有一些什么功能:
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");
}
接著是我們的幫助選項(xiàng):
//打印幫助信息
void ContactHelp(Contact *p)
{
printf("*******************************************\n");
printf("****** add ---- 添加聯(lián)系人信息 ******\n");
printf("****** del ---- 刪除聯(lián)系人信息 ******\n");
printf("****** search ---- 查找聯(lián)系人信息 ******\n");
printf("****** modify ---- 修改聯(lián)系人信息 ******\n");
printf("****** show ---- 展示聯(lián)系人信息 ******\n");
printf("****** help ---- 幫助信息 ******\n");
printf("****** sort ---- 排序聯(lián)系人信息 ******\n");
printf("****** exit ---- 退出通訊錄 ******\n");
printf("*******************************************\n");
}
以及我們來用枚舉來定義一些常量,方便在switch()結(jié)構(gòu)中 來辨別它走了哪條路線:
//枚舉來作為常量使得在看代碼時(shí)比較清晰
enum choice
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT,
HELP
};
以及寫出我們的選擇結(jié)構(gòu):我們采用do-while循環(huán)
void test()
{
Contact list;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
int input = 0;
do
{
menu();
printf("請(qǐng)輸入你的選擇:> ");
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);
}
這樣的好處是當(dāng)用戶輸入0時(shí)循環(huán)便自己停止,不用我們?cè)俅稳ヅ袛喈?dāng)用戶輸入0時(shí)我們要退出的問題,接下來我們就來填寫我們函數(shù)的內(nèi)容了:
1.添加聯(lián)系人
//添加聯(lián)系人
void ContactAdd(Contact *p)
{
//斷言保證p不為NULL
assert(p);
//如果聯(lián)系人容量已經(jīng)等于最大容量了
if(p->size==MAX)
{
printf("通訊錄已滿,請(qǐng)刪除一些后繼續(xù)添加!\n");
return ;
}
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[p->size] = person;
p->size++;
}

我們要是觀察到我們輸入的信息,最好就是把我們所輸入的信息給打印出來:
2.展示聯(lián)系人
//展示聯(lián)系人信息
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);
}
}
測(cè)試結(jié)果:


接下來就是刪除聯(lián)系人了
3.刪除聯(lián)系人
首先刪除聯(lián)系人肯定需要查找信息,又因?yàn)楹竺娴膸讉€(gè)函數(shù)也要用到它,所以我們單獨(dú)來寫一個(gè)查找模塊:
//查找模塊
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;//找到就返回下標(biāo)
}
}
return -1;//找不到就返回-1
}
刪除:
//刪除聯(lián)系人
void ContactDel(Contact *p)
{
assert(p);
char DelName[NAME_MAX] = {0};
printf("請(qǐng)輸入你要?jiǎng)h除的聯(lián)系人姓名:>");
scanf("%s", DelName);
int ret = ContactFind(p, DelName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
int j = 0;
for (j = ret; j < p->size; j++)
{
//從前往后依次挪動(dòng)覆蓋
p->data[j] = p->data[j + 1];
}
//刪除完成之后,聯(lián)系人個(gè)數(shù)減一
p->size--;
}
}



4.查找聯(lián)系人信息
//查找聯(lián)系人
void ContactSearch(Contact *p)
{
assert(p);
char SearchName[NAME_MAX];
printf("請(qǐng)輸入你要查找的聯(lián)系人姓名:>\n");
scanf("%s",SearchName);
//查找有無此人
int ret = ContactFind(p,SearchName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
printf("你所查找的聯(lián)系人信息為:\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.修改聯(lián)系人信息
//修改聯(lián)系人信息
void ContactModify(Contact *p)
{
assert(p);
char ModifyName[NAME_MAX];
printf("請(qǐng)輸入你要修改的聯(lián)系人姓名:>");
scanf("%s",ModifyName);
int ret = ContactFind(p,ModifyName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[ret] = person;
}
}


6.排序聯(lián)系人 --- 我們使用 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);
}
//排序聯(lián)系人
void ContactSort(Contact *p)
{
assert(p);
int choice;
sort_menu();
printf("請(qǐng)選擇排序的參考量:>");
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("輸入有誤,請(qǐng)檢查輸入!\n");
}
}


到這,我們的靜態(tài)通訊錄就完了,但是我們?nèi)钥蓪?duì)用戶操作優(yōu)化一下,如:及時(shí)的清屏等,以及暫停:
例:
do
{
menu();
printf("請(qǐng)輸入你的選擇:>");
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("非法輸入,請(qǐng)檢查輸入!\n");
system("pause");
system("cls");
break;
}
} while (input);
這樣我們的界面看起來就干凈多了,但是有沒有發(fā)現(xiàn),我們?yōu)榱诉_(dá)到這個(gè)效果,我們寫了很多重復(fù)的代碼!
那這樣我們應(yīng)該怎么辦呢 --- 還記得我們之前所提到的函數(shù)指針數(shù)組嗎?
void test2()
{
Contact list;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
//用一個(gè)函數(shù)指針數(shù)組來存放函數(shù)指針
void (*fun[])(Contact *) ={ContactExit,
ContactAdd,
ContactDel,
ContactSearch,
ContactModify,
ContactShow,
ContactSort,
ContactHelp};
int input = 0;//存放用戶選擇的信息
do{
menu();
printf("請(qǐng)輸入你的選擇:>");
scanf("%d", &input);
system("cls");
if(input>=0&&input<=sizeof(fun))
{
fun[input](p);
system("cls");
}
else
{
system("cls");
printf("輸入非法,請(qǐng)檢查輸入!\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
//存放個(gè)人信息的結(jié)構(gòu)體
typedef struct Data
{
char name[NAME_MAX];//姓名
int age;//年齡
char sex[SEX_MAX];//性別
char pnum[PNUM_MAX];//電話
char addr[ADDR_MAX];//地址
} Data;
//存放MAX個(gè)個(gè)人信息的通訊錄
typedef struct Contact
Data data[MAX];
int size;
} Contact;
//枚舉來作為常量使得在看代碼時(shí)比較清晰
enum choice
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT,
HELP
};
enum sort_by
NAME=1,
SEX,
AGE,
PNUM,
ADDR
//初始化通訊錄
void ContactInit(Contact *p);
//添加聯(lián)系人
void ContactAdd(Contact* p);
//刪除聯(lián)系人
void ContactDel(Contact* p);
//查找聯(lián)系人
void ContactSearch(Contact* p);
//修改聯(lián)系人信息
void ContactModify(Contact* p);
//展示聯(lián)系人信息
void ContactShow(Contact* p);
//排序聯(lián)系人
void ContactSort(Contact* p);
//打印幫助
void ContactHelp(Contact* p);
//退出通訊錄
void ContactExit(Contact* p);
#endif //CONTACT_CONTACT_H
Contact.c
#include "Contact.h"
// 強(qiáng)調(diào)?。?!
//調(diào)試請(qǐng)加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;//找到就返回下標(biāo)
}
}
return -1;//找不到就返回-1
}
void ContactInit(Contact *p)
{
//保證p不為NULL
assert(p);
//置零
memset(p->data, 0, sizeof(p->data));
p->size = 0;
}
//添加聯(lián)系人
void ContactAdd(Contact *p)
{
//斷言保證p不為NULL
assert(p);
//如果聯(lián)系人容量已經(jīng)等于最大容量了
if (p->size == MAX)
{
printf("通訊錄已滿,請(qǐng)刪除一些后繼續(xù)添加!\n");
return;
}
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[p->size] = person;
p->size++;
}
//刪除聯(lián)系人
void ContactDel(Contact *p)
{
assert(p);
char DelName[NAME_MAX] = {0};
printf("請(qǐng)輸入你要?jiǎng)h除的聯(lián)系人姓名:>");
scanf("%s", DelName);
int ret = ContactFind(p, DelName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
int j = 0;
for (j = ret; j < p->size; j++)
{
//從前往后依次挪動(dòng)覆蓋
p->data[j] = p->data[j + 1];
}
//刪除完成之后,聯(lián)系人個(gè)數(shù)減一
p->size--;
}
}
//查找聯(lián)系人
void ContactSearch(Contact *p)
{
assert(p);
char SearchName[NAME_MAX];
printf("請(qǐng)輸入你要查找的聯(lián)系人姓名:>");
scanf("%s", SearchName);
//查找有無此人
int ret = ContactFind(p, SearchName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
printf("你所查找的聯(lián)系人信息為:\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);
}
}
//修改聯(lián)系人信息
void ContactModify(Contact *p)
{
assert(p);
char ModifyName[NAME_MAX];
printf("請(qǐng)輸入你要修改的聯(lián)系人姓名:>");
scanf("%s", ModifyName);
int ret = ContactFind(p, ModifyName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[ret] = person;
}
}
//展示聯(lián)系人信息
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);
}
//排序聯(lián)系人
void ContactSort(Contact *p)
{
assert(p);
int choice;
sort_menu();
printf("請(qǐng)選擇排序的參考量:>");
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("輸入有誤,請(qǐng)檢查輸入!\n");
}
}
//打印幫助信息
void ContactHelp(Contact *p)
{
printf("*******************************************\n");
printf("****** add ---- 添加聯(lián)系人信息 ******\n");
printf("****** del ---- 刪除聯(lián)系人信息 ******\n");
printf("****** search ---- 查找聯(lián)系人信息 ******\n");
printf("****** modify ---- 修改聯(lián)系人信息 ******\n");
printf("****** show ---- 展示聯(lián)系人信息 ******\n");
printf("****** help ---- 幫助信息 ******\n");
printf("****** sort ---- 排序聯(lián)系人信息 ******\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;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
int input = 0;//存放用戶選擇的信息
do
{
menu();
printf("請(qǐng)輸入你的選擇:>");
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;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
//用一個(gè)函數(shù)指針數(shù)組來存放函數(shù)指針
void (*fun[])(Contact *) ={ContactExit,
ContactAdd,
ContactDel,
ContactSearch,
ContactModify,
ContactShow,
ContactSort,
ContactHelp};
int input = 0;//存放用戶選擇的信息
do{
menu();
printf("請(qǐng)輸入你的選擇:>");
scanf("%d", &input);
system("cls");
if(input>=0&&input<=sizeof(fun))
{
fun[input](p);
system("cls");
}
else
{
system("cls");
printf("輸入非法,請(qǐng)檢查輸入!\n");
}
}while(input);
}
int main()
{
//test();
test2();
return 0;
}
二.動(dòng)態(tài)通訊錄
動(dòng)態(tài)實(shí)現(xiàn)的問題主要在于它的容量不再是一變不變的,而是可隨著我們的數(shù)據(jù)量來變化的,所以在我們?cè)瓉矶x的Contact結(jié)構(gòu)體就要微微改變一下了:
typedef struct Contact
{
Data* data;//存放數(shù)據(jù)
int size;//有效數(shù)據(jù)的個(gè)數(shù)
int capacity;//容量的大小
} Contact;
初始化函數(shù)也要改改:
//初始化 --- 動(dòng)態(tài)
void ContactInit(Contact *p)
{
assert(p);
p->data=NULL;
p->size=0;
p->capacity=1;
}
那么這樣,添加函數(shù)也有一定的變化:
//檢查容量函數(shù)
void CheckCapacity(Contact *p)
{
assert(p);
//如果聯(lián)系人個(gè)數(shù)為0或與容量相同,就需要擴(kuò)容
if (p->size == 0 || p->size == p->capacity)
{
//動(dòng)態(tài)內(nèi)存開辟
Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2);
if (ptr == NULL)//開辟失敗
{
//報(bào)錯(cuò)
perror("CHECK CAPACITY ERROE !\n");
exit(-1);
}
//開辟成功,重新賦值
p->data = ptr;
//擴(kuò)容之后,容量也相應(yīng)擴(kuò)大
p->capacity *= 2;
}
//反之什么都不需要干
}
//添加聯(lián)系人 --- 動(dòng)態(tài)
void ContactAdd(Contact *p)
{
//斷言保證p不為NULL
assert(p);
//如果聯(lián)系人個(gè)數(shù)等于容量,或聯(lián)系人個(gè)數(shù)等于0,這時(shí)我們就需要擴(kuò)容了,我們來使用一個(gè)函數(shù)來干這事
CheckCapacity(p);
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[p->size] = person;
p->size++;
}
最后我們還要記得釋放我們開辟的內(nèi)存 --- 退出
//退出通訊錄 --- 動(dòng)態(tài)
void ContactExit(Contact *p)
{
//釋放我們開辟的內(nèi)存
free(p->data);
printf("exit !\n");
}
動(dòng)態(tài)通訊錄的修改就只有這些:
完整代碼展示:
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
//存放個(gè)人信息的結(jié)構(gòu)體
typedef struct Data
{
char name[NAME_MAX];//姓名
int age;//年齡
char sex[SEX_MAX];//性別
char pnum[PNUM_MAX];//電話
char addr[ADDR_MAX];//地址
} Data;
/*
//存放MAX個(gè)個(gè)人信息的通訊錄 --- 靜態(tài)
typedef struct Contact
{
Data data[MAX];
int size;
} Contact;
*/
//存放MAX個(gè)個(gè)人信息的通訊錄 --- 動(dòng)態(tài)
typedef struct Contact
{
Data* data;//存放數(shù)據(jù)
int size;//有效數(shù)據(jù)的個(gè)數(shù)
int capacity;//容量的大小
} Contact;
//枚舉來作為常量使得在看代碼時(shí)比較清晰
enum choice
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT,
HELP
};
enum sort_by
{
NAME=1,
SEX,
AGE,
PNUM,
ADDR
};
//初始化通訊錄
void ContactInit(Contact *p);
//添加聯(lián)系人
void ContactAdd(Contact* p);
//刪除聯(lián)系人
void ContactDel(Contact* p);
//查找聯(lián)系人
void ContactSearch(Contact* p);
//修改聯(lián)系人信息
void ContactModify(Contact* p);
//展示聯(lián)系人信息
void ContactShow(Contact* p);
//排序聯(lián)系人
void ContactSort(Contact* p);
//打印幫助
void ContactHelp(Contact* p);
//退出通訊錄
void ContactExit(Contact* p);
#endif //CONTACT_CONTACT_H
Contact.c
#include "Contact.h"
// 強(qiáng)調(diào)?。。?
//調(diào)試請(qǐng)加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;//找到就返回下標(biāo)
}
}
return -1;//找不到就返回-1
}
/*
//初始化 --- 靜態(tài)
void ContactInit(Contact *p)
{
//保證p不為NULL
assert(p);
//置零
memset(p->data, 0, sizeof(p->data));
p->size = 0;
}
*/
//初始化 --- 動(dòng)態(tài)
void ContactInit(Contact *p)
{
assert(p);
p->data = NULL;
p->size = 0;
p->capacity = 1;
}
/*//添加聯(lián)系人 --- 靜態(tài)
void ContactAdd(Contact *p)
{
//斷言保證p不為NULL
assert(p);
//如果聯(lián)系人容量已經(jīng)等于最大容量了
if (p->size == MAX)
{
printf("通訊錄已滿,請(qǐng)刪除一些后繼續(xù)添加!\n");
return;
}
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[p->size] = person;
p->size++;
}*/
//檢查容量函數(shù)
void CheckCapacity(Contact *p)
{
assert(p);
//如果聯(lián)系人個(gè)數(shù)為0或與容量相同,就需要擴(kuò)容
if (p->size == 0 || p->size == p->capacity)
{
//動(dòng)態(tài)內(nèi)存開辟
Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2);
if (ptr == NULL)//開辟失敗
{
//報(bào)錯(cuò)
perror("CHECK CAPACITY ERROE !\n");
exit(-1);
}
//開辟成功,重新賦值
p->data = ptr;
//擴(kuò)容之后,容量也相應(yīng)擴(kuò)大
p->capacity *= 2;
}
//反之什么都不需要干
}
//添加聯(lián)系人 --- 動(dòng)態(tài)
void ContactAdd(Contact *p)
{
//斷言保證p不為NULL
assert(p);
//如果聯(lián)系人個(gè)數(shù)等于容量,或聯(lián)系人個(gè)數(shù)等于0,這時(shí)我們就需要擴(kuò)容了,我們來使用一個(gè)函數(shù)來干這事
CheckCapacity(p);
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[p->size] = person;
p->size++;
}
//刪除聯(lián)系人
void ContactDel(Contact *p)
{
assert(p);
char DelName[NAME_MAX] = {0};
printf("請(qǐng)輸入你要?jiǎng)h除的聯(lián)系人姓名:>");
scanf("%s", DelName);
int ret = ContactFind(p, DelName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
int j = 0;
for (j = ret; j < p->size; j++)
{
//從前往后依次挪動(dòng)覆蓋
p->data[j] = p->data[j + 1];
}
//刪除完成之后,聯(lián)系人個(gè)數(shù)減一
p->size--;
}
}
//查找聯(lián)系人
void ContactSearch(Contact *p)
{
assert(p);
char SearchName[NAME_MAX];
printf("請(qǐng)輸入你要查找的聯(lián)系人姓名:>");
scanf("%s", SearchName);
//查找有無此人
int ret = ContactFind(p, SearchName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
printf("你所查找的聯(lián)系人信息為:\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);
}
}
//修改聯(lián)系人信息
void ContactModify(Contact *p)
{
assert(p);
char ModifyName[NAME_MAX];
printf("請(qǐng)輸入你要修改的聯(lián)系人姓名:>");
scanf("%s", ModifyName);
int ret = ContactFind(p, ModifyName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[ret] = person;
}
}
//展示聯(lián)系人信息
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);
}
//排序聯(lián)系人
void ContactSort(Contact *p)
{
assert(p);
int choice;
sort_menu();
printf("請(qǐng)選擇排序的參考量:>");
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("輸入有誤,請(qǐng)檢查輸入!\n");
}
}
//打印幫助信息
void ContactHelp(Contact *p)
{
printf("*******************************************\n");
printf("****** add ---- 添加聯(lián)系人信息 ******\n");
printf("****** del ---- 刪除聯(lián)系人信息 ******\n");
printf("****** search ---- 查找聯(lián)系人信息 ******\n");
printf("****** modify ---- 修改聯(lián)系人信息 ******\n");
printf("****** show ---- 展示聯(lián)系人信息 ******\n");
printf("****** help ---- 幫助信息 ******\n");
printf("****** sort ---- 排序聯(lián)系人信息 ******\n");
printf("****** exit ---- 退出通訊錄 ******\n");
printf("*******************************************\n");
}
/*//退出通訊錄
void ContactExit(Contact *p)
{
printf("exit !\n");
}*/
//退出通訊錄 --- 動(dòng)態(tài)
void ContactExit(Contact *p)
{
//釋放我們開辟的內(nèi)存
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;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
int input = 0;//存放用戶選擇的信息
do
{
menu();
printf("請(qǐng)輸入你的選擇:>");
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;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
//用一個(gè)函數(shù)指針數(shù)組來存放函數(shù)指針
void (*fun[])(Contact *) ={ContactExit,
ContactAdd,
ContactDel,
ContactSearch,
ContactModify,
ContactShow,
ContactSort,
ContactHelp};
int input = 0;//存放用戶選擇的信息
do{
menu();
printf("請(qǐng)輸入你的選擇:>");
scanf("%d", &input);
if(input>=0&&input<=sizeof(fun))
{
//system("cls");
fun[input](p);
}
else
{
system("cls");
printf("輸入非法,請(qǐng)檢查輸入!\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;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
int input = 0;//存放用戶選擇的信息
do
{
menu();
printf("請(qǐng)輸入你的選擇:>");
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;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
//用一個(gè)函數(shù)指針數(shù)組來存放函數(shù)指針
void (*fun[])(Contact *) ={ContactExit,
ContactAdd,
ContactDel,
ContactSearch,
ContactModify,
ContactShow,
ContactSort,
ContactHelp};
int input = 0;//存放用戶選擇的信息
do{
menu();
printf("請(qǐng)輸入你的選擇:>");
scanf("%d", &input);
if(input>=0&&input<=sizeof(fun))
{
//system("cls");
fun[input](p);
}
else
{
system("cls");
printf("輸入非法,請(qǐng)檢查輸入!\n");
}
}while(input);
}
int main()
{
//test();
test2();
return 0;
}
三.帶文件的動(dòng)態(tài)通訊錄
在這個(gè)里面,我們只需在初始化時(shí)進(jìn)行文件的讀取及關(guān)閉時(shí)文件的保存:
初始化:
//從文件載入信息
void Lodging(Contact *p)
{
assert(p);
//打開一文件
FILE *fp = fopen("../Contact.dat", "ab");//如果不存在就創(chuàng)建,存在就追加
if (fp == NULL)
{
perror("FILE: Ab");
exit(-1);
}
fclose(fp);//關(guān)閉文件,我們這一步只是為了確保文件存在
//打開一文件
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);//關(guān)閉文件
}
//初始化 --- 帶文件
void ContactInit(Contact *p)
{
assert(p);
p->data = NULL;
p->size = 0;
p->capacity = 1;
Lodging(p);
}
結(jié)束時(shí)保存:
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);
//釋放我們開辟的內(nèi)存
free(p->data);
printf("exit !\n");
}
除此之外,其他都與動(dòng)態(tài)通訊錄相同
完整代碼:
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
//存放個(gè)人信息的結(jié)構(gòu)體
typedef struct Data
{
char name[NAME_MAX];//姓名
int age;//年齡
char sex[SEX_MAX];//性別
char pnum[PNUM_MAX];//電話
char addr[ADDR_MAX];//地址
} Data;
/*
//存放MAX個(gè)個(gè)人信息的通訊錄 --- 靜態(tài)
typedef struct Contact
{
Data data[MAX];
int size;
} Contact;
*/
//存放MAX個(gè)個(gè)人信息的通訊錄 --- 動(dòng)態(tài)
typedef struct Contact
{
Data* data;//存放數(shù)據(jù)
int size;//有效數(shù)據(jù)的個(gè)數(shù)
int capacity;//容量的大小
} Contact;
//枚舉來作為常量使得在看代碼時(shí)比較清晰
enum choice
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT,
HELP
};
enum sort_by
{
NAME=1,
SEX,
AGE,
PNUM,
ADDR
};
//初始化通訊錄
void ContactInit(Contact *p);
//添加聯(lián)系人
void ContactAdd(Contact* p);
//刪除聯(lián)系人
void ContactDel(Contact* p);
//查找聯(lián)系人
void ContactSearch(Contact* p);
//修改聯(lián)系人信息
void ContactModify(Contact* p);
//展示聯(lián)系人信息
void ContactShow(Contact* p);
//排序聯(lián)系人
void ContactSort(Contact* p);
//打印幫助
void ContactHelp(Contact* p);
//退出通訊錄
void ContactExit(Contact* p);
//檢查容量函數(shù)
void CheckCapacity(Contact *p);
#endif //CONTACT_CONTACT_H
Contact.c
#include "Contact.h"
// 強(qiáng)調(diào)!??!
//調(diào)試請(qǐng)加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;//找到就返回下標(biāo)
}
}
return -1;//找不到就返回-1
}
/*
//初始化 --- 靜態(tài)
void ContactInit(Contact *p)
{
//保證p不為NULL
assert(p);
//置零
memset(p->data, 0, sizeof(p->data));
p->size = 0;
}
*/
/*
//初始化 --- 動(dòng)態(tài)
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");//如果不存在就創(chuàng)建,存在就追加
if (fp == NULL)
{
perror("FILE: Ab");
exit(-1);
}
fclose(fp);//關(guān)閉文件,我們這一步只是為了確保文件存在
//打開一文件
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);//關(guān)閉文件
}
//初始化 --- 帶文件
void ContactInit(Contact *p)
{
assert(p);
p->data = NULL;
p->size = 0;
p->capacity = 1;
Lodging(p);
}
/*//添加聯(lián)系人 --- 靜態(tài)
void ContactAdd(Contact *p)
{
//斷言保證p不為NULL
assert(p);
//如果聯(lián)系人容量已經(jīng)等于最大容量了
if (p->size == MAX)
{
printf("通訊錄已滿,請(qǐng)刪除一些后繼續(xù)添加!\n");
return;
}
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[p->size] = person;
p->size++;
}*/
//檢查容量函數(shù)
void CheckCapacity(Contact *p)
{
assert(p);
//如果聯(lián)系人個(gè)數(shù)為0或與容量相同,就需要擴(kuò)容
if (p->size == 0 || p->size == p->capacity)
{
//動(dòng)態(tài)內(nèi)存開辟
Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2);
if (ptr == NULL)//開辟失敗
{
//報(bào)錯(cuò)
perror("CHECK CAPACITY ERROE !\n");
exit(-1);
}
//開辟成功,重新賦值
p->data = ptr;
//擴(kuò)容之后,容量也相應(yīng)擴(kuò)大
p->capacity *= 2;
}
//反之什么都不需要干
}
//添加聯(lián)系人 --- 動(dòng)態(tài)
void ContactAdd(Contact *p)
{
//斷言保證p不為NULL
assert(p);
//如果聯(lián)系人個(gè)數(shù)等于容量,或聯(lián)系人個(gè)數(shù)等于0,這時(shí)我們就需要擴(kuò)容了,我們來使用一個(gè)函數(shù)來干這事
CheckCapacity(p);
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[p->size] = person;
p->size++;
}
//刪除聯(lián)系人
void ContactDel(Contact *p)
{
assert(p);
char DelName[NAME_MAX] = {0};
printf("請(qǐng)輸入你要?jiǎng)h除的聯(lián)系人姓名:>");
scanf("%s", DelName);
int ret = ContactFind(p, DelName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
int j = 0;
for (j = ret; j < p->size; j++)
{
//從前往后依次挪動(dòng)覆蓋
p->data[j] = p->data[j + 1];
}
//刪除完成之后,聯(lián)系人個(gè)數(shù)減一
p->size--;
}
}
//查找聯(lián)系人
void ContactSearch(Contact *p)
{
assert(p);
char SearchName[NAME_MAX];
printf("請(qǐng)輸入你要查找的聯(lián)系人姓名:>");
scanf("%s", SearchName);
//查找有無此人
int ret = ContactFind(p, SearchName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
printf("你所查找的聯(lián)系人信息為:\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);
}
}
//修改聯(lián)系人信息
void ContactModify(Contact *p)
{
assert(p);
char ModifyName[NAME_MAX];
printf("請(qǐng)輸入你要修改的聯(lián)系人姓名:>");
scanf("%s", ModifyName);
int ret = ContactFind(p, ModifyName);
if (ret == -1)
{
printf("通訊錄中并無此人,請(qǐng)重新檢查輸入!\n");
} else
{
Data person;//記錄聯(lián)系人信息
printf("請(qǐng)輸入聯(lián)系人的姓名:>");
scanf("%s", person.name);
printf("請(qǐng)輸入聯(lián)系人的年齡:>");
scanf("%d", &person.age);
printf("請(qǐng)輸入聯(lián)系人的性別:>");
scanf("%s", person.sex);
printf("請(qǐng)輸入聯(lián)系人的電話:>");
scanf("%s", person.pnum);
printf("請(qǐng)輸入聯(lián)系人的住址:>");
scanf("%s", person.addr);
//將聯(lián)系人信息存到通訊錄中
p->data[ret] = person;
}
}
//展示聯(lián)系人信息
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);
}
//排序聯(lián)系人
void ContactSort(Contact *p)
{
assert(p);
int choice;
sort_menu();
printf("請(qǐng)選擇排序的參考量:>");
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("輸入有誤,請(qǐng)檢查輸入!\n");
}
}
//打印幫助信息
void ContactHelp(Contact *p)
{
printf("*******************************************\n");
printf("****** add ---- 添加聯(lián)系人信息 ******\n");
printf("****** del ---- 刪除聯(lián)系人信息 ******\n");
printf("****** search ---- 查找聯(lián)系人信息 ******\n");
printf("****** modify ---- 修改聯(lián)系人信息 ******\n");
printf("****** show ---- 展示聯(lián)系人信息 ******\n");
printf("****** help ---- 幫助信息 ******\n");
printf("****** sort ---- 排序聯(lián)系人信息 ******\n");
printf("****** exit ---- 退出通訊錄 ******\n");
printf("*******************************************\n");
}
/*//退出通訊錄
void ContactExit(Contact *p)
{
printf("exit !\n");
}*/
/*
//退出通訊錄 --- 動(dòng)態(tài)
void ContactExit(Contact *p)
{
//釋放我們開辟的內(nèi)存
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);
//釋放我們開辟的內(nèi)存
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;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
int input = 0;//存放用戶選擇的信息
do
{
menu();
printf("請(qǐng)輸入你的選擇:>");
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;//定義一個(gè)通訊錄
Contact *p = &list;//賦址
//初始化
ContactInit(p);
//用一個(gè)函數(shù)指針數(shù)組來存放函數(shù)指針
void (*fun[])(Contact *) ={ContactExit,
ContactAdd,
ContactDel,
ContactSearch,
ContactModify,
ContactShow,
ContactSort,
ContactHelp};
int input = 0;//存放用戶選擇的信息
do{
menu();
printf("請(qǐng)輸入你的選擇:>");
scanf("%d", &input);
if(input>=0&&input<=sizeof(fun))
{
//system("cls");
fun[input](p);
}
else
{
system("cls");
printf("輸入非法,請(qǐng)檢查輸入!\n");
}
}while(input);
}
int main()
{
//test();
test2();
return 0;
}
到此這篇關(guān)于C語言之通訊錄的模擬實(shí)現(xiàn)代碼的文章就介紹到這了,更多相關(guān)C語言通訊錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c語言 數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)之字符串
這篇文章主要介紹了c語言 數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)之字符串的相關(guān)資料,需要的朋友可以參考下2017-05-05
C++找出字符串中出現(xiàn)最多的字符和次數(shù),時(shí)間復(fù)雜度小于O(n^2)
今天小編就為大家分享一篇關(guān)于C++找出字符串中出現(xiàn)最多的字符和次數(shù),時(shí)間復(fù)雜度小于O(n^2),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12
C++設(shè)計(jì)模式編程中Facade外觀模式的使用實(shí)例解析
這篇文章主要介紹了C++設(shè)計(jì)模式編程中Facade外觀模式的使用實(shí)例解析,外觀模式的主要用途就是為子系統(tǒng)的復(fù)雜處理過程提供方便的調(diào)用方法,需要的朋友可以參考下2016-03-03
C++11標(biāo)準(zhǔn)庫bind函數(shù)應(yīng)用教程
bind函數(shù)定義在頭文件functional中,可以將bind函數(shù)看做成一個(gè)通用的函數(shù)適配器,他接收一個(gè)可調(diào)用對(duì)象,生成一個(gè)新的可調(diào)用對(duì)象來"適應(yīng)"原對(duì)象的參數(shù)列表。本文將帶大家詳細(xì)了解一下bind函數(shù)的應(yīng)用詳解2021-12-12
c語言輸出字符串中最大對(duì)稱子串長(zhǎng)度的3種解決方案
這篇文章主要介紹了c語言輸出字符串中最大對(duì)稱子串長(zhǎng)度的3種解決方案,需要的朋友可以參考下2014-03-03
VSCode遠(yuǎn)程開發(fā)調(diào)試服務(wù)器c/c++代碼
語音相關(guān)的好多項(xiàng)目要在linux上跑,但代碼開發(fā)大多是在PC機(jī)上,本篇簡(jiǎn)單介紹一下怎么在個(gè)人電腦上用VSCode遠(yuǎn)程開發(fā)調(diào)試服務(wù)器上的c/c++代碼。感興趣的朋友跟隨小編一起看看吧2020-04-04
visual studio2019的安裝以及使用圖文步驟詳解
這篇文章主要介紹了visual studio2019的安裝以及使用圖文步驟詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03

