深入篇【C++】类与对象:运算符重载详解 -(下)+日期类的实现

news2024/7/6 20:01:13

@[TOC](深入篇【C++】类与对象:运算符重载详解-(下)+日期类的实现💯干货满满!)在这里插入图片描述

⏰一.运算符重载

内置类型(int /double…… )是可以之间进行运算符之间的比较的,因为编译器知道它们之间的比较规则,可以之间转化为指令。
那如果自定义类型能否之间进行运算符之间的比较呢?当然不能了,因为编译器是不知道这个自定义类型的规则是什么,不知道如何进行比较。
1.内置类型是可以之间比较的。
2.自定义类型是无法之间进行比较的。
那如何使自定义类型也能进行比较呢?这时C++给出了办法,让这个运算符重载成一个函数,当自定义类型进行比较时,其本质就是在调用重载函数。

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有器返回值类型,函数名字以及参数列表,其返回值类型与参数列表和普通函数类似。

比如我们想对下面这个自定义类型进行运算符的使用,该如何使用呢?


class Data
{
	
public:
	Data(int year = 1, int month = 1, int day = 1)//构造函数要写,拷贝构造函数不用写,赋值重载不用写
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	
	
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
    Data d1(2023,5,1);
    Data d2(2023,10,15);
}

我们知道并不是所有的运算符都能重载的,主要是那些对类有意义的运算符才可以重载。

🕓①.<=运算符重载

两个日期进行比较大小,是有意义的,所以和<=运算符是可以重载的。而我在运算符重载详解 -(上)中已经将部分运算符介绍,接下来继续介绍运算符重载。在这里插入图片描述

<=运算符重载该如何写呢?

是不是直接可以在 <运算符重载的基础上直接改动即可呀。

下面是<运算符重载函数

bool Data:: operator<(const Data& d)
{
		if (_year < d._year)
		{
			return true;
		}
		else if (_year == d._year && _month < d._month)
		{
			return true;
		}
		else if (_year == d._year && _month == d._month && _day < d._day)
		{
			return true;
		}
		return false;
	
}

直接在原函数上将<改成<=即可:

bool Data:: operator<(const Data& d)
{
		if (_year <= d._year)
		{
			return true;
		}
		else if (_year == d._year && _month <= d._month)
		{
			return true;
		}
		else if (_year == d._year && _month == d._month && _day <= d._day)
		{
			return true;
		}
		return false;
	
}

不过这里有一个更好的方法喔!!!
那就是函数【复用】,这个在很多场景下都很有用的。
怎么复用呢?我们是不是已经将<运算符重载 和==运算符重载写完了?
那我们就可以直接复用这两个运算符重载来写其他的比较运算符
1.<= 是不是就是 小于或者等于呀,或者大于的逆命题。
2.>=是不是就是 大于或者等于呀或者就是小于的逆命题。
3.!=是不是就是 等于的逆命题呀。

bool Data::operator<=(const Data& d)//直接复用<运算符重载和==运算符重载
{
	return *this < d || *this == d;
}

🕒②.>=运算符重载

.>=运算符重载可以复用 >运算符和等于==运算符重载
或者是<运算符重载的逆命题:

bool Data::operator>=(const Data& d)
{
	return !(*this < d);//复用<运算符重载 ,<的逆命题就是>=
}

🕑③. !=运算符重载

= =的逆命题就是!=所以可以直接复用= =运算符重载

bool Data::operator!=(const Data& d)
{
	return !(*this == d);//直接复用==运算符重载的  -- 逆命题
}

总结:所以我们在写这些比较运算符,习惯先将<运算符重载和==运算符重载先写出来,然后其他比较运算符直接复用这两个运算符重载即可。

🕐④.+=运算符重载

我们知道日期加上一个日期是没有什么意义的,但是一个日期加上一个天数,这就有意义了,可以知道该天数后是什么日期。所以日期类是允许+=运算符重载的。
那+=运算符如何重载呢?

我们首先要知道如何进行日期的计算,当天数大于当前月的最大天数时,天数就要减去当前月份的最大天数,然后月份就要进一。
注意点:
1.当天数很大时,月份不断进一,但要注意月份不能超过12,当月份再进一应该是1,而不是13.
2.要注意每个月份的天数是不同的,要考虑闰年的2月和其他年的2月天数也是不同的。

