C语言之动态内存管理实现通讯录(完整版)

我们在之前的博客中写过静态版的通讯录,我们今天来写一个动态版的,不需要规定它到底需要多大空间,只要还有内存,我们都可以存放的下!同时,函数实现原理,我在通讯录静态版的博客里做了详细的讲解,这里就不详细分析了,不了解原理的小伙伴们可以去C语言通讯录静态版了解一下!

目录

1.函数各部分功能

1.1初始化通讯录

1.2检测通讯录是否需要增容

1.3增加联系人

1.4删除联系人

1.5显示联系人

1.6按名字查找联系人

1.7查找指定联系人

1.8修改指定联系人的信息

1.9对所有联系人按姓名进行排序

1.10销毁通讯录,进行动态空间内存的释放

2.函数源码

2.1test.c测试代码

2.2contact.c函数各功能实现代码

2.3contact.h实现通讯录所需要的头文件代码

3.运行结果


我们在以前静态 的基础上不仅加入内存动态管理,还加入枚举,增强代码的可读性,同时我在代码难以理解的地方增加了详细的注释,相信大家可以理解!

1.函数各部分功能

1.1初始化通讯录

//初始化这个通讯录,初始化为对应的值
void InitContact(Contact* pc)
{
	assert(pc);
	//为通讯录存放人的信息的结构体分配初始空间,并把里面数据直接
	//初始化为0,calloc函数很合适
	PeopInfo* str = (PeopInfo*)calloc(DEFAULT_SZ, sizeof(PeopInfo));
	if (str == NULL)
	{
		perror("calloc");
		return;
	}
	pc->data = str;
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
}

1.2检测通讯录是否需要增容

//空间增容函数
void check_capacity(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		//通讯录已满,进行增容
		PeopInfo* str = (PeopInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeopInfo));
		if (str == NULL)
		{
			perror("realloc");
			return;
		}
		pc->data = str;
		pc->capacity += INC_SZ;//总容量增加
		printf("空间增容成功,可以继续添加联系人\n");
	}
}

1.3增加联系人

//增加通讯录联系人
void AddContact(Contact* pc)
{
	assert(pc);
	check_capacity(pc);//检查通讯录是否需要增容
	//增加人的信息
	printf("请输入联系人姓名:>");
	scanf("%s", pc->data[pc->sz].Name);
	printf("请输入联系人年龄:>");
	scanf("%d", &pc->data[pc->sz].Age);
	printf("请输入联系人性别:>");
	scanf("%s", pc->data[pc->sz].Sex);
	printf("请输入联系人电话号码:>");
	scanf("%s", pc->data[pc->sz].Tele);
	printf("请输入联系人家庭住址:>");
	scanf("%s", pc->data[pc->sz].Addr);
	pc->sz++;
}

1.4删除联系人

//删除指定联系人
void DelContact(Contact* pc)
{
	assert(pc);
	char Name[NAME_MAX] = { 0 };
	int i = 0;
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除!\n");
		return;
	}
	printf("请输入要删除的人的姓名:>");
	scanf("%s", Name);
	int pos = FindByName(pc, Name);
	if (pos == -1)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	for (i = pos; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功!\n");
}

1.5显示联系人

//显示所有联系人
void ShowContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法显示!\n");
		return;
	}
	int i = 0;
	printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n","姓名","年龄","性别","电话号码","家庭住址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",
			pc->data[i].Name,
		    pc->data[i].Age,
			pc->data[i].Sex,
			pc->data[i].Tele,
			pc->data[i].Addr);
	}
}

1.6按名字查找联系人

//通过名字查找
int FindByName(const Contact* pc, char* Name)
{
	assert(pc);
	int i = 0;
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法查找!");
		return;
	}
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(Name, pc->data[i].Name) == 0)
			return i;
	}
	return -1;
}

1.7查找指定联系人

//查找指定联系人
void SehContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法查找!\n");
		return;
	}
	char Name[NAME_MAX] = { 0 };
	printf("请输入要查找的人的姓名:>");
	scanf("%s", Name);
	int pos = FindByName(pc, Name);
	if (pos == -1)
	{
		printf("要查找的联系人不存在!\n");
		return;
	}
	printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话号码", "家庭住址");
	printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",
		pc->data[pos].Name,
		pc->data[pos].Age,
		pc->data[pos].Sex,
		pc->data[pos].Tele,
		pc->data[pos].Addr);
}

