浪漫的通讯录(顺序表篇)

news2024/9/24 9:22:16

本篇会加入个人的所谓‘鱼式疯言’
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!
在这里插入图片描述

前言

哈哈哈,有没有被小编的标题所吸引住,那么友子们是否也想做个有意思的通讯录来制造点浪漫氛围呢💕💕💕
想必友友们答案一定是想的吧 ! ! !
在本篇博文中,我们主要讲解

目录

1.静态顺序表和动态顺序表
2.利用动态顺序表实现通讯录
3.通讯录的功能和逻辑框架
4.每个逻辑功能的实现
5.通讯录源文件的展示

一.静态顺序表和动态顺序表

<1>. 顺序表的概念

友友们一定很疑惑顺序表是什么吧 ?
让小编来一一为大家解惑吧 💖 💖 💖

顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口

<2>. 顺序表的种类

而我们的顺序表又分两种:

静态顺序表

动态顺序表

这两个的区别在哪呢 ?
在这里插入图片描述

其实啊,主要看我们怎么给我们数组长度怎么创建 🤔 🤔 🤔
如果是一开始就给定我们的数组长度呢,我们就叫它静态顺序表
如果我们一开不给长度而只是给个指针,需要我们后期来开辟的.这是我们就叫它动态顺序表

那么我们爱提问的小爱同学就抛出问题来了,
我们今天要学的通讯录是用动态还是静态的顺序表呢 😲 😲 😲

很显然我们需要用的是动态顺序表
宝子们可以想想,动态顺序表我们需要用多少空间就可以开辟相对应的空间
在这里插入图片描述

而我们的静态的话,万一空间不足就会造成 数据的丢失 (如果数据丢失很严重的话,是要吃牢饭的) 😣 😣 😣
空间足够就会造成 空间的浪费

在这里插入图片描述

鱼式疯言

本质上我们的顺序表就是一个 “披着羊皮” 伪装成 顺序表数组
怎么样修饰就觉得着是怎么样的顺序表,其他都一样。

二 . 利用动态顺序表实现通讯录

<1>.顺序表的选择

友友们还是会思考如果我们知道动态顺序表
然后呢?
该怎么样去建立之间的架构呢 🤔 🤔 🤔

宝子们都学过,我们数组存放的是一些同类型的数据,那如果把这些数据都比喻成我们的联系人呢,是不是就可以建立我们的联系人的大图谱成为我们的通讯录了 💖 💖 💖
在这里插入图片描述

#define _NAMEMAX_ 50
#define _SEXMAX_  20
#define _PHONEMAX_ 100
#define _POSITMAX_ 300

typedef struct PresonInt
{
	char name[_NAMEMAX_];
	//名字

	char sex[_SEXMAX_];
	//性别
	int  age;
	//年龄
	char phone[_PHONEMAX_];
	//电话

	char posit[_POSITMAX_];
	//地址
}Prt;


typedef Prt SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{
    SLDataType* a;
    int size;     // 有效数据个数
    int capacity; // 空间容量
}SL;

于是我们就有了以上的这些类型的声明

鱼式疯言

其实友友们可以和我这样看,我们的 a 就是数组,
那么这个数组存的是什么数据呢,我们平常存的 整型字符 一类的

但我们学了结构体之后我们就可以利用就结构体把我们想要存储的各种数据类型打包成一个
那就是我们的 结构体类型

三.通讯录的功能和逻辑框架

<1>.功能简介

1)至少能够存储100个人的通讯信息
2)能够保存用户信息:名字、性别、年龄、电话、地址等
3)增加联系人信息
4)删除指定联系人
5)查找制定联系人
6)修改指定联系人
7)显示联系人信息

case 1:
	ContastAdd(&con);
	//添加联系人
	break;
case 2:
	ContastFind(&con);
	//查找联系人
	break;
case 3:
	Contastdele(&con);
	//删除联系人
	break;	
case 4:
	ContastSet(&con);
	//修改联系人
	break;
case 5:
	ContastShow(&con);
	//显示通讯录
	break;
