基于顺序表实现通讯录项目

通讯录项目的实现以及动态顺序表(基于顺序表) 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝,顺序表分为静态顺序表(使⽤定⻓数组存储元素)和动态顺序表(按需申请)静态顺序表缺点:空间给少了不够⽤,给多了造成空间浪费因为我们要做的是通讯录,所以能够保存⽤⼾信息:名字、性别、年龄、电话、地址等 增加联系⼈信息 删除指定联系⼈ 查找制定联系⼈ 修改指定联系⼈ 显⽰联系⼈信息这些功能是要包含实现的。接下来我们一步步实现改进!!! 阅读详情

本文将在实现了顺序表的基础上,将其应用到一个通讯录项目上。(顺序表的实现,请看这里:

顺序表:概念解析与C语言代码实现-优快云博客)

一、创建文件

我们在上次已经写好的顺序表文件的基础上,再创建一个头文件Contact.h和一个源文件Contact.c用于实现通讯录。

二、定义联系人数据结构

通讯录里存储的信息是一条一条的联系人。每个联系人有姓名、性别、年龄、电话号码、地址等,所以我们创建一个结构体来存储这些信息。为了提高代码的可维护性、可读性、可扩展性和避免“魔法数字”,我们用#define来定义每个数组成员的元素个数。

#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100

typedef struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char address[ADDR_MAX];
}peoInfo;

通讯录所需要的增删查改等功能都是与上次实现的顺序表中的功能差不多的,所以接下来要做的事情其实就是把名字“对齐”:把上次定义的SeqList类型重新命名为Contact,把上次实现的顺序表中的int类型数据改成刚刚定义好的结构体类型,这样我们就得到了名为“Contact”的顺序表,里面管理的是名为“peoInfo”的数据类型。

把SeqList类型重新命名为Contact:

//Contact.h

typedef struct SeqList Contact;

头文件不能互相包含,所以Contact.h中没有包含SeqList.h,所以Contact.h就不认识SL是什么,我们必须重新定义struct SeqList。

int类型数据改成刚刚定义好的peoInfo:

//SeqList.h

#include "Contact.h"

//typedef int SLDataType;
typedef peoInfo SLDataType;

这里,顺序表存储的数据类型被定义为peoInfo。为了让编译器认识peoInfo这个类型,SeqList.h或SeqList.c就必须包含定义了peoInfo的Contact.h。

这其实是一种紧耦合的实现方式,违背了“高内聚,低耦合”的设计原则,牺牲了代码的复用性。

什么意思呢?具体解释如下。

耦合度描述的是模块之间的依赖程度,“紧耦合” 意味着模块之间的关联过于紧密,一个模块的修改会直接影响另一个模块。

正常设计逻辑中,顺序表作为底层数据结构模块,应独立于业务逻辑(通讯录)存在;但像我们这样操作之后,顺序表的头文件 / 源文件必须包含Contact.h才能识别peoInfo类型,导致顺序表模块 “绑定” 了通讯录模块。

这样一来,如果后续想要实现其他数据的存储,没法直接复用,只能复制一份顺序表代码再修改SLDataType。

不过,现在我们的目的是理解顺序表在具体项目上的应用,为了方便先这样写。

上次的方法我们是按照上次定义的结构体类型来写的,比如SLFind函数里出现了“ps->arr[i]”,SLPrint函数里用%d打印整型数据,现在存储的数据类型不是int了,代码会报错。所以我们先把这两个函数注释掉。

三、通讯录各种功能的实现

3.1 声明

我们要实现通讯录的初始化、销毁以及增删查改等方法。声明如下:

//通讯录相关的方法

//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);
3.2 实现
3.2.1 通讯录的初始化和销毁

实际上要进行的就是顺序表的初始化,而顺序表的初始化已经实现好了,我们只需把写好的顺序表头文件加载到Contact.c文件中。

void ContactInit(Contact* con)
{
	SLInit(con);
}

就这样,实现完了。

