【结构体版】通讯录

news2024/9/21 5:37:46

在这里插入图片描述

👦个人主页:@Weraphael
✍🏻作者简介:目前是C语言学习者
✈️专栏:项目
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注


前言

结构体知识回顾:【C语言初阶】结构体+【C语言进阶】结构体
这篇博客将带你用结构体相关知识来写一个简单的通讯录

目录

  • 前言
  • 一、通讯录的要求
  • 二、创建文件
  • 三、创建菜单
  • 四、功能选择逻辑实现
  • 五、创建用户信息
  • 六、创建通讯录
  • 七、完善通讯录功能1 --- 增加联系人
  • 八、完善通讯录功能5 --- 显示联系人的信息
  • 九、完善通讯录功能2 --- 删除指定联系人
  • 十、完善通讯录功能3 --- 查找指定联系人
  • 十一、完善通讯录功能4 --- 修改指定联系人的信息
  • 十二、完善通讯录功能6 --- 排序
  • 十三、源码

一、通讯录的要求

  1. 包含人的相关信息:姓名、年龄、性别、地址和电话
  2. 假设通讯录要存放100个人(具体情况自己定)
  3. 功能:
    增加联系人
    删除指定联系人
    查找指定联系人的信息
    修改指定联系人的信息
    显示所有人的信息
    ⑥可以按照联系人的年龄或者按照名字排序(具体情况自己定)

二、创建文件

为了方便管理,我们可以创建多个文件来实现

  1. test.c - 测试通讯录 (源文件)
  2. contact.c - 通讯录的实现 (源文件)
  3. contact.h - 存放函数的声明 (头文件)
    在这里插入图片描述

三、创建菜单

按照我们的要求,其功能有6种,为了后期要选择相对应的功能,因此我们可以创建一个简易的菜单。

为了能使程序变得更简短而清晰,我们可以封装一个函数menu

【代码实现test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "contact.h"

void menu()                
{
	printf("**********************************\n");  //Add - 添加联系人								
	printf("****   1. Add     2. del      ****\n");  //del - 删除联系人
	printf("****   3. search  4. modify   ****\n");  //search - 查找指定联系人
	printf("****   5. show    6. sort     ****\n");  //modify - 修改指定联系人
	printf("****        0. exit           ****\n");  //show - 展示联系人
	printf("**********************************\n");  //sort - 对通讯录排序
													 //exit - 退出程序
}
int main()
{
	do
	{
		//创建菜单
		menu();

	} while ();
	return 0;
}

四、功能选择逻辑实现

创建好菜单后,还要能选择菜单上的功能

