通讯录动态+文件版本

news2024/10/5 5:17:44

通讯录

  • 前言
    • 初始化通讯录
    • 增加联系人
    • 展示通讯录
    • 查找联系人
    • 删除联系人
    • 修改联系人
    • 排序
    • 加载文件到通讯录
    • 保存通讯录到文件
    • 销毁通讯录
  • 源代码
  • 文末

前言

🎊个人主页:https://blog.csdn.net/2401_83251330?spm=1000.2115.3001.5343
🎀 🎉欢迎大家点赞👍收藏⭐文章
✌️ 🤞 🤟 🤘 🤙 👈 👉 👆 🖕 👇 ☝️ 👍

• 通讯录是底层是数组实现的,我们要在通讯录增删查改等功能,通过这些功能,我们可以很好的完成对成员信息的存储和查找。需要我们能够熟练的使用c语言,对指针,结构体,数组,动态内存管理等知识,完成通讯录,对数据结构的顺序表也有了一定的帮助

通讯录主逻辑和猜数字和扫雷主函数逻辑相同: https://blog.csdn.net/2401_83251330/article/details/140579897?spm=1001.2014.3001.5501
通讯录test.c主逻辑

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");
}

int main()
{
	int input;
	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);
			//DESTROY(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误:请重新选择:\n");
			break;
		}
	} while (input);
}

• 接着我们先来思考,写一个通讯录的时候,先考虑数据的类型,通讯类的每一个数据类型是一个人的信息,我们可以用一个结构体(PeoInfo)来维护通讯录中人💁 People 的信息;
而要把通讯录里的所有数据串起来,我们是不是还需要一个结构体 (Contact),这个结构体不仅要存放数据类型(PeoInfo),最好成员是指向(PeoInfo)类型的指针,还要有数据的个数(count),每一个PeoInfo都是一个数据。为了让通讯录满了能够自动扩容,动态起来,我们还可以用一个容量(capacity)来实现扩容的效果,这都是由这个结构体维护的。

contact.h结构体数据类型定义和函数声明

#pragma once
#include <stdio.h>
#include <stdlib.h>

enum Status
{
	ADD = 1,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	EXIT
};
typedef struct PeoInfo
{
	char name[20];
	char sex[10];
	char tel[13];
	int age;
}PeoInfo;
typedef struct Contact
{
	PeoInfo* data;//指向通讯录数据的指针
	int count;//通讯录的当前大小
	int capacity;//通讯录的容量
}Contact,*pContact;


//初始化通讯录
void Initcontact(pContact pc);


//保存通讯录
void SaveContact(pContact pc);

//销毁通讯录
void DESTROY(pContact pc);

//添加联系人
void AddContact(pContact pc);

//展示通讯录
void ShowContact(pContact pc);

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

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

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

//排序通讯录
void Sortcontact(pContact pc);

//加载文件到通讯录
void LoadContact(pContact pc);

这里声明了我们所要需要函数,下面不再声明,还有宏定义,小编给一点点写,再大家补充,下面我们一一来实现。

初始化通讯录

•下面我们先来定义这两个结构体和函数声明,初始化通讯录为空,即一个成员也没有,这里你也可以初始的时候添加成员。我默认没有成员了。

//初始化通讯录
void Initcontact(pContact pc)
{
	pc->data = NULL;
	pc->count = pc->capacity = 0;
}

增加联系人

•想添加联系人就要申请空间,由于小编的通讯录为空,所以需要申请空间,不过申请空间,首先要判断当前容capacity够不够支持我的有效数据count,每次我在添加联系人都需要判断,所以我封装一个函数IncreaseCapacity(),这个函数是用于检查是否需要扩容,如果扩容,ppc->data重新指向已经开辟扩容的空间,这里需要用到realloc():
https://legacy.cplusplus.com/reference/cstdlib/realloc/?kw=realloc
函数来实现扩容。
代码如下:

void IncreaseCapacity(pContact ppc)
{
	assert(ppc);
		//增容*2
	ppc->capacity = ppc->capacity == 0 ? 4 : 2 * ppc->capacity;
	PeoInfo* ptr = (PeoInfo*)realloc(ppc->data, ppc->capacity *sizeof(PeoInfo));
	if (ptr == NULL)
	{
		perror("IncreaseCapacity::fai");
		return;
	}
	ppc->data = ptr;
}
//添加联系人
void AddContact(pContact pc)
{
	assert(pc);
	//判断增容
	if (pc->count == pc->capacity)
	{
		IncreaseCapacity(pc);
		printf("增容成功\n");
	}

	printf("请输入要添加联系人的名字");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入要添加联系人的性别");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入要添加联系人的电话");
	scanf("%s", pc->data[pc->count].tel);
	printf("请输入要添加联系人的年龄");
	scanf("%d", &pc->data[pc->count].age);
	pc->count++;
	printf("\n添加成功\n");
}

展示通讯录

然后我们可以展示通讯录:
代码如下:

//展示通讯录
void ShowContact(pContact pc)
{

	printf("%-20s\t%-10s\t%-15s\t%-5s\t\n", "名字", "性别", "电话", "年龄");
	for (int i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-10s\t%-15s\t%5d\t\n", pc->data[i].name,
			pc->data[i].sex,
			pc->data[i].tel,
			pc->data[i].age
			);
	}
}

查找联系人

•查找联系人,只需要遍历整个数组,通过名字比较,这里封装了一个查找方法,对查找以及后续删除,修改联系人都有用。
代码如下:

//查找方法,找到了返回下标,找不到返回-1
int Find_message(pContact ppc,char* name)
{
	assert(ppc);
	int i;
	for (i = 0; i < ppc->count; i++)
	{
		if (strcmp(ppc->data[i].name, name) == 0)
			return i;
	}
	return -1;
}

//查找联系人
void SearchContact(pContact pc)
{
	assert(pc);

	char name[20];
	if (pc->count == 0)
	{
		printf("通讯录为空,无法查找\n");
		return;
	}
	printf("请输入要查找的人的姓名");
	scanf("%s", name);
	int ret = Find_message(pc,name);
	if ( ret == -1)
	{
		printf("没有这个联系人\n");
	}
	else
	{
		printf("查找成功!信息如下\n");
		printf("%-20s\t%-10s\t%-5s\t%-15s\t\n", "名字", "性别", "电话", "年龄");
		printf("%-20s\t%-10s\t%-15s%-5d\t\n", pc->data[ret].name,
			pc->data[ret].sex,
			pc->data[ret].tel,
			pc->data[ret].age
			);
	}
}

删除联系人

•删除联系人与查找联系人类似,只需要先找到该联系人,调用Find_message()方法,再覆盖元素通过移动数组元素即可完成删除操作。
代码如下:

//删除联系人
void DelContact(pContact pc)
{
	assert(pc);

	char name[20];
	if (pc->count == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	printf("请输入要删除的人的姓名");
	scanf("%s", name);
	int ret = Find_message(pc, name);//返回下标
	if (ret == -1)
	{
		printf("没有这个联系人\n");
	}
	else
	{
		for (int i = ret; i < pc->count-1; i++)
		{
			pc->data[i] = pc->data[i+1];
		}
		pc->count--;
		printf("删除成功\n");
	}
}

修改联系人

•修改联系人也是需要先找到是否有该联系人,调用Find_message()方法,然后修改信息。
代码如下:

//修改联系人
void ModifyContact(pContact pc)
{
	assert(pc);

	char name[20];
	if (pc->count == 0)
	{
		printf("通讯录为空,无法修改\n");
		return;
	}
	printf("请输入要修改的人的姓名");
	scanf("%s", name);
	int ret = Find_message(pc, name);//返回下标
	if (ret == -1)
	{
		printf("没有这个联系人\n");
	}
	else
	{
		printf("请输入新联系人的名字");
		scanf("%s", pc->data[ret].name);
		printf("请输入新联系人的性别");
		scanf("%s", pc->data[ret].sex);
		printf("请输入新联系人的电话");
		scanf("%s", pc->data[ret].tel);
		printf("请输入新联系人的年龄");
		scanf("%d", &pc->data[ret].age);
		printf("修改成功\n");
	}
}

排序

•排序通讯录,理论上我们可以按照名字,年龄,性别,电话排序,这里用qsort排序方法,可以参照我的qsort函数链接: https://mp.csdn.net/mp_blog/creation/editor/141337645
这里仅排序年龄,其余同理,小伙伴们也可以完成剩下功能的排序方式,代码如下:

int cmp_by_age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//排序通讯录
void Sortcontact(pContact pc)
{
	//按年龄排序
	qsort(pc->data, pc->count, sizeof(pc->data[0]), cmp_by_age);
	printf("排序成功\n");
}

加载文件到通讯录

现在为了让我们的通讯录更加真实,能够切实的保存通讯录中人的信息,而不是直接让操作系统释放掉,所以我们希望能保存。这里使用c语言的文件操作,我们只需要在初始化通讯录时的逻辑,加载文件到通讯录,本质是将文件加载到文件缓冲区,然后通过输入流输入到内存。

代码如下:

//从文件读取内容到内存
void LoadContact(pContact pc)
{
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact()::fail");
		return;
	}
	//读取文件
	PeoInfo tmp;
	while (fread(&tmp, sizeof(PeoInfo), 1, pf) == 1)
	{
		//增容
		if (pc->count == pc->capacity)
		{
			IncreaseCapacity(pc);
		}
		pc->data[pc->count] = tmp;
		pc->count++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

保存通讯录到文件

> •保存通讯录的逻辑在退出通讯录,我们需要在退出通讯录前,将内存区联系人的内容一一保存到文件"contact.txt"中

文件操作代码如下:

//保存通讯录
void SaveContact(pContact pc)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("SaveContact()::fail");
		return;
	}
	//保存文件
	int i;
	for (i = 0; i < pc->count; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

销毁通讯录

我们在调用增容函数时向内存申请了空间,这就需要我们释放,所以我们在退出逻辑,先保存通讯录后再释放申请的那块空间也就是销毁通讯录

销毁通讯录代码如下:

//销毁通讯录
void DESTROY(pContact pc)
{
	assert(pc);
	free(pc->data);
	pc->data = NULL;
}

源代码

contact.h

#pragma once
#define  _CRT_SECURE_NO_WARNINGS 1


#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
enum Status
{
	ADD=1,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	EXIT = 0
};
typedef struct PeoInfo
{
	char name[20];
	char sex[10];
	char tel[13];
	int age;
}PeoInfo;
typedef struct Contact
{
	PeoInfo* data;//指向通讯录数据的指针
	int count;//通讯录的当前大小
	int capacity;//通讯录的容量
}Contact, * pContact;


//初始化通讯录
void Initcontact(pContact pc);
//增容
void IncreaseCapacity(pContact ppc);

//保存通讯录
void SaveContact(pContact pc);

//销毁通讯录
void DESTROY(pContact pc);

//添加联系人
void AddContact(pContact pc);

//展示通讯录
void ShowContact(pContact pc);

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

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

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

//排序通讯录
void Sortcontact(pContact pc);

//加载文件到通讯录
void LoadContact(pContact pc);

contact.c

在这里插入代码片#include "contact.h"
//初始化通讯录

//从文件读取内容到内存
void LoadContact(pContact pc)
{
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact()::fail");
		return;
	}
	//读取文件
	PeoInfo tmp;
	while (fread(&tmp, sizeof(PeoInfo), 1, pf) == 1)
	{
		//增容
		if (pc->count == pc->capacity)
		{
			IncreaseCapacity(pc);
		}
		pc->data[pc->count] = tmp;
		pc->count++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}
void Initcontact(pContact pc)
{
	assert(pc);

	pc->data = NULL;
	pc->count = pc->capacity = 0;
	//加载文件到通讯录
	LoadContact(pc);
}

void IncreaseCapacity(pContact ppc)
{
	assert(ppc);
	//增容*2
	ppc->capacity = ppc->capacity == 0 ? 4 : 2 * ppc->capacity;
	PeoInfo* ptr = (PeoInfo*)realloc(ppc->data, ppc->capacity * sizeof(PeoInfo));
	if (ptr == NULL)
	{
		perror("IncreaseCapacity::fai");
		return;
	}
	ppc->data = ptr;
}
//添加联系人
void AddContact(pContact pc)
{
	assert(pc);
	//判断增容
	if (pc->count == pc->capacity)
	{
		IncreaseCapacity(pc);
		printf("增容成功\n");
	}

	printf("请输入要添加联系人的名字");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入要添加联系人的性别");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入要添加联系人的电话");
	scanf("%s", pc->data[pc->count].tel);
	printf("请输入要添加联系人的年龄");
	scanf("%d", &pc->data[pc->count].age);
	pc->count++;
	printf("\n添加成功\n");
}

//展示通讯录
void ShowContact(pContact pc)
{

	printf("%-20s\t%-10s\t%-15s\t%-5s\t\n", "名字", "性别", "电话", "年龄");
	for (int i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-10s\t%-15s\t%5d\t\n", pc->data[i].name,
			pc->data[i].sex,
			pc->data[i].tel,
			pc->data[i].age
			);
	}
}

