C语言之数据结构初见篇(2):顺序表之通讯录的实现(续)

目录

一、通讯录代码的实现

二、通讯录的总结


一、通讯录代码的实现

1.定义联系人的数据结构

关于联系人我们将从姓名、 性别 、年龄、 电话 、地址五个方面进行相对应的查找

代码如下:

cpp 复制代码
//定义联系人数据结构
//姓名 性别 年龄 电话 地址
typedef struct personInfo     // personInfo 是联系人的意思
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];

}peoInfo;

通讯录实现的方法:对顺序表进行操作就行了

此时我们给顺序表改一个名字,叫通讯录 ,方便我们更好的去理解

代码如下:

cpp 复制代码
typedef struct Seqlist Contact;

2.通讯录的初始化

实际上要进行的是顺序表的初始化,由于顺序表的初始化已经实现好了,于是我们直接调用函就行了

Contact.c原文件代码如下:

cpp 复制代码
//通讯录的初始化
void ContactInit(Contact* con)
{
	//实际上要进行的是顺序表的初始化
	//但是,顺序表的初始化已经实现好了
	//于是我们直接调用函就行了
	SLInit(con);
}

Contact.h头文件的代码如下:

这里我们进行了通讯录初始化的声明

cpp 复制代码
void ContactInit(Contact* con); //这里的 con 就是顺序表

3.通讯录的销毁

这里的销毁和上面的初始化一样,直接调用函数(基于顺序表的代码内容)就行了

代码如下:

Contact.c原文件代码如下:

cpp 复制代码
//通讯录的销毁
void ContactDesTroy(Contact* con)
{
	SLDestroy(con); //这里的销毁和上面的初始化一样,直接调用函数就行了
}

Contact.h头文件的代码如下:

这里我们进行了通讯录初始化的声明

cpp 复制代码
//通讯录的销毁
void ContactDesTroy(Contact* con);

4.通讯录增添数据

Contact.c原文件代码如下:

cpp 复制代码
//通讯录的增添
void ContactAdd(Contact* con)
{
	//获取用户输入的内容 :姓名 性别 年龄 电话 地址
	peoInfo info; //直接引入之前已经声明好的内容

	printf("请输入要添加的联系人的姓名");
	scanf("%s", info.name);

	printf("请输入要添加的联系人的性别");
	scanf("%s", info.gender);

	printf("请输入要添加的联系人的年龄");
	scanf("%d", &info.age); //唯一一个不是数组名的变量,因为使用scanf必须要取地址

	printf("请输入要添加的联系人的电话");
	scanf("%s", info.tel);

	printf("请输入要添加的联系人的地址");
	scanf("%s", info.addr);

	//此时往通讯录中添加联系人的数据
	//头插尾插......都可以
	//这里我们选择尾插
	SLPushBack(con, info);  //con是通讯录   info是我们要插入的数据
}

这里我们来解析一下上面的代码内容

cpp 复制代码
void ContactAdd(Contact* con)
  • 函数名ContactAdd - 添加联系人

  • 返回值void - 无返回值

  • 参数Contact* con - 指向通讯录的指针

  • 功能:向通讯录中添加一个新的联系人

创建联系人信息变量

cpp 复制代码
peoInfo info;  // 直接引入之前已经声明好的内容
  • peoInfo 是联系人信息结构体类型(应该是 typedef 定义过的)

  • info 是结构体变量,用于临时存储用户输入的联系人信息

  • 注释说明这个结构体在前面已经定义好了

获取姓名

cpp 复制代码
printf("请输入要添加的联系人的姓名");
scanf("%s", info.name);
  • info.name 是字符数组,数组名本身就是地址,所以不需要 &

  • 使用 %s 格式符读取字符串

后面的性别和年龄地址是一样的意思,这里我们就不解析了

添加到通讯录

cpp 复制代码
// 头插尾插......都可以
// 这里我们选择尾插
SLPushBack(con, info);  // con是通讯录,info是我们要插入的数据
  • SLPushBack 是顺序表的尾插函数

  • 将填写好的 info 插入到通讯录 con 的末尾

  • 注释说明有多种插入方式,这里选择最简单的尾插

Contact.h头文件的代码如下:

这里我们进行了通讯录初始化的声明

cpp 复制代码
//通讯录增添数据
void ContactAdd(Contact* con);

