通讯录的实现

> 作者简介:დ旧言~,目前大一,现在学习Java,c,c++,Python等
> 座右铭:松树千年终是朽,槿花一日自为荣。
> 望小伙伴们点赞👍收藏✨加关注哟💕💕 

🌟前言 

       当我们需要办一些业务时,需要录入我们的个人信息,我们的个人信息放在一个系统中,我们简称这个系统为通讯录,而这个通讯录可以存储我们的名字,性别,电话,地址....等等等。今天我们实现一个简单的通讯录。

 🌙主体

咱们需要建立一个项目,项目里面有test.c,Contact.h,Contact.c

其实这里contact.c是重点,咱们一个一个文件看看它们是如何实现的。

 🌠contact.h的实现

这个文件用来声明的,其中包括函数声明,包含头文件,实现动态通讯录,枚举的实现,定义元素类型。咱们逐个实现。

💤定义枚举和元素类型

定义枚举是为了方便使用switch,枚举第一个元素以0为起始位置。

//定义枚举,方便使用switch改变
enum OPTION
{EXIT,//0ADD,//1DEL,//2SEARCH,//3MODIFY,//4SHOW,//5SORT//6
};

通讯录需要存入的数据有名字,性别,电话,地址,因此来定义类型。

//宏定义
#define MAX 100//为静态通讯录服务
#define MAX_NAME 20//名字的最大值
#define MAX_SEX 5//性别的最大值
#define MAX_TELE 12//电话的最大值
#define MAX_ADDR 30//地址的最大值#define DEFAULT_SZ 3//开始通讯录空间大小
#define INC_SZ 2//开辟空间数值大小//定义通讯录所包含的元素类型
typedef struct PeoInfo
{char name[MAX_NAME];int age;char sex[MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR];
}PeoInfo;

 这里用typedef来给结构体重新定义名字。

💤动态通讯录

正常我们写入的代码是这样的

//静态通讯录
//typedef struct Contact
//{
//	PeoInfo data[MAX];
//	int sz;
//}Contact;

这样就把通讯录写死了,当通讯录的空间不够时,无法实现扩容,因此我们需要一个动态的通讯录,而动态的通讯录有什么呢?

1.存放数据的空间(这里需要结构体指针,才能指向下一个元素(这里在动态内存管理已经讲解过了哟))

2.当前放的有效元素的个数

3.通讯录当前的最大容量

//动态通讯录
typedef struct Contact
{PeoInfo* data;//指向了存放数据的空间int sz;//记录的当前放的有效元素的个数int capacity;//通讯录当前的最大容量
}Contact;

💤函数声明

这里就直接上代码了,具体内容咱们到contact.c里面讲解

//函数声明//初始化通讯录
void InitContact(Contact* pc);//增加联系人
void AddContact(Contact* pc);//显示所有联系人的信息
void ShowContact(const Contact* pc);//删除指定联系人
void DelContact(Contact* pc);//查找指定联系人
void SearchContact(const Contact* pc);//修改指定联系人
void ModifyContact(Contact* pc);//销毁通讯录
void DestroyContact(Contact* pc);//保存通讯录信息到文件
void SaveContact(Contact* pc);//排序
void SortContact(Contact* pc)

 🌠test.c的实现

       这里的内容和博主写的三子棋与扫雷极其相似,首先打印菜单,其次能实现循环(进行多次玩),最后根据自己选定内容进行不同的程序。

1.首先需要包含头文件,包含#include"contact.h"

2.其次写上简单的void  menu(),实现打印菜单

3.然后写上void test(),来实现通讯录的各种功能

4.最后写上主函数

