基于C语言 --- 自己写一个通讯录

news2024/12/23 3:37:55

C语言程序设计笔记---039

  • C语言之实现通讯录
    • 1、介绍C/C++程序的内存开辟
    • 2、C语言实现通讯录
      • 2.1、ContactMain.c程序大纲
      • 2.2、Contact2.h
      • 2.3、Contact2.c
        • 2.3.1 InitContact( )初始化通讯录函数
        • 2.3.2 AddContact( )添加联系人和CheckCapaticy( )检查容量函数
        • 2.3.3、ShowContact( )显示联系人函数
        • 2.3.4、DelContact( )删除联系人和FindByName( )函数
        • 2.3.5、SearchContact( )查找联系人
        • 2.3.6、ModifyContact( )修改联系人
        • 2.3.7、CleanContact( )清空联系人
        • 2.3.8、SortContact( )排序联系人
    • 4、结语

C语言之实现通讯录

前言:
通过C语言自定义类型的知识,这篇将对动态内存的管理知识,接下来进行应用学习写一个简易的通讯录。

/知识点汇总/

1、介绍C/C++程序的内存开辟

大致整体空间的分配
内核空间:用户代码…(不能读写)
栈区:局部变量、形式参数…
内存映射段:文件映射、动态库、匿名映射…
堆区:动态内存、malloc/calloc/free…
数据段(数据段):全局数据、静态数据、static常变量…
代码段:可执行代码、只读常量
具体如下图所示
在这里插入图片描述

2、C语言实现通讯录

实现一个通讯录;
通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址
提供方法:
1.添加联系人信息
2.删除指定联系人信息
3.查找指定联系人信息
4.修改指定联系人信息
5.显示所有联系人信息
6.清空所有联系人
7.以名字排序所有联系人

2.1、ContactMain.c程序大纲

首先,从生活实际使用的角度出发,我们需要一个显示的菜单,显示我们需要的功能集。
这里可以前面篇章所学的menu( )自定义函数,设计一个简易的菜单。

//菜单
void menu()
{
	printf("*************************************\n");
	printf("******** 1.add          2.del   *****\n");
	printf("******** 3.sreach       4.modify*****\n");
	printf("******** 5.show         6.sort  *****\n");
	printf("******** 7.clean        0.exit  *****\n");
	printf("*************************************\n");
}

为了让选项贴合实际,数字0~7可以使用一个自定义类型所学的枚举类型来列举引用即可。

//枚举常量
enum Option
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,//3
	MODIFY,//4
	SHOW,//5
	SORT,//6
	CLEAN//7
};

其中可以看见,我把EXIT写在第一个,这样是为了利用枚举成员变量未初始化是默认从0开始的特点,从而与选项一致对应。
那么接下来,主函数中就是利用do while和 switch 搭建一个程序执行框架。

int main()
{
	int input = 0;
	//创建通讯录
	Contact con;
	//初始化通讯录
	InitContatc(&con);
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		 case ADD:
			 printf("\n添加联系人\n\n");
			 AddContact(&con);
			 break;
		 case DEL:
			 printf("\n删除联系人\n\n");
			 DelContact(&con);
			 break;
		 case SEARCH:
			 printf("\n搜索联系人\n\n");
			 SearchContact(&con);
			 break;
		 case MODIFY:
			 printf("\n修改联系人\n\n");
			 ModifyContact(&con);
			 break;
		 case SHOW:
			 printf("\n显示联系人\n\n");
			 ShowContact(&con);
			 break;
		 case SORT:
			 printf("\n排序联系人\n\n");
			 SortContact(&con);
			 break;
		 case CLEAN:
			 printf("\n清空联系人\n\n");
			 CleanContact(&con);
			 break;
		 case EXIT:
			 printf("\n退出通讯录\n\n");
			 break;
		 default:
			 printf("\n输入错误请重新输入\n\n");
			 break;
		}
	} while (input);
	return 0;
}

主函数首先定义一个input由玩家输入的变量,然后同步switch语句,根据选项进入不同的入口,分别执行添加联系人、删除联系人、搜索联系人、修改联系人、显示联系人、排序联系人、清空联系人、退出通讯录以及输入数值不对做出一个反馈,输入错误的提示信息。

2.2、Contact2.h

