C语言结构体练习:【通讯录(静态数组简易版)的实现】

news2024/11/17 21:48:10

全文目录

  • 😀 前言
  • 🤔 模块和功能划分
  • 🤨 数据类型的选择
    • 😮 功能序号类型 `enum`
    • 😮 个人信息类型 `PeoInfo`
    • 😮 通讯录类型 `Contact`
  • 😵‍💫 功能的实现
    • 🙄 初始化通讯录 `InitContact`
    • 🙄 添加功能 `AddContact`
    • 🙄 打印功能 `PrintContact`
    • 🙄 删除联系人 `DeleteContact`
      • 😍 通过名字查找对应下标 `FindByName`
    • 🙄 查找联系人 `SearchContact`
    • 🙄 修改联系人信息 `ModifyContact`
    • 🙄 清空通讯录 `EmptyContact`
    • 🙄 排序功能 `SortContact`
  • 🌈 总结

😀 前言

前面我们学习了C语言的结构体等自定义类型的知识,乌泱泱的一大堆知识,没有练习肯定是学不扎实的,所以今天我们将前面学到的所有C语言知识整合起来进行实现一个小项目:通讯录(静态数组简易版),达到一个复习的目的。

🤔 模块和功能划分

我们实现的通讯录主要有以下几个功能:

  1. 退出(exit)
  2. 添加(add)
  3. 删除(delete)
  4. 查找(search)
  5. 修改(modify)
  6. 打印(print)
  7. 清空(empty)
  8. 排序(sort)

同时为了方便调试和代码的美观,我们将代码分为三个源文件:test.c, contact.h, contact.c
通话录模块功能划分

🤨 数据类型的选择

😮 功能序号类型 enum

对于各种功能,在实现的时候是通过switch case 语句来实现各种功能的:

do {
	menu();
	printf("请选择->");
	scanf("%d", &input);
	switch (input) {
	case 1: 	// 添加
		...
		break;
	case 2: 	// 删除
		...
		break;
	case 3: 	// 查找
		...
		break;
	case 4: 	// 修改
		...
		break;
	case 5: 	// 打印
		...
		break;
	case 6: 	// 清空
		...
		break;
	case 7: 	// 排序
		...
		break;
	case 0: 	// 退出
		...
		break;
	default: 	// 输入其他提示错误
		printf("选择错误\n");
	}
	
} while (input);

我们可以使用枚举类型将功能和对应的序号关联起来,这样代码的可读性就能大大地提高了:

enum Option 
{
	EXIT,	// 0
	ADD,	// 1
	DELETE, 	// 2
	SEARCH, 	// 3
	MODIFY, 	// 4
	PRINT, 	// 5
	EMPTY, 	// 6
	SORT 	// 7
};

do {
	menu();
	printf("请选择->");
	scanf("%d", &input);
	switch (input) {
	case ADD: 	// 添加
		...
		break;
	case DELETE: 	// 删除
		...
		break;
	case SEARCH: 	// 查找
		...
		break;
	case MODIFY: 	// 修改
		...
		break;
	case PRINT: 	// 打印
		...
		break;
	case EMPTY: 	// 清空
		...
		break;
	case SORT: 	// 排序
		...
		break;
	case EXIT: 	// 退出
		...
		break;
	default: 	// 输入其他提示错误
		printf("选择错误\n");
	}
	
} while (input);

😮 个人信息类型 PeoInfo

对于一个人的信息,基本上都是通过字符串来描述,都需要使用字符数组来存放,数组的长度可以使用宏定义来进行替换,方便后期管理。对于每个人的信息我们可以将其定义为结构体:

#define MAX_NAME 20
#define MAX_SEX 3
#define MAX_AGE 3
#define MAX_TELE 12
#define MAX_ADDRS 30

typedef struct PeoInform 
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	char age[MAX_AGE];
	char telephon[MAX_TELE];
	char addrs[MAX_ADDRS];
} PeoInform;

😮 通讯录类型 Contact

通讯录的是存放所有人的信息的,那么需要能够存放所有人的信息的空间,我们直接使用数组来实现,因为添加操作的时候我们需要标记哪个位置可以使用,所以需要使用size来记录通讯录的大小。

#define MAX 1000 	// 通讯录人数的上限

typedef struct Contact 
{
	PeoInform data[1000];
	int size;
} Contact;

😵‍💫 功能的实现

数据的类型确定了,我们就可以来实现各种功能了。

🙄 初始化通讯录 InitContact

由于通讯录是一个结构体,定义出来的又是局部变量,其内容是随机值。所以在使用之前需要先初始化一下,为了后期更好的维护,还是通过函数来进行初始化。