写完了一个功能,立刻进行调试!

//通讯录的测试方法
void ContactTest01()
{
	Contact con;
	ContactInit(&con);
}

int main()
{
	ContactTest01();
	return 0;
}

从调试界面里可以看到,Contact就是我们的SeqList,里面同样是数组、有效数据个数和容量三个成员。同时也可以看到成功完成了初始化,说明写得没问题。

通讯录的销毁也一样。

void ContactDestroy(Contact* con)
{
	SLDestroy(con);
}
3.2.2 添加联系人数据

我们让用户输入要添加的联系人数据,然后用上次写好的尾插功能来插入。

void ContactAdd(Contact* con)
{
	//获取用户输入的内容:姓名+性别+年龄+电话+地址
	peoInfo info;
	printf("请输入要添加的联系人姓名:\n");
	scanf("%s", info.name);

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

	printf("请输入要添加的联系人年龄:\n");
	scanf("%d", &info.age);

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

	printf("请输入要添加的联系人住址:\n");
	scanf("%s", info.address);

	//往通讯录中添加联系人数据
	SLPushBack(con, info);
}

写好之后调试一下,随便输入一组数据,在监视窗口看到以下界面。我们看到,数组的容量变为了4,有效数据个数变为了1,刚才输入的数据也成功插入进去了,说明刚才写的没有问题!

3.2.3 删除联系人数据

要删除联系人,我们首先要找到需删除的这条数据。我们写一个函数来实现这个功能。以按名字查找为例,遍历数组元素,找到与输入的姓名相符的数据之后,返回该数组元素对应的下标。如果遍历完了还没有找到,就返回一个无效的下标(-1)。

int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(name, con->arr[i].name))
		{
			return i;
		}
	}
	return -1;
}

我们可以通过检验上面这个函数的返回值来判断要删除的数据是否存在。之后,就可以用上次写的“指定位置删除”的方法来实现删除联系人的功能了。

void ContactDel(Contact* con)
{
	char name[NAME_MAX] = { 0 };
	printf("请输入要删除的联系人姓名\n");
	scanf("%s", name);

	int find = FindByNmae(con, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	//要删除的数据存在
	SLErase(con, find);
	printf("删除成功!\n");
}

调试一下。

从监视窗口可以看到,第一组输入的联系人数据被成功删除了。

3.2.4 展示通讯录数据

遍历数组中元素打印即可。

void ContactShow(Contact* con)
{
	printf("%6s %3s %4s %6s %14s\n", 
		"姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%6s %4s %3d %6s %14s\n", 
			con->arr[i].name, 
			con->arr[i].gender, 
			con->arr[i].age,
			con->arr[i].tel, 
			con->arr[i].address);
	}
}

调试一下:

3.2.5 修改联系人信息

先判断要修改的联系人是否存在,然后再进行修改。

void ContactModify(Contact* con)
{
	char name[NAME_MAX];
	printf("请输入要修改的联系人姓名\n");
	scanf("%s", name);
	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要修改的联系人数据不存在\n");
	}
	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].address);
}

调试一下:

可见,成功修改了信息。

3.2.6 查找联系人信息

我们已经实现过了按姓名查找的功能。不过,我们希望在此处的查找函数能够打印出被查找的联系人的所有信息。

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

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人不存在\n");
	}
	printf("%6s %3s %4s %6s %14s\n",
		"姓名", "性别", "年龄", "电话", "地址");
	printf("%6s %4s %3d %6s %14s\n",
		con->arr[find].name,
		con->arr[find].gender,
		con->arr[find].age,
		con->arr[find].tel,
		con->arr[find].address);
}

调试一下:

四、功能整合

我们写个菜单主函数把上述功能串起来。

void menu()
{
	printf("**********通讯录************\n");
	printf("1.增加联系人     2.删除联系人\n");
	printf("3.修改联系人     4.查找联系人\n");
	printf("5.展示联系人     0.  退出\n");
	printf("****************************\n");
}