所以我们首先手搓一个获得不同月份的天数的函数,要考虑闰年和不同年的2月不同。

int Data::GetMonDay(int year, int month)
{
    int monday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)&&month==2)
	{
		return 29;
	}
	else
	return monday[month];
}

有一个点提一下,这里可以改进。
这里我们要的是每个月的天数,但每次调这个函数我们都要进行一次闰年的判断,判断然后再看是不是2月,这样很麻烦,这里的if条件句的目的是为了获得2月的天数,如果不是2月那就不要再去判断闰年了,所以我们可以将判断是否是2月放在前面先判断就可以避免每次都要判断是否是闰年了。
然后还有我们要频繁的调用这个函数,也就是这个月份日期数组每次调用都会开辟,太浪费效率了,所以我们可以让它变成静态区的,开辟一次就可以啦。不用每次调用都开辟一次。所以改进后的代码如下:

int Data::GetMonDay(int year, int month)
{
	static int monday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	//频繁调用
	if (month == 2&&(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) )//先判断是否是2月,如果不是直接走开。
	{
		return 29;
	}
	else
	return monday[month];
}

接下来我们就要进行这个对+=运算符的重载了

//这里可以用引用返回喔,因为返回的是对象本身,对象本身并不在该重载函数里面,所以函数结束,对象还存在。
Data& Data::operator+=(int day)
{
	//第一步将天数全部加起来
	_day += day;
	while (_day > GetMonDay(_year, _month))//当天数大于当月最大天数时,就要进行循环
	{
		_day -= GetMonDay(_year, _month);//要减去当月的最大天数
		++_month;//然后月份++
		if (_month == 13)//要考虑月份不能超过12,当月份变成13时这是,正确的是1月,并且年也要加1
		{
			++_year;
			_month = 1;
		}
	}
	return *this;//最后将日期对象返回
}

🕦⑤.+运算符重载

+运算符和+=运算符的区别是什么呢?

int b=2;
b+=1;
b+1;

+=将变量本身改变了,而+并没有将变量改变。
所以同理,对于自定义类型,+=也将自定义变量本身发生改变,而+并不会改变自定义变量本身。

+运算符重载函数和+=运算符重载函数的区别就在于它们的返回值不同。
虽然最后结果相同,但是+运算符重载返回值是一个临时拷贝的对象,并不是真正改变的对象。
+=运算符重载函数的返回值是真正改变的对象。

//这里不可以使用引用返回,因为返回的是拷贝对象,函数结束,拷贝对象就销毁了
Data Data::operator+(int day)
{
	Data tmp(*this);//拷贝一份,让tmp返回,*this没有改变
	tmp._day += day;
	while (tmp._day > GetMonDay(tmp._year, tmp._month))
	{
		tmp._day -= GetMonDay(tmp._year, tmp._month);
		++tmp._month;
		if (tmp._month == 13)
		{
			++_year;
			tmp._month = 1;
		}
	}
	return tmp;
}

我们注意到,+运算符重载函数里是让拷贝对象去实现+=运算符函数的相关操作,最后返回是拷贝对象
,真正的对象并没有修改。
这里我们也可以使用函数复用,+运算符重载直接复用+=运算符重载函数。

Data Data::operator+(int day)  //+运算符重载 复用+=运算符重载
{
	Data tmp(*this);//拷贝一份,让tmp返回,*this没有改变
	tmp += day;//复用+=重载函数
这里其实就是tmp去调用+=运算符重载函数,tmp作为左参数。 
	return tmp;
}

其实+=运算符重载函数也可以直接复用+运算符重载

Data& Data::operator+=(int day)//用+=复用+
{
	*this=*this + day;
	//注意的是+是不修改本身的,所以对象变量+day还要再赋给对象变量
	这里的+就是+运算符重载函数,*this对象去调用这个对象
	return *this;
}

但是最好先实现+=运算符重载 再复用实现 +运算符重载,而不推荐用+=运算符重载来复用实现+运算符重载,为什么呢?

因为+运算符是不改变对象变量本身,所以必须要拷贝对象,也就是会调用拷贝构造函数,让拷贝对象去操作。并且最后返回的是拷贝对象,当函数结束时,该拷贝对象就销毁了,不能用引用做返回值。所以返回时又会调用一次拷贝构造构造。所以如果用+运算符重载来复用实现+=运算符重载,每调用一次+运算符重载该函数就要再调用两次拷贝构造。
在这里插入图片描述