case 6:
	PutSLFile(&con);
	//保存通讯录文档
	break;
case 7:
	GetSLFile(&con);
	//读取通讯录信息
	break;

在这里插入图片描述

<2>.逻辑框架

1.通讯录的初始化过程

3,.联系人数据的保存和通讯录的销毁过程

void PutSLFile(SL* ps);
//保存联系人文件
void GetSLFile(SL* ps);
//读取通讯录文档


void SLInit(SL* ps);
void SLDestroy(SL* ps);
//顺序表初始化和销毁


void ContastInit(SL* ps);
//通讯录初始化
void ContastDestory(SL* ps);
//销毁通讯录

2.通讯录与顺序表功能连接与维护过程

void SLCheckCapacity(SL* ps);
//顺序表扩容


void ContastAdd(SL* ps);
//添加联系人

void ContastShow(SL* ps);
//显示通讯录

void ContastFind(SL* ps);
//查找联系人

void ContastSet(SL* ps);
//修改指定联系人信息

void SLErase(SL* ps, int pos);
//指定位置删除数据


void Contastdele(SL* ps);
//删除指定联系人

在这里插入图片描述

四.每个逻辑功能的实现

<1> 菜单打印和通讯录的初始化

 void Meau()
//菜单功能介绍
{
	printf("------------------ 通讯录 -------------------\n");
	printf("--------- 1.添加联系人 2.查找联系人 ---------\n");	
	printf("--------- 3.删除联系人 4.修改联系人 ---------\n");
	printf("--------- 5.显示通讯录 6.保存通讯录 ---------\n");
	printf("----------7.读取已存通讯录 0. 退出 ----------\n");
	
}
void ContastInit(SL*ps)
//通讯录初始化
{
	SLInit(ps);
}

void SLInit(SL*ps)
//对顺序表进行初始化
{
	ps->a = NULL;
	//数组元素为0
	
	ps->capacity = 0;
	//最大容量放置为0

	ps->size = 0;
	//有效数据为0
}

<2>.顺序表的扩容(如果数组长度不够)

void SLCheckCapacity(SL* ps)
//扩容顺序表空间
{
	assert(ps);
	if (ps->capacity == ps->size)
	{
		
		int newcapaacity = ps->capacity == 0 ? INIT_CAPACITY : 2 * (ps->capacity);
		//用三目操作符来判断总容量是否位0
		
		SLDataType* p1 = (SLDataType*)realloc(ps->a, newcapaacity * sizeof(SLDataType));
		//开辟成倍空间大小的空间

		if (p1 == NULL)
		//判断是否开辟成功
		{
			perror("malloc");
			return;
		}

		ps->a = p1;
		//开辟成功就放入
		ps->capacity = newcapaacity;

	}

}

<3>.添加联系人数据(功能一)

void ContastAdd(SL* ps)
//添加联系人
{
	SLCheckCapacity(ps);
	//空间不够时

	puts("亲,请输入你的姓名:");
	scanf("%s", ps->a[ps->size].name);
	
	puts("亲,请输入你的性别:");
	scanf("%s", ps->a[ps->size].sex);
	
	puts("亲,请输入你的年龄:");
	scanf("%d", &ps->a[ps->size].age);
	
	puts("亲,请输入你的电话:");
	scanf("%s", ps->a[ps->size].phone);
	
	puts("亲,请输入你的住址:");
	scanf("%s", ps->a[ps->size].posit);

	ps->size++;
}

在这里插入图片描述

<4>.查询联系人(以名字为根据查询)

int Findname(SL*ps, char nm[])
//查找名字
{
	for (int i = 0; i < ps->size; i++)
	{
		if (strcmp(ps->a[i].name, nm) == 0)
		{
			return i;
		}
	}
	return -1;
}

<5>. 查找联系人 (功能二)