// 初始化
void InitContact(Contact* con)
{
	assert(con);
	con->size = 0;
	memset(con->data, 0, sizeof(con->data));
}

🙄 添加功能 AddContact

因为有了size,所以新加入的联系人可以之间存放在data数组的size位置上。如果

// 添加联系人
void AddContact(Contact* con)
{
	assert(con);
	puts("");

	if (con->size == MAX)	// 满了就不能再添加
	{
		puts("通讯录已满!!!");
	}
	else
	{
		printf("请输入姓名 ->");
		scanf("%s", con->data[con->size].name);
		printf("请输入性别 ->");
		scanf("%s", con->data[con->size].sex);
		printf("请输入年龄 ->");
		scanf("%s", con->data[con->size].age);
		printf("请输入电话号码 ->");
		scanf("%s", con->data[con->size].telephon);
		printf("请输入地址 ->");
		scanf("%s", con->data[con->size].addrs);
		puts("");

		con->size++;

		printf("添加成功!\n");
	}
}

🙄 打印功能 PrintContact

添加成功后我们可以通过打印功能来进行查看,在参数方面,因为我们只是访问一下数据,所以加上const修饰一下比较好。

// 打印联系人的信息
void PrintContact(const Contact* con)
{
	assert(con);

	printf("%-20s %-5s %-5s %-12s %-30s\n",
			"名字", "性别", "年龄", "电话号码", "地址");
	
	for (int i = 0; i < con->size; i++) 
	{
		printf("%-20s %-5s %-5s %-12s %-30s\n", 
			con->data[i].name, con->data[i].sex, 
			con->data[i].age, con->data[i].telephon, 
			con->data[i].addrs);
	}
}

🙄 删除联系人 DeleteContact

😍 通过名字查找对应下标 FindByName

删除联系人一般是按照名字来进行删除的,所以我们需要先通过名字找到对应的下标再进行删除,因为后面需要查找的功能也需要通过名字来找人,所以这里之间实现一个函数:FindByName

// 通过名字来寻找联系人所在的下标
int FindByName(Contact* con, char* name)
{
	int i = 0;
	for (; i < con->size; i++)
	{
		if (strcmp(con->data[i].name, name) == 0) return i;
	}

	return -1;
}

如果通讯录中没有该名字,提示后返回,如果有,找到后通过覆盖的方式进行删除

// 删除指定联系人
void DeleteContact(Contact* con)
{
	assert(con);
	puts("");
	// 1. 找到联系人
	char name[MAX_NAME] = { 0 };
	printf("请输入需要删除的联系人的姓名->");
	scanf("%s", name);
	int pos = FindByName(con, name);


	// 2. 覆盖删除联系人
	if (pos == -1)
	{
		puts("");
		puts("无该联系人!!!");
	}
	else
	{
		for (int i = pos; i < con->size - 1; i++) 
		{
			con->data[i] = con->data[i + 1];
		}
		con->size--;
		printf("删除成功!\n");
	}
}

🙄 查找联系人 SearchContact

通过名字查找,找到后直接输出信息,没找到提示后返回

// 查找指定联系人
void SearchContact(const Contact* con)
{
	assert(con);

	puts("");
	// 1. 找到联系人
	char name[MAX_NAME] = { 0 };
	printf("请输入需要删除的联系人的姓名->");
	scanf("%s", name);
	int pos = FindByName(con, name);

	if (pos == -1)
	{
		puts("找不到该联系人???");
	}
	else
	{
		printf("%-20s %-5s %-5s %-12s %-30s\n",
			"名字", "性别", "年龄", "电话号码", "地址");

		printf("%-20s %-5s %-5s %-12s %-30s\n",
			con->data[pos].name, con->data[pos].sex,
			con->data[pos].age, con->data[pos].telephon,
			con->data[pos].addrs);
	}
}

🙄 修改联系人信息 ModifyContact

名字作为关键字来修改个人信息。

// 修改指定联系人信息
void ModifeContact(Contact* con)
{
	assert(con);

	puts("");
	// 1. 找到联系人
	char name[MAX_NAME] = { 0 };
	printf("请输入需要删除的联系人的姓名->");
	scanf("%s", name);
	int pos = FindByName(con, name);

	if (pos == -1)
	{
		puts("找不到该联系人???");
	}
	else
	{
		printf("请输入姓名 ->");
		scanf("%s", con->data[pos].name);
		printf("请输入性别 ->");
		scanf("%s", con->data[pos].sex);
		printf("请输入年龄 ->");
		scanf("%s", con->data[pos].age);
		printf("请输入电话号码 ->");
		scanf("%s", con->data[pos].telephon);
		printf("请输入地址 ->");
		scanf("%s", con->data[pos].addrs);
		printf("\n");

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

		printf("%-20s %-5s %-5s %-12s %-30s\n", 
				"名字", "性别", "年龄", "电话号码", "地址");

		printf("%-20s %-5s %-5s %-12s %-30s\n", 
				con->data[pos].name, con->data[pos].sex, 
				con->data[pos].age, con->data[pos].telephon, 
				con->data[pos].addrs);
	}
}