1.8修改指定联系人的信息

//修改指点联系人的信息
void MofContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法修改!\n");
		return;
	}
	char Name[NAME_MAX] = { 0 };
	printf("请输入要修改的人的姓名:>");
	scanf("%s", Name);
	int pos = FindByName(pc, Name);
	if (pos == -1)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}
	printf("请输入联系人姓名:>");
	scanf("%s", pc->data[pos].Name);
	printf("请输入联系人年龄:>");
	scanf("%d", &pc->data[pos].Age);
	printf("请输入联系人性别:>");
	scanf("%s", pc->data[pos].Sex);
	printf("请输入联系人电话号码:>");
	scanf("%s", pc->data[pos].Tele);
	printf("请输入联系人家庭住址:>");
	scanf("%s", pc->data[pos].Addr);
}

1.9对所有联系人按姓名进行排序

//对所有联系人按姓名进行排序
void SortContact(const Contact* pc)
{
	assert(pc);
	int i = 0;
	int j = 0;
	for (i = 0; i < pc->sz; i++)
	{
		for (j = i; j < pc->sz; j++)
		{
			if (strcmp(pc->data[i].Name, pc->data[j].Name) > 0)
			{
				PeopInfo temp[] = { 0 };
				temp[0] = pc->data[i];
				pc->data[i] = pc->data[j];
				pc->data[j] = temp[0];
			}
		}
	}
	ShowContact(pc);//显示一下排列结果
}

1.10销毁通讯录,进行动态空间内存的释放

//销毁通讯录,释放动态内存空间
void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	pc = NULL;
	printf("通讯录已销毁\n");
}

2.函数源码

2.1test.c测试代码

//创建一个动态空间内存通讯录,里面存放人的信息,包括姓名,年龄,性别
//电话号码和家庭住址
//结合枚举,必要时要增容
//它包括一下功能
//1.增加联系人
//2.删除指定联系人
//3.查找指定联系人
//4.修改指定联系人
//5.显示所有联系人
//6.对所有联系人进行排序(按姓名)
//7.退出通讯录(这时要记得释放动态内存开辟的空间,避免内存泄漏

#include"contact.h"//引用自己创建的头文件,用双引号

//加入枚举,给下面Switch case语句一个提示,函数写到了通讯录的哪个功能
enum contact
{
	exitContact,
	addContact,
	delContact,
	showContact,
	sehContact,
	mofContact,
	sortContact,
};
void menu(void)
{
	printf("*******************************************\n");
	printf("**********     1.AddContact      **********\n");
	printf("**********     2.DelContact      **********\n");
	printf("**********     3.ShowContact     **********\n");
	printf("**********     4.SehContact      **********\n");
	printf("**********     5.MofContact      **********\n");
	printf("**********     6.SortContact     **********\n");
	printf("**********     0.ExitContact     **********\n");
	printf("*******************************************\n");
}
int main()
{
	int input = 0;
	Contact con;
	//初始化通讯录
	InitContact(&con);
	//打印菜单
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case addContact:
			AddContact(&con);
			break;
		case delContact:
			DelContact(&con);
			break;
		case showContact:
			ShowContact(&con);
			break;
		case sehContact:
			SehContact(&con);
			break;
		case mofContact:
			MofContact(&con);
			break;
		case sortContact:
			SortContact(&con);
			break;
		case exitContact:
			//销毁通讯录,进行动态空间的释放
			DestoryContact(&con);
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);
	return 0;
}

2.2contact.c函数各功能实现代码

#include"contact.h"

//空间增容函数
void check_capacity(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		//通讯录已满,进行增容
		PeopInfo* str = (PeopInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeopInfo));
		if (str == NULL)
		{
			perror("realloc");
			return;
		}
		pc->data = str;
		pc->capacity += INC_SZ;//总容量增加
		printf("空间增容成功,可以继续添加联系人\n");
	}
}

//通过名字查找
int FindByName(const Contact* pc, char* Name)
{
	assert(pc);
	int i = 0;
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法查找!");
		return;
	}
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(Name, pc->data[i].Name) == 0)
			return i;
	}
	return -1;
}
//初始化这个通讯录,初始化为对应的值
void InitContact(Contact* pc)
{
	assert(pc);
	//为通讯录存放人的信息的结构体分配初始空间,并把里面数据直接
	//初始化为0,calloc函数很合适
	PeopInfo* str = (PeopInfo*)calloc(DEFAULT_SZ, sizeof(PeopInfo));
	if (str == NULL)
	{
		perror("calloc");
		return;
	}
	pc->data = str;
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
}

