【c语言进阶】动态通讯录

news2024/9/20 0:10:43

在这里插入图片描述

🚀write in front🚀
📜所属专栏: c语言学习
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

文章目录

  • 前言:
  • 一、静态通讯录的弊端:
  • 二、动态增容优化通讯录:
    • 2.1.枚举类型的加入
    • 2.2.结构体的修改
    • 2.3.Initcontact函数的修改
    • 2.4.Addcontact函数的修改
    • 2.5.Desdrycontact函数的添加
  • 三、文件操作优化通讯录:
    • 3.1.Savecontact函数的添加(通讯录信息保存)
    • 3.2.Loadcontact函数的添加(导入通讯录信息)
  • 四、完整代码展示:
    • contact.h:
    • test.c
    • contact.c
  • 总结:

前言:

  在前面的学习中,我们写了静态通讯录:c语言实现静态通讯录

一、静态通讯录的弊端:

  对于简易版本的通讯录来说,我们是直接指定了通讯录的大小,那么此时我们会发现两个弊端:

弊端1:

  如果我们创建的通讯录空间过大,就会浪费空间;如果我们创建的通讯录太小又不够使用 。所以,此时我们就得优化通信录给定空间上的问题,不能再给其指定大小的空间,而是让其空间有灵活性此时我们以动态增容的方式来给定通讯录的空间,就很好的规避了这一问题!

弊端2:

  我们知道程序运行起来我们输入的数据都是保存在内存上的,在简易版本中我们在运行通讯录之后添加的数据,在程序结束的时候都会被清除。当而我们既然要保存联系人的信息,就得做到数据持久化的保存,我们就得将数据保存到硬盘中,也就是文件当中,此时我们可以用文件操作的方式来实现持久化的保存联系人信息。

二、动态增容优化通讯录:

2.1.枚举类型的加入

  在前面我们学习了枚举类型的使用,我们在写menu菜单的switch函数时,常常会因为不知道数字对应的是哪一个功能而弄混。
  枚举类型中各成员的从零开始依次递增,于是我们可以再使用一个枚举类型来使我们的选项对应用户的选择:

enum OPTION
{
	Exit = 0,
	Add = 1,
	Del,
	Search,
	Modify,
	Print,
	sort
};

  这样一来,我们就可以把case后面的1,2,3等数据换成对应的功能名字。
case 1:替换为case Add:

2.2.结构体的修改

  之前我们创建了两个结构体,第一个存放信息,第二个存放信息的数组和联系人数量,可是第二个存放的人信息的数组规定死了100个元素。所以我们将第二个结构体做一下改动即可:

//静态版本
//typedef struct contact
//{
//	PeoInfo data[MAX];
//	int sz;
//}contact;

//动态版本
typedef struct Contact
{
	PeoInfo* data;//指向存放人的信息的空间
	int sz;//当前已经放的信息的个数
	int capacity;//当前通讯录的最大容量
}contact;

  这里我们用sz记录联系人数量,用capacity指向当前通讯录的最大容量。在这里我们会发现结构体明显小了很多,因为存放人信息的空间我们还没有创建!

2.3.Initcontact函数的修改

  之前的初始化仅仅只是将所有的数据初始化为0,但是动态版本的通讯录还没有开辟联系人的空间。所有我们要在初始化函数里完成这个操作。

//静态版本:
//void Initcontact(contact* con)
//{
//	assert(con);
//	con->sz = 0;
//	memset(con->data, 0, sizeof(con->data));
//}