而如果使用+=运算符重载来复用+运算符重载,就不需要调用拷贝构造了,因为+=运算符重载函数是会对对象本身修改,所以不需要拷贝对象,并且最后返回的是对象本身,可以用引用做返回,提高了效率哎,这不美滋滋?在这里插入图片描述

所以呢,我们在写这类运算符时,最好先写+=运算符重载,然后再用+=运算符重载复用实现+运算符重载。

🕚⑥.-=运算符重载

有了日期加天数,那肯定也要有日期减天数呀。而且根据上面的介绍,我们是不是应该先从-=运算符重载写起,然后-运算符重载再复用-=运算符重载实现呀。

我们首先要分析,日期如何减一个天数

1.当日期的天数减去给定的天数结果小于等于0时,我们就需要对月改动,如果大于0那就不需要改动
2.当天数小于0时,我们需要借上个月的天数来还(注意是上个月,不是本月)
3.借着借着,要注意月份不能小于1了,当月份借到为0时,正确的应该是12月,并且年份要减一。

//跟+=运算符重载一样,这里-=运算符重载也可以使用引用做返回,因为最后返回的是对象本身,而不是对象的拷贝什么的。
Data& Data::operator-=(int day)
{
   //首先将天数全部减去
	_day -= day;
	while (_day <= 0)//当天数小于等于0时,就要进循环来借上月份中的天数
	{
		--_month;//首先需要将月份减一,因为我们借的是上个月的天数,而不是本月的,本月没有天数辣,都用来减去天数变成负数了都,哪里的剩余天数。
		if (_month == 0)//要注意月份不能小于1,当月份为0时
		{
			--_year;//年份要减一
			_month = 12;//要将月份改成12
		}
		_day += GetMonDay(_year, _month);//借上个月份的天数来还。
	}
	return *this;
}

其实这个函数还有一点点问题,那就是下面这样:

int main()
{
	Data d1(2023, 4, 26);
	d1-=-10;
	//日期减去一个天数,但这个天数却是负数,那结果是对的吗?
	
}

在这里插入图片描述
可以明显看出肯定错误了,因为天数怎么能超过31呢。
正确的场景是,如果天数为负数,那么-=天数应该变成了+=天数。
而+=天数就应该变成-=天数。
所以我们在-=运算符重载函数里再完善一点。

Data& Data::operator-=(int day)
{
	if (day < 0)//如果天数小于0,那么-=天数就应该变成+=天数
	{
		return *this += -day;//这里的day还是负数所以加上负号让它变成正号。
	}
	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonDay(_year, _month);
	}
	return *this;
}

同理+=运算符重载函数里也应该这样写。

Data& Data::operator+=(int day)
{
	if (day < 0)//如果天数小于0,那么+=天数就应该变成-=天数
	{
		return *this -= -day;//这里的day还是负数所以加上负号让它变成正号。
	}
	_day += day;
	while (_day > GetMonDay(_year, _month))
	{
		_day -= GetMonDay(_year, _month);
		++_month;
		if (_month == 13)
		{
			++_year;
			_month = 1;
		}
	}
	return *this;
}

🕗⑦.-运算符重载(1)

有了-=运算符重载,我们还怕-运算符重载无法完成?笑话!
在这里插入图片描述
我们直接复用-=运算符重载即可,但要注意的是-运算符重载函数,需要拷贝对象,因为-运算符不修改对象本身喔。

Data Data::operator-(int day)
{
	Data tmp(*this);//需要拷贝构造一个对象,让这个对象去操作
	tmp -= day;//复用-=运算符重载
	return tmp;
}

🕖⑧.-运算符重载(2)

日期-天数是有意义,可以知道天数之前是什么日期。
那日期-日期有没有意义呢?肯定有呀,这可以知道你小子从出生到现在活了多久。 在这里插入图片描述
这个就是对-运算符进行再重载。参数由天数(int类型)变成了,日期(日期类)。
因为函数名相同,但参数不同所以就可以构成重载。

那日期-日期如何计算呢?

data1 - data2 看起来很麻烦,涉及天数和月份甚至年份一起要改变。
不过我们可以不直接相减,换一种方法来求它们之间的天数。
1.只要让日期小的不断的加加到大的日期,每加一次就计数一次
2.当两个日期相同时,计数器所显示的就是它们之间的天数
3.不过要注意的是,一开始我们可不知道哪个日期大,哪个日期小,需要讨论。