主要用于存放所自定义的函数和头文件等声明的程序
由于涉及多种类型的数据,所以最好的方法就是定义一个结构体类型。
然后,这里同时提供通讯录初始化的静态数组的版本,也提供动态内存的写法,利用前篇动态内存空间管理的知识,申请动态开辟空间和管理。
其它的声明,通俗易懂,就不多赘述,详见代码注释的说明。

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 20
#define ADDR_MAX 20

//#define MAX 100
#define DEFAULT_SZ 3   //默认容量
#define DEFAULT_INC 2  //增容量
//结构体类型申明
typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}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 DestoryContact(Contact* pc);

//显示通讯录
void ShowContact(Contact* pc);

//删除联系人
void DelContact(Contact* pc);


//查找联系人
void SearchContact(Contact* pc);

//修改联系人
void ModifyContact(Contact* pc);

//清空通讯录
void CleanContact(Contact* pc);

//排序通讯录
void SortContact(Contact* pc);

2.3、Contact2.c

主要用于存放对 ContactMain.c 程序大纲做提到的函数进行封装,实现具体的功能的程序
说明:基于ContactMain.c 程序大纲逻辑对代码进行讲解

2.3.1 InitContact( )初始化通讯录函数

首先在头文件中,定义了结构体成员和创建好后,根据主函数逻辑对通讯录进行初始化.
初始化可以理解为将通讯录的数据赋予一个初始值,方便我们后续对其进行操作。
sz清零就是使得当前存放的长度为0;capacity清零就是让容量为默认的3个容量;
接下来就是将数据初始化,这里为了直接方便的初始化所以选择使用calloc而不是malloc函数来初始化,因为它们的区别就在于calloc会直接将每个字节初始化为0,而malloc不会初始化。
然后结合参数的意思就是将申请开辟默认容量乘以结构体得的大小的空间。
为了代码的规范性、健壮性需要做开辟空间失败的反馈。

//初始化通讯录 -- 静态版本
//void InitContact(Contact* pc)
//{
//	assert(pc);
//	pc->sz = 0;
//	memset(pc->data, 0, sizeof(pc->data));//将数据以每个字节设置或初始化为0
//}

//初始化通讯录 -- 动态版本
void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = calloc(pc->capacity , sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc\n");
		return;
	}
}
2.3.2 AddContact( )添加联系人和CheckCapaticy( )检查容量函数

同样,提供了静态版本和动态版本,简单说明一下静态和动态的区别,当我们不清楚需要多大的空间时,比如需要存放1000个数据,静态给10太小,给10000太大,所以存在空间资源的浪费甚至是溢出等情况,那么就引用动态的方式存储,就可以实现灵活的开辟空间和释放空间,既满足需求,也能合理使用空间资源。那么接下来,都是以动态进行分享思路。
回到添加联系人的函数体,我们每次存入数据前,肯定需要检查是否能够存放得下,那么就需要对当前空间的剩余量与数据的大小,进行判断,如果放不下那么就执行扩容,反之就是放得下。
那么就可以继续执行添加联系人得信息,利用的是按照逻辑访问结构体成员依次添加,最后完成一个数据添加后,sz当前通讯录的信息个数随着加1。
对于,增容函数,主要是依靠realloc函数实现增容。参数是开辟空间的首地址和增容的大小。
另外,对于realloc还有一种特殊情况,就不展开了,详见前篇动态内存空间管理的知识。

//增加联系人 --- 静态版本
//void AddContact(Contact* pc)
//{
//	assert(pc);
//	if (pc->sz == MAX)
//	{
//		printf("\n通讯录已满,无法增加\n\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增加成功\n\n");
//}

//增容函数
static void CheckCapaticy(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += DEFAULT_INC;
			printf("\n增容成功\n\n");
		}
		else
		{
			perror("AddContact->realloc\n");
			return;
		}
	}
}
//增加联系人 --- 动态版本
void AddContact(Contact* pc)
{
	assert(pc);
	//如果容量与信息相等,自动增加容量
	CheckCapaticy(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++;
	printf("\n增加成功\n\n");
}

在这里插入图片描述

2.3.3、ShowContact( )显示联系人函数

这个函数的逻辑就比较简单了,就是遍历数据成员依次打印出来就行,重点在于对界面符合一定的审美,包括占位符、缩进。标题行的重要性等比较灵活,这里仅提供参考一种打印效果如下所示:
在这里插入图片描述

//显示通讯录
void ShowContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("\n无法显示,通讯录为空\n\n");
		return;
	}
	//显示联系人
	//打印标题 -- 美化
	printf("%-10s%-5s%-5s%-20s%-20s\n", "姓名", "年龄", "性别", "电话", "地址");
	//打印联系人信息
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s%-5d%-5s%-20s%-20s\n",
			pc->data[i].name, 
			pc->data[i].age, 
			pc->data[i].sex, 
			pc->data[i].tele, 
			pc->data[i].addr
			);
	}
}