//动态版本:
void Initcontact(contact* con)
{
	assert(con);
	//DEFAULT_SZ是宏定义的3,在contact.h有添加!
	PeoInfo *ptr= (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
	if (ptr == NULL)
	{
		perror("InitContact::calloc");
		return;
	}
	con->sz = 0;
	con->capacity = DEFAULT_SZ;
	con->data = ptr;

//这里的Loadcontact函数在下面会提到!
	LoadContact(con);
}

  在这里大家就不用自己初始化联系人信息了!因为calloc本身就有这个功能!

2.4.Addcontact函数的修改

  之前静态通讯录的添加联系人只需要在不超过容量的基础上添加即可,超过容量就不能操作了。但是动态通讯录在发现容量不足时要有自动增容的功能,这也是动态通讯录的有点所在!

//静态add
//void AddContact(contact* con)
//{
//	assert(con);
//	if (con->sz == 99)
//	{
//		printf("通讯录已经存满,请联系操作人员");
//		return;
//	}
//	printf("请输入联系人姓名:>");
//	scanf("%s", con->data[con->sz].name);
//	printf("请输入联系人性别:>");
//	scanf("%s",con->data[con->sz].sex);
//	printf("请输入联系人年龄:>");
//	scanf("%d", &(con->data[con->sz].age));
//	printf("请输入联系人联系方式:>");
//	scanf("%s", con->data[con->sz].tele);
//	printf("请输入联系人住址:>");
//	scanf("%s", con->data[con->sz].addr);
//	printf("联系人信息添加成功!\n");
//	con->sz++;
//}
// 
//判断容量是否够用!并且自动增容
void check_capacity(contact* con)
{
	assert(con);
	if (con->sz == con->capacity)
	{
		printf("内存已满,正在扩容——\n");
		Sleep(1000);
		PeoInfo* ptr = (PeoInfo*)realloc(con->data, (con->capacity + INC_SZ) * sizeof(PeoInfo));
		if (ptr==NULL)
		{
			perror("check_capacity::realloc");
			return;
		}
		con->capacity += INC_SZ;
		con->data = ptr;
		printf("扩容成功\n");
	}
}
//动态add
void AddContact(contact* con)
{
	assert(con);
	check_capacity(con);
	printf("请输入联系人姓名:>");
	scanf("%s", con->data[con->sz].name);
	printf("请输入联系人性别:>");
	scanf("%s", con->data[con->sz].sex);
	printf("请输入联系人年龄:>");
	scanf("%d", &(con->data[con->sz].age));
	printf("请输入联系人联系方式:>");
	scanf("%s", con->data[con->sz].tele);
	printf("请输入联系人住址:>");
	scanf("%s", con->data[con->sz].addr);
	printf("联系人信息添加成功!\n");
	con->sz++;
}

2.5.Desdrycontact函数的添加

  在使用完堆区的空间之后,最重要的事情是什么?当然是释放这块空间呀!

void DestroyContact(contact* con)
{
	free(con->data);
	con->data = NULL;
	con->sz = 0;
	con->capacity = 0;
	con = NULL;
}

三、文件操作优化通讯录:

3.1.Savecontact函数的添加(通讯录信息保存)

  为了在保存内存中操作完成后的所有联系人信息,我们在程序退出之前将联系人信息以2进制的方式写进文件里面

void SaveContact(contact* con)
{
	FILE* fp = fopen("contact.txt", "wb");
	if (fp==NULL)
	{
		perror("SaveContact");
	}
	else
	{ 
		printf("正在保存\n");
		Sleep(1000);
		for (int i = 0; i < con->sz; i++)
			fwrite(con->data + i, sizeof(PeoInfo), 1, fp);
		fclose(fp);
		fp = NULL;
		printf("保存成功\n");
	}
}

3.2.Loadcontact函数的添加(导入通讯录信息)

  在我们对于通讯录进行修改时,要将之前文件中存好的信息导入内存中去,这个步骤也应该在初始化函数中进行,我们将他分装为函数,代码如下:

void LoadContact(contact* con)
{
	FILE* fp = fopen("contact.txt", "rb");
	PeoInfo str={ 0 };
	if (fp==NULL)
	{
		perror("LoadContact");
	}
	else
	{
		printf("正在加载>>>\n");
		Sleep(1000);
		int i = 0;
		while (fread(&str, sizeof(PeoInfo), 1, fp))
		{
			check_capacity(con);
			con->data[i] = str;
			con->sz++;
			i++;
		}
	}
	fclose(fp);
	fp = NULL;
	printf("加载成功!\n");
}

四、完整代码展示:

contact.h:


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

#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 20

#define DEFAULT_SZ 3
#define INC_SZ 2

enum OPTION
{
	Exit = 0,
	Add = 1,
	Del,
	Search,
	Modify,
	Print,
	sort
};

typedef struct PeoInfo
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char addr[MAX_ADDR];
	char tele[MAX_TELE];
}PeoInfo;