int Data::operator-(Data& d)//这是日期-日期 -运算符重载函数
{
	Data max = *this;//默认*this日期对象大
	Data min = d;//d对象小
	int flag = 1;

	if (*this < d)//如果错了
	{
		max = d;
		min = *this;
		flag = -1;//那就将flag置为-1
	}
	int n = 0;//计数器
	while (min != max)//让小的日期不断的加加到大的日期
	{
		++min;//每加一次
		++n;//计数器计数一次
	}
	return n*flag;//最后计数器n就是它们之间的天数,而flag决定是正的还是负的。
}

🕕⑨.前置++运算符重载

C语言中++这个运算符分为前置++和后置++,前置++是先++再使用,而后置++是先使用后++。
在C++中如果要对自定义类型进行前置或者后置++,需要将它们重载成运算符函数。

C++规定前置++就正常按照运算符重载函数写,而后置++重载是要多增加一个int类型的参数,但是调用函数时该参数不用传递,编译器会自动传递。

//这里可以用引用做返回值,因为最后返回的是对象本身
Data& Data::operator++()//前置++运算符重载
{
	*this += 1;//这里的+=其实就是+=运算符重载
	return *this;
}

🕔⑩.后置++运算符重载

//这里不可以用引用左返回,因为返回的是拷贝对象,不是对象本身,函数结束,就销毁了
Data Data::operator++(int)//后置++运算符重载---比前置++多一个参数,为什么呢?因为这样才可以和前置++构成承载,因为函数名相同,参数不同才可以构成承载,因为不需要使用参数,所以可以只写类型
{
	Data tmp(*this);//后置++,返回的是使用前的状态,因为后置++是先使用后++
	*this += 1;//对象先使用,再++,也就是要将没++之前的对象返回过去。
	return tmp;
}

⏰二.日期类的实现

TEST.h文件
#pragma once
#include <iostream>
using namespace std;

class Data
{
	//析构也不用写
public:
	Data(int year = 1, int month = 1, int day = 1)//构造函数要写,拷贝构造函数不用写,赋值重载不用写
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	Data(const Data& d)
	{
	
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	bool operator<(const Data& d);
	bool operator==(const Data& d);
	bool operator<=(const Data& d);
	bool operator>(const Data& d);
	bool operator>=(const Data& d);
	bool operator!=(const Data& d);
	Data operator++();//前置++
	Data operator++(int);//后置++
	int GetMonDay(int year, int month);
	Data& operator+=(int day);
	Data operator+(int day);
	Data& operator-=(int day);
	Data operator-(int day);
	int operator-(Data& d);
private:
	int _year;
	int _month;
	int _day;
};

```c



TEST.c文件

```c

bool Data:: operator<(const Data& d)
{
		if (_year < d._year)
		{
			return true;
		}
		else if (_year == d._year && _month < d._month)
		{
			return true;
		}
		else if (_year == d._year && _month == d._month && _day < d._day)
		{
			return true;
		}
		return false;
	
}
bool Data::operator==(const Data& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}
bool Data::operator<=(const Data& d)//直接复用上面的
{
	return *this < d || *this == d;
}
bool Data::operator>(const Data& d)
{
	return !(*this <= d);
}

bool Data::operator>=(const Data& d)
{
	return !(*this < d);
}
bool Data::operator!=(const Data& d)
{
	return !(*this == d);
}

int Data::GetMonDay(int year, int month)
{
	static int monday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//频繁调用
	/*if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)&&month==2)*/
	if (month == 2&&(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) )
	{
		return 29;
	}
	else
	return monday[month];
}
//Data& Data::operator+=(int day)//用+复用+=-最好先实现+= 再复用实现 +
//{
//	*this=*this + day;
//	
//	return *this;
//}
Data& Data::operator+=(int day)
{
	if (day < 0)
	{
		return *this -= -day;
	}
	_day += day;
	while (_day > GetMonDay(_year, _month))
	{
		_day -= GetMonDay(_year, _month);
		++_month;
		if (_month == 13)
		{
			++_year;
			_month = 1;
		}
	}
	return *this;
}
Data Data::operator+(int day)
{
	Data tmp(*this);//拷贝一份,让tmp返回,*this没有改变
	tmp._day += day;
	while (tmp._day > GetMonDay(tmp._year, tmp._month))
	{
		tmp._day -= GetMonDay(tmp._year, tmp._month);
		++tmp._month;
		if (tmp._month == 13)
		{
			++_year;
			tmp._month = 1;
		}
	}
	return tmp;
}
//Data Data::operator+(int day)  //+ 复用+=
//{
//	Data tmp(*this);//拷贝一份,让tmp返回,*this没有改变
//	tmp += day;//复用+=重载函数 
//	return tmp;
//}
Data Data::operator++()//前置++运算符重载
{
	*this += 1;
	return *this;
}
Data Data::operator++(int)//后置++运算符重载
{
	Data tmp(*this);
	*this += 1;
	return tmp;
}
Data& Data::operator-=(int day)
{
	if (day < 0)
	{
		return *this += -day;
	}
	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonDay(_year, _month);
	}
	return *this;
}
Data Data::operator-(int day)
{
	Data tmp(*this);
	tmp -= day;
	return tmp;
}
//d1 - d2
int Data::operator-(Data& d)
{
	Data max = *this;
	Data min = d;
	int flag = 1;

	if (*this < d)
	{
		max = d;
		min = *this;
		flag = -1;
	}
	int n = 0;
	while (min != max)
	{
		++min;
		++n;
	}
	return n*flag;
}

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

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

