基于单链表实现通讯管理系统!(有完整源码!)

news2024/11/24 2:17:27

                                                                                个人主页:秋风起,再归来~

                                                                                文章专栏:C语言实战项目                              

                                                                        个人格言:悟已往之不谏,知来者犹可追

                                                                                        克心守己,律己则安!

1、前言

友友们,这篇文章是基于单链表来实现通讯管理系统的,所以一定要先看完我之前写过的一篇关于单链表的实现(文章链接)的文章哦~

其实基于单链表实现通讯录的思路与基于顺讯表实现通讯录的思路是一样的,在这里我就不进行赘述了。如果还没有看过我之前写的一篇基于顺序表实现通讯录(文章链接)的宝子们一定要去看看哦~

2、各种接口的实现

以下是我们希望实现的接口~

//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100

//前置声明
typedef struct SListNode contact;

//用户数据
typedef struct PersonInfo
{
    char name[NAME_MAX];
    char sex[SEX_MAX];
    int age;
    char tel[TEL_MAX];
    char addr[ADDR_MAX];
}PeoInfo;

//初始化通讯录
void InitContact(contact** con);

//添加通讯录数据
void AddContact(contact** con);

//展示通讯录数据
void ShowContact(contact* con);

//删除通讯录数据
void DelContact(contact** con);

//查找通讯录数据
void FindContact(contact* con);

//修改通讯录数据
void ModifyContact(contact** con);

//销毁通讯录数据
void DestroyContact(contact** con);

2.1 初始化通讯录

我们希望在初始化通讯录时导入之前我们原有文件中的数据,那我们就可以进行如下的操作~

//从文件中导入原数据
void DLoadContact(contact** con)
{
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("open fail\n");
		return;
	}
	PeoInfo p = { 0 };
	while (fread(&p, sizeof(PeoInfo),1,pf))
	{
		SListPushBack(con, p);
	}
	printf("历史数据导入成功!\n");
	fclose(pf);
	pf = NULL;
}

在初始化通讯录之后加载数据! 

//初始化通讯录
void InitContact(contact** con)
{
	assert(con);
	(*con) = NULL;
	DLoadContact(con);
}

2.2 添加通讯录数据

//添加通讯录数据
void AddContact(contact** con)
{
	assert(con);
	PeoInfo p = {0};
	printf("请输入添加联系人的姓名:");
	scanf("%s", p.name);
	printf("请输入添加联系人的性别:");
	scanf("%s", p.sex);
	printf("请输入添加联系人的年龄:");
	scanf("%d", &(p.age));
	printf("请输入添加联系人的电话:");
	scanf("%s", p.tel);
	printf("请输入添加联系人的住址:");
	scanf("%s", p.addr);
	SListPushBack(con,p);
	printf("\n");
}

2.3 删除通讯录数据

在查找通讯录数据之外封装一个函数(findByName)来通过名字查找联系人!

(因为我们在之后的查找和修改接口中都会用到这个方法,所以我们把它封装成一个函数方便我们后续的使用!)

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{
	assert(con);
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

在原有单链表的删除指定数据的接口上进行封装(让单链表摇身一变成为通讯录!)

//删除通讯录数据
void DelContact(contact** con)
{
	assert(con && (*con));
	char name[NAME_MAX];
	printf("请输入你要删除的联系人的名字:");
	scanf("%s", name);
	contact* pos = findByName(*con,name);
	if (pos == NULL)
	{
		printf("您要删除的联系人不存在!\n");
		return;
	}
	SListErase(con, pos);
	printf("删除成功!\n");
}

2.4 展示通讯录数据

遍历我们的通讯录打印信息!

//展示通讯录数据
void ShowContact(contact* con)
{
	assert(con);
	contact* cur = con;
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头
	while (cur)
	{
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			cur->data.name,
			cur->data.sex,
			cur->data.age,
			cur->data.tel,
			cur->data.addr);
		cur = cur->next;
	}
}

2.5 查找通讯录数据

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{
	assert(con);
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

在接口内部调用该函数! 

//查找通讯录数据
void FindContact(contact* con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入你要查找的联系人的名字:");
	scanf("%s", name);
	contact* ret = findByName(con, name);
	if (ret == NULL)
	{
		printf("您要查找的联系人不存在!\n");
		return;
	}
	printf("找到了!\n");
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			ret->data.name,
			ret->data.sex,
			ret->data.age,
			ret->data.tel,
			ret->data.addr);
}