void ContastFind(SL*ps)
//查找联系人
{
	char nm[50] = {0};
	puts("请输入要查找的联系人姓名");
	scanf("%s", nm);
	int m = Findname(ps, nm);
	if (m>=0)
	{
		printf("名字\t性别\t年龄\t电话\t地址\n");
		printf("%s\t", ps->a[m].name);
		printf("%s\t", ps->a[m].sex);
		printf("%d\t", ps->a[m].age);
		printf("%s\t", ps->a[m].phone);
		printf("%s\n", ps->a[m].posit);
		return;
	}
	printf("未搜索到该联系人,查找错误!\n");


}

在这里插入图片描述

如果没有找到就会显示错误

在这里插入图片描述

<6> . 删除联系人 (功能三)

void Contastdele(SL*ps)
//删除指定联系人
{
	char nm[50] = { 0 };
	puts("请输入要删除的联系人姓名");
	scanf("%s", nm);
	int m = Findname(ps, nm);
	if (m >= 0)
	{
		SLErase(ps, m + 1);
		printf("删除成功!\n");
		return;
	}
	puts("未搜索到该联系人, 删除错误!");
}

在这里插入图片描述

<7>.修改联系人(功能四)

void ContastSet(SL* ps)
//修改指定联系人信息
{
	char nm[50] = { 0 };
	puts("请输入要修改的联系人姓名");
	scanf("%s", nm);
	int m = Findname(ps, nm);
	if (m >=0)
	{
		puts("亲,请输入你修改后的姓名:");
		scanf("%s", ps->a[m].name);
		puts("亲,请输入你修改后的性别:");

		scanf("%s", ps->a[m].sex);
		puts("亲,请输入你修改后的年龄:");

		scanf("%d", &ps->a[m].age);
		puts("亲,请输入你修改后的电话:");

		scanf("%s", ps->a[m].phone);
		puts("亲,请输入你修改后的住址:");

		scanf("%s", ps->a[m].posit);

		printf("该联系人修改成功!\n");
		return ;
	}
	puts("未搜索到该联系人,修改失败!");
}

在这里插入图片描述

<8>.显示通讯录(功能五)

void ContastShow(SL* ps)
//显示通讯录
{
	assert(ps && ps->size);
	printf("名字\t性别\t年龄\t电话\t地址\n");
	for (int i = 0; i < ps->size; i++)
	{
		printf("%s\t", ps->a[i].name);
		printf("%s\t", ps->a[i].sex);
		printf("%d\t", ps->a[i].age);
		printf("%s\t", ps->a[i].phone);
		printf("%s\n", ps->a[i].posit);
	}
}

在这里插入图片描述

<9>.保存通讯录信息(功能六)

//这个函数接口时保存通讯录文档,就是将通讯录的信息写入到文件
//保存通讯录文档
void PutSLFile(SL* ps)
{
	//写入文件
	FILE* pfwrite = fopen("contact.txt","w");
	
	//判断 pfwrite 是否为NULL
	if (fwrite == NULL)
	{
		perror("fopen->fwrite");
		return;
	}

	for (int i = 0; i < ps->size; i++)
	{
		//用循环的方式
		//把每个数据以格式化的方式存入
		fprintf(pfwrite,"%s\n", ps->a[i].name);
		fprintf(pfwrite,"%s\n", ps->a[i].sex);
		fprintf(pfwrite,"%d\n", ps->a[i].age);
		fprintf(pfwrite,"%s\n", ps->a[i].phone);
		fprintf(pfwrite,"%s\n", ps->a[i].posit);
	}


	printf("保存成功!\n");

	fclose(pfwrite);
	pfwrite = NULL;
}

在这里插入图片描述

<10>. 读取已有联系人数据(功能七)

//读取通讯录文档
void GetSLFile(SL* ps)
{
	FILE* pfread = fopen("contact.txt", "r");
	
	//防止NULL出现
	if (pfread == NULL)
	{
		perror("fopen->pfread");
		return;
	}

	//先开辟空间
	//防止野指针的出现
	SLCheckCapacity(ps);

	//将数组每个数据进行初始存放
	while (fscanf(pfread,"%s%s%d%s%s",ps->a[ps->size].name, ps->a[ps->size].sex, &ps->a[ps->size].age, ps->a[ps->size].phone, ps->a[ps->size].posit) != EOF)
	{
		SLCheckCapacity(ps);
		ps->size++;
	}


	//打印提示信息
	printf("读取成功!\n");

	//关闭文件
	fclose(pfread);

	//防止野指针
	pfread = NULL;
}