int main()
{
	int op = -1;
	Contact con;
	ContactInit(&con);
	do {
		menu();
		printf("请选择您的操作:\n");
		scanf("%d", &op);
		switch (op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactFind(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 0:
			printf("已退出通讯录!\n");
            break;
        default:
	        printf("输入错误,请重新选择您的操作!\n");
		}
	} while (op != 0);

	ContactDestroy(&con);
	return 0;
}

为了解决每次退出程序通讯录就被销毁,联系人数据丢失的问题,我们可以利用C语言中的文件操作来在每次初始化之后从文件中导入历史数据。

//读取通讯录历史数据
void LoadContact(Contact* con)
{
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen error");
		return;
	}

	//循环读取文件数据
	peoInfo info;
	while (fread(&info, sizeof(peoInfo), 1, pf))
	{
		SLPushBack(&con, info);
	}
	printf("历史数据导入成功!\n");
}


//通讯录的初始化
void ContactInit(Contact* con)
{
	SLInit(con);
	LoadContact(con);
}

至此,一个完整的通讯录项目就完成啦!

BUUCTF--[OGeek2019]babyrop 才学习了基本的ROP流程,到处找题练,不过也没做出来几道题,以这道32位的题作为例题吧。 这道题是BUUCTF上pwn练习题里的[OGeek2019]babyrop。 代码审计 老规矩先checksec一下: 没有canary保护,nx保护开启排除shellcode可能性,FULL RELEO为地址随机化。 观察主函数,先设定了一个闹铃,到时间就会强制退出程序,解除闹铃的方法在上一篇博客中提到过了, 这道题中闹铃函数依然对我们解题起不到什么干扰作用。 主函数的思路大概是:生成一个随机数,把这个随机数作为 阅读详情

相关推荐

P450酶催化循环的Amber-Gromacs混合模拟实战:从血红素加氧到产物释放

本文详细介绍了针对P450酶完整催化循环的Amber-Gromacs混合模拟实战策略。通过Amber为关键氧合血红素中间体(CPDI)构建精确力场,再利用Gromacs的高效GPU加速进行长时间尺度动力学模拟,完整覆盖从底物结合到产物释放的催化过程,为研究酶催化机制提供了强大的计算工具。

weixin_29201859的博客 315

顺序表实现通讯录项目

实际上要进行的是顺序表的初始化,顺序表的初始化已经实现好了,所有直接调用顺序表中的SLlnit函数,便可以实现通讯录的初始化,定义ContactInit函数。要删除的数据必须存在,才能执行删除操作,所以在这之前要先实现一个查找函数FindByName。因为要用到SeqList.h中的顺序表,所以要改一下数据类型,改成创建好的通讯录类型。因为要用到顺序表相关的方法,对通讯录的操作实际就是对顺序表进行操作。这里首先接收用户要添加的数据,然后调用顺序表当中的头插或尾插。也是一样,可以直接调用顺序表实现好的方法。

pzn2506的博客 786

日语五十音图速记攻略:从形象联想法到实战训练

语言学习中的记忆编码与条件反射构建是高效掌握基础的关键。其核心原理在于通过将抽象符号与具象图像、故事或已知概念关联,利用大脑对视觉和叙事信息的天然高记忆效率,从而降低认知负荷,加速识别与反应速度。这一方法的技术价值在于将机械重复转化为意义联结,显著提升长期记忆的牢固度与提取速度。在日语学习这一具体应用场景中,五十音图作为表音文字系统,正是实践这一记忆技术的绝佳对象。通过系统化的形象联想、分组对比(如平假名与片假名的对应关系)以及间隔重复的实战训练,学习者可以高效攻克这一入门难关,为后续的词汇、语法学习铺设坚

weixin_29032489的博客 378

(超详细)基于动态顺序表实现简单的通讯录项目