#include"contact.h"//续写菜单
void menu()
{printf("*******************************\n");printf("***** 1.add      2.del    *****\n");printf("***** 3.search   4.modify *****\n");printf("***** 5.show     6.sort   *****\n");printf("*****       0.exit        *****\n");printf("*******************************\n");
}void test()
{//定义变量来实现输入int input = 0;//创建结构体Contact con;//初始化通讯录InitContact(&con);//循环do{//先打印菜单menu();printf("请选择->");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case SORT://排序//按照名字排序?//按照年龄排序?break;case EXIT:SaveContact(&con);DestroyContact(&con);printf("退出通讯录\n");break;default:printf("选择错误, 重新选择\n");break;}} while (input);
}//主函数
int main()
{//调用函数test();return 0;
}

 🌠contact.c的实现(重点)

       其实contact.c是通讯录的核心,也是通讯录最难的部分,咱们把这部分分成一块一块,一起来学习这部分。

💤初始化讯录

        如果我们写上静态版本的通讯录就无法实现录入多个用户信息,因此我们只能续写动态版本的通讯录。

💦1.需要为data(指向了存放数据的空间)开辟空间

💦2.判断data是否为空,防止在增删查找本身为空

💦3.对sz(记录的当前放的有效元素的个数)和capacity(通讯录当前的最大容量)初始化

💦4.保存在文件(调用函数,后面会讲解)

//静态版本
//void InitContact(Contact* pc)
//{
//	assert(pc);
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//}//初始化通讯录(动态)
void InitContact(Contact* pc)
{//判断pc是否为空assert(pc);//开辟空间pc->data = (PeoInfo*)malloc(sizeof(PeoInfo));//判断是否为空if (pc->data == NULL){perror("InitContact");return 0;}//初始化pc->sz = 0;pc->capacity = DEFAULT_SZ;//文件中保存的信息加载到通讯录中LoadContact(pc);
}

 💤保存文件

这里因为还没讲到文件管理,大家就算看看啦。

void LoadContact(Contact* pc)
{//打开文件FILE* pf = fopen("contact.dat", "rb");if (pf == NULL){perror("LoadContact");return;}//读文件PeoInfo tmp = { 0 };while (fread(&tmp, sizeof(PeoInfo), 1, pf)){//这里如果内存不足需要扩容if (0 == CheckCapacity(pc))return;pc->data[pc->sz] = tmp;pc->sz++;}//关闭文件fclose(pf);pf = NULL;
}//保存通讯录信息到文件
void SaveContact(Contact* pc)
{FILE* pf = fopen("contact.dat", "wb");if (pf == NULL){perror("SaveContact");return;}//写数据int i = 0;for (i = 0; i < pc->sz; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}

 💤扩容

        当我们的内存不够时我们就需要括容。我们这里的sz(记录的当前放的有效元素的个数),等于capacity(通讯录当前的最大容量)时,就需要扩容。这里我们用realloc来开辟空间,做到对动态开辟内存大小的调整。

💦1.开辟空间,采用结构体指针来接收开辟的空间。

💦2.判断是否开好相应的空间。

💦3.赋值

//是否需要扩容
int CheckCapacity(Contact* pc)
{//判断sz是否等于capacityif (pc->sz == pc->capacity){//开辟空间PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));//判断if (ptr == NULL){perror("CheckCapacity");return;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功\n");return 1;}}
}

 💤增加联系人

        这个函数我们已经熟清熟路了,这里我们只需注意sz(记录的当前放的有效元素的个数)需要++,因为需要指向下一个元素的位置

//增加联系人
void AddContact(Contact* pc)
{//断言assert(pc);//如果通讯录为空直接跳出循环if (CheckCapacity(pc) == 0){return;}//输入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);//当空间不够时需要扩容CheckCapacity(pc);//指向下个元素pc->sz++;printf("成功增加联系人\n");
}

 💤显示所有联系人的信息

这里和打印没啥区别,太简单了。

//显示所有联系人的信息
void ShowContact(const Contact* pc)
{//断言assert(pc);int i = 0;//打印列标题printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-10s\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);}
}

💤删除指定联系人

       因为这里删除指定联系人和查找指定联系人都需要查找指定的人,因此我们这里直接再写一个函数,来遍历整个通讯录。

       我们采用向前覆盖的方式来删除指定联系人。这里和数据结构的重合了,大家有兴趣可以看看博主写的数据结构相关内容。

//查找元素下标
static int FindByName(const Contact* pc, char name[])
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//找不到
}//删除指定联系人
void DelContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}char name[MAX_NAME] = { 0 };assert(pc);//删除printf("请输入要删除的人名字:>");scanf("%s", name);//找到要删除的人int del = FindByName(pc, name);if (del == -1){printf("要删除的人不存在\n");return;}int i = 0;//删除坐标位del的联系人(向前覆盖)for (i = del; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}//要向后退一个元素pc->sz--;printf("成功删除联系人\n");
}

 注意需要让sz(记录的当前放的有效元素的个数)--.