在这里插入图片描述

2.3.4、DelContact( )删除联系人和FindByName( )函数

对于删除函数,我们需要先判断是否为空,当数据为空,没有删除的对象了,顾名思义就不能删除了;其次,我们需要删除某个联系人对象,与后面的查找联系人和修改联系人都需要去遍历查找所以,为了方便调用就封装了一个匹配联系人的函数FindByName,并且是根据联系人姓名来进行匹配的。直接使用strcmp即可。在删除目标联系人后,后面的数据就得向前移动。使用for语句移动,最后sz也需要随着减1。

//匹配联系人函数
static int FindByName(Contact* pc, char* name)
{
	assert(pc);
	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)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("\n无法删除,通讯录为空\n\n");
		return;
	}
	//输入要删除的联系人姓名
	char name[NAME_MAX];
	printf("请输入要删除联系人的姓名:>");
	scanf("%s", name);
	//查找匹配联系人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("\n无此联系人\n\n");
		return;
	}
	//删除联系人
	int i = 0;
	for (i = ret; i < pc->sz; i++)
	{
		pc->data[i] = pc->data[ i + 1];
	}
	//处理最后一个联系人
	pc->sz--;
	printf("\n删除成功\n\n");
}

在这里插入图片描述
在这里插入图片描述

2.3.5、SearchContact( )查找联系人

查找联系人的套路都大相径庭了,结合匹配函数找到对应的联系人,然后单独打印输出即可。

//查找联系人
void SearchContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("\n无法查找,通讯录为空\n\n");
		return;
	}
	//输入要查找的联系人姓名
	char name[NAME_MAX];
	printf("请输入要查找联系人的姓名:>");
	scanf("%s", name);
	//查找匹配联系人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("\n无此联系人\n\n");
		return;
	}
	//显示对应联系人
	//打印标题 -- 美化
	printf("%-10s%-5s%-5s%-20s%-20s\n", "姓名", "年龄", "性别", "电话", "地址");
	//打印联系人信息
	printf("%-10s%-5d%-5s%-20s%-20s\n",
		pc->data[ret].name,
		pc->data[ret].age,
		pc->data[ret].sex,
		pc->data[ret].tele,
		pc->data[ret].addr
	);
}

在这里插入图片描述

2.3.6、ModifyContact( )修改联系人

修改联系人,在理解了前面的内容,也不难理解,结合匹配联系人的函数找到需要修改的联系人,然后,输入修改后的信息即可。但是,这里比较冗余,不难发现会修改联系人的所有属性。可以增加一个switch选择只需要更改的属性即可。值得注意的是,在以上结合匹配函数的条件下,使用的是返回值ret才能正确符合逻辑运行哦,不能盲目复制粘贴前面的添加联系人的输入信息部分的代码。

//修改联系人
void ModifyContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("\n无法修改,通讯录为空\n\n");
		return;
	}
	//输入要修改的联系人姓名
	char name[NAME_MAX];
	printf("请输入要修改联系人的姓名:>");
	scanf("%s", name);
	//查找匹配联系人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("\n无此联系人\n\n");
		return;
	}
	//找到了,则修改
	printf("请输入新的姓名:>");
	scanf("%s", pc->data[ret].name);
	printf("请输入年龄:>");
	scanf("%d", &pc->data[ret].age);
	printf("请输入性别:>");
	scanf("%s", pc->data[ret].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[ret].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[ret].addr);

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

在这里插入图片描述
在这里插入图片描述

2.3.7、CleanContact( )清空联系人

清空通讯录,跟初始化通讯录类似,信息重新清零或者复位即可。

//清空通讯录
void CleanContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capacity = 0;
	free(pc->data);
	pc->data = NULL;
	//pc->data = 0;
	printf("\n已清空通讯录\n\n");
}

在这里插入图片描述
在这里插入图片描述

2.3.8、SortContact( )排序联系人