在这里插入图片描述

<11>.通讯录的销毁

void ContastDestory(SL* ps)
//销毁通讯录
{
	SLDestroy(ps);
}
void SLDestroy(SL*ps)
//销毁顺序表
{
	assert(ps);
	
	ps->capacity = 0;
	
	ps->size = 0;
	//容量和大小都置为0
	
	free(ps->a);
	//释放空间
	
	ps->a = NULL;
	//a置为空指针
}

在这里插入图片描述

鱼式疯言

上面的十个逻辑功能的实现,都是基于函数来分装的 ❤️ ❤️ ❤️
亲爱的宝子们,小编在写 通讯录 的时候是反复调用功能 相同的函数
函数的意义就在于我们能够反复利用,不要写多余的代码
宝子们也可以利用这一特点来快速实现我们的通讯录哦💕💕💕

五 . 通讯录源代码展示

顺序表和通讯录的头文件

<1>. seqlist.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#define INIT_CAPACITY 4
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>

#define _NAMEMAX_ 50
#define _SEXMAX_  20
#define _PHONEMAX_ 100
#define _POSITMAX_ 300

typedef struct PresonInt
{
	char name[_NAMEMAX_];
	//名字

	char sex[_SEXMAX_];
	//性别
	int  age;
	//年龄
	char phone[_PHONEMAX_];
	//电话

	char posit[_POSITMAX_];
	//地址
}Prt;


typedef Prt SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{
    SLDataType* a;
    int size;     // 有效数据个数
    int capacity; // 空间容量
}SL;



//顺序表初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);

void ContastInit(SL* ps);
//通讯录初始化
void ContastDestory(SL* ps);
//销毁通讯录


void SLCheckCapacity(SL* ps);
//顺序表扩容


void ContastAdd(SL* ps);
//添加联系人

void ContastShow(SL* ps);
//显示通讯录

void ContastFind(SL* ps);
//查找联系人

void ContastSet(SL* ps);
//修改指定联系人信息

void SLErase(SL* ps, int pos);
//指定位置删除数据


void Contastdele(SL* ps);
//删除指定联系人


void PutSLFile(SL* ps);
//保存联系人文件


//读取通讯录文档
void GetSLFile(SL* ps);

顺序表测试文件

<2>. seqlist.c

#include "seqlist.h"

void SLInit(SL*ps)
//对顺序表进行初始化
{
	ps->a = NULL;
	//数组元素为0
	
	ps->capacity = 0;
	//最大容量放置为0

	ps->size = 0;
	//有效数据为0
}

void SLCheckCapacity(SL* ps)
//扩容顺序表空间
{
	assert(ps);
	if (ps->capacity == ps->size)
	{
		
		int newcapaacity = ps->capacity == 0 ? INIT_CAPACITY : 2 * (ps->capacity);
		//用三目操作符来判断总容量是否位0
		
		SLDataType* p1 = (SLDataType*)realloc(ps->a, newcapaacity * sizeof(SLDataType));
		//开辟成倍空间大小的空间

		if (p1 == NULL)
		//判断是否开辟成功
		{
			perror("malloc");
			return;
		}

		ps->a = p1;
		//开辟成功就放入
		ps->capacity = newcapaacity;

	}

}


void SLErase(SL* ps, int pos)
//指定位置删除数据
{
	assert(ps && ps->size&&pos>0&&pos<ps->size+1);

	//删除后
	//向左移动
	for (int u = pos-1; u < ps->size-1; u++)
	{
		ps->a[u] = ps->a[u + 1];
	}
	
	

	(ps->size)--;
	//大小--
}