💤查找指定联系人

有了删除指定联系人的函数,实现这个函数太简单了。

//查找指定联系人
void SearchContact(const Contact* pc)
{//断言assert(pc);char name[MAX_NAME] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1)printf("要查找的人不存在\n");else{printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据printf("%-10s\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 ModifyContact(Contact* pc)
{//断言assert(pc);char name[MAX_NAME] = { 0 };printf("请输入要修改人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1)printf("要修改的人不存在\n");else{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);printf("修改成功\n");}
}

💤销毁通讯录

当我们不再使用通讯录了,就要释放内存,所有的元素置0。

//销毁通讯录
void DestroyContact(Contact* pc)
{//释放free(pc->data);//置为空和0pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}

 💤排序

        这里我们就不得不提快排了,博主写过一篇关于快排的博客,大家可以仔细阅读一下,在这里我们就不再多多赘述了。

//排序
int cmp_s(const void* elem1, const void* elem2)
{return strcmp((char*)elem1, (char*)elem2);
}void SortContact(Contact* pc)
{qsort(pc, pc->sz, sizeof(pc->data[0]), cmp_s);printf("%-10s\t%-5s\t%-10s\t%-5s\t%-10s\n", "姓名", "年龄", "电话", "性别", "地址");for (int i = 0; i < pc->sz; i++){printf("%-10s\t%-5d\t%-10s\t%-5s\t%-10s\n",pc->data[i].name,pc->data[i].age,pc->data[i].tele,pc->data[i].sex,pc->data[i].addr);}
}

 🌠整体代码

 💤contact.h

#pragma once//包含头文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>//宏定义
#define MAX 100//为静态通讯录服务
#define MAX_NAME 20//名字的最大值
#define MAX_SEX 5//性别的最大值
#define MAX_TELE 12//电话的最大值
#define MAX_ADDR 30//地址的最大值#define DEFAULT_SZ 3//开始通讯录空间大小
#define INC_SZ 2//开辟空间数值大小//定义枚举,方便使用switch改变
enum OPTION
{EXIT,//0ADD,//1DEL,//2SEARCH,//3MODIFY,//4SHOW,//5SORT//6
};//定义通讯录所包含的元素类型
typedef struct PeoInfo
{char name[MAX_NAME];int age;char sex[MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR];
}PeoInfo;//静态通讯录
//typedef struct Contact
//{
//	PeoInfo data[MAX];
//	int sz;
//}Contact;//动态通讯录
typedef struct Contact
{PeoInfo* data;//指向了存放数据的空间int sz;//记录的当前放的有效元素的个数int capacity;//通讯录当前的最大容量
}Contact;//函数声明//初始化通讯录
void InitContact(Contact* pc);//增加联系人
void AddContact(Contact* pc);//显示所有联系人的信息
void ShowContact(const Contact* pc);//删除指定联系人
void DelContact(Contact* pc);//查找指定联系人
void SearchContact(const Contact* pc);//修改指定联系人
void ModifyContact(Contact* pc);//销毁通讯录
void DestroyContact(Contact* pc);//保存通讯录信息到文件
void SaveContact(Contact* pc);//排序
void SortContact(Contact* pc);

 💤test.c

#include"contact.h"//续写菜单
void menu()
{printf("*******************************\n");printf("***** 1.add      2.del    *****\n");printf("***** 3.search   4.modify *****\n");printf("***** 5.show     6.sort   *****\n");printf("*****       0.exit        *****\n");printf("*******************************\n");
}void test()
{//定义变量来实现输入int input = 0;//创建结构体Contact con;//初始化通讯录InitContact(&con);//循环do{//先打印菜单menu();printf("请选择->");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case SORT:SortContact(&con);break;case EXIT:SaveContact(&con);DestroyContact(&con);printf("退出通讯录\n");break;default:printf("选择错误, 重新选择\n");break;}} while (input);
}//主函数
int main()
{test();return 0;
}

 💤contact.c

#include"contact.h"//静态版本
//void InitContact(Contact* pc)
//{
//	assert(pc);
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//}//静态版本
//
//void AddContact(Contact* pc)
//{
//	assert(pc);
//	if (pc->sz == MAX)
//	{
//		printf("通讯录已满,无法添加\n");
//		return;
//	}
//
//	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++;
//	printf("成功增加联系人\n");
//}//是否需要扩容(声明函数)
int CheckCapacity(Contact* pc);void LoadContact(Contact* pc)
{//打开文件FILE* pf = fopen("contact.dat", "rb");if (pf == NULL){perror("LoadContact");return;}//读文件PeoInfo tmp = { 0 };while (fread(&tmp, sizeof(PeoInfo), 1, pf)){if (0 == CheckCapacity(pc))return;pc->data[pc->sz] = tmp;pc->sz++;}//关闭文件fclose(pf);pf = NULL;
}//初始化通讯录(动态)
void InitContact(Contact* pc)
{//判断pc是否为空assert(pc);//开辟空间pc->data = (PeoInfo*)malloc(sizeof(PeoInfo));//判断是否为空if (pc->data == NULL){perror("InitContact");return 0;}//初始化pc->sz = 0;pc->capacity = DEFAULT_SZ;//文件中保存的信息加载到通讯录中LoadContact(pc);
}//是否需要扩容
int CheckCapacity(Contact* pc)
{//判断sz是否等于capacityif (pc->sz == pc->capacity){//开辟空间PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));//判断if (ptr == NULL){perror("CheckCapacity");return;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功\n");return 1;}}
}//增加联系人
void AddContact(Contact* pc)
{//断言assert(pc);//如果通讯录为空直接跳出循环if (CheckCapacity(pc) == 0){return;}//输入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);//CheckCapacity(pc);//指向下个元素pc->sz++;printf("成功增加联系人\n");
}//显示所有联系人的信息
void ShowContact(const Contact* pc)
{//断言assert(pc);int i = 0;//打印列标题printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-10s\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);}
}//查找元素下标
static int FindByName(const Contact* pc, char name[])
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//找不到
}//删除指定联系人
void DelContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}char name[MAX_NAME] = { 0 };assert(pc);//删除printf("请输入要删除的人名字:>");scanf("%s", name);//找到要删除的人int del = FindByName(pc, name);if (del == -1){printf("要删除的人不存在\n");return;}int i = 0;//删除坐标位del的联系人(向前覆盖)for (i = del; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}//要向后退一个元素pc->sz--;printf("成功删除联系人\n");
}//查找指定联系人
void SearchContact(const Contact* pc)
{//断言assert(pc);char name[MAX_NAME] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1)printf("要查找的人不存在\n");else{printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据printf("%-10s\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 ModifyContact(Contact* pc)
{//断言assert(pc);char name[MAX_NAME] = { 0 };printf("请输入要修改人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1)printf("要修改的人不存在\n");else{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);printf("修改成功\n");}
}//销毁通讯录
void DestroyContact(Contact* pc)
{//释放free(pc->data);//置为空和0pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}//保存通讯录信息到文件
void SaveContact(Contact* pc)
{FILE* pf = fopen("contact.dat", "wb");if (pf == NULL){perror("SaveContact");return;}//写数据int i = 0;for (i = 0; i < pc->sz; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}//排序
int cmp_s(const void* elem1, const void* elem2)
{return strcmp((char*)elem1, (char*)elem2);
}void SortContact(Contact* pc)
{qsort(pc, pc->sz, sizeof(pc->data[0]), cmp_s);printf("%-10s\t%-5s\t%-10s\t%-5s\t%-10s\n", "姓名", "年龄", "电话", "性别", "地址");for (int i = 0; i < pc->sz; i++){printf("%-10s\t%-5d\t%-10s\t%-5s\t%-10s\n",pc->data[i].name,pc->data[i].age,pc->data[i].tele,pc->data[i].sex,pc->data[i].addr);}
}

🌟结束语

今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小说手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谷歌推出首款量子弹性 FIDO2 安全密钥

谷歌在本周二宣布推出首个量子弹性 FIDO2 安全密钥&#xff0c;作为其 OpenSK 安全密钥计划的一部分。 Elie Bursztein和Fabian Kaczmarczyck表示&#xff1a;这一开源硬件优化的实现采用了一种新颖的ECC/Dilithium混合签名模式&#xff0c;它结合了ECC抵御标准攻击的安全性和…

Tomcat 一次请求的生命周期

在使用 Tomcat 的时候&#xff0c;我们只需要在 Servlet 实现类中写我们的业务逻辑代码即可&#xff0c;不需要管 Socket 连接、协议处理要怎么实现&#xff0c;因为这部分作为不经常变动的部分&#xff0c;被封装到了 Tomcat 中&#xff0c;程序员只需要引入 Tomcat 中即可&am…

【LeetCode-中等题】49. 字母异位词分组

题目 题解一:排序哈希表 思路:由于互为字母异位词的两个字符串包含的字母相同&#xff0c;因此对两个字符串分别进行排序之后得到的字符串一定是相同的&#xff0c;故可以将排序之后的字符串作为哈希表的键。 核心api: //将字符串转换为字符数组char[] ch str.toCharArray();…

页面滑动到可视区域加载更多内容思维流程

页面滑动到可视区域加载更多内容思维流程

GEEMAP 中如何拉伸图像

图像拉伸是最基础的图像增强显示处理方法&#xff0c;主要用来改善图像显示的对比度&#xff0c;地物提取流程中往往首先要对图像进行拉伸处理。图像拉伸主要有三种方式&#xff1a;线性拉伸、直方图均衡化拉伸和直方图归一化拉伸。 GEE 中使用 .sldStyle() 的方法来进行图像的…

Android岗位技能实训室建设方案

一 、系统概述 Android岗位技能作为新一代信息技术的重点和促进信息消费的核心产业&#xff0c;已成为我国转变信息服务业的发展新热点&#xff1a;成为信息通信领域发展最快、市场潜力最大的业务领域。互联网尤其是移动互联网&#xff0c;以其巨大的信息交换能力和快速渗透能力…

机器学习编译系列---张量程序抽象

机器学习编译系列---张量程序抽象 1. 张量函数概念的引入与抽象的必要性 1. 张量函数概念的引入与抽象的必要性 在文章机器学习编译系列—概述中提到&#xff0c;机器学习编译的一个很重要操作是做等价变换来减少内存或者提高运行效率。变换是以“元张量函数”(private tensor …

Viewpager2+Fragment+指示器

Viewpager2Fragment指示器 效果展示&#xff1a; MainActivity.java package com.huawei.myviewpager;import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.viewpager2.widget.ViewPager2;import android.os.Bundle; …

小白到运维工程师自学之路 第七十五集 (Kubernetes 企业级高可用部署)2

8、添加master节点 在k8s-master2和k8s-master3节点创建文件夹 mkdir -p /etc/kubernetes/pki/etcd在k8s-master1节点执行 从k8s-master1复制密钥和相关文件到k8s-master2和k8s-master3 scp /etc/kubernetes/admin.conf root192.168.77.15:/etc/kubernetes scp /etc/kubernet…

jmap(Memory Map for Java)Java内存映像工具

jmap&#xff08;Memory Map for Java&#xff09;Java内存映像工具 jmap&#xff08;Memory Map for Java&#xff09;命令用于生成堆转储快照&#xff08;一般称为heapdump或dump文件&#xff09; 如果不使用jmap命令&#xff0c;要想获取Java堆转储快照也还有一些比较“暴…

RabbitMq:Topic exchange(主题交换机)的理解和使用

RabbitMq:Topic exchange(主题交换机)的理解和使用 在RabbitMq中&#xff0c;生产者的消息都是通过交换机来接收&#xff0c;然后再从交换机分发到不同的队列中去&#xff0c;在分发的过程中交换机类型会影响分发的逻辑&#xff0c;下面主要讲解一下主题交换机。 ​ 主题交换…

2023面试八股文 ——Java基础知识

Java基础知识 一.Java概述何为编程什么是Javajdk1.5之后的三大版本JVM、JRE和JDK的关系什么是跨平台性&#xff1f;原理是什么Java语言有哪些特点什么是字节码&#xff1f;采用字节码的大好处是什么什么是Java程序的主类&#xff1f;应用程序和小程序的主类有何不同&#xff1f…

数据结构之并查集

并查集 1. 并查集原理2. 并查集实现3. 并查集应用3.1 省份数量3.2 等式方程的可满足性 4. 并查集的优缺点及时间复杂度 1. 并查集原理 并查表原理是一种树型的数据结构&#xff0c;用于处理一些不相交集合的合并及查询问题。并查集的思想是用一个数组表示了整片森林&#xff0…

微服务中间件--微服务保护

微服务保护 微服务保护a.sentinelb.sentinel限流规则1) 流控模式1.a) 关联模式1.b) 链路模式 2) 流控效果2.a) 预热模式2.b) 排队等待 3) 热点参数限流 c.隔离和降级1) Feign整合Sentinel2) 线程隔离2.a) 线程隔离&#xff08;舱壁模式&#xff09; 3) 熔断降级3.a) 熔断策略-慢…