2.6 修改通讯录数据

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{
	assert(con);
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

在接口内部调用该函数! 

//修改通讯录数据
void ModifyContact(contact** con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入你要修改的联系人的名字:");
	scanf("%s", name);
	contact* ret = findByName(*con, name);
	if (ret == NULL)
	{
		printf("您要修改的联系人不存在!\n");
		return;
	}
	PeoInfo p = { 0 };
	printf("请输入修改后联系人的姓名:");
	scanf("%s", p.name);
	printf("请输入修改后联系人的性别:");
	scanf("%s", p.sex);
	printf("请输入修改后加联系人的年龄:");
	scanf("%d", &(p.age));
	printf("请输入修改后联系人的电话:");
	scanf("%s", p.tel);
	printf("请输入修改后联系人的住址:");
	scanf("%s", p.addr);
	SListModify(ret, p);
	printf("修改成功!\n");
}

2.7 销毁通讯录数据

因为我们希望在退出通讯管理系统的时候可以将我们的操作都保留下来,所以我们可以对其进行文件操作!

//将输入的数据保存到文件中
void SaveContact(contact** con)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("open fail!\n");
		return;
	}
	contact* cur = *con;
	while (cur)
	{
		fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);
		cur = cur->next;
	}
	printf("历史数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}

 在销毁通讯录之前保留数据!

//销毁通讯录数据
void DestroyContact(contact** con)
{
	SaveContact(con);
	SListDestroy(con);
}

3、完整源码

SeqList.h

#pragma once//避免头文件被多次引用
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Contact.h"
typedef PeoInfo SListDataType;//便于改变数据类型

//定义一个结构体类型的节点
typedef struct SListNode
{
	SListDataType data;
	struct SListNode* next;//存储下一个节点的地址
}SListNode;

//1. 新节点的创建
SListNode* SListCreatNode(SListDataType x);

//2. 打印单链表
void PrintSList(SListNode* phead);

//3. 头插
void SListPushFront(SListNode** phead, SListDataType x);

//4. 头删
void  SListPopFront(SListNode** phead);

//5. 尾差
void SListPushBack(SListNode** phead, SListDataType x);

//6. 尾删
void  SListPopBack(SListNode** phead);

//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x);

//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x);

//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x);

//10. 在任意位置删除
void SListErase(SListNode** phead, SListNode* pos);

//11. 销毁单链表
void SListDestroy(SListNode** phead);

Contact.h

#define _CRT_SECURE_NO_WARNINGS

//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100

//前置声明
typedef struct SListNode contact;

//用户数据
typedef struct PersonInfo
{
    char name[NAME_MAX];
    char sex[SEX_MAX];
    int age;
    char tel[TEL_MAX];
    char addr[ADDR_MAX];
}PeoInfo;

//初始化通讯录
void InitContact(contact** con);

//添加通讯录数据
void AddContact(contact** con);

//展示通讯录数据
void ShowContact(contact* con);

//删除通讯录数据
void DelContact(contact** con);

//查找通讯录数据
void FindContact(contact* con);

//修改通讯录数据
void ModifyContact(contact** con);

//销毁通讯录数据
void DestroyContact(contact** con);

SeqList.c

#include"SList.h"

//1. 新节点的创建
SListNode* SListCreatNode(SListDataType x)
{
	SListNode* NewNode = (SListNode*)malloc(sizeof(SListNode));//开辟空间
	if (NewNode == NULL)//判断空间是否开辟成功
	{
		perror("malloc fail");
		return NULL;
	}
	NewNode->data = x;//赋值
	NewNode->next = NULL;//置空
	return NewNode;
}

#if 0
//2. 打印单链表
void PrintSList(SListNode* phead)
{
	if (phead == NULL)
	{
		printf("NULL");//如果链表没有元素就打印NULL
		return;
	}
	SListNode* cur = phead;
	//循环单链表打印
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
#endif

//3. 头插
void SListPushFront(SListNode** phead, SListDataType x)
{
	assert(phead);
	SListNode* newnode = SListCreatNode(x);//创建一个新节点
	newnode->next = *phead;
	*phead = newnode;
}

//4. 头删
void  SListPopFront(SListNode** phead)
{
	assert(phead);
	assert(*phead);//如果没有数据就不用头删,并报错
	SListNode* cur = (*phead)->next;
	free(*phead);
	*phead = cur;
}

//5. 尾插
void SListPushBack(SListNode** phead, SListDataType x)
{
	assert(phead);
	if (*phead == NULL)
	{
		*phead = SListCreatNode(x);//创建新节点并插入
	}
	else
	{
		SListNode* tail = *phead;
		while (tail->next != NULL)//找到尾节点
		{
			tail = tail->next;
		}
		tail->next = SListCreatNode(x);//创建新节点并插入
	}
}

//6. 尾删
void  SListPopBack(SListNode** phead)
{
	assert(phead);
	assert(*phead);//链表为空就不进行尾删
	SListNode* tail = *phead;
	if (tail->next == NULL)//如果链表就只有一个元素就进行头删
	{
		SListPopFront(phead);
	}
	else
	{
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}

#if 0
//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x)
{
	assert(phead);
	while (phead->next != NULL)//注意最后一个节点是没有查找的
	{
		if (phead->data == x)
			return phead;
		phead = phead->next;
	}
	if (phead->data == x)
		return phead;//最后一个节点没有查找
	else
		return NULL;//没找到
}
#endif

//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x)
{
	assert(pos);
	pos->data = x;
}

//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x)
{
	assert(phead);
	assert(*phead);
	if (pos == *phead)//如果pos位置刚好是第一个节点就进行头插
	{
		SListPushFront(phead, x);
	}
	else
	{
		SListNode* newnode = SListCreatNode(x);
		SListNode* cur = *phead;
		while (cur->next != pos)//找到pos前一个节点
		{
			cur = cur->next;
		}
		cur->next = newnode;
		newnode->next = pos;
	}
}

//10. 在任意位置删除
void SListErase(SListNode** phead, SListNode* pos)
{
	assert(phead && *phead && pos);
	if (pos == *phead)//如果pos位置就是第一个节点就进行头删
	{
		SListPopFront(phead);
	}
	else
	{
		SListNode* cur = *phead;
		while (cur->next != pos)//找到pos前一个节点
		{
			cur = cur->next;
		}
		cur->next = pos->next;
		free(pos);
	}
}

//11. 销毁单链表
void SListDestroy(SListNode** phead)
{
	assert(*phead && phead);
	SListNode* cur = *phead;
	while (cur != NULL)
	{
		SListNode* tmp = cur->next;
		free(cur);
		cur = tmp;
	}
	*phead = NULL;
}

Contact.c

#include"SList.h"

//从文件中导入原数据
void DLoadContact(contact** con)
{
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("open fail\n");
		return;
	}
	PeoInfo p = { 0 };
	while (fread(&p, sizeof(PeoInfo),1,pf))
	{
		SListPushBack(con, p);
	}
	printf("历史数据导入成功!\n");
	fclose(pf);
	pf = NULL;
}

//初始化通讯录
void InitContact(contact** con)
{
	assert(con);
	(*con) = NULL;
	DLoadContact(con);
}

//添加通讯录数据
void AddContact(contact** con)
{
	assert(con);
	PeoInfo p = {0};
	printf("请输入添加联系人的姓名:");
	scanf("%s", p.name);
	printf("请输入添加联系人的性别:");
	scanf("%s", p.sex);
	printf("请输入添加联系人的年龄:");
	scanf("%d", &(p.age));
	printf("请输入添加联系人的电话:");
	scanf("%s", p.tel);
	printf("请输入添加联系人的住址:");
	scanf("%s", p.addr);
	SListPushBack(con,p);
	printf("\n");
}

//展示通讯录数据
void ShowContact(contact* con)
{
	assert(con);
	contact* cur = con;
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头
	while (cur)
	{
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			cur->data.name,
			cur->data.sex,
			cur->data.age,
			cur->data.tel,
			cur->data.addr);
		cur = cur->next;
	}
}

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{
	assert(con);
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//删除通讯录数据
void DelContact(contact** con)
{
	assert(con && (*con));
	char name[NAME_MAX];
	printf("请输入你要删除的联系人的名字:");
	scanf("%s", name);
	contact* pos = findByName(*con,name);
	if (pos == NULL)
	{
		printf("您要删除的联系人不存在!\n");
		return;
	}
	SListErase(con, pos);
	printf("删除成功!\n");
}

//查找通讯录数据
void FindContact(contact* con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入你要查找的联系人的名字:");
	scanf("%s", name);
	contact* ret = findByName(con, name);
	if (ret == NULL)
	{
		printf("您要查找的联系人不存在!\n");
		return;
	}
	printf("找到了!\n");
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			ret->data.name,
			ret->data.sex,
			ret->data.age,
			ret->data.tel,
			ret->data.addr);
}

//修改通讯录数据
void ModifyContact(contact** con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入你要修改的联系人的名字:");
	scanf("%s", name);
	contact* ret = findByName(*con, name);
	if (ret == NULL)
	{
		printf("您要修改的联系人不存在!\n");
		return;
	}
	PeoInfo p = { 0 };
	printf("请输入修改后联系人的姓名:");
	scanf("%s", p.name);
	printf("请输入修改后联系人的性别:");
	scanf("%s", p.sex);
	printf("请输入修改后加联系人的年龄:");
	scanf("%d", &(p.age));
	printf("请输入修改后联系人的电话:");
	scanf("%s", p.tel);
	printf("请输入修改后联系人的住址:");
	scanf("%s", p.addr);
	SListModify(ret, p);
	printf("修改成功!\n");
}

//将输入的数据保存到文件中
void SaveContact(contact** con)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("open fail!\n");
		return;
	}
	contact* cur = *con;
	while (cur)
	{
		fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);
		cur = cur->next;
	}
	printf("历史数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}
//销毁通讯录数据
void DestroyContact(contact** con)
{
	SaveContact(con);
	SListDestroy(con);
}

 这里我就没有单独去写一个菜单了,本身的意义也并不大,但是如果友友们想写一个来玩一玩,可以看看我之前那篇基于顺序表实现通讯录(文章链接,那里有菜单的模版(只要改几个接口的名字就行了)~

4、 完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​

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

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

相关文章

005Node.js模块URL的使用

引入 URL 模块 要使用 URL 模块&#xff0c;首先需要在代码中引入它。可以使用以下代码将 URL 模块导入到你的脚本中&#xff1a; const url require(url);实例代码 const urlrequire(url); var apihttp://www.baidu.com?nameshixiaobin&age20; console.log(url.parse(…

Android应用和开发环境

&#x1f308;个人主页&#xff1a;小新_- &#x1f388;个人座右铭&#xff1a;“成功者不是从不失败的人&#xff0c;而是从不放弃的人&#xff01;”&#x1f388; &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f3c6;所属专栏&#xff1…

70 个常用的GIS Python 库

由于其多功能性、广泛的库生态系统和用户友好的语法&#xff0c;Python 已成为地理信息系统 (GIS) 和遥感领域的主导语言。这个 70 个地理空间 Python 库的汇编展示了可用于 GIS 和遥感数据处理和分析的丰富工具包。 Python 在 GIS 中的重要性源于它处理复杂地理空间数据的能力…

rancher踩坑日志:prometheus访问kubelet 10250端口提示鉴权失败

该原因是因为kubectl禁止了非授权用户访问10250端口来获取node的数据。 解决思路&#xff1a; 添加prometheus访问kubelet时带上证书进行验证匹配 --> 由于我的prometheus是rancher安装的&#xff0c;不知道要怎么修改所以研究了一会没研究明白就放弃了。设置prometheus访问…

运动听歌哪款耳机靠谱?精选五款热门开放式耳机

随着人们对运动健康的重视&#xff0c;越来越多的运动爱好者开始关注如何在运动中享受音乐。开放式蓝牙耳机凭借其独特的设计&#xff0c;成为了户外运动的理想选择。它不仅让你在运动时能够清晰听到周围环境的声音&#xff0c;保持警觉&#xff0c;还能让你在需要时与他人轻松…

gym界面修改

资料&#xff1a;https://blog.csdn.net/weixin_46178278/article/details/135962782 在gym环境中使用mujoco的时候&#xff0c;有一个很难受的地方&#xff0c;界面上没有实时显示动作空间和状态空间状态的地方。 gym自己原始带的环境是用pygame画的图&#xff0c;所以在定义…

【爬虫+数据清洗+可视化分析】Python文本分析《狂飙》电视剧的哔哩哔哩评论

一、背景介绍 把《狂飙》换成其他影视剧&#xff0c;套用代码即可得分析结论&#xff01; 2023《狂飙》热播剧引发全民追剧&#xff0c;不仅全员演技在线&#xff0c;且符合主旋律&#xff0c;创下多个收视记录&#xff01; 基于此热门事件&#xff0c;我用python抓取了B站上千…

【SpringBoot】获取参数

获取参数 传递单个参数传递多个参数传递对象后端参数重命名传递数组传递 json 数据获取 URL 中参数上传文件获取 cookie 和 session获取cookie获取session 传递单个参数 RequestMapping("/user") RestController public class UserController {// 传递单个参数Reque…

力扣 | 160. 相交链表

import ListNodeInfo.ListNode;import java.util.HashSet; import java.util.Set;public class Problem_160_IntersectionOfTwoLinkedList {//双指针方法 public ListNode getIntersectionListNode(ListNode headA, ListNode headB){if(headA null || headB null) return nul…

S32K324 CANFD报文接收超限分析

文章目录 前言问题描述原因分析问题处理总结 前言 随着汽车软件复杂度越来越高&#xff0c;传输的数据越来越多&#xff0c;CAN总线到CANFD总线已经是发展的必然了。CANFD总线中单个报文ID可以传递至多64byte数据&#xff0c;对CAN Driver来说&#xff0c;所需的MCU资源也将变…

数据集学习

1&#xff0c;CIFAR-10数据集 CIFAR-10数据集由10个类的60000个32x32彩色图像组成&#xff0c;每个类有6000个图像。有50000个训练图像和10000个测试图像。 数据集分为五个训练批次和一个测试批次&#xff0c;每个批次有10000个图像。测试批次包含来自每个类别的恰好1000个随机…

Ubuntu桌面系统安装成功后的简单配置

目录 更换软件源设置系统时间同步 更换软件源 本文使用的换源方法仅限于桌面版 前提有网络连接&#xff0c;能够访问互联网 在Ubuntu18.04桌面版中&#xff0c;点击左下角“显示应用程序”&#xff0c;搜索“软件更新器”&#xff0c;点击进入。 暂时不要点击立即安装&#xff…

ES6: promise对象与回调地狱

ES6&#xff1a; promise对象与回调地狱 一、回调地狱二、Promise概述三、Promise的组成四、用函数封装Promise读取文件操作 一、回调地狱 在js中大量使用回调函数进行异步操作&#xff0c;而异步操作什么时候返回结果是不可控的&#xff0c;所以希望一段程序按我们制定的顺序执…

免费ssl证书能一直续签吗?如何获取SSL免费证书?

免费SSL证书是否可以一直续签。我们需要了解SSL证书的基本工作原理。当你访问一个使用HTTPS协议的网站时&#xff0c;该网站实际上在使用一个SSL证书。这个证书相当于一个数字身份证明&#xff0c;它验证了网站的真实性和安全性。而这个证明是由受信任的第三方机构——通常是证…

Unity之C#面试题(二)

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之C#面试题&#xff08;二&#xff09; TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取&a…

配置交换机SSH管理和端口安全——实验2:配置交换机端口安全

实验目的 通过本实验可以掌握&#xff1a; 交换机管理地址配置及接口配置。查看交换机的MAC地址表。配置静态端口安全、动态端口安全和粘滞端口安全的方法 实验拓扑 配置交换机端口安全的实验拓扑如图所示。 配置交换机端口安全的实验拓扑 实验步骤 &#xff08;1&#x…

EasyPoi表格导入添加校验

EasyPoi表格导入添加校验 项目添加maven依赖实体类自定义校验controller测试结果 项目添加maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2…

【目标检测数据集】VOC2007 数据集介绍

一、介绍 VOC 数据是 PASCAL VOC Challenge 用到的数据集&#xff0c;官网&#xff1a;http://host.robots.ox.ac.uk/pascal/VOC/ 备注&#xff1a;VOC数据集常用的均值为&#xff1a;mean_RGB(122.67891434, 116.66876762, 104.00698793) Pytorch 上通用的数据集的归一化指…

(三)ffmpeg 解码流程以及函数介绍

一、视频解码流程 二、函数介绍 1.avformat_network_init 函数作用&#xff1a; 执行网络库的全局初始化。这是可选的&#xff0c;不再推荐。 此函数仅用于解决旧GnuTLS或OpenSSL库的线程安全问题。如果libavformat链接到这些库的较新版本&#xff0c;或者不使用它们&#…

AI大模型探索之路-应用篇1:Langchain框架概述—快速构建大模型应用

目录 一、什么是LangChain&#xff1f; 二、LangChain解决了哪些问题&#xff1f; 三、LangChain总体架构 四、代码实践样例 总结 一、什么是LangChain&#xff1f; 为大模型应用提供简便之道。 LangChain&#xff0c;专为构建庞大的语言模型应用程序设计的框架&#xff0…