相关文章

Linux下C/C++(端口扫描技术)

随着互联网使用的不断增加&#xff0c;网络攻击也在增加。互联网本质上已经成为现代。因此&#xff0c;了解互联网和使用互联网是非常重要的。网络技术的安全性在当今时代是非常重要和必要的。 在本文中&#xff0c;我们将讨论一个非常重要的主题&#xff0c;即可能破坏计算机…

es 7.x 通过DSL的常用查询语句

一 模拟造数 1.1 模拟数据 添加数据修改数据的请求方式为post http://localhost:9200/student/_doc/101 { "name":"zhangsan", "nickname":"zhangsan","sex":"男","age":30,"createTime":…

InnoDB线程模型

新版本结构演变 MySQL 5.7 版本 将 Undo日志表空间从共享表空间 ibdata 文件中分离出来&#xff0c;可以在安装 MySQL 时由用户自行指定文件大小和数量增加了 temporary 临时表空间&#xff0c;里面存储着临时表或临时查询结果集的数据Buffer Pool 大小可以动态修改&#xff0…

2.3 利用NumPy进行统计分析

2.3 利用NumPy进行统计分析 2.3.1 读/写文件1、二进制的文件读写2、读取文本格式的数据 2.3.2 使用数组进行简单统计分析1、排序2、去重与重复数据3、常用的统计函数 2.3.1 读/写文件 NumPy文件读写主要有二进制的文件读写和文件列表形式的数据读写两种形式 1、二进制的文件读…

代码随想录算法训练营第三十六天 | 重叠区间

435. 无重叠区间 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;贪心算法&#xff0c;依然是判断重叠区间 | LeetCode&#xff1a;435.无重叠区间_哔哩哔哩_bilibili 状态&#xff1a;能做出来&#xff0c;用的“补充(1)”的左边界排序&#xff0c…

SpringCloud —— eureka

目录 1.认识微服务 1.0.学习目标 1.1.单体架构 1.2.分布式架构 1.3.微服务 1.4.SpringCloud 1.5.总结 2.服务拆分和远程调用 2.1.服务拆分原则 2.2.服务拆分示例 2.2.1.导入Sql语句 2.2.2.导入demo工程 2.3.实现远程调用案例 2.3.1.案例需求&#xff1a; 2.3.2.注…

4. Mysql索引优化实战一

一条SQL在MySQL中是如何执行的 1. 示例表举一个大家不容易理解的综合例子 本文是按照自己的理解进行笔记总结&#xff0c;如有不正确的地方&#xff0c;还望大佬多多指点纠正&#xff0c;勿喷。 本节课内容&#xff1a; 索引下推优化详解Mysql优化器索引选择探究索引优化Order…

解决winstore下载mincraft 出现错误提示的问题,以及minecraft.exe出现此应用无法在你的电脑上运行的原因分析。