//增加通讯录联系人
void AddContact(Contact* pc)
{
	assert(pc);
	check_capacity(pc);//检查通讯录是否需要增容
	//增加人的信息
	printf("请输入联系人姓名:>");
	scanf("%s", pc->data[pc->sz].Name);
	printf("请输入联系人年龄:>");
	scanf("%d", &pc->data[pc->sz].Age);
	printf("请输入联系人性别:>");
	scanf("%s", pc->data[pc->sz].Sex);
	printf("请输入联系人电话号码:>");
	scanf("%s", pc->data[pc->sz].Tele);
	printf("请输入联系人家庭住址:>");
	scanf("%s", pc->data[pc->sz].Addr);
	pc->sz++;
}
//删除指定联系人
void DelContact(Contact* pc)
{
	assert(pc);
	char Name[NAME_MAX] = { 0 };
	int i = 0;
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除!\n");
		return;
	}
	printf("请输入要删除的人的姓名:>");
	scanf("%s", Name);
	int pos = FindByName(pc, Name);
	if (pos == -1)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	for (i = pos; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功!\n");
}

//显示所有联系人
void ShowContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法显示!\n");
		return;
	}
	int i = 0;
	printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n","姓名","年龄","性别","电话号码","家庭住址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",
			pc->data[i].Name,
		    pc->data[i].Age,
			pc->data[i].Sex,
			pc->data[i].Tele,
			pc->data[i].Addr);
	}
}

//查找指定联系人
void SehContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法查找!\n");
		return;
	}
	char Name[NAME_MAX] = { 0 };
	printf("请输入要查找的人的姓名:>");
	scanf("%s", Name);
	int pos = FindByName(pc, Name);
	if (pos == -1)
	{
		printf("要查找的联系人不存在!\n");
		return;
	}
	printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话号码", "家庭住址");
	printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",
		pc->data[pos].Name,
		pc->data[pos].Age,
		pc->data[pos].Sex,
		pc->data[pos].Tele,
		pc->data[pos].Addr);
}
//修改指点联系人的信息
void MofContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法修改!\n");
		return;
	}
	char Name[NAME_MAX] = { 0 };
	printf("请输入要修改的人的姓名:>");
	scanf("%s", Name);
	int pos = FindByName(pc, Name);
	if (pos == -1)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}
	printf("请输入联系人姓名:>");
	scanf("%s", pc->data[pos].Name);
	printf("请输入联系人年龄:>");
	scanf("%d", &pc->data[pos].Age);
	printf("请输入联系人性别:>");
	scanf("%s", pc->data[pos].Sex);
	printf("请输入联系人电话号码:>");
	scanf("%s", pc->data[pos].Tele);
	printf("请输入联系人家庭住址:>");
	scanf("%s", pc->data[pos].Addr);
}

//对所有联系人按姓名进行排序
void SortContact(const Contact* pc)
{
	assert(pc);
	int i = 0;
	int j = 0;
	for (i = 0; i < pc->sz; i++)
	{
		for (j = i; j < pc->sz; j++)
		{
			if (strcmp(pc->data[i].Name, pc->data[j].Name) > 0)
			{
				PeopInfo temp[] = { 0 };
				temp[0] = pc->data[i];
				pc->data[i] = pc->data[j];
				pc->data[j] = temp[0];
			}
		}
	}
	ShowContact(pc);//显示一下排列结果
}

//销毁通讯录,释放动态内存空间
void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	pc = NULL;
	printf("通讯录已销毁\n");
}

2.3contact.h实现通讯录所需要的头文件代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<errno.h>


#define DEFAULT_SZ 3//初始通讯录内存放的联系人个数
#define INC_SZ 2//每次增容的空间
#define NAME_MAX  20
#define SEX_MAX  5
#define TELE_MAX 12
#define ADDR_MAX 30

//创建一个结构体,用来存放人的信息
typedef struct PeopInfo
{
	char Name[NAME_MAX];
	int Age;
	char Sex[SEX_MAX];
	char Tele[TELE_MAX];
	char Addr[ADDR_MAX];
}PeopInfo;