排序联系人主要结合了前面篇章的qsort函数的功能,这里完成的是以姓名排序。

//排序通讯录
//void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
static cmp_by_name(const void* e1,const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}

void SortContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("\n无法排序,通讯录为空\n\n");
		return;
	}
	//排序联系人
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_by_name);
	printf("\n排序成功\n\n");
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、结语

相信通过这样一个简易通讯录的实现,更具掌握了对数组、动态内存管理的操作以及对自定义函数的深刻认识;
如果觉着文章对您有所帮助,请不要吝啬的一赞三连哦,谢谢阅读,不足之处还请多多指教。

半亩方糖一鉴开,天光云影共徘徊。
问渠哪得清如许?为有源头活水来。–朱熹(观书有感)

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

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

相关文章

重大技术问题,iPhone 15 Pro Max面临“烧屏门”风波 | 百能云芯

近期&#xff0c;社交媒体平台上陆续涌现大量用户和数码博主就iPhone 15 Pro Max出现烧屏问题的投诉与评论。 烧屏问题是OLED屏幕常见的一个缺陷&#xff0c;这是由OLED屏幕发光机制引发的&#xff0c;OLED屏幕可视为由无数微小的灯泡-像素点构成&#xff0c;这些像素点可以独立…

redis场用命令及其Java操作

目录 1. Redis入门 1.1 Redis简介 1.2 Redis下载与安装 1.2.1 Redis下载 1.2.2 Redis安装 1.3 Redis服务启动与停止 1.3.1 服务启动命令 1.3.2 客户端连接命令 1.3.3 修改Redis配置文件 1.3.4 Redis客户端图形工具 2. Redis数据类型 2.1 五种常用数据类型介绍 2.2 …

【单片机基础】按键状态机实现短按、长按、双击、三击和N击

下载地址&#xff1a; 【CSDNNaiva】源码&#xff1a;HK32F030M-按键扫描-短按长按检测 参考资料 [1] 【CSDNPillarPeng】【按键】[独立按键] - 1&#xff1a; 单击&#xff0c;双击&#xff0c;三击以及N击 [2] 【CSDNPillarPeng】【按键】[独立按键] - 2&#xff1a;双击 …

git简介和指令

git是一个开源的的分布式版本控制系统&#xff0c;用于高效的管理各种大小项目和文件 用途&#xff1a;防止代码丢失&#xff0c;做备份 项目的版本管理和控制&#xff0c;可以通过设置节点进行跳转 建立各自的开发环境分支&#xff0c;互不影响&#xff0c;方便合并 在多终端开…

git pull 和 git fetch 有什么区别?

一、是什么 先回顾两个命令的定义 git fetch 命令用于从另一个存储库下载对象和引用git pull 命令用于从另一个存储库或本地分支获取并集成(整合) 再来看一次git的工作流程图&#xff0c;如下所示&#xff1a; 可以看到&#xff0c;git fetch是将远程主机的最新内容拉到本地…

md5算法实现

前言 md5算法是我们经常会用到的一个hash函数, 虽然已经被证明是不安全的了, 但其应用依然十分广泛. 哈希函数具有如下特点: 将任意长度的字符串映射为固定长度源数据微小的改动会导致结果差异巨大不可逆暴力破解困难 你有没有好奇过, 哈希函数是如何做到这些的呢? 本文就…

LSTM 与 GRU

RNN无法处理长距离依赖问题&#xff0c;通俗点就是不能处理一些较长的序列数据&#xff0c;那么今天就来介绍一下两个能处理长距离依赖问题地RNN变种结构&#xff0c;LSTM和GRU。 1. LSTM&#xff08;Long short-term memory&#xff09; 1.1 LSTM结构 上左图是普通RNN结构图…

深入浅出排序算法之归并排序

目录 1. 归并排序的原理 1.1 二路归并排序执行流程 2. 代码分析 2.1 代码设计 3. 性能分析 4. 非递归版本 1. 归并排序的原理 “归并”一词的中文含义就是合并、并入的意思&#xff0c;而在数据结构中的定义是将两个或者两个以上的有序表组合成一个新的有序表。 归并排序…

前端性能优化 - 虚拟滚动

一 需求背景 需求&#xff1a;在一个表格里面一次性渲染全部数据&#xff0c;不采用分页形式&#xff0c;每行数据都有Echart图插入。 问题&#xff1a;图表渲染卡顿 技术栈&#xff1a;Element UI 卡顿原因&#xff1a;页面渲染时大量的元素参与到了重排的动作中&#xff0c;…

