C语言 — 静态顺序表实现通讯录

本文介绍了如何使用C语言实现一个静态顺序表结构的通讯录,包括创建结构体、增删查改接口及排序功能。通讯录结构体包含姓名、性别等字段,最多可存储100个联系人。文章详细讲解了每个功能的实现细节,如添加联系人、按姓名查询、删除和修改联系人信息,并展示了冒泡排序的实现。最后讨论了静态顺序表的空间开销问题,提出了动态顺序表作为改进方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.通讯录结构体的创建

2.通讯录增删查改接口的实现

3.通讯录排序的实现

4.通讯录整体逻辑及代码


目标:

实现一个通讯录,最大可以保存的联系人数量为100

每个人的信息包括:姓名、性别、年龄、电话、住址

通讯录功能:

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 查找指定联系人信息
  4. 修改指定联系人信息
  5. 显示所有联系人信息
  6. 清空所有联系人
  7. 以名字排序所有联系人

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值