mincraft 点开显示此应用无法在你的电脑上运行&#xff0c;去C:\XboxGames\Minecraft Launcher\Content下看了下&#xff1a; 但是别人电脑上相同目录下一样的文件能运行&#xff0c;于是选择重装&#xff0c;但是刚开始下载就遇到这个问题&#xff1a; 商店提示这个 点开一…

Neural Network学习笔记2

torch.nn: Containers: 神经网络骨架 Convolution Layers 卷积层 Pooling Layers 池化层 Normalization Layers 正则化层 Non-linear Activations (weighted sum, nonlinearity) 非线性激活 Convolution Layers Conv2d torch.nn.Conv2d(in_channels, out_channels, ke…

Web缓存利用分析(三)

导语&#xff1a;前一篇文章介绍了Server Cache Poisoning在实际应用场景下&#xff0c;产生DOS攻击的利用方式。本篇文章则介绍Web Cache Deception在真实场景下的应用方式和测试情况。 前言 前一篇文章介绍了Server Cache Poisoning在实际应用场景下&#xff0c;产生DOS攻击…

产品经理入门书籍有哪些?

说到入门产品经理&#xff0c;应该看哪些书籍呢&#xff1f;下面咱们就从产品经理的各种能力维度来聊聊&#xff0c;这样更有针对性。 一、夯实产品经理的基础&#xff0c;建立产品思维 首先我们入行&#xff0c;要清楚产品经理具体的工作怎么做&#xff0c;比如&#xff1a;…

分享一个造成azkaban上传文件失败的案例

背景&#xff1a; 当初由于开发的需求&#xff0c;需要将传统方式部署azkaban以容器的方案部署&#xff0c;不但可以满足业务需求&#xff0c;还可以将用于构建的azkaban ECS虚拟机空闲出来&#xff0c;用作k8s节点。 但是在构建azkaban容器实例的时候由于azkaban参数配…

Flink第三章:基本操作(二)

系列文章目录 Flink第一章:环境搭建 Flink第二章:基本操作. Flink第三章:基本操作(二) 文章目录 系列文章目录前言一、物理分区1.shuffle(随机分区)2.Round-Robin(轮询)3.rescale(重缩放分区)4.broadcast(广播)5.Custom(自定义分区) 二、Sink1.写出到文件2.写入到Kafka3.写入到…

leetcode:203.移除链表元素(两种方法详解)

前言&#xff1a;内容包括-题目&#xff0c;代码实现&#xff08;两种方法&#xff09;&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 …

【CSS系列】第五章 · CSS文本属性

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

QT With OpenGL(SSAO)(Screen-Space Ambient Occlusion)

文章目录 在G_Buffer中加入深度信息使用深度信息得到环境遮蔽的结果1. 新建SSAO帧缓存类2.生成法向半球核心3. 生成随机核心转动纹理为什么要生成随机核心转动创建一个小的随机旋转向量纹理 4.使用G_Buffer渲染SSAO纹理传入参数着色器1. 获取当前像素在纹理中的信息2.计算TBN矩…

SpringBoot -- AOP

一直只听过AOP&#xff0c;但是并不知道AOP的原理使用&#xff0c;参考深入浅出SpringBoot2.x学习一下SpringBoot AOP编程 AOP是基于动态代理实现的 静态代理就是代理类中有一个实现类&#xff0c;和实现类相同名称的方法&#xff0c;调用代理的request方法&#xff0c;执行顺…

RF检测器/控制器MS2351可pin对pin兼容AD8314、MAX4003

MS2351M/MS2351D 是一款对数放大器芯片&#xff0c;主要用于接收信号强度指示 (RSSI) 与控制功率放大器&#xff0c;工作频率范围是50MHz&#xff5e;3000MHz&#xff0c;动态范围可达 35dB 到 45dB。可pin对pin兼容AD8314、MAX4003。 MS2351M/MS2351D 是电压响应器件&#xff…

【c语言】结构体详解 | 结构体数组/指针

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c语言系列专栏&#xff1a;c语言之路重点知识整合 &#x…

【ChirpStack 】如何获取 JWT TOKEN

LoRa App Server 提供了两类 API 接口&#xff0c;其中 RESTful JSON API 提供了一个 API console&#xff0c;在AS地址的基础上使用 /api 即可访问&#xff0c;罗列了 API 端点和文档介绍&#xff0c;测试起来非常方便。 本文主要介绍 如何使用 chirpstack 的API 进行测试以及…