//创建通讯录,里面包含人的信息,通讯录原本空间大小,以及当前通讯录
//存放了多少人
typedef struct Contact
{
	PeopInfo* data;//不可以是数组了,如果是数组,这块空间就已经被开辟好了
	//不能在进行动态开辟,后续使用时变为了不可修改的左值,建议用指针
	int sz;//当前以存放人的信息的个数
	int capacity;//目前通讯录空间的容量
}Contact;

//空间增容函数
void check_capacity(Contact* pc);

//初始化这个通讯录,初始化为对应的值
void InitContact(Contact* pc);
//增加通讯录联系人
void AddContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//显示所有联系人
void ShowContact(const Contact* pc);
//通过名字查找
int FindByName(const Contact* pc, char* Name);
//查找指定联系人
void SehContact(const Contact* pc);
//修改指点联系人的信息
void MofContact(Contact* pc);
//对所有联系人按姓名进行排序
void SortContact(const Contact* pc);

//销毁通讯录,释放动态内存空间
void DestoryContact(Contact* pc);

3.运行结果


这就是动态通讯录完整版,大家下期再见!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

当Dubbo遇到高并发:探究流量控制解决方案

系列文章目录 面试Dubbo &#xff0c;却问我和Springcloud有什么区别&#xff1f; 超简单&#xff0c;手把手教你搭建Dubbo工程&#xff08;内附源码&#xff09; 【收藏向】从用法到源码&#xff0c;一篇文章让你精通Dubbo的SPI机制 Dubbo最核心功能——服务暴露的配置、使用…

VSCode 设置平滑光标

1.点击左下角的设置按钮&#xff0c;再点击设置 2.点击文本编辑器&#xff0c;点击光标&#xff0c;勾选控制是否启用平滑插入动画。 3.随便打开一个文件&#xff0c;上下左右移动光标时&#xff0c;会发现非常的流畅。 原创作者&#xff1a;吴小糖 创作时间&#xff1a;2023…

华为RS设备状态及接口配置命令

1、查看硬件信息 ①查看序列号 查看整机序列号 display esn display sn ②、查看功率 电源功率 display power 查看光模块功率 display transceiver interface gigabitethernet 1/0/0 verbose ③、查看风扇 display fan ④、查看温度 display temperature all ⑤、查看硬…

安全防御——二、ENSP防火墙实验学习

安全防御 一、防火墙接口以及模式配置1、untrust区域2、trust区域3、DMZ区域4、接口对演示 二、防火墙的策略1、定义与原理2、防火墙策略配置2.1 安全策略工作流程2.2 查询和创建会话 3、实验策略配置3.1 trust-to-untrust3.2 trust-to-dmz3.3 untrust-to-dmz 三、防火墙的区域…

ssh登录界面变成vim提示,进不去系统

是ubuntu系统 使用远程连接root&#xff0c;进去后发现界面变成vim编辑器的介绍界面了 使用普通用户登录 查询用户的登录shell是不是有问题 sudo vim /etc/passwd 发现用户shell变成了vim编辑器 修改为/bin/bash就可以正常登录了 重新登录测试就正常了

【Linux】 man命令使用

介绍 man命令是Linux下最核心的命令之一。而man命令也并不是英文单词“man”的意思&#xff0c;它是单词manual的缩写&#xff0c;即使用手册的意思。 man命令会列出一份完整的说明。 其内容包括命令语法、各选项的意义及相关命令 。更为强大的是&#xff0c;不仅可以查看Lin…

【计算机网络实验/wireshark】tcp建立和释放

wireshark开始捕获后&#xff0c;浏览器打开xg.swjtu.edu.cn&#xff0c;网页传输完成后&#xff0c;关闭浏览器&#xff0c;然后停止报文捕获。 若捕获不到dns报文&#xff0c;先运行ipconfig/flushdns命令清空dns缓存 DNS报文 设置了筛选条件&#xff1a;dns 查询报文目的…

openpnp - 74路西门子飞达控制板(主控板STM32_NUCLEO-144)实现

文章目录 openpnp - 74路西门子飞达控制板(主控板STM32_NUCLEO-144)实现概述飞达控制底板硬件电路程序的修改END openpnp - 74路西门子飞达控制板(主控板STM32_NUCLEO-144)实现 概述 现在调试自己的openpnp设备, 在收尾, 将飞达控制板弄好, 能正常控制设备飞达安装平台上装满…

go语言 | grpc原理介绍(二)