//这个函数接口时保存通讯录文档,就是将通讯录的信息写入到文件
//保存通讯录文档
void PutSLFile(SL* ps)
{
	//写入文件
	FILE* pfwrite = fopen("contact.txt","w");
	
	//判断 pfwrite 是否为NULL
	if (fwrite == NULL)
	{
		perror("fopen->fwrite");
		return;
	}

	for (int i = 0; i < ps->size; i++)
	{
		//用循环的方式
		//把每个数据以格式化的方式存入
		fprintf(pfwrite,"%s\n", ps->a[i].name);
		fprintf(pfwrite,"%s\n", ps->a[i].sex);
		fprintf(pfwrite,"%d\n", ps->a[i].age);
		fprintf(pfwrite,"%s\n", ps->a[i].phone);
		fprintf(pfwrite,"%s\n", ps->a[i].posit);
	}




	printf("保存成功!\n");

	fclose(pfwrite);
	pfwrite = NULL;
}

//读取通讯录文档
void GetSLFile(SL* ps)
{
	FILE* pfread = fopen("contact.txt", "r");
	
	//防止NULL出现
	if (pfread == NULL)
	{
		perror("fopen->pfread");
		return;
	}

	//先开辟空间
	//防止野指针的出现
	SLCheckCapacity(ps);

	//将数组每个数据进行初始存放
	while (fscanf(pfread,"%s%s%d%s%s",ps->a[ps->size].name, ps->a[ps->size].sex, &ps->a[ps->size].age, ps->a[ps->size].phone, ps->a[ps->size].posit) != EOF)
	{
		SLCheckCapacity(ps);
		ps->size++;
	}


	//打印提示信息
	printf("读取成功!\n");

	//关闭文件
	fclose(pfread);

	//防止野指针
	pfread = NULL;
}



void SLDestroy(SL*ps)
//销毁顺序表
{
	assert(ps);
	
	ps->capacity = 0;
	
	ps->size = 0;
	//容量和大小都置为0
	
	free(ps->a);
	//释放空间
	
	ps->a = NULL;
	//a置为空指针
}

通讯录测试文件

<3>. contact.c

#include "seqlist.h"


void Meau()
//菜单功能介绍
{
	printf("------------------ 通讯录 -------------------\n");
	printf("--------- 1.添加联系人 2.查找联系人 ---------\n");	
	printf("--------- 3.删除联系人 4.修改联系人 ---------\n");
	printf("--------- 5.显示通讯录 6.保存通讯录 ---------\n");
	printf("----------7.读取已存通讯录 0. 退出 ----------\n");
	
}


void ContastInit(SL*ps)
//通讯录初始化
{
	SLInit(ps);
}

void ContastDestory(SL* ps)
//销毁通讯录
{
	SLDestroy(ps);
}

void ContastAdd(SL* ps)
//添加联系人
{
	SLCheckCapacity(ps);
	//空间不够时

	puts("亲,请输入你的姓名:");
	scanf("%s", ps->a[ps->size].name);
	
	puts("亲,请输入你的性别:");
	scanf("%s", ps->a[ps->size].sex);
	
	puts("亲,请输入你的年龄:");
	scanf("%d", &ps->a[ps->size].age);
	
	puts("亲,请输入你的电话:");
	scanf("%s", ps->a[ps->size].phone);
	
	puts("亲,请输入你的住址:");
	scanf("%s", ps->a[ps->size].posit);

	ps->size++;
}

void ContastShow(SL* ps)
//显示通讯录
{
	assert(ps && ps->size);
	printf("名字\t性别\t年龄\t电话\t地址\n");
	for (int i = 0; i < ps->size; i++)
	{
		printf("%s\t", ps->a[i].name);
		printf("%s\t", ps->a[i].sex);
		printf("%d\t", ps->a[i].age);
		printf("%s\t", ps->a[i].phone);
		printf("%s\n", ps->a[i].posit);
	}
}