//静态版本
//typedef struct contact
//{
//	PeoInfo data[MAX];
//	int sz;
//}contact;

//动态版本
typedef struct Contact
{
	PeoInfo* data;//指向存放人的信息的空间
	int sz;//当前已经放的信息的个数
	int capacity;//当前通讯录的最大容量
}contact;

//初始化消息
void Initcontact(contact *con);

//增加消息
void AddContact(contact *con);

//删除信息
void DelContact(contact *con);

//查找个别人消息
void SeachContact(contact *con);

//修改个别人消息
void ModifyContact(contact* con);

//打印全部通讯录
void PrintContact(contact* con);

//排序通讯录
void sortContact(contact* con);

//保存通讯录中的信息到文件中
void SaveContact(contact* con);

//加载文件信息到通讯录
void LoadContact(contact* con);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"


void menu()
{
	printf("**********************************\n");
	printf("**********************************\n");
	printf("******** 欢迎使用本通讯录 ********\n");
	printf("**********************************\n");
	printf("***** 本通讯录现提供以下功能 *****\n");
	printf("************ 1.Add ***************\n");
	printf("************ 2.Del ***************\n");
	printf("************ 3.Search ************\n");
	printf("************ 4.Modify ************\n");
	printf("************ 5.Print *************\n");
	printf("************ 6.sort **************\n");
	printf("************ 0.exit**************\n");
	printf("**********************************\n");
}
void Contact()
{
	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 Search:
			SeachContact(&con);
			break;
		case Modify:
			ModifyContact(&con);
			break;
		case Print:
			PrintContact(&con);
			break;
		case sort:
			sortContact(&con);
			break;
		case Exit:
			SaveContact(&con);
			DestroyContact(&con);
			printf("已成功退出");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);

}
int main()
{
	Contact();
	return 0;
}

contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

int FindByName(contact* con, char name[])
{
	assert(con);
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if (strcmp(con->data[i].name,name) == 0)
		{
			return i;
		}
	}
	return -1;
}
//静态版本:
//void Initcontact(contact* con)
//{
//	assert(con);
//	con->sz = 0;
//	memset(con->data, 0, sizeof(con->data));
//}

//动态版本:
void Initcontact(contact* con)
{
	assert(con);
	PeoInfo *ptr= (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
	if (ptr == NULL)
	{
		perror("InitContact::calloc");
		return;
	}
	con->sz = 0;
	con->capacity = DEFAULT_SZ;
	con->data = ptr;

	LoadContact(con);
}

void DestroyContact(contact* con)
{
	free(con->data);
	con->data = NULL;
	con->sz = 0;
	con->capacity = 0;
	con = NULL;//??

}
//静态add
//void AddContact(contact* con)
//{
//	assert(con);
//	if (con->sz == 99)
//	{
//		printf("通讯录已经存满,请联系操作人员");
//		return;
//	}
//	printf("请输入联系人姓名:>");
//	scanf("%s", con->data[con->sz].name);
//	printf("请输入联系人性别:>");
//	scanf("%s",con->data[con->sz].sex);
//	printf("请输入联系人年龄:>");
//	scanf("%d", &(con->data[con->sz].age));
//	printf("请输入联系人联系方式:>");
//	scanf("%s", con->data[con->sz].tele);
//	printf("请输入联系人住址:>");
//	scanf("%s", con->data[con->sz].addr);
//	printf("联系人信息添加成功!\n");
//	con->sz++;
//}
// 

void check_capacity(contact* con)
{
	assert(con);
	if (con->sz == con->capacity)
	{
		printf("内存已满,正在扩容——\n");
		Sleep(1000);
		PeoInfo* ptr = (PeoInfo*)realloc(con->data, (con->capacity + INC_SZ) * sizeof(PeoInfo));
		if (ptr==NULL)
		{
			perror("check_capacity::realloc");
			return;
		}
		con->capacity += INC_SZ;
		con->data = ptr;
		printf("扩容成功\n");
	}
}
//动态add
void AddContact(contact* con)
{
	assert(con);
	check_capacity(con);
	printf("请输入联系人姓名:>");
	scanf("%s", con->data[con->sz].name);
	printf("请输入联系人性别:>");
	scanf("%s", con->data[con->sz].sex);
	printf("请输入联系人年龄:>");
	scanf("%d", &(con->data[con->sz].age));
	printf("请输入联系人联系方式:>");
	scanf("%s", con->data[con->sz].tele);
	printf("请输入联系人住址:>");
	scanf("%s", con->data[con->sz].addr);
	printf("联系人信息添加成功!\n");
	con->sz++;
}
void DelContact(contact* con)
{
	assert(con);
	char name[100];
	if (con->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	printf("请输入要删除人名字:>");
	scanf("%s", name);
	int ret = FindByName(con, name);
	int i = 0;
	if (-1 == ret)
	{
		printf("没有找到此人\n");
		return;
	}
	else
	{
		for (i = ret; i < con->sz-1; i++)
		{
			con->data[i] = con->data[i + 1];
		}
		con->sz--;
		memset(&con->data[i], 0, sizeof(con->data[i]));
		printf("删除成功!\n");
	}
}

void SeachContact(contact* con)
{
	assert(con);
	char name[MAX_NAME];
	if (con->sz == 0)
	{
		printf("通讯录为空,无法输入\n");
		return;
	}
	printf("请输入查找人名字");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret == -1)
	{
		printf("您查找的人不存在!\n");
		return;
	}
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", con->data[ret].name, 
		con->data[ret].age, 
		con->data[ret].sex, 
		con->data[ret].addr, 
		con->data[ret].tele);
}

