目录
一、通讯录的实现(静态版)
1.1文件的创建
1.2通讯录要存放的信息
1.3通讯录的功能
1.4通讯录的创建
1.5菜单打印以及基本逻辑的实现
1.6初始化通讯录
1.7增加联系人
1.8显示联系人
1.9删除联系人
1.10查找联系人
1.11修改联系人
1.12按名字排序
1.13完整代码
二、通讯录的实现(动态版)
2.1通讯录的创建
2.2初始化通讯录
2.3增加联系人
2.4完整代码
前言:这篇文章博主带着大家一步一步实现通讯录,让你不在是“文”盲。
test.c 测试通讯录
contcat.h 函数和类型的声明
contcat.c 函数的实现
在实现通讯录的程序中,我们使用多文件编程,真是为什么呢?
1.方便代码复用:模块化的代码可以很方便的迁移到其他项目中。
2.方便分工合作:各个功能模块分成多个文件同时编辑,可以有效地提高团队分工合作的效率
3.便于后续维护:当程序出现错误时,可以分模块进行排查,可以提高效率,使程序更加容易管理
头文件的作用
我们可以将函数、数据的声明,宏的定义,库函数所用到的头文件放在一起,在源文件中只要引用
#include “contact.h”就可以实现,这样可以减少代码的重复编写,提高效率。
我们要是一个可以存放100个人信息的通讯录
创建一个结构体,结构体中放我们要存的信息,姓名、年龄、性别、电话号、住址。
typedef struct PeoInfo
{
char name[10];
int age;
char sex[5];
char tele[12];
char addr[15];
}PeoInfo;
1.增加联系人 2.删除联系人
3.查找联系人 4.修改联系人
5.显示所有联系人 6.对联系人排序
PeoInfo date[100];
int sz = 0;
我们创建好可以存放100个人的通讯录后,还要创建一个变量sz来记录通讯录中存放的人数,所以这两个变量要绑定在一起。我们在创建一个结构体,这样在传参时会更方便。
typedef struct Contact
{
PeoInfo date[100];
int sz;
}Contact;
#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(" 0. Exit \n");
printf("------------------------------------\n");
}
void test()
{
int input = 0;
Contact con; //通讯录
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 0:
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
在case语句里,别人使用我们的代码并不知道1,2,3……代表的是什么功能,所以我们可以使用枚举,让使用者了解我们的功能,提高代码可读性
优化代码:
enum OPTION
{
Exit,
Add,
Del,
Serach,
Modify,
Show,
Sort
};
case Add:
break;
case Del:
break;
case Serach:
break;
case Modify:
break;
case Show:
break;
case Sort:
break;
case Exit:
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
初始化通讯录,我们要改变里面的内容,所以我们要传指针过去。注意要在头文件中对函数声明。
void InitContact(Contact* pc)
{
memset(pc->date, 0, sizeof(pc->date));
pc->sz = 0;
}
我们要考虑通讯录有没有满,如果没有满添加的联系人放到下标sz的地方。我们要使用pc指针,所以用assert断言指针是否有效。
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == MAX)
{
printf("通讯录已满,无法添加\n");
return;
}
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].name));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
我们只是显示联系人的数据,不会修改通讯录中的内容,所以在声明时用const修饰:
void ShowContact(const Contact* pc);
void ShowContact(const Contact* pc)
{
assert(pc);
//打印标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
int i = 0;
for (i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
注意:有 ‘ - ’ 是左对齐,没有 ‘ - ’ 是右对齐。
我们要考虑通信录中是否存在要删除的联系人,所以我们定义一个flag标签。
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
}
char name[20] = { 0 };
int del = 0;
int flag = 0;
printf("要删除的联系人:>");
scanf("%s", name);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
del = i;
flag = 1;
break;
}
}
if (flag == 0)
{
printf("要删除的联系人不存在\n");
return;
}
for (i = del; i < pc->sz - 1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->sz--;
printf("成功删除联系人\n");
}
在删除,查找,修改的功能中都有查找的程序,所以我们可以把查找的功能封装成一个函数,更加方便 。
优化代码:
int FindByname(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
}
char name[20] = { 0 };
int flag = 0;
printf("要删除的联系人:>");
scanf("%s", name);
int del = FindByname(pc, name);
if (del == -1)
{
printf("要删除的联系人不存在\n");
return;
}
int i = 0;
for (i = del; i < pc->sz - 1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->sz--;
printf("成功删除联系人\n");
}
使用上面封装好的查找的函数,如果我们要查找的人存在,就把信息打印在屏幕上。
void SearchContact(const Contact* pc)
{
assert(pc);
char name[20] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[pos].name,
pc->date[pos].age,
pc->date[pos].sex,
pc->date[pos].tele,
pc->date[pos].addr);
}
}
使用上面封装好的查找的函数,要修改的人存在就重新录入它的信息。
void ModifyContact(Contact* pc)
{
assert(pc);
char name[20] = { 0 };
printf("请输入要修改的人的名字:>");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->date[pos].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pos].age));
printf("请输入性别:>");
scanf("%s", pc->date[pos].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pos].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pos].addr);
}
printf("修改成功\n");
}
case Sort:
//按名字排序
qsort(con.date, con.sz, sizeof(PeoInfo), cmp_by_name);
break;
int cmp_by_name(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
contact.h
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#define MAX 100
typedef struct PeoInfo
{
char name[20];
int age;
char sex[5];
char tele[12];
char addr[15];
}PeoInfo;
typedef struct Contact
{
PeoInfo date[MAX];
int sz;
}Contact;
enum OPTION
{
Exit,
Add,
Del,
Serach,
Modify,
Show,
Sort
};
//函数声明
//初始化
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示联系人
void ShowContact(const Contact* pc);
//删除联系人
void DelContact(Contact* pc);
//查找联系人
void SearchContact(const Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//排序
int cmp_by_name(const void* p1, const void* p2);
test.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(" 0. Exit \n");
printf("------------------------------------\n");
}
void test()
{
int input = 0;
Contact con; //通讯录
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case Add:
AddContact(&con);
break;
case Del:
DelContact(&con);
break;
case Serach:
SearchContact(&con);
break;
case Modify:
ModifyContact(&con);
break;
case Show:
ShowContact(&con);
break;
case Sort:
//按名字排序
qsort(con.date, con.sz, sizeof(PeoInfo), cmp_by_name);
break;
case Exit:
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
contact.c
#include "contact.h"
void InitContact(Contact* pc)
{
memset(pc->date, 0, sizeof(pc->date));
pc->sz = 0;
}
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == MAX)
{
printf("通讯录已满,无法添加\n");
return;
}
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
void ShowContact(const Contact* pc)
{
assert(pc);
//打印标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
int i = 0;
for (i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
int FindByname(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
}
char name[20] = { 0 };
int flag = 0;
printf("要删除的联系人:>");
scanf("%s", name);
/*int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
del = i;
flag = 1;
break;
}
}
if (flag == 0)
{
printf("要删除的联系人不存在\n");
return;
}*/
int del = FindByname(pc, name);
if (del == -1)
{
printf("要删除的联系人不存在\n");
return;
}
int i = 0;
for (i = del; i < pc->sz - 1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->sz--;
printf("成功删除联系人\n");
}
void SearchContact(const Contact* pc)
{
assert(pc);
char name[20] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[pos].name,
pc->date[pos].age,
pc->date[pos].sex,
pc->date[pos].tele,
pc->date[pos].addr);
}
}
void ModifyContact(Contact* pc)
{
assert(pc);
char name[20] = { 0 };
printf("请输入要修改的人的名字:>");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->date[pos].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pos].age));
printf("请输入性别:>");
scanf("%s", pc->date[pos].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pos].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pos].addr);
}
printf("修改成功\n");
}
int cmp_by_name(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
改造的目标:
1.通讯录的大小不是固定的,大小是可以调整的。
2.默认初始能放三个人的信息,如果不够,每次增加两个人的信息。
动态版本就不用数组来创建,使用malloc函数创建空间。还需要一个变量来存储我们通讯录的最大容量,当存储的信息到达最大容量,我们可以增容。
typedef struct Contact
{
PeoInfo* date; //指向存放数据的空间
int sz; //当前通讯录存储的信息的个数
int cap; //通讯录当前最大容量
}Contact;
使用动态内存函数要引用头文件
#include
我们初始为开始可以存放三个人的信息。
void InitContact(Contact* pc)
{
assert(pc);
pc->date = (PeoInfo*)malloc(3 * sizeof(PeoInfo));
if (pc->date == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->cap = DEFAULT_SZ;
}
在动态版本中不存在填满的情况,我们要判断增容。在填满的情况下,每次增加两个。我们使用的初始容量和要增加的量可以使用define定义。
#define DEFAULT_SZ 3
#define INC_SZ 2
如果增容成功或不需要增容,返回1,增加联系人;如果增容失败,返回0。
int CheckCapacity(Contact* pc)
{
if (pc->sz == pc->cap)
{
PeoInfo* ptr=(PeoInfo*)realloc(pc->date, (pc->cap + INC_SZ) * sizeof(PeoInfo));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;
}
else
{
pc->date = ptr;
pc->cap += INC_SZ;
printf("增容成功\n");
return 1;
}
}
return 1;
}
void AddContact(Contact* pc)
{
assert(pc);
if (0 == CheckCapacity(pc))
{
return;
}
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
contact,h
#include
#include
#include
#include
#define MAX 100
#define DEFAULT_SZ 3
#define INC_SZ 2
typedef struct PeoInfo
{
char name[20];
int age;
char sex[5];
char tele[12];
char addr[15];
}PeoInfo;
typedef struct Contact
{
PeoInfo* date; //指向存放数据的空间
int sz; //当前通讯录存储的信息的个数
int cap; //通讯录当前最大容量
}Contact;
enum OPTION
{
Exit,
Add,
Del,
Serach,
Modify,
Show,
Sort
};
//函数声明
//初始化
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示联系人
void ShowContact(const Contact* pc);
//删除联系人
void DelContact(Contact* pc);
//查找联系人
void SearchContact(const Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//排序
int cmp_by_name(const void* p1, const void* p2);
//释放
void DestoryContact(Contact* pc);
test.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(" 0. Exit \n");
printf("------------------------------------\n");
}
void test()
{
int input = 0;
Contact con; //通讯录
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case Add:
AddContact(&con);
break;
case Del:
DelContact(&con);
break;
case Serach:
SearchContact(&con);
break;
case Modify:
ModifyContact(&con);
break;
case Show:
ShowContact(&con);
break;
case Sort:
//按名字排序
qsort(con.date, con.sz, sizeof(PeoInfo), cmp_by_name);
break;
case Exit:
DestoryContact(&con);
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
contact.c
#include "contact.h"
void InitContact(Contact* pc)
{
assert(pc);
pc->date = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
if (pc->date == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->cap = DEFAULT_SZ;
}
int CheckCapacity(Contact* pc)
{
if (pc->sz == pc->cap)
{
PeoInfo* ptr=(PeoInfo*)realloc(pc->date, (pc->cap + INC_SZ) * sizeof(PeoInfo));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;
}
else
{
pc->date = ptr;
pc->cap += INC_SZ;
printf("增容成功\n");
return 1;
}
}
return 1;
}
void AddContact(Contact* pc)
{
assert(pc);
if (0 == CheckCapacity(pc))
{
return;
}
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
void ShowContact(const Contact* pc)
{
assert(pc);
//打印标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
int i = 0;
for (i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
int FindByname(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
}
char name[20] = { 0 };
int flag = 0;
printf("要删除的联系人:>");
scanf("%s", name);
/*int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
del = i;
flag = 1;
break;
}
}
if (flag == 0)
{
printf("要删除的联系人不存在\n");
return;
}*/
int del = FindByname(pc, name);
if (del == -1)
{
printf("要删除的联系人不存在\n");
return;
}
int i = 0;
for (i = del; i < pc->sz - 1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->sz--;
printf("成功删除联系人\n");
}
void SearchContact(const Contact* pc)
{
assert(pc);
char name[20] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[pos].name,
pc->date[pos].age,
pc->date[pos].sex,
pc->date[pos].tele,
pc->date[pos].addr);
}
}
void ModifyContact(Contact* pc)
{
assert(pc);
char name[20] = { 0 };
printf("请输入要修改的人的名字:>");
scanf("%s", name);
int pos = FindByname(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->date[pos].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pos].age));
printf("请输入性别:>");
scanf("%s", pc->date[pos].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pos].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pos].addr);
}
printf("修改成功\n");
}
int cmp_by_name(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
void DestoryContact(Contact* pc)
{
free(pc->date);
pc->date = NULL;
pc->cap = 0;
pc->sz = 0;
}
本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。