int Findname(SL*ps, char nm[])
//查找名字
{
	for (int i = 0; i < ps->size; i++)
	{
		if (strcmp(ps->a[i].name, nm) == 0)
		{
			return i;
		}
	}
	return -1;
}
void ContastFind(SL*ps)
//查找联系人
{
	char nm[50] = {0};
	puts("请输入要查找的联系人姓名");
	scanf("%s", nm);
	int m = Findname(ps, nm);
	if (m>=0)
	{
		printf("名字\t性别\t年龄\t电话\t地址\n");
		printf("%s\t", ps->a[m].name);
		printf("%s\t", ps->a[m].sex);
		printf("%d\t", ps->a[m].age);
		printf("%s\t", ps->a[m].phone);
		printf("%s\n", ps->a[m].posit);
		return;
	}
	printf("未搜索到该联系人,查找错误!\n");


}

void Contastdele(SL*ps)
//删除指定联系人
{
	char nm[50] = { 0 };
	puts("请输入要删除的联系人姓名");
	scanf("%s", nm);
	int m = Findname(ps, nm);
	if (m >= 0)
	{
		SLErase(ps, m + 1);
		printf("删除成功!\n");
		return;
	}
	puts("未搜索到该联系人, 删除错误!");
}

void ContastSet(SL* ps)
//修改指定联系人信息
{
	char nm[50] = { 0 };
	puts("请输入要修改的联系人姓名");
	scanf("%s", nm);
	int m = Findname(ps, nm);
	if (m >=0)
	{
		puts("亲,请输入你修改后的姓名:");
		scanf("%s", ps->a[m].name);
		puts("亲,请输入你修改后的性别:");

		scanf("%s", ps->a[m].sex);
		puts("亲,请输入你修改后的年龄:");

		scanf("%d", &ps->a[m].age);
		puts("亲,请输入你修改后的电话:");

		scanf("%s", ps->a[m].phone);
		puts("亲,请输入你修改后的住址:");

		scanf("%s", ps->a[m].posit);

		printf("该联系人修改成功!\n");
		return ;
	}
	puts("未搜索到该联系人,修改失败!");
}

逻辑测试文件

<4>. test.c

#include "seqlist.h"


int main()
{
	int n = 0;
	SL con;//con就是你存储的通讯录
	ContastInit(&con);
	do
	{
		Meau();
		puts("请进行以上操作:");
		scanf("%d", &n);
		switch (n)
		{
		case 1:
			ContastAdd(&con);
			//添加联系人
			break;
		case 2:
			ContastFind(&con);
			//查找联系人
			break;
		case 3:
			Contastdele(&con);
			//删除联系人
			break;	
		case 4:
			ContastSet(&con);
			//修改联系人
			break;
		case 5:
			ContastShow(&con);
			//显示通讯录
			break;
		case 6:
			PutSLFile(&con);
			//保存通讯录文档
			break;
		case 7:
			GetSLFile(&con);
			//读取通讯录信息
			break;
		case 0:
			//退出通讯录
			puts("通讯录正在退出中...");
			break;
		default:
			printf("输入错误,请重新操作!!!\n");
			break;
		}

	} 
	while (n);
	ContastDestory(&con);
	return 0;
}

总结

这次小编带大家实现了我们的通讯录的小功能,虽不说浪漫,但还是饶有趣味的吧 😊 😊 😊
最后让小编梳理下本篇文章我们收获了什么吧 😍 😍 😍

  • 静态顺序表和动态顺序表:

我们知道了静态和动态顺序表的本质都是 数组 ,不同的在于他们数组 长度大小 的是否固定

  • 利用动态顺序表实现通讯录:

比起固定的静态顺序表,我们更常用 数组长度 灵活多变 的动态顺序表

  • 通讯录的功能和逻辑框架:

首先带着宝子们建立通讯录的大体框架和各部分功能的简介

  • 每个逻辑功能的实现:

小编一步一步带着友友们见证了咱们通讯录的 “出生”“成长”“销毁” 的 全过程

  • 通讯录源代码展示:

展示了本次基于 顺序表 实现的通讯录全部的代码 💕💕💕

如果觉得小编写的还不错的咱可支持三关下,不妥当的咱评论区指正