gRPC gRPC 是一个高性能、通用的开源 RPC 框架&#xff0c;其由 Google 2015 年主要面向移动应用开发并基于 HTTP/2 协议标准而设计&#xff0c;基于 ProtoBuf 序列化协议开发&#xff0c;且支持众多开发语言。 由于是开源框架&#xff0c;通信的双方可以进行二次开发&#x…

前端基础之CSS

目录 一、CSS介绍 CSS语法 CSS注释 CSS的几种引入方式 二、CSS选择器 基本选择器 组合选择器 属性选择器 分组和嵌套选择器 伪类选择器 伪元素选择器 选择器的优先级 三、CSS属性相关 宽和高 字体属性 文字属性 背景属性 边框 border-radius display属性 …

与AI对话的艺术:如何优化Prompt以获得更好的响应反馈

前言 在当今数字化时代&#xff0c;人工智能系统已经成为我们生活的一部分。我们可以在智能助手、聊天机器人、搜索引擎等各种场合与AI进行对话。然而&#xff0c;要获得有益的回应&#xff0c;我们需要学会与AI进行有效的沟通&#xff0c;这就涉及到如何编写好的Prompt。 与…

docker 安装 minio (单体架构)

文字归档&#xff1a;https://www.yuque.com/u27599042/coding_star/qcsmgom7basm6y64 查询 minio 镜像 docker search minio拉取镜像 docker pull minio/minio创建启动 minio 容器 用户名长度至少为 3&#xff0c;密码长度至少为 8 docker run \ -p 9000:9000 \ -p 9090:909…

轻量封装WebGPU渲染系统示例<13>- 屏幕空间后处理效果(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/ScreenPostEffect.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 细节请见&#xff1a;引擎系统设计思路 - 用户态与系统态隔离-CSDN博客 2. 高频调用与低频调用隔离。…

C++基础——对于C语言缺点的补充(1)

目录 1.命名空间&#xff1a; 1.1 为什么要引入命名空间&#xff1a; 1.2 命名空间的作用&#xff1a; 1.3 如何访问命名空间内的变量&#xff1a; 1.4 命名空间的嵌套&#xff1a; 1.5 不同文件下同名命名空间的合并&#xff1a; 1.6 命名空间的展开&#xff1a; 2. C…

canal+es+kibana+springboot

1、环境准备 服务器&#xff1a;Centos7 Jdk版本&#xff1a;1.8 Mysql版本&#xff1a;5.7.44 Canal版本&#xff1a;1.17 Es版本&#xff1a;7.12.1 kibana版本&#xff1a;7.12.1 软件包下载地址&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1jRpCJP0-hr9aI…

openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期

文章目录 openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期114.1 注意事项114.2 操作步骤 openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期 114.1 注意事项 创建新用户时&#xff0c;需要限制用户的操作期限&#xff08;有…

antv/g6元素之combo

介绍 在 G6 中&#xff0c;“Combo” 是一种特殊的元素&#xff0c;用于组合和展示多个节点元素的一种方式。它通常用于表示一个组或子图&#xff0c;将多个相关节点组织在一起&#xff0c;并在图形中以单一的形状显示。 属性 type&#xff1a;Combo 的类型&#xff0c;通常是…

【Redis】Redis常用命令-getsetkeysexistsexpirettltype

文章目录 读取文档注意事项set命令get命令全局/通用命令KEYSEXISTSDELEXPIRETTLTYPE 读取文档注意事项 官方文档链接&#xff1a;https://redis.io/ 注意&#xff1a;redis的命令不区分大小写 在redis文档给出的语法格式说明&#xff1a; []&#xff1a;相当于一个独立的单元&a…

面试—如何介绍项目中的多级缓存?

项目中使用的多级缓存也就是 分布式缓存 Redis 本地缓存 Caffeine&#xff0c;那么令 Caffeine 作为一级缓存&#xff0c;Redis 作为二级缓存&#xff0c;在项目中通过记录数据的访问次数&#xff0c;将热点数据放在 本地缓存&#xff0c;将非热点数据放在 Redis缓存 中&#…

详解RSA加密算法 | Java模拟实现RSA算法

目录 一.什么是RSA算法 二.RSA算法的算法原理 算法描述 三.RSA算法安全性 四.RSA算法的速度 五.用java实现RSA算法 一.什么是RSA算法 1976年&#xff0c;Diffie和Hellman在文章“密码学新方向&#xff08;New Direction in Cryptography&#xff09;”中首次提出了公开…