5.通讯录删除数据

Contact.c原文件代码如下:

cpp 复制代码
//通讯录删除数据 
void ContactDel(Contact* con)
{
	//只有当数数据存在的时候,才能执行删除操作
	//所以我们删除数据之前,先必须查找是否存在数据
	char name[NAME_MAX];
	printf("请输入要删除的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);

	if (find < 0)
	{
		printf("输入的联系人数据不存在 \n");
		return;
	}

	//此时要删除的联系人的数据存在
	SLErase(con, find);
	printf("删除成功 \n");
}

注意:这里我们在进行删除联系人数据的时候,我们必须得知道此时的联系人是否存在这个数据,否则没有了怎么删除,所以在进行删除之前,我们必须进行判断

判断联系人数据是否存在的代码如下:

cpp 复制代码
int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(con->arr[i].name, name)) //进行比较,如果相等则返回为0
		{
			//找到了
			return 1;
		}
	}

	//此时没有找到
	return -1; //返回假值,退出程序
}

这里我们来解释一下上面的整个删除联系人数据的代码意思

函数分析

项目 说明
函数名 ContactDel - 删除联系人
返回值 void - 无返回值
参数 Contact* con - 指向通讯录的指针
核心逻辑 查找 → 判断 → 删除

定义姓名数组

cpp 复制代码
char name[NAME_MAX];
  • NAME_MAX 是宏定义,表示姓名的最大长度

获取要删除的姓名

cpp 复制代码
printf("请输入要删除的联系人姓名:\n");
scanf("%s", name);
  • 提示用户输入

  • name是数组名,本身就是地址,不需要&

查找联系人

cpp 复制代码
int find = FindByName(con, name);
  • 调用查找函数,返回结果存入find

  • 这里存在逻辑错误(后面会详细分析)

判断是否存在

cpp 复制代码
if (find < 0)
{
    printf("输入的联系人数据不存在\n");
    return;
}
  • 如果返回值小于0,说明没找到

  • 直接返回,不执行删除

执行删除

cpp 复制代码
SLErase(con, find);
printf("删除成功\n");
  • SLErase是顺序表的删除函数

  • 传入通讯录指针和要删除的位置find

查找功能代码解析

cpp 复制代码
// 查找数据
int FindByName(Contact* con, char name[])
{
    for (int i = 0; i < con->size; i++)
    {
        if (0 == strcmp(con->arr[i].name, name)) // 进行比较,如果相等则返回为0
        {
            // 找到了
            return 1;
        }
    }
}

// 此时没有找到
return -1; // 返回值,退出程序

函数分析

项目 说明
函数名 FindByName - 按姓名查找
返回值 int - 返回位置或状态码
参数1 Contact* con - 通讯录指针
参数2 char name[] - 要查找的姓名
核心逻辑 遍历比较 → 返回结果

Contact.h头文件的代码如下:

这里我们进行了通讯录初始化的声明

cpp 复制代码
//通讯录删除数据
void ContactDel(Contact* con);

6.通讯录的修改

Contact.c原文件代码如下:

cpp 复制代码
//通讯录的修改
void ContactModify(Contact* con)
{
	//要修改的联系人数据必须存在
	char name[NAME_MAX];
	printf("请输入要修改的用户姓名: \n");
	scanf("%s", name);

	int find = FindByName(con, name); //判断联系人是否存在
	if (find < 0)
	{
		printf("要修改的联系人数据不存在\n");
		return;
	}
	//此时联系人存在
	//可以进行修改
	printf("请输入新的姓名 :\n");
	scanf("%s", con->arr[find].name);

	printf("请输入新的性别 :\n");
	scanf("%s", con->arr[find].gender);

	printf("请输入新的年龄 :\n");
	scanf("%d", &con->arr[find].age);

	printf("请输入新的电话 :\n");
	scanf("%s", con->arr[find].tel);

	printf("请输入新的地址 :\n");
	scanf("%s", con->arr[find].addr);

	printf("修改成功\n");
}

我们来一一解释上面的代码意思

cpp 复制代码
//通讯录的修改
void ContactModify(Contact* con)
项目 说明
函数名 ContactModify - 修改联系人
返回值 void - 无返回值
参数 Contact* con - 指向通讯录的指针
功能 修改指定联系人的信息

