c语言:通讯录管理系统(文件版本)

news2024/11/15 9:01:50

 

        前言:在大多数高校内,都是通过设计一个通讯录管理系统来作为c语言课程设计,通过一个具体的系统设计将我们学习过的结构体和函数等知识糅合起来,可以很好的锻炼学生的编程思维,本文旨在为通讯录管理系统的设计提供思路和示例讲解,并且对如何将数据合理的用文件的形式进行保存进行了讲解和完整代码展示(完整代码放在文章末尾) 

目录

一.非文件操作版本

头文件部分(Contact.h)

函数实现部分(Contact.cpp)

主函数部分(test.cpp)

二.文件的生成

选择何种方式写文件?

SaveContact

三.文件数据的读取

LoadContact

四.运行结果截图

五.完整代码 

头文件部分(Contact.h)

函数实现部分(Contact.cpp)

主函数部分(test.cpp)


        关于通讯录管理系统,笔者一共设计了3套,分别是最基础的版本动态管理内存版本文件操作版本,本文是在动态管理的通讯录管理系统上进行改进,如果对于普通的通讯录管理系统有什么不懂的地方,可以参考笔者的前俩篇文章,里面有详细的万字解读,大家也可以根据自己的需求提取完整代码: 

c语言:通讯录管理系统(增删查改)

c语言:通讯录管理系统(动态分配内存版)

一.非文件操作版本

这里我们给出不包含文件操作版本的代码,然后本文后续内容都是基于此进行改进

我们分为 3 个文件来设计:

  • Contact.h: 包含头文件的声明,对函数的声明,以及宏的申明
  • Contact.cpp: 通讯录管理系统中具体每一个函数的实现
  • test.cpp: 主函数,根据用户的选择进行调用相应的函数

 

头文件部分Contact.h

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

#define Name_Max 20
#define Tel_Number 12
#define Sex_Max 5
#define Address_Max 30
#define Contact_Max 100
#define Contact_SZ 3

//联系人结构体
typedef struct PeopleInformation
{
	char name[Name_Max];
	char telnumber[Tel_Number];
	int age;
	char sex[Sex_Max];
	char address[Address_Max];
}PeoInfor;

//通讯录结构体
typedef struct Contact
{
	PeoInfor* data;//结构体数组存放联系人结构体
	int size;//记录当前通讯录中有多少个联系人
	int capacity;//记录当前存放的容量
}Contact;


//目录
void menu();

//初始化通讯录
void InitContact(Contact* cp);

//增加联系人
void AddContact(Contact* cp);

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

//通过姓名进行查找联系人
int FindPeople(Contact* cp, char name[]);

//展示全部通讯录信息
void ShowContact(const Contact* cp);

//查询联系人
void SeachPeople(Contact* cp);

//修改联系人信息
void ModifyContact(Contact* cp);

//扩容
void CheckContact(Contact* cp);

//销毁通讯录
void DestoryContact(Contact* cp);

函数实现部分Contact.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"

void menu()
{
	printf("\n");
	printf("-----------------------------\n");
	printf("---   1.添加联系人      -----\n");
	printf("---   2.删除联系人      -----\n");
	printf("---   3.查找联系人      -----\n");
	printf("---   4.修改联系人信息  -----\n");
	printf("---   5.显示全部信息    -----\n");
	printf("---   0.退出通讯录      -----\n");
	printf("-----------------------------\n");
}