【代码实现test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include "contact.h"
void menu()                
{
	printf("**********************************\n");  //Add - 添加联系人
	printf("****   1. Add     2. del      ****\n");  //del - 删除联系人
	printf("****   3. search  4. modify   ****\n");  //search - 查找联系人
	printf("****   5. show    6. sort     ****\n");  //modify - 修改联系人
	printf("****        0. exit           ****\n");  //show - 展示联系人
	printf("**********************************\n");  //sort - 排序
													 //exit - 退出程序
}
int main()
{
	int input = 0;
	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 0:
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

这里的input可以输入任何值,输入1~6,用户则可以选择相对应的功能,但万一用户不小心输入其他值时,我们可以提醒“选择错误,重新选择”,这时switch语句就派上用场了。最后do while循环条件是input,大家想想,假如input为0,0为假,则结束循环,这不就和退出程序相互匹配上了。(功能的实现还未完善)

五、创建用户信息

根据要求,人的信息必须包含姓名、年龄、性别、地址和电话。因为在信息中,有charint不同的类型,因此我们可以创建一个结构体(概念:结构是一些值的集合,这些值可以称为成员变量结构的每个成员可以是不同类型的变量。)
然后我们把类型的定义以及声明放到contact.h

【代码实现contact.h

//用户信息
typedef struct PeoInfo
{
	char name[20];//名字
	int age; //年龄
	char sex[5]//性别
	char addr[30] //地址
	char tele[12]; //电话号码
}PeoInfo;

上面的代码还能优化

#define MAX 100     //通讯录人数的最大值
#define NAME_MAX 20 //人名字符串的最大值
#define SEX_MAX 5   //性别字符的最大值
#define ADDR_MAX 30 //地址字符的最大值
#define TELE_MAX 12 //电话字符的最大值

//用户的信息
typedef struct PeoInfo
{
	char name[NAME_MAX];    //名字
	int age;                //年龄
	char sex[SEX_MAX];	    //性别
	char addr[ADDR_MAX];	//地址
	char tele[TELE_MAX];    //电话
}PeoInfo;

优化的好处是:万一下次要改变数值的大小就方便多了

六、创建通讯录

定义完用户信息后,接下来就要存放100个人的信息,然后还要记录下当前已经存放的人的信息的个数。那该如何创建通讯录呢?一个是结构体类型、一个是int类型,所以我们再封装一个结构体。老样子,类型的声明和定义我们都放在contact.h

contact.h

#define MAX 100 //人的个数最大值
#define NAME_MAX 20//人名字符串的最大值
#define SEX_MAX 5  //性别字符的最大值
#define ADDR_MAX 30 //地址字符的最大值
#define TELE_MAX 12 //电话字符的最大值


//人的信息
typedef struct PeoInfo
{
	char name[NAME_MAX];    //名字
	int age;                //年龄
	char sex[SEX_MAX];	    //性别
	char addr[ADDR_MAX];	//地址
	char tele[TELE_MAX];    //电话
}PeoInfo;

//创建通讯录
typedef struct Contact
{
	PeoInfo data[MAX]; //存放人的信息
	int sz;  //表示当前通讯录有多少个人的信息
}Contact;

接下来就是创建通讯录以及它的初始化

【创建通讯录test.c

在这里插入图片描述

【初始化通讯录test.c

可以封装一个函数来帮助我们初始化(&结构体变量的效率更高)

在这里插入图片描述

初始化通讯录函数的声明放到contact.h

在这里插入图片描述

然后前期又创建一个contact.c文件,它的作用就是用来实现通讯录

在这里插入图片描述

2个可能有疑惑的问题

  1. 头文件:
    由于结构体类型的定义在contact.h中,而我们又想在另外一个文件中使用contact.h的内容,就要包含头文件,而又因为这个头文件不是C语言函数库提供的,所以要用双引号
    2.初始化通讯录
    创建完变量就初始化是一个非常好的编程习惯!但有很多人疑问为什么不这样初始化Contact con = {0},其实这样是可以的,但是这种方法太暴力了。为了提高逼格,我们可以封装一个函数来对其初始化。而函数的声明我们还是要放到contact.h

七、完善通讯录功能1 — 增加联系人

首先在test.c封装一个函数

test.c

在这里插入图片描述

对应的函数的声明,我们定义在contact.h

contact.h

在这里插入图片描述

Add函数的实现

contact.c

在这里插入图片描述

八、完善通讯录功能5 — 显示联系人的信息

显示联系人的信息无非就是打印嘛,那就非常简单了,只需要把通讯录内容遍历打印就行。

首先在test.c封装一个show函数

在这里插入图片描述

然后再对其进行函数的声明,声明就在contact.h中。

在这里插入图片描述

最后实现就在contact.c即可

在这里插入图片描述

接下来我们现在来调试,像代码量大的工程一定要学会调试,不然写到后面发现一堆bug,那就非常尴尬了。
因为我们上一步已经把添加联系人(Add函数)写好了,现在利用show来看看代码效果
在这里插入图片描述

九、完善通讯录功能2 — 删除指定联系人

首先现在test.c中封装del函数

在这里插入图片描述

然后在contact.h对其声明

在这里插入图片描述

最后,在contact.c里实现

void del(Contact* pc)
{
	char name[NAME_MAX];
	//记录要删除用户的位置,因为我们的删除方法是从后往前覆盖要删除的对象
	int position = 0; 
	//通讯录可能一位联系人都没有
	if (pc->sz == 0)
	{
		printf("您的通讯录没有联系人,无法删除\n");
		return;
	}
	//通讯录有人
	//1.找到要删除的人
	printf("请输入您要删除的对象:");
	scanf("%s", name);
	//2.查找通讯录是否有这个人(遍历)
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0) //=0说明找到了
		{
			position = i;
			break;
		}
	}
	//3.删除(将后面的人覆盖掉要删除的对象)
	for (int i = position; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

上面的代码其实还可以再优化一下,大家想:后面还要完善查找联系人信息和修改联系人信息的功能,它们有一个共同的步骤都是要先查找有没有对应的联系人,因此我们可以将查找这一步封装成一个函数。


int fine_by_name(Contact* pc,char name[])
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0) //=0说明找到了
		{
			return i;//返回下标
		}
	}
	return -1;
}
void del(Contact* pc)
{
	char name[NAME_MAX];
	if (pc->sz == 0)
	{
		printf("您的通讯录没有用户,无法删除\n");
		return;
	}
	//1.找到要删除的人
	printf("请输入您要删除的对象:");
	scanf("%s", name);
	
	//2.查找通讯录是否有这个人(查找函数)
	int res = fine_by_name(pc, name);
	if (res == -1)
	{
		printf("您的通讯录没有这个人\n");
		return;
	}
	
	//3.删除(将后面的人覆盖掉要删除的对象)
	for (int i = res; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

十、完善通讯录功能3 — 查找指定联系人

test.c封装一个search函数

在这里插入图片描述

然后在contact.h进行函数的声明

在这里插入图片描述

最后在contact.c实现

在这里插入图片描述

十一、完善通讯录功能4 — 修改指定联系人的信息

首先在test.c封装一个modify函数

在这里插入图片描述

然后在contact.h进行声明

在这里插入图片描述

最后再contact.c中实现即可

void modify(Contact* pc)
{
	char name[NAME_MAX];
	printf("请输入要修改人的名字:");
	scanf("%s", name);
	//1.查找
	int res = fine_by_name(pc, name);
	if (-1 == res)
	{
		printf("您要修改的对象不存在\n");
		return;
	}
	//2.修改(重新输入)
	printf("请输入名字:");
	scanf("%s", pc->data[res].name);

	printf("请输入年龄:");
	scanf("%d", &(pc->data[res].age));

	printf("请输入性别:");
	scanf("%s", pc->data[res].sex);

	printf("请输入地址:");
	scanf("%s", pc->data[res].addr);

	printf("请输入电话号码:");
	scanf("%s", pc->data[res].tele);

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

十二、完善通讯录功能6 — 排序

对于排序大家可以用很多种方式实现,我这里使用的是qsort函数,毕竟是我前几天刚刚学的知识。如果大家也想了解qsort,可以看看我往期的博客 -> 传送门

test.c部分

在这里插入图片描述

contact.h部分

在这里插入图片描述

contact.c部分

在这里插入图片描述

十三、源码

test.c部分

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include "contact.h"
void menu()                
{
	printf("**********************************\n");  //Add - 添加联系人
	printf("****   1. Add     2. del      ****\n");  //del - 删除联系人
	printf("****   3. search  4. modify   ****\n");  //search - 查找联系人
	printf("****   5. show    6. sort     ****\n");  //modify - 修改联系人
	printf("****        0. exit           ****\n");  //show - 展示联系人
	printf("**********************************\n");  //sort - 排序
													 //exit - 退出程序
}
int main()
{
	int input = 0;
	//创建通讯录
	Contact con;
	//初始化通讯录
	InitContact(&con);//结构体传参
	do
	{
		//创建菜单
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			Add(&con);
			break;
		case 2:
			del(&con);
			break;
		case 3:
			search(&con);
			break;
		case 4:
			modify(&con);
			break;
		case 5:
			show(&con);
			break;
		case 6:
			sort(&con);
			break;
		case 0:
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

contact.h部分

#define _CRT_SECURE_NO_WARNINGS 1
#define MAX 100 //人的个数最大值
#define NAME_MAX 20//人名字符串的最大值
#define SEX_MAX 5  //性别字符的最大值
#define ADDR_MAX 30 //地址字符的最大值
#define TELE_MAX 12 //电话字符的最大值


//人的信息
typedef struct PeoInfo
{
	char name[NAME_MAX];     //名字
	int age;           //年龄
	char sex[SEX_MAX];	  //性别
	char addr[ADDR_MAX];	  //地址
	char tele[TELE_MAX];    //电话
}PeoInfo;

//创建通讯录
typedef struct Contact
{
	
	PeoInfo data[MAX]; //存放人的信息
	int sz;//表示当前通讯录有多少个人的信息
}Contact;

//初始化通讯录函数
void InitContact(Contact* pc);

//增加联系人
void Add(Contact* pc);
//显示联系人
void show(Contact* pc);
//删除联系人
void del(Contact* pc);
//查找联系人
void search(Contact* pc);
//修改联系人
void modify(Contact* pc);
//排序
void sort(Contact* pc);

contact.c部分

#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>

#include <stdlib.h>
#include "contact.h"

//通讯录的初始化
void InitContact(Contact* pc)
{
	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data)); //初始化为0
}


void Add(Contact* pc)
{
	if (pc ->sz == MAX) //MAX在头文件定义了,表示通讯录最大人数
	{
		printf("添加失败,通讯录空间已满\n");
		return;
	}
	//否则就能增加一个人的信息

	printf("请输入名字:");
	scanf("%s", pc->data[pc->sz].name);//name是数组名

	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->sz].age));

	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);//sex是数组名

	printf("请输入地址:");
	scanf("%s", pc->data[pc->sz].addr);//addr是数组名

	printf("请输入电话号码:");
	scanf("%s", pc->data[pc->sz].tele);//tele是数组名

	pc->sz++; //增加一个人对于的sz也要增加
}