//查找方法,找到了返回下标,找不到返回-1
int Find_message(pContact ppc,char* name)
{
	assert(ppc);
	int i;
	for (i = 0; i < ppc->count; i++)
	{
		if (strcmp(ppc->data[i].name, name) == 0)
			return i;
	}
	return -1;
}

//查找联系人
void SearchContact(pContact pc)
{
	assert(pc);

	char name[20];
	if (pc->count == 0)
	{
		printf("通讯录为空,无法查找\n");
		return;
	}
	printf("请输入要查找的人的姓名");
	scanf("%s", name);
	int ret = Find_message(pc,name);
	if ( ret == -1)
	{
		printf("没有这个联系人\n");
	}
	else
	{
		printf("查找成功!信息如下\n");
		printf("%-20s\t%-10s\t%-5s\t%-15s\t\n", "名字", "性别", "电话", "年龄");
		printf("%-20s\t%-10s\t%-15s%-5d\t\n", pc->data[ret].name,
			pc->data[ret].sex,
			pc->data[ret].tel,
			pc->data[ret].age
			);
	}
}

//删除联系人
void DelContact(pContact pc)
{
	assert(pc);

	char name[20];
	if (pc->count == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	printf("请输入要删除的人的姓名");
	scanf("%s", name);
	int ret = Find_message(pc, name);//返回下标
	if (ret == -1)
	{
		printf("没有这个联系人\n");
	}
	else
	{
		for (int i = ret; i < pc->count - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->count--;
		printf("删除成功\n");
	}
}

//修改联系人
void ModifyContact(pContact pc)
{
	assert(pc);

	char name[20];
	if (pc->count == 0)
	{
		printf("通讯录为空,无法修改\n");
		return;
	}
	printf("请输入要修改的人的姓名");
	scanf("%s", name);
	int ret = Find_message(pc, name);//返回下标
	if (ret == -1)
	{
		printf("没有这个联系人\n");
	}
	else
	{
		printf("请输入新联系人的名字");
		scanf("%s", pc->data[ret].name);
		printf("请输入新联系人的性别");
		scanf("%s", pc->data[ret].sex);
		printf("请输入新联系人的电话");
		scanf("%s", pc->data[ret].tel);
		printf("请输入新联系人的年龄");
		scanf("%d", &pc->data[ret].age);
		printf("修改成功\n");
	}
}

int cmp_by_age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//排序通讯录
void Sortcontact(pContact pc)
{
	//按年龄排序
	qsort(pc->data, pc->count, sizeof(pc->data[0]), cmp_by_age);
	printf("排序成功\n");
}


//保存通讯录
void SaveContact(pContact pc)
{
	assert(pc);
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("SaveContact()::fail");
		return;
	}
	//保存文件
	int i;
	for (i = 0; i < pc->count; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}


//销毁通讯录
void DESTROY(pContact pc)
{
	assert(pc);
	free(pc->data);
	pc->data = NULL;
}

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");
}

int main()
{
	int input;
	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);
			DESTROY(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误:请重新选择:\n");
			break;
		}
	} while (input);
}