我们在上一章节用c语言实现了线性表中的的动态顺序表,那么顺序表就只是顺序表吗?当然不是,使用顺序表结构可以实现很多项目,许多项目的数据结构都会用到顺序表,本章节我们就要使用顺序表实现一个简易的通讯录项目。

qq_58761784的博客 2209

我的老款Intel MacBook Pro,如何用OpenVINO把本地大模型推理速度提升10倍?

本文详细介绍了如何在老款Intel MacBook Pro上使用OpenVINO工具包将本地大模型推理速度提升10倍。通过对比Ollama CPU原生、Transformers原生和OpenVINO优化三种方案,展示了OpenVINO在性能优化上的显著优势,并提供了从环境配置到模型转换、性能调优的完整实战指南。

weixin_28694295的博客 302

Cadence原理图设计10个高效技巧:从封装绑定到BOM表导出全流程

本文为硬件工程师提供了一套Cadence OrCAD Capture CIS原理图设计的高效实战指南。文章深度解析了从封装库的精准管理与CIS数据库绑定、封装批量处理技巧,到设计缓存清理、跨页信号追踪,再到关键的DRC检查、网表导出以及智能BOM报表生成的全流程核心技巧,旨在帮助工程师提升设计效率与可靠性,规避常见错误。

weixin_29178069的博客 201

基于顺序表基础实现通讯录项目

基于顺序表基础上实现通讯录项目

2301_80309505的博客 505

SAP CDS View association 的工作原理,与数据库传统 join 操作的区别讲解

笔者前一篇教程,介绍了 SAP CDS View 里如何创建 association:本文就来一一对这些问题进行解答。首先我们来研究如何消费创建好的 SAP CDS View 中的 association 数据。在上图 ABAP Development Tool 里展示的 CDS View 界面,点击 F8 快捷键,进入 Data Preview 即数据预览界面。我们随便选中一条行项目,右键,发现右键菜单里,赫然有一条的菜单项。看来这个功能肯定和 association 相关了。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1008

对于使用顺序表实现通讯录项目的保姆级解析

本文介绍了一个基于顺序表实现的通讯录项目。通过将顺序表从存储整型数据扩展为存储结构体数据,实现了联系人信息的增删改查功能。项目详细讲解了通讯录结构体的设计、初始化、数据添加、查找、删除、修改和展示等核心功能的实现逻辑,并强调了数据结构与实际问题相结合的重要性。作者分享了在开发过程中对"抽象结构到具体应用"转化的思考,指出工具设计应围绕用户需求而非技术复杂度。文章最后展望了项目可能的优化方向,如加入文件操作、多条件查找等,鼓励读者在实践中不断学习和完善。

2503_92929084的博客 1691

Vue - 列表拖曳排序 / 鼠标拖动改变顺序排列高效简洁组件(支持PC端与移动端触屏拖动,也可在滚动条内排序自动滚动,流畅丝滑无 BUG)

Vue-高效简洁列表拖曳排序/鼠标拖动改变顺序排列组件支持PC端与移动端触屏拖动,也可在滚动条内排序自动滚动,流畅丝滑无BUG列表拖曳排序插件vuedraggable拉动拽动拖动顺序改变排序js,vue.js,nuxt.js列表如何实现鼠标拖曳改变顺序排列支持滚动条内复杂数据对象带拖动效果动画排序完毕自动排列数组位置克隆Vue.Draggable官方文档教程SortableJS与vuedraggable列表拖动排序Vue拖拽组件库vuedraggable的安装与使用用户用鼠标拖动排序功能源码最好

🏆 前端领域优质创作者 4847

实现电脑同时上内网和外网(或通过外网访问到该电脑通过该电脑访问内网)

一、需求描述 目前使用的公司网络只能够上内网,但是又有上外网查资料的需求: ①想要实现电脑既能上内网的同时也可以上外网; ②想要使用其他外网电脑使用外网连接到该电脑,通过该电脑访问内部的网络内容。 二、准备内容 电脑必须具备两个网卡,即:可以同时连接内网和外网(比如我的笔记本就可以:使用网线连接笔记本网口与内网通讯,使用WIFI连接手机热点访问外部网络); 注意:如果只有一个网口,可以另外购买USB的无线网卡来实现上网卡。 三、实现电脑同时上内网和外网的操作步骤 3.1、网络拓扑图 ..

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 2万+