void show(Contact* pc)
{
	printf("%s\t%s\t%s\t%s\t%s\n", "名字", "年龄", "性别", "地址", "电话");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%s\t%d\t%s\t%s\t%s\n", pc->data[i].name,
									   pc->data[i].age,
									   pc->data[i].sex,
									   pc->data[i].addr,
									   pc->data[i].tele);
	}
}


int fine_by_name(Contact* pc,char name[])
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0) //=0说明找到了
		{
			return i;
		}
	}
	return -1;
}
void del(Contact* pc)
{
	char name[NAME_MAX];
	if (pc->sz == 0)
	{
		printf("您的通讯录没有用户,无法删除\n");
		return;
	}
	//通讯录有人删除
	//1.找到要删除的人
	printf("请输入您要删除的对象:");
	scanf("%s", name);
	
	//2.查找通讯录是否有这个人
	//查找函数
	int res = fine_by_name(pc, name);
	if (res == -1)
	{
		printf("您的通讯录没有这个人\n");
		return;
	}
	
	//3.删除(将后面的人覆盖掉要删除的对象)
	for (int i = res; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}


void search(Contact* pc)
{
	char name[NAME_MAX];
	printf("请输入要查找人的名字:");
	scanf("%s", name);

	//利用上一步的查找函数
	int res = fine_by_name(pc, name);
	if (-1 == res)
	{
		printf("您查找的该用户不存在\n");
		return;
	}
	//找到了就打印
	printf("%s\t%s\t%s\t%s\t%s\n", "名字", "年龄", "性别", "地址", "电话");
	printf("%s\t%d\t%s\t%s\t%s\n", pc->data[res].name,
		pc->data[res].age,
		pc->data[res].sex,
		pc->data[res].addr,
		pc->data[res].tele);
}

void modify(Contact* pc)
{
	char name[NAME_MAX];
	printf("请输入要修改人的名字:");
	scanf("%s", name);
	//1.查找
	int res = fine_by_name(pc, name);
	if (-1 == res)
	{
		printf("您要修改的对象不存在\n");
		return;
	}
	//2.找到(重新输入)
	printf("请输入名字:");
	scanf("%s", pc->data[res].name);

	printf("请输入年龄:");
	scanf("%d", &(pc->data[res].age));

	printf("请输入性别:");
	scanf("%s", pc->data[res].sex);

	printf("请输入地址:");
	scanf("%s", pc->data[res].addr);

	printf("请输入电话号码:");
	scanf("%s", pc->data[res].tele);

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

int cmp_name(void* p1, void* p2)
{
	return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}

int cmp_age(void* p1, void* p2)
{
	return ((PeoInfo*)p1)->age - ((PeoInfo*)p2)->age;
}
void sort(Contact* pc)
{
	int input = 0;
	printf("请选择排序方式(默认从小到大):1(年龄)/2(姓名):");
	scanf("%d", &input);
	if (input == 2)
		qsort(pc, pc->sz, sizeof(PeoInfo), cmp_name);
	else
		qsort(pc, pc->sz, sizeof(PeoInfo), cmp_age);
	printf("恭喜你排序成功,请在选择show中观察效果\n");
}

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

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

相关文章

扬帆优配|五千亿巨头一度涨停! 4天3倍,港股又现“狂飙”股!

周一&#xff0c;A股三大指数走势分化。到午间收盘&#xff0c;沪指震荡走高涨近1%&#xff0c;深证成指涨0.75%&#xff0c;创业板指继续弱势调整。 盘面上&#xff0c;钢铁、煤炭、大金融等权重板块团体走强&#xff0c;三大通讯运营商一同拉升&#xff0c;其间我国电信盘中一…

合作协议书合同怎么写?

合作协议书合同怎么写&#xff1f;以品牌推广的合作协议书合同为例&#xff0c;参考内容如下&#xff1a;业务合作协议甲方&#xff08;项目方&#xff09;&#xff1a;乙方&#xff08;客户推荐方&#xff09;&#xff1a;甲乙双方本着平等自愿、互惠互利原则&#xff0c;就结…

(十五)docker安装sentinel,客户端配置规则本地持久化

一、简介 操作系统&#xff1a;Linux CentOS 7.3 64位 docker版本&#xff1a;19.03.8 sentinel版本&#xff1a;1.8.0 二、实践 1、拉取镜像 docker pull bladex/sentinel-dashboard:1.8.0 2、运行容器 docker run --name sentinel \ -p 8858:8858 \ --privilegedtrue …

django项目实战三(django+bootstrap实现增删改查)进阶分页

目录 一、分页 1、修改case_list.html页面 2、修改views.py的case_list方法&#xff08;分页未封装&#xff09; 二、分页封装 1、新建类Pagination 2、修改views.py的case_list方法 三、再优化&#xff0c;实现搜索分页qing情况 四、优化其他查询页面实现分页和查询 五…

如何寻找SAP中的增强

文章目录0 简介1 寻找一代增强2 寻找二代增强2.2 在包里也可以看到2.3 在出口对象里输入包的名字也可以找到2.4 通过以下函数可以发现已有的增强2.5 也可以在cmod里直接找2.6 总结3 寻找第三代增强0 简介 在SAP中&#xff0c;对原代码的修改最不容易的是找增强&#xff0c;以下…

Springboot 整合 分布式定时任务 XXL-JOB

起因 恰逢周末&#xff0c; 最近公司接入了分布式定时任务&#xff0c;我是负责接入这块的&#xff0c;正好在网上想起了之前看过的分布式任务的文章&#xff0c;然后学习一下 各路框架发现看了很多框架比如 elasticjob 跟xxl-job不同的是&#xff0c;elasticjob是采用zookeepe…

Cesium 卫星轨迹、卫星通信、卫星过境,模拟数据传输。

起因&#xff1a;看了cesium官网卫星通信示例发现只有cmzl版本的&#xff0c;决定自己动手写一个。欢迎大家一起探讨&#xff0c;评论留言。 效果 全部代码在最后 起步 寻找卫星轨迹数据&#xff0c;在网站space-track上找的&#xff0c;自己注册账号QQ邮箱即可。 卫星轨道类…

stm32f407探索者开发板(十六)——串行通信原理讲解-UART

文章目录一、串口通信接口背景知识1.1 处理器与外部设备通信的两种方式1.2 按照数据传送方向1.3 是否带有时钟信号1.4 常见的串行通信接口二、STM32F4串口通信基础2.1 STM32的串口通信接口2.2 UART异步通信方式引脚连接方法2.3 UART异步通信方式引脚(STM32F407ZGT6)2.4 UART异步…

模拟物流快递系统程序设计-课后程序(JAVA基础案例教程-黑马程序员编著-第四章-课后作业)

【案例4-8】模拟物流快递系统程序设计 欢迎点赞收藏关注 【案例介绍】 案例描述 网购已成为人们生活的重要组成部分&#xff0c;当人们在购物网站中下订单后&#xff0c;订单中的货物就会在经过一系列的流程后&#xff0c;送到客户的手中。而在送货期间&#xff0c;物流管理…

实际项目角度优化App性能

前言&#xff1a;前年替公司实现了一个在线检疫App&#xff0c;接下来一年时不时收到该App的需求功能迭代&#xff0c;部分线下问题跟进。随着新冠疫情防控政策放开&#xff0c;该项目也是下线了。 从技术角度来看&#xff0c;有自己的独特技术处理特点。下面我想记录一下该App…

c++动态内存分布以及和C语言的比较

文章目录 前言一.c/c内存分布 C语言的动态内存管理方式 C内存管理方式 operator new和operator delete函数 malloc/free和new/delete的区别 定位new 内存泄漏的危害总结前言 c是在c的基础上开发出来的&#xff0c;所以关于内存管理这一方面是兼容c的&…

02- OpenCV绘制图形及图像算术变换 (OpenCV基础) (机器视觉)

知识重点 OpenCV用的最多的色彩空间是HSV. 方便OpenCV做图像处理img2 img.view() # 浅拷贝img3 img.copy() # 深拷贝split(mat) 分割图像的通道: b, g, r cv2.split(img) # b, g, r 都是数组merge((ch1, ch2, ch3)) 融合多个通道cvtColor(img, colorspace): 颜…

Centos7系统编译Hadoop3.3.4

1、背景 最近在学习hadoop&#xff0c;此篇文章简单记录一下通过源码来编译hadoop。为什么要重新编译hadoop源码&#xff0c;是因为为了匹配不同操作系统的本地库环境。 2、编译源码 2.1 下载并解压源码 [roothadoop01 ~]# mkdir /opt/hadoop [roothadoop01 ~]# cd /opt/had…

运动蓝牙耳机哪个牌子好性价比高、性价比高的运动蓝牙耳机推荐

如今耳机是我们生活中很常见的数码产品了&#xff0c;在街上看到跑步、骑行&#xff0c;室内健身房&#xff0c;都能看到大家人手一副耳机&#xff0c;运动耳机已经成为很多人的运动必备品&#xff0c;因大众佩戴耳机的种类和风格有所不同&#xff0c;这也造就了市场上琳琅满目…

RT-Thread SPI使用教程

RT-Thread SPI 使用教程 实验环境使用的是正点原子的潘多拉开发板。 SPI从机设备使用的是BMP280温湿度大气压传感器。 使用RT-Thread Studio搭建基础功能。 1. 创建工程 使用RT-Thread Studio IDE创建芯片级的工程。创建完成后&#xff0c;可以直接编译下载进行测试。 2.…

电源电路设计(一)(文末有易灵思核心板及下载线)

现在随着电子技术的高速发展&#xff0c;电子系统的应用领域也变得越来越广泛&#xff0c;电子设备的种类也在逐渐的不断更新、不断增多&#xff0c;电子设备与人们日常的工作、生活的关系也是日益密切。任何的电子设备都离不开安全有效的电源&#xff0c;电源是一切电力电子设…

后来我放弃了Obsidian手机端,改用Flomo | Obsidian实践

Obsidian在本地管理笔记文件的方式是把双刃剑。一方面&#xff0c;用户自行管理笔记文件可以获得更多的安全感&#xff0c;不用担心会出现“平台挂掉了&#xff0c;笔记丢失”的情况&#xff1b;另一方面&#xff0c;免费版Obsidian无法进行多终端笔记同步的问题又常常遭人诟病…

c++11 标准模板(STL)(std::unordered_set)(三)

定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…

wafw00f工具

wafw00f Web应用程序防火墙指纹识别工具 github地址&#xff1a;https://github.com/EnableSecurity/wafw00f 安装环境&#xff1a;python3环境 —>使用 pip install wafw00f 进行安装 安装成功后目录&#xff1a;python安装目录中的Lib\site-packages\wafw00f 本机为&a…

Hadoop - HDFS

Hadoop - HDFS 1. HDFS介绍 1.1 定义 HDFS是一个分布式文件系统&#xff0c;适合一次写入&#xff0c;多次读出的场景 数据可以保存在多个副本当中&#xff0c;可以通过增加副本的数量来增加容错 不适用于低延时数据访问的场景 不能高效的对小文件进行存储 因为会占用Na…