通讯录最主要的就是需要保存联系人的姓名,电话号码.所以定义联系人信息的结构体
// 联系人信息
typedef struct ContactInfo {
char name[1024];
char phone_number[1024];
} ContactInfo;
联系人有多少也不一定,所以用一个动态顺序表存储所有联系人
// 通讯录
typedef struct AddressBook {
ContactInfo *contact_info; // 存储联系人
int size; // 有效联系人个数
int cap; // 当前存储联系人的容量
} AddressBook;
主函数
int main() {
// 转移表
void(*pfunc[3])() = { AddContact, SearchContact, ClearAllContact };
Init(); // 初始化
while (1) {
system("cls");
Menu(); // 开始界面
int chiose;
// 联系人序号和其他操作序号
while (scanf("%d", &chiose) == 0 || chiose < 0 ||
(chiose >= g_address_book.size && chiose < 10000) ||
chiose > 10003) {
setbuf(stdin, NULL); // 清空缓冲区
printf("输入非法!请重输: ");
}
if (chiose == 10003) { // 退出
SaveContactInfo();
free(g_address_book.contact_info);
break;
}
else if ((chiose - 10000) >= 0) { // 功能
(*pfunc[chiose - 10000])();
}
else {
DetailInfo(chiose); // 联系人详细信息
}
}
system("pause");
return 0;
}
初始化
// 初始化
void Init() {
// 初始化联系人上限为64人
g_address_book.contact_info = (ContactInfo *)malloc(64 * sizeof(ContactInfo));
g_address_book.size = 0; // 有效联系人为空
g_address_book.cap = 64; // 上限为64
loadContactInfo(); // 加载已有的联系人
}
加载已有的联系人
// 加载联系人
void loadContactInfo() {
// 打开文件
FILE *fp = fopen("../contactinfo.txt", "r");
if (fp == NULL) { // 判空
printf("%s\n", strerror(errno));
system("pause");
return;
}
char buf[1024] = { 0 }; // 输入缓冲
while (fgets(buf,1024,fp) != NULL) {
if (g_address_book.size >= g_address_book.cap) { // 内存空间满了
// 重新申请内存空间
g_address_book.contact_info =
(ContactInfo *)realloc(g_address_book.contact_info, 2 * g_address_book.size * sizeof(ContactInfo));
// 修改容量
g_address_book.cap = 2 * g_address_book.size;
}
// 读入联系人信息
ContactInfo *info = &g_address_book.contact_info[g_address_book.size];
// fgets函数会将换行一并读取, 所以在此将换行去掉
// 读入姓名
strcpy(info->name, DelWrap(buf));
// 读入电话号码
if (fgets(buf, 1024, fp) != NULL) {
strcpy(info->phone_number, DelWrap(buf));
}
// 有效联系人增加
++g_address_book.size;
}
// 关闭文件
fclose(fp);
}
去掉换行符
// 去掉加载联系人是读入的换行符
char * DelWrap(char *str) {
if (str == NULL) {
return NULL;
}
// 用结束符覆盖换行符
int len = strlen(str);
str[len - 1] = str[len];
return str;
}
保存联系人到磁盘
// 保存联系人信息
void SaveContactInfo() {
// 打开文件
FILE *fp = fopen("../contactinfo.txt", "w");
if (fp == NULL) { // 判空
printf("%s\n", strerror(errno));
system("pause");
return;
}
// 将数据保存到文件中
for (int curr = 0; curr < g_address_book.size; ++curr) {
ContactInfo *info = &g_address_book.contact_info[curr];
// 使用格式化输出
fprintf(fp, "%s\n", info->name);
fprintf(fp, "%s\n", info->phone_number);
}
// 关闭文件
fclose(fp);
}
初始界面
// 通讯录界面
void Menu() {
printf("********************************\n");
printf("*********** 通 讯 录 ***********\n");
printf("********************************\n");
PrintAllContact(); // 打印全部联系人
printf("** 10000 :新建 ** 10001 :搜索 **\n");
printf("********************************\n");
printf("** 10002 :清空 ** 10003 :退出 **\n");
printf("********************************\n");
printf("请输入: ");
}
打印全部联系人
// 打印全部联系人
void PrintAllContact() {
printf(" 共 %d 个联系人\n", g_address_book.size);
// 遍历打印联系人
for (int curr = 0; curr < g_address_book.size; ++curr) {
ContactInfo *info = &g_address_book.contact_info[curr];
printf(" [%4d] %s\n", curr, info->name);
}
// 有联系人才输出
if (g_address_book.size != 0) {
printf("********************************\n");
printf("**** 输入序号以查看详细信息 ****\n");
}
printf("********************************\n");
}
查看联系人详细信息
// 根据序号查看联系人详细信息
void DetailInfo(int number) {
int(*pfunc[2])(int num) = { UpdateContactInfo, DeleteContact };
while (1) {
system("cls");
printf("********************************\n");
printf("******** 联系人详细信息 ********\n");
printf("********************************\n");
ContactInfo *info = &g_address_book.contact_info[number];
printf(" 姓名: %s\n", info->name);
printf(" 电话: %s\n", info->phone_number);
printf("********************************\n");
printf("** 10000 :修改 ** 10001 :删除 **\n");
printf("********************************\n");
printf("********* 10002 :退出 **********\n");
printf("********************************\n");
printf("请输入: ");
int chiose;
// 功能选项
while (scanf("%d", &chiose) == 0 || chiose < 10000 || chiose > 10002) {
setbuf(stdin, NULL); // 清空缓冲区
printf("输入非法!请重输: ");
}
// 返回上一级
if (chiose == 10002) {
break;
}
else if ((*pfunc[chiose - 10000])(number)) {
break; // 删除联系人后退出到主界面
}
}
}
修改联系人信息
// 修改联系人信息
int UpdateContactInfo(int number) {
system("cls");
printf("********************************\n");
printf("******** 修改联系人信息 ********\n");
printf("********************************\n");
printf("****** 输入 '/' 跳过该项 *******\n");
printf("********************************\n");
ContactInfo *info = &g_address_book.contact_info[number];
char tmp_info[1024] = { 0 };
setbuf(stdin, NULL); // 清空输入缓冲,以免读错
printf(" 姓名(%s): ", info->name);
gets(tmp_info);
if (tmp_info[0] != '/') {
strcpy(info->name, tmp_info);
}
printf(" 电话(%s): ", info->phone_number);
gets(tmp_info);
if (tmp_info[0] != '/') {
strcpy(info->phone_number, tmp_info);
}
printf("********************************\n");
printf("*********** 修改成功 ***********\n");
printf("********************************\n");
system("pause");
return 0;
}
删除联系人
// 删除联系人
int DeleteContact(int number) {
printf("********************************\n");
printf("****** 确定要删除该联系人 ******\n");
printf("********************************\n");
printf("****** / Y / ****** / N / ******\n");
printf("********************************\n");
printf("请输入: ");
setbuf(stdin, NULL);
char chiose = getchar();
setbuf(stdin, NULL); // 怕用户乱输,清空缓冲区
if (chiose == 'Y' || chiose == 'y') { // 大小写均可
// 无序
//g_address_book.contact_info[number] = g_address_book.contact_info[g_address_book.size - 1];
//--g_address_book.size;
// 有序
// 所有元素number之后的元素向前移动
ContactInfo *info = g_address_book.contact_info;
for (int curr = number; curr < g_address_book.size - 1; ++curr) {
info[curr] = info[curr + 1];
}
--g_address_book.size; // 有效联系人减少
printf("********************************\n");
printf("*********** 删除成功 ***********\n");
printf("********************************\n");
system("pause");
return 1;
}
return 0; // 取消删除,乱输都视为删除失败
}
新建联系人
// 新建联系人
void AddContact() {
system("cls");
// 联系人上限固定不能改
//if (g_address_book.size >= 1024) {
// printf("********************************\n");
// printf("******* 新增未能成功执行 *******\n");
// printf("********************************\n");
// system("pause");
// return;
//}
// 动态内存
if (g_address_book.size >= g_address_book.cap) { // 内存空间满了
// 重新申请内存空间
g_address_book.contact_info =
(ContactInfo *)realloc(g_address_book.contact_info, 2 * g_address_book.size * sizeof(ContactInfo));
// 修改容量
g_address_book.cap = 2 * g_address_book.size;
}
ContactInfo *info = &g_address_book.contact_info[g_address_book.size];
printf("********************************\n");
printf("********** 新建联系人 **********\n");
printf("********************************\n");
printf(" 姓名: ");
setbuf(stdin, NULL);
gets(info->name);
printf(" 电话: ");
gets(info->phone_number);
printf("********************************\n");
printf("*********** 新增成功 ***********\n");
printf("********************************\n");
++g_address_book.size; // 有效联系人增加
SortContact(); // 对新增的联系人进行插入排序
system("pause");
}
对联系人排序
// 对新增联系人排序
void SortContact() {
ContactInfo *info = g_address_book.contact_info;
ContactInfo tmp_info = info[g_address_book.size - 1]; // 最后一个元素
int curr = g_address_book.size - 1; // 最后一个元素位置
for (; curr > 0; --curr) {
if (strcmp(info[curr - 1].name, tmp_info.name) > 0) { // 前一个元素比待排序元素大
info[curr] = info[curr - 1]; // 前一个元素后移
}
else {
info[curr] = tmp_info; // 否则,待排序数就在当前位置
break; // 只排序最新的联系人
}
}
if (curr == 0) { // 循环结束,待排序元素比所有元素都小
info[curr] = tmp_info;
}
}
根据姓名查找联系人信息
// 搜索联系人
void SearchContact() {
if (g_address_book.size == 0) {
printf("********************************\n");
printf("********** 通讯录为空 **********\n");
printf("********************************\n");
system("pause");
return;
}
system("cls");
printf("********************************\n");
printf("********** 搜索联系人 **********\n");
printf("********************************\n");
printf("请输入姓名: ");
char name[1024] = { 0 };
scanf("%s", name);
printf("********************************\n");
int count = 0;
for (int curr = 0; curr < g_address_book.size; ++curr) { // 打印所有匹配姓名的信息
ContactInfo *info = &g_address_book.contact_info[curr];
if (strcmp(info->name, name) == 0) {
printf(" [%4d] %s\t%s\n", curr, info->name, info->phone_number);
++count;
}
}
printf(" 共找到 %d 个联系人\n", count);
if (count != 0) {
printf("********************************\n");
printf("**** 输入序号以查看详细信息 ****\n");
}
printf("********************************\n");
printf("********* 10000 :退出 **********\n");
printf("********************************\n");
printf("请输入: ");
int chiose;
while (scanf("%d", &chiose) == 0 || chiose < 0 ||
(chiose >= g_address_book.size && chiose != 10000)) {
setbuf(stdin, NULL); // 清空缓冲区
printf("输入非法!请重输: ");
}
if (chiose != 10000) {
DetailInfo(chiose); // 联系人详细信息
}
return;
}
清空所有联系人
// 清空联系人
void ClearAllContact() {
if (g_address_book.size == 0) {
printf("********************************\n");
printf("********** 通讯录为空 **********\n");
printf("********************************\n");
system("pause");
return;
}
printf("********************************\n");
printf("******* 确定要清空联系人 *******\n");
printf("********************************\n");
printf("****** / Y / ****** / N / ******\n");
printf("********************************\n");
printf("请输入: ");
setbuf(stdin, NULL); // 怕用户乱输,清空缓冲区
char chiose = getchar();
if (chiose == 'Y' || chiose == 'y') { // 大小写均可
g_address_book.size = 0;
printf("********************************\n");
printf("*********** 清空成功 ***********\n");
printf("********************************\n");
system("pause");
}
// 取消,乱输都视为失败
}