文末

通讯录的动态+文件版本小编给大家在这里实现了,通过结构体Contact来维护通讯录,通过PeoInfo来维护联系人的信息,这都是通过结构体和指针来维护的,希望能加深大家的理解,如果本片文章有什么不严谨的地方希望小伙伴们指出,你的三连👨🏽‍❤️‍👨🏻就是我优质文章的动力,谢谢大家啦。
😀 😃 😄 😁 😆 😛 😝 😜 🤪

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

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

相关文章

MySQL 查询优化器

文章目录 控制查询计划optimizer_prune_leveloptimizer_search_depth 优化器参数优化器提示索引提示成本模型server_costcost_name engine_cost 控制查询计划 https://dev.mysql.com/doc/refman/8.4/en/controlling-query-plan-evaluation.html 在执行SQL前会根据优化器选择执…

Leetcode 第 140 场双周赛题解

Leetcode 第 140 场双周赛题解 Leetcode 第 140 场双周赛题解题目1&#xff1a;3300. 替换为数位和以后的最小元素思路代码复杂度分析 题目2&#xff1a;3301. 高度互不相同的最大塔高和思路代码复杂度分析 题目3&#xff1a;3302. 字典序最小的合法序列思路代码复杂度分析 题目…

入手一个小扒菜fqrr#com

fqrr#com 既带q又带r是很多人不喜的类型&#xff0c; 父亲 夫妻 番茄 分期 人人 日日 好无聊的米呀&#xff0c;竟然组合不出来意思 这个不是购买的&#xff0c;别人说他1150元购买的&#xff0c;算是半抵给我的吧 其实我也不喜欢&#xff0c;我4声母.com 已经够多了&am…

【教程】文字转语音的3个方法,文字转语音使用攻略

文字转语音的需求还是蛮多的&#xff0c;很多用户在视频剪辑中会遇到。不想用本人的声音&#xff0c;那么视频中的旁白就只能通过文字转语音软件实现了。 想要将文字转为语音那还是蛮好解决的&#xff0c;如果你还在找方法&#xff0c;那么以下内容可以了解下。本文整理了三种简…

2c 操作符详解

1. 操作符分类&#xff1a; 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 2. 算术操作符 - * / % 1除了 % 操作符之外&#xff0c;其他的几个操作符可以作用于整数和浮点数。对于 / 操作…

NVIDIA NVLink-C2C

NVIDIA NVLink-C2C 文章目录 前言一、介绍1. 用于定制芯片集成的超快芯片互连技术2. 构建半定制芯片设计3. 使用 NVLink-C2C 技术的产品 二、NVLink-C2C 技术优势1. 高带宽2. 低延迟3. 低功率和高密度4. 行业标准协议 前言 将 NVLink 扩展至芯片级集成 一、介绍 1. 用于定制芯…

Candance仿真二阶米勒补偿OTA

1.OTA电路搭建目标——25Mhz GBW&#xff0c;65dB的增益 2.电路参照 3.candance电路搭建 实现步骤&#xff1a;应该是从下面这个公式开始推导 然后那个CL就是两边的那个CCa或CCb的大小 算出来就是gm75us

MongoDB-aggregate流式计算:带条件的关联查询使用案例分析

在数据库的查询中&#xff0c;是一定会遇到表关联查询的。当两张大表关联时&#xff0c;时常会遇到性能和资源问题。这篇文章就是用一个例子来分享MongoDB带条件的关联查询发挥的作用。 假设工作环境中有两张MongoDB集合&#xff1a;SC_DATA&#xff08;学生基本信息集合&…

基于微信小程序的旅游拼团系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

Colorize: 0 variables Colorize is not activated for this file. VsCode