🙄 清空通讯录 EmptyContact

因为全部的访问操作都跟size有关,所以清空时只需要将size置为0即可。

// 清空通讯录
void EmptyContact(Contact* con)
{
	assert(con);

	con->size = 0;
	printf("清空成功!\n");
}

🙄 排序功能 SortContact

还是老样子,用名字作为关键字,这里我使用的是冒泡排序,相对简单一点。

// 通过姓名排序
void SortContact(Contact* con)
{
	assert(con);

	for (int i = 0; i < con->size; i ++)
		for (int j = 0; j < con->size - 1 - i; j++)
		{
			if (strcmp(con->data[j].name, con->data[j + 1].name) > 0)
			{
				PeoInform temp = con->data[j];
				con->data[j] = con->data[j + 1];
				con->data[j + 1] = temp;
			}
		}

	puts("排序成功");
}

🌈 总结

以上就是第一个版本的通讯录的实现了。看似简单,但是对C语言的基础知识也是有一定的考验的,想要打牢基础还是要多写写联系一下的。

源码地址:静态数组版通讯录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MYSQL命令大全(详细版)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

【快乐手撕LeetCode题解系列】——移除链表元素

【【快乐手撕LeetCode题解系列】——移除链表元素&#x1f60e;前言&#x1f64c;删除有序数组中的重复项&#x1f64c;解法一&#xff1a;画图分析&#xff1a;&#x1f60d;思路分析&#xff1a;&#x1f60d;源代码分享&#xff1a;&#x1f60d;解法二&#xff1a;画图分析…

Vite打包后直接使用浏览器打开,显示空白问题

vite打包后&#xff0c;直接用浏览器打开显示空白 1.需求&#xff1a; 安卓webview等浏览器直接打开文件显示 2.原因 &#xff08;1&#xff09;资源路径错误&#xff1a; vite.config.js 配置 base: “./” &#xff08;在webpack中则配置publicPath: "./"即可…

Windows ActiveMQ安装

Windows ActiveMQ 安装 ActiveMQ下载&#xff1a;ActiveMQ Java JDK下载&#xff1a;Java JDK20 下载完成之后解压ZIP安装包&#xff0c;解压后得到如下文件夹 找到根目录下/bin/win64/activemq.bat 双击打开&#xff0c;如果提示权限记得使用管理员身份 。 如提示Unable to e…

学习数据结构第5天(线性表的链式表示)

线性表的链式表示单链表的定义单链表的基本操作双链表双链表的基本操作循环链表块状链表存储结构顺序表和链表的比较线性表的顺序存储结构的特点是逻辑关系上相邻的两个数据元素在物理位置上也是相邻的。我们会发现虽然顺序表的查询很快&#xff0c;时间复杂度为O(1)O(1)O(1),但…

Java EE企业级应用开发(SSM)第5章

第5章Spring MVC入门一.预习笔记 1.Spring MVC是所有使用OOP编程语言都应该遵守的规范 2.Spring MVC的特点 强大的灵活性、非侵入性和可配置性 提供了一个前端控制器DispatcherServlet&#xff0c;开发者无须额外开发控制器对象 分工明确&#xff0c;每一个功能由一个专门…

日前、日内两阶段需求响应热电综合能源联合调度研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

深度学习之卷积神经网络0基础入门学习教程——浅层深度学习(全网最详细,不详细你打我)(看不懂你打我)(对小白没用你打我)

作为一个双非学校的人工智能硕士研究生&#xff0c;我在深度学习入门之初&#xff0c;学校里没人带&#xff0c;只能靠自己一点一点的摸索&#xff0c;走了很多弯路&#xff0c;因为自己并不懂得从哪里入手&#xff0c;从吴恩达的课到李沐的课等等无数种课&#xff0c;无数种书…

Microsoft project 2013安装教程(含激活方法)

目录 一、介绍 二、安装教程 三、激活 一、介绍 Microsoft project 2013中文版是由微软推出的一款项目管理软件&#xff0c;软件将可用性、功能和灵活性等完美地融合在一起&#xff0c;可以有效提升办公人员的效率&#xff0c;利用project 2013用户可以制作出…

SecureCRT8.5的下载、安装和注册(详细图解)