2023 uniapp( vue3)使用canvas生成海报并保存,taro/微信小程序也适用

有段时间没写vue了&#xff0c;有点生疏了...... 1、代码有注释&#xff0c;完整代码如下 <template><view class"page"><canvas class"canvas" v-if"isShow" :style"{width:${canvasWidth}px,height:${canvasHeight}px}&…

格式化之 %d,%2d, %02d

在Java中&#xff0c;%d&#xff0c;%2d 和 %02d 都用于格式化整数&#xff1a; %d&#xff1a; %d 是格式化整数的基本占位符。当使用 %d 格式化整数时&#xff0c;它将使用默认的对齐方式&#xff0c;通常是右对齐&#xff0c;并没有指定宽度。例如&#xff0c;System.out.…

解决 webpack 4.X:autoprefixer 插件使用不起作用的两种解决方案

1、问题描述&#xff1a; 其一、存在的问题为&#xff1a; 加载 autoprefixer 插件的过程中&#xff0c;页面却显示并没有自动添加浏览器的厂商前缀; 其二、问题描述为&#xff1a; 在写 CSS3 这些新的特性时&#xff0c;存在着不同的浏览器解析这些新特性时&#xff0c;需…

学习package.json

package.json 文件&#xff0c;它是项目的配置文件&#xff0c;常见的配置有配置项目启动、打包命令&#xff0c;声明依赖包等。package.json 文件是一个 JSON 对象&#xff0c;该对象的每一个成员就是当前项目的一项设置。 {"name": "monorepo_frame",&q…

FTP服务器操作手册

FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机&#xff0c;它们依照FTP协议提供服务。FTP协议是File Transfer Protocol(文件传输协议)&#xff0c;专门用来传输文件的协议。FTP服务器是企业里经常用到的服务器&#xff0c;今天就介绍一…

RGB与YUV公式转换推导

目录 简介 Full Range公式推导 Limit Range推导 验证测试 参考资料 简介 RGB与YUV之间的转换有很多种标准&#xff0c;不同标准系数不一样&#xff0c;而且经常容易搞混淆&#xff0c;另外还有full range和limitrange的不同。其实这些转换系数都是推导出来的&#xff0c;…

【通览一百个大模型】Baize(UCSD)

【通览一百个大模型】Baize&#xff08;UCSD&#xff09; 作者&#xff1a;王嘉宁&#xff0c;本文章内容为原创&#xff0c;仓库链接&#xff1a;https://github.com/wjn1996/LLMs-NLP-Algo 订阅专栏【大模型&NLP&算法】可获得博主多年积累的全部NLP、大模型和算法干货…

【数据结构与算法】two X 树的遍历以及功能实现

前言&#xff1a; 前面我们已经提到过树、二叉树的概念及结构、堆排序、Top-k问题等的知识点&#xff0c;这篇文章我们来详解一下二叉树的链式结构等问题。 &#x1f4a5;&#x1f388;个人主页:​​​​​​Dream_Chaser&#xff5e; &#x1f388;&#x1f4a5; ✨✨专栏:htt…

JVM工具使用(jstat + jmap)

命令格式 jstat -gcutil pid interval(ms) 举例&#xff1a; jstat -gcutil 16361 1000 线上服务器的GC情况如下&#xff1a; 参数说明如下&#xff1a; S0: 新生代中Survivor space 0区已使用空间的百分比S1: 新生代中Survivor space 1区已使用空间的百分比E: 新生代已使用空…

ETL实现实时文件监听

一、实时文件监听的作用及应用场景 实时文件监听是一种监测指定目录下的文件变化的技术&#xff0c;当产生新文件或者文件被修改时&#xff0c;可实时提醒用户并进行相应处理。这种技术广泛应用于数据备份、日志管理、文件同步和版本控制等场景&#xff0c;它可以帮助用户及时…

Nacos 下载运行及配置

Nacos 服务注册与配置中心&#xff0c;兼顾两者 文章目录 Nacos 服务注册与配置中心&#xff0c;兼顾两者一、简介二、相关文档2.1 Nacos官网2.2 官方文档 三、下载并运行Nacos3.1 下载压缩包3.2 解压缩3.3 运行命令3.4 访问Nacos控制台 附录&#xff1a;各种注册中心比较 Naco…