目录
目标:
实现一个通讯录,最大可以保存的联系人数量为100
每个人的信息包括:姓名、性别、年龄、电话、住址
通讯录功能:
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 以名字排序所有联系人
1.通讯录结构体的创建
根据每个人的信息,我们可以创建如下的结构体用于存储联系人信息:
#define name_size 25
#define sex_size 5
#define tele_size 15
#define addr_size 30
struct PeopleList
{
char name[name_size];
char sex[sex_size];
int age;
char phone_number[tele_size];
char address[addr_size];
};
很显然,这样的结构体只能存储一个联系人的信息,因此为了实现通讯录可以存下100个联系人的目标,我们需要一个结构体数组,因此,我们想到了数据结构中的静态顺序表,如下:
#define MaxSize 100
typedef struct Contact
{
struct PeopleList people [MaxSize];
int size;
}Contact;
这样将结构体数组与记录联系人个数的 size 放在结构体 Contact 中,这样就完成了通讯录的结构体创建
2.通讯录增删查改接口的实现
2.1添加联系人
首先是增加联系人,很简单,我们只需要传入 Contact 结构体变量的地址,再依次输入姓名、性别、年龄、电话、住址的数据即可,代码如下:
void ContactPush(Contact* con)
{
assert(con);
if (con->size == MaxSize)
{
printf("通讯录已满,无法添加\n");
return;
}
else
{
printf("请输入联系人姓名:");
scanf("%s", con->people[con->size].name);
printf("请输入联系人性别:");
scanf("%s", con->people[con->size].sex);
printf("请输入联系人年龄:");
scanf("%d", &con->people[con->size].age);
printf("请输入联系人电话:");
scanf("%s", con->people[con->size].phone_number);
printf("请输入联系人住址:");
scanf("%s", con->people[con->size].address);
con->size++;
}
}
这里我们首先使用assert对传入的结构体指针进行断言,以防止传入空指针导致后续对空指针的解引用等危险操作。
assert 函数:若函数括号中为是(非0),则无事发生,若括号中为否(即0),则结束程序并报告所在行数
在程序中多使用断言可以让自己更快发现代码中错误的地方,可以减少自己调试找bug的时间
断言无问题之后,判断通讯录是否已满(与设置好的数组最大容量MaxSize比较),若已满,则告知操作者,若未满,则依次输入联系人信息,输入结束后,使记录联系人个数的 size++ 即可。
2.2按名查询联系人
为什么先写查询的操作呢,因为在后续的删除与修改中,都需要按照需要(姓名、性别、年龄、电话、住址)找到对应的联系人,才能进行删除/修改的操作,因此查找可谓是除了插入操作以外的第一步。这里以姓名查找为例。
首先,输入要查找的姓名(字符串),依次比较(strcmp)通讯录中的name成员,若strcmp返回0则说明字符串完全一致,说明找到了,这时令函数返回对应结构体数组的下标,若未找到,则返回 -1 以防止与数组下标相冲突。代码如下:
int ContactFindByName(const Contact* con, char* find)
{
//找到了返回对应数组下标
//没找到返回 -1
assert(con && find);
int ret = -1;//记录返回值
if (con->size == 0)
{
printf("通讯录为空\n");
return ret;
}
for (int i = 0; i < con->size; i++)
{
if (strcmp(con->people[i].name, find) == 0)
{
ret = i;
return ret;
}
}
return ret;
}
2.3按姓名删除联系人
按名查找完成之后,删除就相对容易很多了,我们只需要通过查找找到要删除的姓名对应的数组下标,将对应下标的数据由后面的数据进行依次覆盖,覆盖后将记录联系人数量的 size-- 即可(若删除元素为最后一个,则不进行覆盖,直接将记录联系人数量的 size-- )。 如下:
void ContactDelete_name(Contact* con, char* name)
{
assert(con && name);
int ret = ContactFindByName(con, name);
if (ret != -1)
{
if (ret == con->size - 1)
{
con->size--;
return ;
}
else
{
for (int i = ret; i < con->size - 1; i++)
{
//con->people[i].age = con->people[i + 1].age;
//*con->people[i].address = *con->people[i + 1].address;
//*con->people[i].name = *con->people[i + 1].name;
//*con->people[i].sex = *con->pe