希望我的文章能给各位家人们带来哪怕一点点的收获就是 小编创作 的最大动力 💖 💖 💖
在这里插入图片描述

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

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

相关文章

[python] os.fork

文章目录 使用 os.fork()注意事项示例安全使用 os.fork()底层原理 os.fork() 是 Python 中用于 Unix/Linux 系统的一个函数&#xff0c;它在当前进程中创建一个子进程。这个函数是 os 模块的一部分&#xff0c;直接调用了 Unix/Linux 系统的 fork 系统调用。fork 系统调用非常基…

Wiringpi不支持树莓派5了, Wiringpi官方好像不更新了

买了树莓派5才知道&#xff0c;Wiringpi不支持树莓派5了&#xff0c; Wiringpi官方好像不更新了。那用什么来替代呢&#xff1f; 通过资料查询&#xff0c;libgpiod 支持io控制&#xff1b; https://github.com/brgl/libgpiod //gpio库 gpiodetect #检测支持的io 可以看到&a…

SpringBoot注解--05--注解@Valid

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1 前言1.1 Bean Validation1.2 Valid实际案例1.3 Spring 中的 valid 注解 2 Valid 详解2.1 源码解析2.2 参数校验使用注解2.3 具体使用流程POST 则可以以实体对象为…

再谈Redis三种集群模式:主从模式、哨兵模式和Cluster模式

总结经验 redis主从:可实现高并发(读),典型部署方案:一主二从 redis哨兵:可实现高可用,典型部署方案:一主二从三哨兵 redis集群:可同时支持高可用(读与写)、高并发,典型部署方案:三主三从 一、概述 Redis 支持三种集群模式,分别为主从模式、哨兵模式和Cluster模式。…

Java并发基础:CountDownLatch全面解析!

内容概要 CountDownLatch的优点在于能够简洁高效地协调多个线程的执行顺序&#xff0c;确保一组线程都完成后才触发其他线程的执行&#xff0c;适用于资源加载、任务初始化等场景。它提供了清晰的等待/通知机制&#xff0c;易于理解和使用&#xff0c;是提升多线程程序性能和可…

ChatGPT prompt概述

ChatGPT prompt概述 2022年11月30日&#xff0c;由人工智能实验室Open AI发布的对话式大型语言模型ChatGPT一夜爆火。凭借其强大的文字处理和人机交互能力迅速成为炙手可热的新一代人工智能产品。ChatGPT号称史上最强大的人工智能&#xff0c;它通过学习和理解人类语言与我们对…

玩具取名

看到长度是\(200\)&#xff0c;想到区间DP 但在这里说一下&#xff0c;设\(f[i][j]\)表示前\(i\)个字符&#xff0c;转换后以\(j\)结尾的最短长度是推不走的&#xff0c;因为原来的字符串的第\(i\)个字符合并之后产生的新字符有可能继续合并&#xff0c;这是有问题的

【成品论文57页】2024美赛F题成品论文57页+每一小问配套代码数据

基于数据预测下的减少非法野生动物贸易研究 近年来&#xff0c;非法野生动物贸易每年涉及的金额高达 265 亿美元&#xff0c;被认为是全球第四大 非法贸易。本文基于收集的数据&#xff0c; 对非法野生动物贸易进行研究。 问题一&#xff0c;为了确定五年项目的研究对象我们利用…

PXIe-5842第三代PXI矢量信号收发器简介

内容 简介​PXIe-5842 VST的主要特性PXI VST软件工具PXI VST应用结论下一步 简介 NI于2012年引入了矢量信号收发器(VST)的概念。VST将RF信号发生器、RF信号分析仪和功能强大的FPGA集成在单个PXI模块上。PXIe-5842 VST是首款提供30 MHz到26.5 GHz连续频率覆盖范围的VST。PXIe…

百分点科技:《数据科学技术: 文本分析和知识图谱》

科技进步带来的便利已经渗透到工作生活的方方面面&#xff0c;ChatGPT的出现更是掀起了新一波的智能化浪潮&#xff0c;推动更多智能应用的涌现。这背后离不开一个朴素的逻辑&#xff0c;即对数据的收集、治理、建模、分析和应用&#xff0c;这便是数据科学所重点研究的对象——…

