目录
通讯录
实现一个通讯录,要记录一个人的信息,而人是一个复杂对象
人的信息:名字、年龄、性别、电话、地址等。
可以用结构体把人的信息都包含在一起封装一个结构体类型
通讯录的功能目录
通讯录的功能有7种:
- 存放人的信息
- 增加联系人
- 删除指定联系人
- 查找联系人
- 修改联系人的信息
- 对联系人的排序
- 显示联系人的信息
- 退出通讯录
- 源代码文件:
test.c
测试功能
contact.c
通讯录功能的实现
contact.h
类型的声明
通讯录的实现
创建人的信息的结构体类型
第一步是封装一个人的信息的结构体类型
由于封装的结构体类型的名字太长,总是写的话感觉太麻烦了
对 struct PeoInfo
进行了typdef
类型重命名
struct PeoInfp
改成 PeoInfp
//人的信息
typedef struct PeoInfo
{
char name[20]; //名字
int age; //年龄
char sex[10]; //性别
char tele[13];//电话
char addr[30];//地址
}PeoInfo;
- 以上的数值如果以后会经常用到的话,可以用#define 来定义,方便以后修改
开辟通讯录的空间
上面定义好结构体类型后,还要创建框架,就和猜数字游戏、扫雷一样,之后定义变量开辟通讯录所需空间
之后如果对通讯录进行增加联系人、删除指定联系人、查找联系人等等各种操作时候
通讯录的人的信息和个数都在发生变化,就需要一个变量来记录通讯录里有多少个人的信息
PeoInfo data[100]
和 count
二个变量加起来才能维护通讯录
- 如果放在主函数里,
PeoInfo data[100]
增加一个人的信息后,那count
是不是也要能这变
经常改动的话是不是过于麻烦了,所以能不能把PeoInfo data[100]
和count
封装进一个结构体里呢
就有了下面的写法:
把PeoInfo data[100]
和 count
整合到一起,以后修改和找起来就更加的方便一些
由于封装的结构体类型的名字太长,总是写的话感觉太麻烦了
对 struct Contact
进行了typdef
类型重命名
struct Contact
改成Contact
// 通讯录
typedef struct Contact
{
PeoInfo data[100];//存放人的信息
int count;//记录通讯录中人信息的个数
}Contact;
通讯录的初始化
如果要进行初始化,就先定义通讯录
- 用一个函数进行初始化
- 先在
contact.h
文件里进行类型的声明,然后再contact.c
文件里实现
函数传参传的是地址,所以用指针接收,Contact
是类型 - 第二个用
memset
函数进行初始化,memset
是内存设置
sizeof 计算结构体大小,结果是以字节为单位
//初始化通讯录
void InitContact(Contact* pc)
{
pc->count = 0;
memset(pc->data, 0, sizeof(pc->data));
}
以上就把所有的空间初始化为 0 了
初始化的部分就完成了
增加联系人
上面通过函数传址的方式,把地址传给了 pc
变量,相当于 pc
指向了通讯录中下标为count
的地址
下一步是增加联系人的信息,而增加联系人的前提条件是通讯录的空间没满,满了就增加不了,直接返回(return
)
所以要先加上一个判断
MAX 是#define 定义的全局变量为100
通讯录的空间没有超过100,就进行下一步,增加联系人信息
- 每次存放的信息是放到
con
里data
的数组,下标为count
的位置
人的信息有5种,分别进行输入: - 输入名字:
pc->data[pc->count].name
pc->data
是指向数组
pc->count
是代表数组的下标
. name
是指向结构体的成员,而name
是代表数组首元素的地址,所以不用&
- 输入年龄:由于年龄是
整形变量
,所以要进行&
操作 - 剩下的三种都是和第一种情况相同,所以不用
&
- 最后增加成功后,
count
要++
显示打印
增加成功后,接下来就是显示打印,看打印的数值是否正确
还是以函数的方式进行实现
打印信息,就是打印 count 个人的信息,直接用 for
循环打印
\t
是水平制表
void ShowContact(const Contact* pc)
{
assert(pc);
int i = 0;
for (i = 0; i < pc->count; i++)
{
printf("%20s\t%3d\t%5s\t%13s\t%30s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
下面进行测试:
上面打印时,没有标题,不太好理解
下面就是在输出的前一行增加标题
如果想把格式进行左对齐,就在输入格式的前面加上 -
号
显示打印的信息:
删除联系人
增加联系人有了,那接下来就是删除联系人了,
- 第一步 删除联系人的前提条件是通讯录不为空,还有就是这个联系人的信息,所以先判断一下
- 第二步 删除联系人就要先找到联系人,然后进行判断,最后才是删除
查找是直接封装一个函数(FindByName
)。需要传二个参数(通讯录、要查找的参数)
功能是如果找到就这个数的返回下标,找不到返回 -1
int FindByName(Contact* pc, char name[])
{
assert(pc);
int i = 0;
for (i = 0; i < pc->count; i++)
{
if (0 == strcmp(pc->data[i].name, name))
{
retur