void ModifyContact(contact* con)
{
	assert(con);
	char name[MAX_NAME] = { 0 };
	if (con->sz == 0)
	{
		printf("通讯录为空,无法修改\n");
		return;
	}
	printf("请输入查找人名字");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (-1 == ret)
	{
		printf("您要修改的人不存在\n");
		return;
	}
	printf("请输入联系人姓名:>");
	scanf("%s", con->data[ret].name);
	printf("请输入联系人性别:>");
	scanf("%s", con->data[ret].sex);
	printf("请输入联系人年龄:>");
	scanf("%d", &(con->data[ret].age));
	printf("请输入联系人住址:>");
	scanf("%s", con->data[ret].addr);
	printf("请输入联系人联系方式:>");
	scanf("%s", con->data[ret].tele);
	printf("联系人信息修改成功!\n");
}

void PrintContact(contact* con)
{
	printf("%-10s\t%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n","联系人", "姓名", "年龄", "性别", "地址", "电话");
	for (int i = 0; i < con->sz; i++)
	{
		printf("%-10d\t%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n",i+1, con->data[i].name,
			con->data[i].age,
			con->data[i].sex,
			con->data[i].addr,
			con->data[i].tele);
	}
}

int cmp_con_by_name(const void* e1, const void* e2)
{
	return (strcmp(((PeoInfo *)e1)->name, ((PeoInfo*)e2)->name));
}
void sortContact(contact* con)
{
	assert(con);
	if (0 == con->sz)
	{
		printf("通讯录为空,无法排序\n");
		return;
	}
	qsort(con->data, con->sz, sizeof(con->data[0]), cmp_con_by_name);
	printf("排序成功\n");
}

void SaveContact(contact* con)
{
	FILE* fp = fopen("contact.txt", "wb");
	if (fp==NULL)
	{
		perror("SaveContact");
	}
	else
	{ 
		printf("正在保持\n");
		Sleep(1000);
		for (int i = 0; i < con->sz; i++)
			fwrite(con->data + i, sizeof(PeoInfo), 1, fp);
		fclose(fp);
		fp = NULL;
		printf("保存成功\n");
	}
}

void LoadContact(contact* con)
{
	FILE* fp = fopen("contact.txt", "rb");
	PeoInfo str={ 0 };
	if (fp==NULL)
	{
		perror("LoadContact");
	}
	else
	{
		printf("正在加载>>>\n");
		Sleep(1000);
		int i = 0;
		while (fread(&str, sizeof(PeoInfo), 1, fp))
		{
			check_capacity(con);
			con->data[i] = str;
			con->sz++;
			i++;
		}
	}
	fclose(fp);
	fp = NULL;
	printf("加载成功!\n");
}