Blender 与 3ds Max | 面对面的直接较量(2024)

Blender和3ds Max&#xff0c;哪个动画软件更好&#xff1f;作为一个从事动画领域十年的专业人士&#xff0c;Mark McPherson提供了八条最新建议&#xff0c;帮助你了解哪个软件更适合满足你的3D动画需求。 1.建模 获胜者&#xff1a;3ds Max。3ds Max的建模机制已经被证明是…

Leetcode刷题笔记题解(C++):36. 有效的数独

思路一&#xff1a;暴力破解&#xff0c;两个二维数组记录行、列对应的数字出现的次数&#xff0c;比如rows[i][index]表示的数字index在i行出现的次数&#xff0c;三维数组记录每个块中对应数字出现的次数&#xff0c;比如boxes[i/3][j/3][index]表示的数字index在[i/3][j/3]个…

031 递归

何为递归 示例 public static void main(String[] args) {System.out.println(fn(5)); }static int fn(int a){return a 1 ? 1 : a * fn(a - 1); }

conda虚拟环境基础

【一文搞定最新版Anaconda】Win11 安装 Anaconda&#xff08;2023.9&#xff09;详解&#xff08;不删除旧版情况下下载、安装、注册、登录、设置环境变量、迁移旧环境、配置修改换源等&#xff09;连接Pycharm_win11安装anaconda-CSDN博客 conda命令大全&#xff08;create/in…

基于大数据的淘宝电子产品数据分析的设计与实现

&#xff08;1&#xff09;本次针对开发设计系统并设置了相关的实施方案&#xff0c;利用完整的软件开发流程进行分析&#xff0c;完成了设置不同用户的操作权限和相关功能模块的开发&#xff0c;最后对系统进行测试。 &#xff08;2&#xff09;框架可以帮助程序开发者快速构建…

【Java程序设计】【C00195】基于SSM的影视创作论坛管理系统(论文+PPT)

基于SSM的影视创作论坛管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的影视创作论坛 本系统分为前台系统、后台管理员和后台会员3个功能模块。 前台系统&#xff1a;当游客打开系统的网址后&#xff0c;首先看…

2024美赛B题Searching for Submersibles原创论文完整版

Searching for Submersibles搜索潜水器 2024美赛B题Searching for Submersibles原创论文&#xff08;共38页&#xff09;部分内容&#xff0c;其余见文末&#xff1a; 整体框架&#xff1a; 1.1 问题背景与问题重述 海上游轮迷你潜水艇公司&#xff08;MCMS&#xff09;&…

前端学习笔记 | HTML5+CSS3静态网页制作的技巧(持续更新)

注&#xff1a;本文的css样式均使用less写法 1、字体居中 &#xff08;1&#xff09;先text-align:center;行内元素水平居中 &#xff08;2&#xff09;再line-heigh:(盒子高度);行内元素垂直居中 text-align: center;line-height: ( 30 / vw ); 2、盒子居中 情景1&#…

Vue引入Axios

1.命令安装axios和vue-axios npm install axios --save npm install vue-axios --save 2.package.json查看版本 3.在main.js中引用 import axios from axios; import VueAxios from vue-axios; Vue.use(VueAxios,axios) 4.如何使用 &#xff08;初始化方法&#xff09; 将下列代…

《统计学习方法:李航》笔记 从原理到实现(基于python)-- 第6章 逻辑斯谛回归与最大熵模型(1)6.1 逻辑斯谛回归模型

文章目录 第6章 逻辑斯谛回归与最大熵模型6.1 逻辑斯谛回归模型6.1.1 逻辑斯谛分布6.1.2 二项逻辑斯谛回归模型6.1.3 模型参数估计6.1.4 多项逻辑斯谛回归 《统计学习方法&#xff1a;李航》笔记 从原理到实现&#xff08;基于python&#xff09;-- 第3章 k邻近邻法 《统计学习…