21-注意点说明:scoped样式冲突 / data

组件的三大组成部分 - 注意点说明 组件的样式冲突 scoped 默认情况:写在组件中的样式会 全局生效 -> 因此很容易造成多个组件之间的样式冲突问题 1.全局样式: 默认组件中的样式会作用到全局 2.局部样式: 可以给组件加上 scoped 属性,可以让样式只作用于当前组件 scoped原理…

构建去中心化微服务集群,满足高可用性和高并发需求的实践指南!

随着互联网技术的不断发展&#xff0c;微服务架构已经成为了开发和部署应用程序的一种主流方式。然而&#xff0c;当应用程序需要满足高可用性和高并发需求时&#xff0c;单一中心化的微服务架构可能无法满足性能和可靠性的要求。因此&#xff0c;构建一个去中心化的微服务集群…

岩土工程安全监测隧道中使用振弦采集仪注意要点?

岩土工程安全监测隧道中使用振弦采集仪注意要点&#xff1f; 岩土工程的安全监测是非常重要的&#xff0c;它可以帮助工程师及时发现可能存在的问题&#xff0c;并及时解决&#xff0c;保障施工进度以及施工质量&#xff0c;保障工程的安全运行。其中&#xff0c;振弦采集仪是…

五款拿来就能用的炫酷表白代码

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 五款炫酷表白代码 1、无限弹窗表白2、做我女朋友好吗&#xff0c;不同意就关机3、…

股票交易这个游戏玩法的本质

养家老师的“买在分歧&#xff0c;卖在一致”不用过度解读了&#xff0c;这句话也会是一个人入门标志&#xff0c;那就是这个市场是博弈的市场&#xff0c;预期打满没有任何分歧的话&#xff0c;那就没有继续博弈的价值了&#xff0c;也就只有最后一批接盘的人&#xff0c;而分…

jenkins gitlab 安装

目录 一 准备安装环境 二 安装gitlab软件 三 配置gitlab 四 重新加载配置启动gitlab 五 修改密码 五 创建用户组 一 准备安装环境 sudo yum update sudo yum install -y curl policycoreutils-python openssh-server安装 Postfix 邮件服务器&#xff0c;以便 Git…