总结:

  我们通过文件操作的知识和动态内存空间管理的知识终于完善了动态通讯录的编写!相信大家在自己真正写出来之后都会感觉学有所成!
  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
c语言学习
算法
智力题
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

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

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

相关文章

彭博:预订量未及预期,索尼大幅削减PS VR2首季订单

在索尼VR新品&#xff1a;PS VR2正式发货前夕&#xff0c;彭博社爆料称&#xff1a;因预订量不及预期&#xff0c;索尼已经大幅削减PS VR2首季订单量。消息人士称&#xff0c;索尼PS VR2发布后首个季度的订单目标是200万台&#xff0c;现已根据预订量减半&#xff0c;至约100万…

iOS 视频播放器开发

需求设计 做一个小学生教育辅导视频播放器。 参考小猿搜题视频播放器 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L0GsyFSt-1675164972791)(https://tva1.sinaimg.cn/large/008vxvgGgy1h9xk4fm5xfj31sx0u0mz0.jpg)] [外链图片转存失败,源站可…

Java中的JCA对基于密码的加密进行成功的蛮力搜索攻击所需的时间估计

对于JCA中基于密码的DES加密实现&#xff0c;固定一些盐和迭代计数&#xff0c;并记录加密/解密所需的平均时间;估计成功进行蛮力搜索攻击所需的时间Name: NIHAO DONG Number: 201476606 Password List:N Password 1 P$$W0rD 2 thisismypassword 3 VeryLongP$$W0rD fi…

[0CTF 2016]piapiapia(字符逃逸详解)

目录 知识点 信息收集 尝试SQL注入 源码目录扫描 代码审计 payload生成 知识点 信息泄露参数传递数组绕过字符串检测反序列化字符逃逸 信息收集 收集到了一只超可爱的小喵 尝试SQL注入 用户名不存在的回显 密码无效的回显 用户存在&#xff0c;密码错误的回显 判断闭…

STC15系列PWM功能相关功能寄存器介绍

STC15系列PWM功能相关功能寄存器介绍✨以下数据来源于stc15手册。 &#x1f4d3;增强型PWM波形发生器相关功能寄存器总表 1. 端口配置寄存器&#xff1a;P_SW2 2.PWM配青寄存器:PWMICFG CBTADC: PWM计数器归零时 (CBIF1时) 触发ADC转换 – 0:PWM计数器归零时不触发ADC转换 – …

Web3中文|亚马逊进入web3,将在春季推出NFT计划

亚马逊正向加密行业迈出第一步。 根据Blockworks 1月26日发布的报告&#xff0c;这家电子商务巨头计划在2023年春天推出一项专注于区块链游戏和相关NFT的计划。 该计划仍处于开发阶段&#xff0c;但发布的最后期限定为4月。亚马逊用户将可以体验基于区块链的游戏并领取免费的…

Python采集某乎专栏文章保存成pdf

前言 大家早好、午好、晚好吖 ❤ ~ 环境使用: Python 3.8 Pycharm wkhtmltopdf 软件 --> 文章下方名片信领取 模块使用: requests >>> pip install requests 数据请求 parsel >>> pip install parsel 数据解析 re >>> 内置模块 不需要安装…

域内委派攻击

域委派是指&#xff0c;将域内用户的权限委派给服务账号&#xff0c;使得服务账号能以用户权限开展域内活动。利用委派可获取域管理员权限 域委派主要分为三种&#xff1a; 非约束性委派 约束性委派 基于资源的约束性委派 在Windows系统中&#xff0c;只有服务账号和主机账号…

操作系统权限提升(五)之系统错误配置-PATH环境变量提权

系列文章 操作系统权限提升(一)之操作系统权限介绍 操作系统权限提升(二)之常见提权的环境介绍 操作系统权限提升(三)之Windows系统内核溢出漏洞提权 操作系统权限提升(四)之系统错误配置-Tusted Service Paths提权 注&#xff1a;阅读本编文章前&#xff0c;请先阅读系列文章…

寻找整数

问题描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 有一个不超过 10^{17}1017 的正整数 nn,知道这个数除以 2 至 49 后的余数如下表所示,求这个正整数最小是多少。 运行限制 最大运行时间:1s最大运行内存: 512M参考答案 mp = {2: 1, …

虹科动态 | 虹科HSR/PRP IP核现已支持HSR/PRP最新标准

HSR与PRP是专注于解决高可靠性自动化网络传输的技术&#xff0c;其所属的国际标准为IEC 62439。最初&#xff0c;IEC发布此项标准主要目的是为了满足IEC 61850-5中所提到的变电站自动化应用中各通信组件或服务故障所要求的恢复时间问题&#xff0c;但协议设计时的通用性&#x…

PTA L1-017 到底有多二

前言&#xff1a;本期是关于到底有多二的详解&#xff0c;内容包括四大模块&#xff1a;题目&#xff0c;代码实现&#xff0c;大致思路&#xff0c;代码解读&#xff0c;今天你c了吗&#xff1f; 题目&#xff1a; 一个整数“犯二的程度”定义为该数字中包含2的个数与其位数…

Java多线程:Future和FutureTask

一、Future Future是一个接口&#xff0c;所有方法如下&#xff1a; 上源码&#xff1a; package java.util.concurrent; public interface Future<V> {boolean cancel(boolean mayInterruptIfRunning);boolean isCancelled();boolean isDone();V get() throws Interru…

5.3 场效应管的高频等效模型

由于场效应管各级之间存在极间电容&#xff0c;因而其高频响应与晶体管相似。根据场效应管的结构&#xff0c;可得出图5.3.1(a)所示的高频等效模型&#xff0c;大多数场效应管的参数如表1所示。由于一般情况下 rgsr_{gs}rgs​ 和 rdsr_{ds}rds​ 比外接电阻大得多&#xff0c;因…

Lesson 4.5 梯度下降优化基础:数据归一化与学习率调度

文章目录一、数据归一化方法1. 数据归一化计算公式1.1 0-1 标准化1.2 Z-Score 标准化1.3 非线性标准化2. 数据归一化算法执行过程3. 数据归一化算法评价4. Z-Score 标准化算法评价及横向对比二、梯度下降算法优化初阶1. 数据归一化与梯度下降算法优化2. 学习率调度3. 小批量梯度…

RV1126笔记二十六:lvgl移植

若该文为原创文章,转载请注明原文出处。 之前做项目的时候有了解到LVGL这个开源的gui库,有QT仿真过智能家居控制界面,也在STM32上移植过。 趁着过年期间就想着把它移植到自己的开发板上看看能不能正常跑起来。虽说不难,但也花了一些功夫,因此也在这里做下总结。 下载地址…

STC15系列PWM中断控制寄存器介绍以及PWM相关示例

STC15系列PWM中断控制寄存器介绍以及PWM呼吸灯代码实现&#x1f4cc;相关篇《STC15系列PWM功能相关功能寄存器介绍》✨以下数据来源于stc15手册。 &#x1f4d3;增强型PWM波形发生器的中断控制 1.PWM中断优先级控制寄存器:IP2 PPWMFD:PWM异常检测中断优先级控制位。 当PPWMFD…

微信小程序员010宠物交易系统商城系统

宠物交易系统商城系统分为用户小程序端和管理员后台网页端&#xff0c;其中后端是采用java编程语言&#xff0c;mysql数据库&#xff0c;idea开发工具&#xff0c;ssm框架开发&#xff0c;本系统分为用户和管理员两个端&#xff0c;其中用户可以在小程序端进行注册登陆&#xf…

嵌入式Linux从入门到精通之第十节:系统编程之进程

进程的定义 程序:程序是存放在存储介质上的一个可执行文件。进程:进程是程序的执行实例,包括程序计数器、寄存器和变量的当前值。程序是静态的,进程是动态的: 程序是一些指令的有序集合,而进程是程序执行的过程。进程的状态是变化的,其包括进程的创建、调度和消亡。 在…

【微服务】分布式搜索引擎elasticsearch(1)

分布式搜索引擎elasticsearch&#xff08;1&#xff09;1.elasticsearch1.1.了解ES1.1.1.elasticsearch的作用1.1.2.ELK技术栈1.1.3.elasticsearch和lucene1.1.4.为什么不是其他搜索技术&#xff1f;1.1.5.总结1.2.倒排索引1.2.1.正向索引1.2.2.倒排索引1.2.3.正向和倒排1.3.es…