查找要修改的联系人

cpp 复制代码
//要修改的联系人数据必须存在
char name[NAME_MAX];
printf("请输入要修改的用户姓名: \n");
scanf("%s", name);

int find = FindByName(con, name); //判断联系人是否存在
if (find < 0)
{
    printf("要修改的联系人数据不存在\n");
    return;
}

执行流程

  • 定义字符数组存储要查找的姓名

  • 提示用户输入姓名

  • 调用FindByName查找联系人

  • 判断返回值:如果小于0表示不存在,直接返回

注意 :这里的FindByName函数存在之前分析过的问题,应该返回位置下标,而不是简单的1或-1

Contact.h头文件的代码如下:

这里我们进行了通讯录初始化的声明

cpp 复制代码
//通讯录的修改
void ContactModify(Contact* con);

7.通讯录的查找

Contact.c原文件代码如下:

cpp 复制代码
void ContactFind(Contact* con)
{
	char name[NAME_MAX];
	printf("请输入要查找的联系人姓名\n");
	scanf("%s", name);

	int find = FindByName(con, name); //判断联系人是否存在
	if (find < 0)
	{
		printf("要查找的联系人数据不存在\n");
		return;
	}

	//此时联系人数据存在
	//先将表头打印出来
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%s %s %d %s %s\n", con->arr[find].name, con->arr[find].gender, con->arr[find].age, con->arr[find].tel, con->arr[find].addr);

}

这里的内容之前解释过,差不多是一个意思,这里我们就不仔细讲解了

Contact.h头文件的代码如下:

这里我们进行了通讯录初始化的声明

cpp 复制代码
通讯录的查找
void ContactFind(Contact* con);

8.展示通讯录数据

Contact.c原文件代码如下:

cpp 复制代码
void ContactShow(Contact* con)
{
	//先将表头打印出来
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	//遍历通讯录,按照格式打印每一个联系人数据
	for (int i = 0; i < con->size; i++)
	{
		printf("%s %s %d %s %s\n", con->arr[i].name, con->arr[i].gender, con->arr[i].age, con->arr[i].tel, con->arr[i].addr);

	}
}

这里的内容也是很简单的,所以我们就不解析了

Contact.h头文件的代码如下:

这里我们进行了通讯录初始化的声明

cpp 复制代码
/展示通讯录数据
void ContactShow(Contact* con);

以上8点就是关于通讯录所有代码的书写与意思的解释

二、通讯录总结

关于代码本身

这个通讯录项目,就像一面镜子,照出了C语言学习中的点点滴滴

添加功能 → 教会我们如何获取输入

删除功能 → 教会我们如何查找定位

修改功能 → 教会我们如何更新数据

查找功能 → 教会我们如何展示信息

每一个功能都不是孤立的,它们通过数据紧密相连,共同构成了一个完整的系统。

关于数据结构的理解

通过这个项目,我们真正理解了顺序表

操作 我们做了什么 时间复杂度
添加 放到末尾 O(1)
删除 找到后移动元素 O(n)
修改 找到后直接改 O(1)
查找 遍历比较 O(n)

纸上得来终觉浅,绝知此事要躬行------亲手实现一遍,比看十遍理论都管用。

感谢这个小小的通讯录项目,它让我们真正走进了编程的世界! 🚀

相关推荐
上海锟联科技1 小时前
什么是DAS分布式光纤声波传感系统?原理与应用解析
数据结构·分布式·算法·分布式光纤传感
你这个代码我看不懂1 小时前
JVM栈、方法区和堆内存
java·开发语言·jvm
GIS阵地1 小时前
一场由Qt5 painter的drawRect引起的血雨腥风
开发语言·qt·gis·qgis
学编程就要猛1 小时前
JavaEE初阶:多线程案例
java·开发语言
码不停蹄Zzz1 小时前
对内存堆栈管理的简单理解[C语言]
c语言·开发语言
blackicexs1 小时前
第八周第五天
数据结构·c++·算法
OxyTheCrack2 小时前
【C++】一篇文章悲观锁与乐观锁与其思想在C++语言中的应用
linux·开发语言·数据库·c++·笔记
whycthe2 小时前
c++二叉树详解
数据结构·c++·算法
崇山峻岭之间2 小时前
matlab的FOC仿真
开发语言·matlab