SecureCRT8.5的下载、安装和注册请先关闭杀毒软件和防火墙。 关闭防火墙 先打开电脑的设置&#xff0c;在弹出的界面里找到并点击更新和安全。 找到并点击Windows 安全中心&#xff0c;再在右侧找到并点击防火墙和网络保护选项。 将域网络、专用网络、公用网络这三个选项设…

数据结构入门-11-红黑树

史上最负盛名的平衡二叉树–红黑树&#xff0c;但其实就是2-3树的一种实现 文章目录一、红黑树性质二、红黑树性质推导过程2-3树2.3.1 如何维护绝对平衡2-3树2.3.2 红黑树&2-3树2.3.3 再来看红黑树的性质1.每个节点为 Black or Red2.根节点是Black3.每一个叶子节点(最后的空…

2023年郑州重点建设项目名单公布,中创“算力数据中心”项目入选!

4月7日&#xff0c;郑州市人民政府网站公布2023年郑州市重点建设项目名单&#xff0c;名单共列项目680个&#xff0c;总投资1.08万亿元&#xff0c;年度计划投资2691亿元。 在创新驱动能力提升项目名单里&#xff0c;中创算力与人民网人民数据&#xff08;国家大数据灾备中心&a…

小程序实现消息订阅及发送

在我们的家政服务小程序中&#xff0c;用户可以新增预约。一般的场景是新增预约的时候提醒用户接收通知&#xff0c;在状态变更的时候我们来发送订阅消息。本篇我们来讲解一下小程序订阅消息功能的开发。 1 开通订阅消息模板 要想发送订阅消息&#xff0c;首先需要选用一个消…

【ES】数据同步集群

【ES】数据同步&集群3.数据同步3.1.思路分析3.1.1.同步调用3.1.2.异步通知3.1.3.监听binlog3.1.4.选择3.2.实现数据同步3.2.1.思路3.2.2.导入demo3.2.3.声明交换机、队列1&#xff09;引入依赖2&#xff09;声明队列交换机名称3&#xff09;声明队列交换机3.2.4.发送MQ消息…

解决macOS IntelliJ IDEA 卡顿问题

写在前面的话1&#xff1a;我在撰写这篇博客时候&#xff0c;所用的IntelliJ IDEA版本是IntelliJ IDEA 2022.3.3 (Ultimate Edition)&#xff0c;你需要知道可能对于不同的IntelliJ IDEA版本会有一定的差异 写在前面的话2&#xff1a;如果我这篇博客可以帮助到你&#xff0c;请…

国内可用的 ChatGPT

国内可用的 ChatGPT 替代列表功能和使用顺便推荐列表 https://chatgpt.qdymys.cn/ &#xff1a;三小时只能用10次 https://alllinkai.com/ &#xff1a;体验完&#xff0c;要登录&#xff0c;不推荐 https://gpttalk.live/ &#xff1a;每天限制使用次数 https://chatgpt-c…

深入探讨机器学习中的过拟合现象及其解决方法

1. What❓ 过拟合&#xff08;Overfitting&#xff09;是指在机器学习中&#xff0c;模型在训练集上表现较好&#xff0c;但在测试集或实际应用中表现较差的现象。过拟合发生时&#xff0c;模型过于复杂地学习了训练集中的噪声、异常值或特定模式&#xff0c;从而导致对新样本…

限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)

限流 限流是面试中的常见的面试题&#xff08;尤其是大厂面试、高P面试&#xff09; 注&#xff1a;本文以 PDF 持续更新&#xff0c;最新尼恩 架构笔记、面试题 的PDF文件&#xff0c;请到文末《技术自由圈》公号获取 为什么要限流 简单来说&#xff1a; 限流在很多场景中用来…

教程 | 近红外数据的预处理和平均(上)

前言 近红外光谱(NIRS)是一种测量流经传感器所在组织的血液中氧合水平的方法。它基于这样一个事实&#xff0c;即含氧血红蛋白和脱氧血红蛋白具有不同的吸收光谱&#xff0c;因此你会看到它有不同的颜色。大多数近红外系统在每个光源光电二极管发射2个波长的光&#xff0c;通常…

【记录】ORB_SLAM2 例程(README文件里的单双目RDB-D、ROS、AR、外接摄像头、点云)

第一次跑 ORB_SLAM2&#xff0c;记录一下一、普通环境0.build.sh 遇到的问题&#xff08;1&#xff09;usleep&#xff08;2&#xff09;AlignedBit1.单目、TUM数据集2.双目、KITTI数据集3.RGB-D、TUM数据集二、ROS0.build_ros.sh 遇到的问题&#xff08;1&#xff09;rospack …