//初始化通讯录
void InitContact(Contact* cp)
{
	//判断非空
	assert(cp);

	cp->size = 0;
	cp->capacity = Contact_SZ;
	cp->data =(PeoInfor*)calloc(cp->capacity, sizeof(PeoInfor));
	if (cp->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
}

void CheckContact(Contact* cp)
{
	if (cp->size == cp->capacity)
	{
		PeoInfor* ptr = (PeoInfor*)realloc(cp->data, (cp->capacity + 2) * sizeof(PeoInfor));
		if (ptr != NULL)
		{
			cp->data = ptr;
			cp->capacity += 2;
			printf("增容成功\n");
		}
		else
		{
			perror("AddContact->realloc");
			return;
		}
	}
}

//增加联系人
void AddContact(Contact* cp)
{
	//判断非空
	assert(cp);

	//判断满后扩容
	CheckContact(cp);

	printf("请输入要添加的联系人的姓名:\n");
	scanf("%s", cp->data[cp->size].name);

	printf("请输入要添加的联系人的电话号:\n");
	scanf("%s", cp->data[cp->size].telnumber);

	printf("请输入要添加的联系人的年龄:\n");
	scanf("%d", &(cp->data[cp->size].age));

	printf("请输入要添加的联系人的性别:\n");
	scanf("%s", cp->data[cp->size].sex);

	printf("请输入要添加的联系人的住址:\n");
	scanf("%s", cp->data[cp->size].address);

	cp->size++;
	printf("添加成功\n");
}

//通过姓名进行查找联系人
int FindPeople(Contact* cp, char name[])
{
	assert(cp);
	for (int i = 0; i < cp->size; i++)
	{
		if (strcmp(cp->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

//删除联系人
void DelContact(Contact* cp)
{
	assert(cp);
	char name[Name_Max];
	if (cp->size == 0)
	{
		printf("通讯录为空,无需删除\n");
		return;
	}
	printf("请输入选择删除的联系人的姓名:\n");
	scanf("%s", name);
	int ret = FindPeople(cp, name);
	if (ret == -1)
	{
		printf("要删除的联系人不存在\n");
		return;
	}
	for (int i = ret; i < cp->size - 1; i++)
	{
		cp->data[i] = cp->data[i + 1];
	}
	cp->size--;
	printf("删除成功\n");
}

//查询联系人
void SeachPeople(Contact* cp)
{
	assert(cp);
	char name[Name_Max];
	if (cp->size == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("请输入选择查找的联系人的姓名:\n");
	scanf("%s", name);
	int ret = FindPeople(cp, name);
	if (ret == -1)
	{
		printf("要查找的联系人不存在\n");
		return;
	}

	//名字  年龄  性别    电话    地址
	//xxx   xxx    xxx    xxx     xxx
	printf("%-10s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	//打印个人的信息
	printf("%-10s%-5d%-5s%-12s%-30s\n", cp->data[ret].name, cp->data[ret].age, cp->data[ret].sex, cp->data[ret].telnumber, cp->data[ret].address);
}

//展示全部通讯录信息
void ShowContact(const Contact* cp)
{
	assert(cp);
	if (cp->size == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	//名字  年龄  性别    电话    地址
	//xxx   xxx    xxx    xxx     xxx
	printf("%-10s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < cp->size; i++)
	{
		//打印每个人的信息
		printf("%-10s%-5d%-5s%-12s%-30s\n", cp->data[i].name, cp->data[i].age, cp->data[i].sex, cp->data[i].telnumber, cp->data[i].address);
	}
}

//修改联系人信息
void ModifyContact(Contact* cp)
{
	assert(cp);
	char name[Name_Max];
	if (cp->size == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("请输入选择修改的联系人的姓名:\n");
	scanf("%s", name);
	int ret = FindPeople(cp, name);
	if (ret == -1)
	{
		printf("要修改的联系人信息不存在\n");
		return;
	}

	printf("请输入要修改的联系人的姓名:\n");
	scanf("%s", cp->data[ret].name);

	printf("请输入要修改的联系人的电话号:\n");
	scanf("%s", cp->data[ret].telnumber);

	printf("请输入要修改的联系人的年龄:\n");
	scanf("%d", &(cp->data[ret].age));

	printf("请输入要修改的联系人的性别:\n");
	scanf("%s", cp->data[ret].sex);

	printf("请输入要修改的联系人的住址:\n");
	scanf("%s", cp->data[ret].address);

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

//销毁通讯录
void DestoryContact(Contact* cp)
{
	free(cp->data);
	cp->data = NULL;
	cp->size = 0;
	cp->capacity = 0;
}

主函数部分(test.cpp)

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"

//枚举,增加程序的可读性
enum options
{
	EXIT,
	ADD,
	DEL,
	SEACH,
	MODIFY,
	SHOW
};

int main()
{
	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 SEACH:
			SeachPeople(&con);
			break;
			//修改某个联系人的信息
		case MODIFY:
			ModifyContact(&con);
			break;
			//展示通讯录内的每一个联系人的信息
		case SHOW:
			ShowContact(&con);
			break;
			//退出通讯录管理系统
		case EXIT:
			DestoryContact(&con);
			printf("通讯录已退出\n");
			break;
			//预防非法输入
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);

	return 0;
}

二.文件的生成

        想要把通讯录里的数据保存在文件中,首先就得生成一个文件,但生成文件的思路应该注意,以下笔者给大家提供俩个思路:

  1. 写入一个数据就生成文件,如果文件已生成,那就写入文件
  2. 在用户使用完通讯录后一次性将所有数据写入

        大家可以思考,哪种思路更高效,很显然,频繁的打开,写入,关闭文件是不利于我们执行程序的,因此,我们选择第二条思路,当然第一条思路也是可行的,在某些特定的需求下,可能第一条思路还要更优秀一点,但是作为一般讲,我们还是希望程序运行所需的时间和空间越简单越好 

        因此,本文采取第二种生成文件的思路:在用户使用完通讯录后一次性将所有数据写入,也就是说,我们需要在用户使用完通讯录程序以后,选择退出通讯录的时候进行生成文件,并且将通讯录中的数据导入

因此,我们封装一个函数,来生成通讯录文件

//读取文件信息到通讯录
void LoadContact(Contact* cp);

选择何种方式写文件?

        我们的通讯录管理系统中,有字符串,有整形,还可能有浮点型,短整形,结构体类型等等复杂的数据类型,因此单一的某中写入方式必然是不在我们考虑范围内的,针对我们的需求,我们需要选择一个 “万金油” 的写入方式————二进制写入

        不管是整形,浮点型,字符串,我们使用二进制去读取写入都是通用的,因此后文中对通讯录文件的读取也是使用的二进制读取

SaveContact

我们可以这样设计:

        首先,我们先打开文件,如果打开失败,那就报错提醒,如果正确打开了,那我们就进行写入文件,使用一个循环,一共有多少个联系人信息,我们就写入多少次,每次写入一个联系人的信息,写入完成后关闭文件,并且把指针置为空,避免造成野指针的问题

//生成文件,保存通讯录中的数据
void SaveContact(Contact* cp)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}

	//写文件
	for (int i = 0; i < cp->size; i++)
	{
		fwrite(cp->data + i, sizeof(PeoInfor), 1, pf);
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

三.文件数据的读取

        光有文件的生成是不够的,假如文件内部已经存了许多联系人的信息了,当我们打开通讯录管理系统的时候,这些数据也应该已经被读取了才合理

        因此,我们将文件数据的读取放在通讯录的初始化部分

我们封装一个函数来帮助我们实现这部分功能:

//读取文件信息到通讯录
void LoadContact(Contact* cp);

        当我们打开通讯录管理系统后,首先进行初步的初始化通讯录,然后我们将文件中的数据读取到里面

//初始化通讯录
void InitContact(Contact* cp)
{
	//判断非空
	assert(cp);

	//初步初始化
	cp->size = 0;
	cp->capacity = Contact_SZ;
	cp->data = (PeoInfor*)calloc(cp->capacity, sizeof(PeoInfor));
	if (cp->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}

	//读取文件信息到通讯录
	LoadContact(cp);
}

LoadContact

为了对应我们前面用二进制写入文件,这里我们就应该使用二进制读取文件

	//打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}

        我们构建一个结构体数组的临时变量我们先将数据从文件读出来一个,然后再判断通讯录是否已经满了,如果满了,那就先扩容,然后再把临时变量中的数据放入通讯录中,如果没有满,那就直接放入通讯录 

//读取文件信息到通讯录
void LoadContact(Contact* cp)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}

	//读取文件
	PeoInfor temp = { 0 };
	while (fread(&temp, sizeof(PeoInfor), 1, pf))
	{
		CheckContact(cp);
		cp->data[cp->size] = temp;
		cp->size++;
	}
}

其中判断扩容函数如下:

//检查扩容
void CheckContact(Contact* cp)
{
	if (cp->size == cp->capacity)
	{
		PeoInfor* ptr = (PeoInfor*)realloc(cp->data, (cp->capacity + 2) * sizeof(PeoInfor));
		if (ptr != NULL)
		{
			cp->data = ptr;
			cp->capacity += 2;
			printf("增容成功\n");
		}
		else
		{
			perror("AddContact->realloc");
			return;
		}
	}
}

四.运行结果截图

我们先输入4个人的信息,然后退出程序

        观察文件,因为我们使用的是二进制保存,而记事本使用的是 UTF-8 的格式,故而这里无法直观看到信息,信息相当于被加密了,但是可以确定的是我们确实是将数据保存下来了

然后我们重新再打开一遍程序,可以看见,数据一开始就增容成功读取到了

后续再进行增删查改等操作也是没有影响的


五.完整代码 

头文件部分Contact.h

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

#define Name_Max 20
#define Tel_Number 12
#define Sex_Max 5
#define Address_Max 30
#define Contact_Max 100
#define Contact_SZ 3

//联系人结构体
typedef struct PeopleInformation
{
	char name[Name_Max];
	char telnumber[Tel_Number];
	int age;
	char sex[Sex_Max];
	char address[Address_Max];
}PeoInfor;

//通讯录结构体
typedef struct Contact
{
	PeoInfor* data;//结构体数组存放联系人结构体
	int size;//记录当前通讯录中有多少个联系人
	int capacity;//记录当前存放的容量
}Contact;


//目录
void menu();

//初始化通讯录
void InitContact(Contact* cp);

//增加联系人
void AddContact(Contact* cp);

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

//通过姓名进行查找联系人
int FindPeople(Contact* cp, char name[]);

//展示全部通讯录信息
void ShowContact(const Contact* cp);

//查询联系人
void SeachPeople(Contact* cp);

//修改联系人信息
void ModifyContact(Contact* cp);

//jia扩容
void CheckContact(Contact* cp);

//销毁通讯录
void DestoryContact(Contact* cp);

//生成文件,保存通讯录中的数据
void SaveContact(Contact* cp);

//读取文件信息到通讯录
void LoadContact(Contact* cp);

函数实现部分Contact.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"

void menu()
{
	printf("\n");
	printf("-----------------------------\n");
	printf("---   1.添加联系人      -----\n");
	printf("---   2.删除联系人      -----\n");
	printf("---   3.查找联系人      -----\n");
	printf("---   4.修改联系人信息  -----\n");
	printf("---   5.显示全部信息    -----\n");
	printf("---   0.退出通讯录      -----\n");
	printf("-----------------------------\n");
}


//读取文件信息到通讯录
void LoadContact(Contact* cp)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}

	//读取文件
	PeoInfor temp = { 0 };
	while (fread(&temp, sizeof(PeoInfor), 1, pf))
	{
		CheckContact(cp);
		cp->data[cp->size] = temp;
		cp->size++;
	}
}

//初始化通讯录
void InitContact(Contact* cp)
{
	//判断非空
	assert(cp);

	//初步初始化
	cp->size = 0;
	cp->capacity = Contact_SZ;
	cp->data = (PeoInfor*)calloc(cp->capacity, sizeof(PeoInfor));
	if (cp->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}

	//读取文件信息到通讯录
	LoadContact(cp);
}


//检查扩容
void CheckContact(Contact* cp)
{
	if (cp->size == cp->capacity)
	{
		PeoInfor* ptr = (PeoInfor*)realloc(cp->data, (cp->capacity + 2) * sizeof(PeoInfor));
		if (ptr != NULL)
		{
			cp->data = ptr;
			cp->capacity += 2;
			printf("增容成功\n");
		}
		else
		{
			perror("AddContact->realloc");
			return;
		}
	}
}

//增加联系人
void AddContact(Contact* cp)
{
	//判断非空
	assert(cp);

	//判断满后扩容
	CheckContact(cp);

	printf("请输入要添加的联系人的姓名:\n");
	scanf("%s", cp->data[cp->size].name);

	printf("请输入要添加的联系人的电话号:\n");
	scanf("%s", cp->data[cp->size].telnumber);

	printf("请输入要添加的联系人的年龄:\n");
	scanf("%d", &(cp->data[cp->size].age));

	printf("请输入要添加的联系人的性别:\n");
	scanf("%s", cp->data[cp->size].sex);

	printf("请输入要添加的联系人的住址:\n");
	scanf("%s", cp->data[cp->size].address);

	cp->size++;
	printf("添加成功\n");
}

//通过姓名进行查找联系人
int FindPeople(Contact* cp, char name[])
{
	assert(cp);
	for (int i = 0; i < cp->size; i++)
	{
		if (strcmp(cp->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

//删除联系人
void DelContact(Contact* cp)
{
	assert(cp);
	char name[Name_Max];
	if (cp->size == 0)
	{
		printf("通讯录为空,无需删除\n");
		return;
	}
	printf("请输入选择删除的联系人的姓名:\n");
	scanf("%s", name);
	int ret = FindPeople(cp, name);
	if (ret == -1)
	{
		printf("要删除的联系人不存在\n");
		return;
	}
	for (int i = ret; i < cp->size - 1; i++)
	{
		cp->data[i] = cp->data[i + 1];
	}
	cp->size--;
	printf("删除成功\n");
}

//查询联系人
void SeachPeople(Contact* cp)
{
	assert(cp);
	char name[Name_Max];
	if (cp->size == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("请输入选择查找的联系人的姓名:\n");
	scanf("%s", name);
	int ret = FindPeople(cp, name);
	if (ret == -1)
	{
		printf("要查找的联系人不存在\n");
		return;
	}

	//名字  年龄  性别    电话    地址
	//xxx   xxx    xxx    xxx     xxx
	printf("%-10s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	//打印个人的信息
	printf("%-10s%-5d%-5s%-12s%-30s\n", cp->data[ret].name, cp->data[ret].age, cp->data[ret].sex, cp->data[ret].telnumber, cp->data[ret].address);
}

//展示全部通讯录信息
void ShowContact(const Contact* cp)
{
	assert(cp);
	if (cp->size == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	//名字  年龄  性别    电话    地址
	//xxx   xxx    xxx    xxx     xxx
	printf("%-10s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < cp->size; i++)
	{
		//打印每个人的信息
		printf("%-10s%-5d%-5s%-12s%-30s\n", cp->data[i].name, cp->data[i].age, cp->data[i].sex, cp->data[i].telnumber, cp->data[i].address);
	}
}

//修改联系人信息
void ModifyContact(Contact* cp)
{
	assert(cp);
	char name[Name_Max];
	if (cp->size == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("请输入选择修改的联系人的姓名:\n");
	scanf("%s", name);
	int ret = FindPeople(cp, name);
	if (ret == -1)
	{
		printf("要修改的联系人信息不存在\n");
		return;
	}

	printf("请输入要修改的联系人的姓名:\n");
	scanf("%s", cp->data[ret].name);

	printf("请输入要修改的联系人的电话号:\n");
	scanf("%s", cp->data[ret].telnumber);

	printf("请输入要修改的联系人的年龄:\n");
	scanf("%d", &(cp->data[ret].age));

	printf("请输入要修改的联系人的性别:\n");
	scanf("%s", cp->data[ret].sex);

	printf("请输入要修改的联系人的住址:\n");
	scanf("%s", cp->data[ret].address);

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

//销毁通讯录
void DestoryContact(Contact* cp)
{
	free(cp->data);
	cp->data = NULL;
	cp->size = 0;
	cp->capacity = 0;
}


//生成文件,保存通讯录中的数据
void SaveContact(Contact* cp)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}

	//写文件
	for (int i = 0; i < cp->size; i++)
	{
		fwrite(cp->data + i, sizeof(PeoInfor), 1, pf);
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

主函数部分(test.cpp)

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"

//枚举,增加程序的可读性
enum options
{
	EXIT,
	ADD,
	DEL,
	SEACH,
	MODIFY,
	SHOW
};

int main()
{
	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 SEACH:
			SeachPeople(&con);
			break;
			//修改某个联系人的信息
		case MODIFY:
			ModifyContact(&con);
			break;
			//展示通讯录内的每一个联系人的信息
		case SHOW:
			ShowContact(&con);
			break;
			//退出通讯录管理系统
		case EXIT:
			SaveContact(&con);
			DestoryContact(&con);
			printf("通讯录已退出\n");
			break;
			//预防非法输入
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);

	return 0;
}



本次分享就到此为止了,感谢您的支持,如有错误,欢迎积极指正

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

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

相关文章

智能电表线路单回路双回路的区别

随着科技的发展和能源管理的需求&#xff0c;智能电表已经成为电力系统中不可或缺的一部分。智能电表可以通过数据通信网络将用电信息实时传输到电力公司&#xff0c;为电力公司提供更精确、实时的用电数据&#xff0c;同时也可以为用户提供更加智能化的用电服务。 在智能电表…

局域网上IP多播与IP单播关于MAC地址的区别

IP单播进行到局域网上的时候&#xff1a; 网际层使用IP地址进行寻址&#xff0c;各路由器收到IP数据报后&#xff0c;根据其首部中的目的IP地址的网络号部分&#xff0c;基于路由表进行查表转发。 查表转发的结果可指明IP数据报的下一跳路由器的IP地址&#xff0c;但无法指明…

pid-limit参数实验

fork炸弹命令 :(){ :|:& };: 可以看到&#xff0c;如果docker没有限制&#xff0c;会遭到fork炸弹恶意 参考 https://www.cyberciti.biz/faq/understanding-bash-fork-bomb/

146616-66-2,胺反应性染料BDP FL NHS Ester,聚乙二醇单烯丙基醚

产品概览&#xff1a;Amine reactive bright&#xff0c;一种光稳定性佳的绿色荧光染料&#xff0c;以发挥独特的分子发光性能。此乃改进型的FAM&#xff08;荧光素&#xff09;荧光染料接班人——BDP FL NHS ester&#xff0c;在488nm通道中绽放色彩。这种胺反应性染料&#x…

信息系统项目管理师第四版学习笔记——项目绩效域

干系人绩效域 干系人绩效域涉及与干系人相关的活动和职能。在项目整个生命周期过程中&#xff0c;有效执行本绩效域可以实现的预期目标主要包含&#xff1a;①与干系人建立高效的工作关系&#xff1b;②干系人认同项目目标&#xff1b;③支持项目的干系人提高了满意度&#xf…

在原有的vue(react)项目中引入electron打包成桌面应用(全网最新!)

基于原有的项目中使用electron打包成桌面应用 首先了解electron是什么? 软件简介 Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台的桌面应用程序。它基于 Node.js 和 Chromium,被 Atom 编辑器和许多其他应用程序使用。 Electron 兼容 Mac、Windows 和 Linux,可以…

SpringMVC源码分析(二)启动过程之RequestMappingHandlerMapping分析

a、http请求中的url是如何与对应Handler的即Controller对应method映射的&#xff1f; 在上篇中提到在SpringMVC中&#xff0c;初始化9大内置组件的时候其中有一个组件就是HandlerMapping&#xff0c;在初始化HandlerMapping的时候会加载代码中所有标注了Controller和RequestMap…

视频目标分割数据集分享

MOSE: A New Dataset for Video Object Segmentation in Complex Scenes MOSE 是一个新的视频目标分割数据集&#xff0c;旨在解决复杂环境下的目标跟踪和分割。MOSE 包含 2,149 个视频片段和来自 36 个类别的 5,200 个物体&#xff0c;以及 431,725 个高质量物体分割掩码。MOS…

ubuntu安装依赖包时显示需要先安装其所需要的各种安装包)apt-get源有问题

最近在崭新的ubuntu上安装g以及一些其他的依赖与工具时遇到以下报错情况&#xff1a; 依赖环环相扣&#xff0c;手动无法解决。 总结&#xff1a; 出现需要很多依赖项的情况是因为软件源中没有可用的依赖项或者依赖项版本不正确。 其实在Ubuntu系统中&#xff0c;使用sudo…

Java程序设计实验4 | 面向对象(下)

*本文是博主对Java各种实验的再整理与详解&#xff0c;除了代码部分和解析部分&#xff0c;一些题目还增加了拓展部分&#xff08;⭐&#xff09;。拓展部分不是实验报告中原有的内容&#xff0c;而是博主本人自己的补充&#xff0c;以方便大家额外学习、参考。 &#xff08;没…

AI如何帮助Salesforce从业者找工作?

在当今竞争激烈的就业市场中&#xff0c;找到满意的工作是一项艰巨的任务。成千上万的候选人竞争一个岗位&#xff0c;你需要利用一切优势从求职大军中脱颖而出。 这就是AI的用武之地&#xff0c;特别是像ChatGPT这样的人工智能工具&#xff0c;可以成为你的秘密武器。本篇文章…

2.1、如何在FlinkSQL中读取写出到Kafka

目录 1、环境设置 方式1&#xff1a;在Maven工程中添加pom依赖 方式2&#xff1a;在 sql-client.sh 中添加 jar包依赖 2、读取Kafka 2.1 创建 kafka表 2.2 读取 kafka消息体&#xff08;Value&#xff09; 使用 format json 解析json格式的消息 使用 format csv 解析…

力扣第98题 验证二叉搜索树 c++ 与上一篇文章相似

题目 98. 验证二叉搜索树 中等 相关标签 树 深度优先搜索 二叉搜索树 二叉树 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当…

淘宝天猫商品历史价格API接口

获取淘宝商品历史价格接口的步骤如下&#xff1a; 注册淘宝开放平台&#xff1a;首先在淘宝开放平台上注册一个账号&#xff0c;并进行登录。创建应用&#xff1a;在淘宝开放平台上创建一个应用&#xff0c;并获取该应用的App Key和App Secret&#xff0c;用于后续的接口调用。…

Python“梦寻”淘宝天猫店铺所有数据接口,淘宝店铺所有商品数据API接口,淘宝API接口申请指南(含代码示例)

获取淘宝店铺所有商品数据的接口可以通过淘宝开放平台获取。 具体操作步骤如下&#xff1a; 在淘宝开放平台注册成为开发者&#xff0c;并创建一个应用&#xff0c;获取到所需的 App Key 和 App Secret 等信息。使用获取到的 App Key 和 App Secret&#xff0c;进行签名和认证…

Android组件通信——Intent(二十三)

1. 认识Intent 1.1 知识点 &#xff08;1&#xff09;了解Intent的主要作用&#xff1b; &#xff08;2&#xff09;掌握Activity程序对Intent操作的支持&#xff1b; &#xff08;3&#xff09;可以使用Intent完成Activity程序间的跳转&#xff0c;也可以通过Intent接收返…

QT基础 QChart绘制折线

目录 1.简单折线 2.数学折线 3.可滑动折线 1.简单折线 //![1] //! 折现段坐标QLineSeries *series new QLineSeries(); //![1]//![2] //! 添加点series->append(0, 6);series->append(2, 4);series->append(3, 8);series->append(7, 4);series->append(10, 5)…

YOLOv7改进: CFP:即插即用的多尺度融合模块,EVC助力小目标检测| 顶刊TIP 2023

💡💡💡本文独家改进:即插即用的多尺度融合模块,EVC助力小目标检测 EVC | 亲测在多个数据集实现暴力涨点,强烈推荐,独家首发; 收录: YOLOv7高阶自研专栏介绍:http://t.csdnimg.cn/tYI0c ✨✨✨前沿最新计算机顶会复现 🚀🚀🚀YOLOv7自研创新结合,轻松搞…

MS31804四通道低边驱动器可pin对pin兼容DRV8804

MS31804TE 是一个具有过流保护功能的四通道低边驱动器。MS31804TE 内置钳位二极管&#xff0c;用来钳制由电感负载续流产生的电压。MS31804TE 可以驱动单极步进电机、直流电机、继电器、螺线管或者其它负载。 散热良好的情况下&#xff0c;MS31804TE 可以提供每个通道最高 2A 的…

整理笔记——二极管

一、什么是二极管 二极管是一种由半导体材料制成的一种具有单向导电性能的电子元器件&#xff0c;二极管的核心是PN结。 加在二极管两端的电压和通关的电流被成为&#xff0c;二极管的伏安特性曲线 ​​​ 二极管的正向特性&#xff1a;起初正向电压较小时&#xff0c;正向电流…