C语言数据结构——顺序表,及通讯录项目的模拟实现

摘要:本文介绍了C语言中顺序表的基本概念和实现方法。顺序表是一种物理地址连续的线性结构,分为静态和动态两种类型。重点讲解了动态顺序表的实现过程,包括初始化、增删查改等操作,并通过检查空间、内存管理等关键技术确保程序稳定性。最后以通讯录项目为例,展示了顺序表的实际应用,涉及结构体存储、头文件引用、数据持久化等进阶内容。文章提供了完整的代码实现思路,适合C语言初学者学习基础数据结构。

lunar_coder的博客 787

【WRF模拟】土地利用类型的确定:最大覆盖法/瓦片法

土地利用类型的确定:最大覆盖法/瓦片法

WW、forever的博客 1529

02.【数据结构-C语言】顺序表(线性表概念、顺序表实现:增删查、前向声明、顺序表实现通讯录项目:增删改查、通讯录数据导入及保存到本地文件)

数据结构-C语言顺序表实现,通讯录项目实现:线性表概念;顺序表概念及分类,顺序表实现;使用顺序表实现通讯录项目:前向声明的概念及使用规则,通讯录的增删改查、通讯录数据的保存到本地文件、本地文件数据导入到通讯录中。

恢弘志士之气,不宜妄自菲薄 1062

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【数据结构--基于顺序表实现通讯录项目】

本文系统介绍了通讯录项目的设计与实现,基于顺序表数据结构构建了一个完整的通讯录系统。主要内容包括:1) 定义联系人数据结构(姓名、性别、年龄、地址、电话);2) 实现通讯录的初始化、销毁、增删改查等核心功能,重点讲解了通过姓名查找删除的逻辑;3) 设计用户交互界面,采用菜单驱动模式实现功能选择。项目将顺序表理论应用于实际开发,通过结构体存储联系人信息,并封装了顺序表的基本操作。文章还提供了代码实现细节,如字符串比较函数的使用、输入输出处理等注意事项,最后展示了完整的项目运行流程。

2602_95684935的博客 916

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

通讯录项目—顺序表实现

下面是通讯录要实现的功能。能够保存用户信息:名字、性别、年龄、电话、地址等。增加用户信息。删除指定用户信息。查找用户信息。修改用户信息。显示用户信息。

2301_80662872的博客 1475

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

【通讯录项目 (3 / 3)】基于顺序表的通讯录实现——通讯录项目实现

通讯录项目我们实现了大部分内容,接下来你可以自行探索,丰富功能。祝您前程似锦。

叫我龙翔的博客 535

基于动态顺序表实现通讯录项目

基于顺序表实现通讯录项目

2302_79215415的博客 715

顺序表项目实战(基于动态顺序表实现通讯录)

实现一个基于动态顺序表的通讯录可以是一个很好的顺序表项目实战。动态顺序表是指在顺序表基础上实现了动态扩容和缩容功能,使得其大小可以动态变化,更加灵活和高效。

2303_82176667的博客 635

C语言—顺序表(含通讯录项目)

C语言—顺序表(含通讯录项目)

2302_81120572的博客 3566

通过顺序表实现通讯录项目

pragma once//禁止重复包含//单个个人信息结构体//姓名 性别 年龄 电话号码int age;}per;//前置声明//初始化//销毁//添加//删除//查找//修改//展示。

m0_73946129的博客 965
上一篇: 顺序表:概念解析与C语言代码实现
下一篇: 用双指针法解决两道顺序表基础算法题(LeetCode 27 & 88)
jinyishu_
博客等级 码龄1年 54粉丝 83原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值