问题情况 解决步骤 1.找到setting.json文件 2.输入以下代码&#xff0c;保存setting.json文件 "colorize.languages": ["css", "javascript", "sass", "less", "postcss", "stylus", "xml"…

基于SpringBoot+Vue+MySQL的中医院问诊系统

系统展示 用户前台界面 管理员后台界面 医生后台界面 系统背景 随着信息技术的迅猛发展和医疗服务需求的不断增加&#xff0c;传统的中医院问诊流程已经无法满足患者和医院的需求。纸质病历不仅占用大量存储空间&#xff0c;而且容易丢失和损坏&#xff0c;同时难以实现信息的快…

螺蛳壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习04(环境准备)

4 创建docker容器 4.1创建网络 [rootlocalhost wutool]# docker network create -d macvlan --subnet192.168.137.0/24 --gateway192.168.137.2 --ip-range192.168.137.0/24 -o parentens33 nat 52af11381bfd655d175e4168265b2a507793e8fe48f119db846949ffd4dd27de [rootlocal…

【每天学个新注解】Day 15 Lombok注解简解(十四)—@UtilityClass、@Helper

UtilityClass 生成工具类的注解 将一个类通过注解变成一个工具类&#xff0c;并没有什么用&#xff0c;本来代码中的工具类数量就极为有限&#xff0c;并不能达到减少重复代码的目的 1、如何使用 加在需要委托将其变为工具类的普通类上。 2、代码示例 例&#xff1a; Uti…

设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)

文章目录 设计模式概述1、原型模式2、原型模式的使用场景3、优点4、缺点5、主要角色6、代码示例7、总结题外话关于使用序列化实现深拷贝 设计模式概述 创建型模式&#xff1a;工厂方法、抽象方法、建造者、原型、单例。 结构型模式有&#xff1a;适配器、桥接、组合、装饰器、…

构建高效新闻推荐系统:Spring Boot的力量

1系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;这种种好处使得互联网成了信息传…

MacBook远程连接服务器,显示tensorboard的loss值

尼卡形态 GEAR-5 参考链接 当使用服务器进行模型训练时&#xff0c;想要使用MacBook查看一些可视化结果&#xff0c;如果远程服务器和本机在一个局域网内&#xff0c;可以通过以下命令解决&#xff1a; 登录服务器&#xff1a; 先用ssh工具重定向&#xff1a;ssh -L 16006:127…

java:pdfbox 删除扫描版PDF中文本水印

官网下载 https://pdfbox.apache.org/download.html下载 pdfbox-app-3.0.3.jar cd D:\pdfbox 运行 java -jar pdfbox-app-3.0.3.jar java -jar pdfbox-app-3.0.3.jar Usage: pdfbox [COMMAND] [OPTIONS] Commands:debug Analyzes and inspects the internal structu…

RTSP协议讲解

1.RTSP协议 rtsp&#xff0c;英文全称 Real Time Streaming Protocol&#xff0c;RFC2326&#xff0c;实时流传输协议&#xff0c;是 TCP/IP 协议体系中的一个应用层协议。 RTSP 交互流程 1&#xff09;OPTIONS C--->S 客户端向服务器端发现 OPTIONS&#xff0c;请求可用…

JVM(Java Virtual Machine) 详解

1. JVM 内存区域划分 一个 Java 写的程序&#xff0c;跑起来就得到了一个 Java 进程&#xff08;资源分配的基本单位&#xff09; JVM 上面运行的字节码指令 1) 程序计数器&#xff08;比较小的空间&#xff09;&#xff0c;保存了下一条要执行的指令的地址 这个不是 CPU 的…

API接口开发系列文章:构建高效、安全与可扩展的API服务

前言 在当今的数字化时代&#xff0c;API&#xff08;应用程序编程接口&#xff09;已成为连接不同系统、服务和应用的核心桥梁。无论是企业内部的数据交互&#xff0c;还是面向第三方的服务开放&#xff0c;API都扮演着至关重要的角色。本系列文章将深入探讨API接口开发的各个…