C++类和对象下——实现日期类

 前言

        在学习了类和对象的六大成员函数后,为了巩固我们学习的知识可以手写一个日期类来帮助我们理解类和对象,加深对于其的了解。

默认函数

    构造函数

        既然是写类和对象,我们首先就要定义一个类,然后根据实际需要来加入类的数据与函数。作为一个日期类,肯定要有时间了,我们采用公元纪年法,存储三个变量,年 月 日,如下。

class Date
{

private:
	int _year;
	int _month;
	int _day;
};

        注意这里将三个成员变量定义为private:,是为了防止用户在外面修改,提高安全性。其次这里在每个成员变量前面加了个下划线。 _year,这里是为了防止后面与函数的参数重名。当然重名也有其他解决方法例如用this.year,也可以。具体选那种看读者更适合那种编码风格。

        写完上面的变量后,我们第一个想到要写的函数必定是构造函数了。如下函数

Date(int year=1900, int month=1, int day=1)
{
	_year = year;
	_month = month;
	_day = day;
}

        注意我们这里写成了全缺省,这样做的好处是不用写无参的构造函数,给每个日期对象都有默认值。

拷贝构造函数

        其次我们要写的就是拷贝构造函数。注意这里的形参加了个const,这里加了const一是为了方防止修改形参d,二是为了通用性。如下例子

	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

        假如我们没有加const,有下述程序。这段代码会报错!为什么呢?d1的类型为const Date,而拷贝构造函数参数类型为Date& d,如果传参成功,是不是就可以在构造函数的内部修改原本为const类型的变量,违背了基本的定义语法。但用一个const Date类型拷贝初始化是我们需要的场景,为了让其正常运行,就需要在拷贝构造函数加const。

int main()
{

	const Date d1(2024, 4, 16);
	Date d2(d1);
	
	return 0;
}

        有const变量自然也有普通的变量了。我们就可以写个普通变量的拷贝构造函数。

Date(Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

        其实在很多地方会将上面两个构造函数简化为一个,即保留含const的

Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

        那自然有人问?普通变量的拷贝怎么办呢?在这里就不得不提C++对于变量类型的处理了。我们首先看段熟悉的代码。

int a=0;

a=1.12;

        这段代码会报错么?为什么?大家可以在程序中运行下,结果是不会报错的,有的编译器可能会有警告。大家知道整型与浮点型在内存中的存储方式是不一样的,即使是对浮点型内存的截断读取a也不可能为1.

        但a的结果却是一,这是因为编译器帮我们做了类型转化,称之为隐式转换。如下图。

        同理当我们将Date变量赋给const Date& d,编译器也会额外开辟空间付给形参d。

        或许有读者又有疑问?Date变量赋给const Date& d可以,为什么const Date变量赋给Date& d不可以,因为前者是将内存的权限放小,而后者是将对内存的权限放大。在C++中将权限放小可以,但把权限放大就有可能产生难以预料的后果。

        接下来我们来实现与拷贝构造函数功能十分像的赋值重载函数。

赋值重载函数

        代码如下

	Date& operator=(const Date& d)
	{
		if (&d != this)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

        这里我们任然将参数的类型加上const省去对于普通变量与const变量的分类了,当然对于普通变量会隐式转换,会减少些效率。

        注意这里将d的地址与this比较,这是为了防止自己和自己赋值的情况如 a=a,这样没有任何的意义。

析构函数

        在这个对象中我们没有开辟内存,没有在堆区申请空间,写不写析构函数都可以。

~Date()
{

}

成员函数

<<重载

        我们为了后续的方便,首先要实现的便是cout输出Date类型,对于内置类型cout可以直接的输出,但是对于自定义类型要我们使用操作符重载.

        按照习惯我们极大概率会将<<写在类里面。写出如下的代码

ostream& operator<<(ostream& out)
{
	out << _year << "-" << _month << "-" << _day << endl;
	return out;
}

        其中的ostream参数是输出时要用到的一种类型,返回值为ostream是为了连续输出的原因。这个看起来没有什么错误,但运行的时候就会报错!

        我们明明重载了<<操作符,为什么却提示我们没有匹配类型呢?这就不得不提到this了,在使用cout << d1操作符重载的时候,我们从左向右显然要传递两个参数ostream和Date,在类中的成员函数默认第一个参数传递Date,即形参this指针,第二个实参初始化函数的形参。

        关于this指针详情可以看【C++ 类和对象 上 - CSDN App】http://t.csdnimg.cn/Wx5iO。在这里就不叙述了。

        于是上面的代码也不是不可以用,可以采用如下的方法使用

        但这种方法显然是不符合我们日常认知的。

        为了解决这种问题,我们把<<操作符改为全局函数。就可以解决顺序的问题了。如下代码

ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

        但此时又有一个新的问题,这个重载函数不可以访问Date对象中私有的成员变量,这就体现了我们类的安全性高,为了解决我们需要把这个操作符重载函数声明为友元函数就可以了。

class Date
{
public:
	Date(int year=1900, int month=1, int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	Date& operator=(const Date& d)
	{
		if (&d != this)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}


	friend ostream& operator<<(ostream& out, const Date& d);


private:
	int _year;
	int _month;
	int _day;
};

        这样我们就可以正常输出了。

>>重载

        有了输出,当然要有其对应的输入最好。和输出重载一样,将>>操作符重载为全局函数,并且在类中声明为友元函数。

istream& operator>>(istream& in,  Date& d)
{
	in >> d._year >> d._month >> d._day;
	return in;
}

        如下图,刚开始输出1900时我们写的全缺省参数的作用,而后输出的就是我们输入的2024 5 13.

        光有输入输出函数显然是不可以的,我们也要有对应的函数。

大小比较

        对于一个日期比较大小是符合实际需求的,我们可以写个cmp成员,但更好的使用操作符重载,< >,这个我们最熟悉又可以减小记忆的负担。

>比较

        我们有两种方法比较两个日期的大小。

方法一

        不断地寻找true条件,最后剩下的就是false。注意年数相等的时候要判断月份

bool Date::operator>(Date& d)
{
	if (_year > d._year)
	{
		return true;
	}
	else if (_year == d._year)
	{
		if (_month > d._month)
		{
			return true;
		}
		else if (_month == d._month)
		{
			if (_day > d._day)
			{
				return true;
			}
		}
	}
	return false;
}
方法二

        将日期的比较转换为数的比较。月份最多有12月,天最多有31天,我们就可以将年扩大10000倍,月扩大100倍,将2024年5月13日与2023年4月20日比较转换为2024513与2023420比较。我们知道数的比较大小是从高位往下开始比较的。这与我们比较日期的顺序不谋而合,就可以如下的简化代码。

bool Date::operator>(Date& d)
{
	return _day + _month * 100 + _year * 10000 > 
		d._day + d._month * 100 + d._year * 10000;
}

同理小于等于。大于等于,小于都可以如上比较。

bool Date::operator<(Date& d)
{
	return _day + _month * 100 + _year * 10000 <
		d._day + d._month * 100 + d._year * 10000;
}
bool Date::operator<=(Date& d)
{
	return _day + _month * 100 + _year * 10000 <=
		d._day + d._month * 100 + d._year * 10000;
}
bool Date::operator>=(Date& d)
{
	return _day + _month * 100 + _year * 10000 >=
		d._day + d._month * 100 + d._year * 10000;
}
bool Date::operator!=(Date& d)
{
	return _day + _month * 100 + _year * 10000 !=
		d._day + d._month * 100 + d._year * 10000;
}

        判断两个日期是否相等的代码也十分简单,如下。

相等判断

bool Date::operator==(Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

        到此我们的比较函数就写完了。但光有比较还不可以,我们可能想要知道50天后是哪一天,50天前是那一天,两个日期相差多少天。

加减操作

        在后续的操作中我们不可避免的要访问某年某月有多少天,我们便可以将他封装为成员函数,便于我们查找天数。

获取天数

        我们可以将每个月的天数写在一个数组中,然后哪一个月就读取哪一个数字,但其中2月十分特殊要分为润年的问题要单独判断下。

int Date::GetMonthDay(Date& d)
{
	static int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

	if (d._month == 2 && ((d._year % 400 == 0) || (d._year % 4 == 0 && d._year % 100 != 0)))
	{
		return 29;
	}

	return arr[d._month];
}

        这里将数组加上static 是为了避免重复创建,提高效率。然后就是判断是不是闰年的二月。

+=重载

        我们可以将一个日期类加上n天返回加n天后的日期。

Date& Date::operator+=(int t)
{

	_day += t;

	while (_day > GetMonthDay(*this))
	{
		_day -= GetMonthDay(*this);
		_month++;
		if (_month == 13)
		{
			_month = 1;
			_year++;
		}
	}
	return *this;
}

        我们整体的循环是在找当前月合理的天数,如果不合理就月份加一,天数减去当前月,继续判断直到结束。

        测试结果正确。

        大家写的时候可以用日期计算器 - 天数计算器 | 在线日期计算工具 (sojson.com)这个网站检测。

+重载

        我们之前已经写完+=了,先在写+的思路是不是与+=类似,我们可以仿照+=写出+重载,但是我们还有更加简单的方法,复用+=!!

Date Date::operator+(int t)
{
	Date t1 = *this;
	t1 += t;

	return t1;
}

        这样复用代码就大大简化了我们写代码的复杂度。其实上面的判断也可以复用代码,读者可以自行尝试。

-=重载

        一个日期减去一个天数,与一个日前加上一个天数十分像。天数小于肯定是不合理的日期就加上当前月数。不断的循环判断直到合理数据。

Date& Date::operator-=(int t)
{
	_day -= t;
	while ( _day<1 )
	{
		_month--;
		if (_month == 0)
		{
			_month = 12;
			_year--;
		}
		_day += GetMonthDay(*this);
	}
	return *this;
}

-重载

        与之前一样,我们复用-=的函数。

Date Date::operator-(int t)
{
	Date tmp = *this;
	tmp -= t;

	return tmp;
}

        我们如果对+负数,-负数会怎么样?显然程序会崩溃但这又可能是我们使用者的操作,于是便可以在不同的重载函数互相调用。

        如下代码

Date Date::operator-(int t)
{
	if (t < 0)
		return *this + (-t);
	Date tmp = *this;
	tmp -= t;

	return tmp;
}

    日期相减

方法一

        我们当然会求两个日期之间的差数。便可以重载-。我们可以对小的天数一直加一直到二者相等。如下

int Date::operator-(Date& d)
{
	assert(*this >= d);

	Date t1 = *this;
	Date t2 = d;
	int t = 0;
	//一直加

	while (t1 != t2)
	{
		t2 += 1;
		t++;
	}

	return t;
}

        我们有时也会写的前一个日期小,导致相差负数,为了达到这种效果也可以对上述代码稍加修改。

int Date::operator-(Date& d)
{
	if (*this < d)
		return d - *this;

	Date t1 = *this;
	Date t2 = d;
	int t = 0;
	//一直加

	while (t1 != t2)
	{
		t2 += 1;
		t++;
	}

	return t;
}
方法二

        上述的代码十分简单,效率有些不理想,我们可以换种方法。

        首先我们先判断二者是否相同,不相同在判断t2的天数是否小于t1,小于说明可能只是天数不同,将天数加到t1的天数,然后判断是否相等。如果t1的天数等于t2的天数,说明月份不同,将t2的月份一次往上加一判断二者是否相等。

int Date::operator-(Date& d)
{
	if (*this < d)
		return d - *this;
	
	Date t1 = *this;
	Date t2 = d;
	int t = 0;
	//一直加
	while (t1 != t2)
	{
		int c = GetMonthDay(t2);
		if (t2._day < t1._day && t1._day <= c)
		{
			
			t += t1._day - t2._day;
			t2._day = t1._day;
		}
		else 
		{
			t2._month++;
			if (t2._month == 13)
			{
				t2._year++;
				t2._month = 1;
			}
			t += c - t2._day + 1;
			t2._day = 1;
		}
	}

	return t;
}

        这种方法的效率比第一种高了许多。

结语

        到这里本篇文章就结束了。喜欢的点点关注!

全部代码如下。

#include<iostream>
#include<assert.h>
using namespace std;


class Date
{
public:
	Date(int year=1900, int month=1, int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	Date& operator=(const Date& d)
	{
		if (&d != this)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

	//友元函数声明
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);


	//比较函数
	bool operator==(Date& d);
	bool operator>(Date& d);
	bool operator<(Date& d);
	bool operator<=(Date& d);
	bool operator>=(Date& d);
	bool operator!=(Date& d);


	//加减操作函数
	Date& operator+=(int t);
	Date operator+(int t);
	Date& operator-=(int t);
	Date operator-(int t);
	int operator-(Date& d);
	int GetMonthDay(Date& d);

private:
	int _year;
	int _month;
	int _day;
};


//bool Date::operator>(Date& d)
//{
//	if (_year > d._year)
//	{
//		return true;
//	}
//	else if (_year == d._year)
//	{
//		if (_month > d._month)
//		{
//			return true;
//		}
//		else if (_month == d._month)
//		{
//			if (_day > d._day)
//			{
//				return true;
//			}
//		}
//	}
//	return false;
//}
//bool Date::operator<(Date& d)
//{
//	return !(*this >= d);
//}
//bool Date::operator<=(Date& d)
//{
//	return *this < d || d == *this;
//}
//bool Date::operator>=(Date& d)
//{
//	return *this > d || d == *this;
//}
//bool Date::operator!=(Date & d)
//{
//	return !(d == *this);
//}

bool Date::operator>(Date& d)
{
	return _day + _month * 100 + _year * 10000 > 
		d._day + d._month * 100 + d._year * 10000;
}


bool Date::operator<(Date& d)
{
	return _day + _month * 100 + _year * 10000 <
		d._day + d._month * 100 + d._year * 10000;
}
bool Date::operator<=(Date& d)
{
	return _day + _month * 100 + _year * 10000 <=
		d._day + d._month * 100 + d._year * 10000;
}
bool Date::operator>=(Date& d)
{
	return _day + _month * 100 + _year * 10000 >=
		d._day + d._month * 100 + d._year * 10000;
}
bool Date::operator!=(Date& d)
{
	return _day + _month * 100 + _year * 10000 !=
		d._day + d._month * 100 + d._year * 10000;
}
bool Date::operator==(Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}



int Date::GetMonthDay(Date& d)
{
	static int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

	if (d._month == 2 && ((d._year % 400 == 0) || (d._year % 4 == 0 && d._year % 100 != 0)))
	{
		return 29;
	}

	return arr[d._month];
}

Date& Date::operator+=(int t)
{
	if (t < 0)
		return *this -= (-t);
	_day += t;

	while (_day > GetMonthDay(*this))
	{
		_day -= GetMonthDay(*this);
		_month++;
		if (_month == 13)
		{
			_month = 1;
			_year++;
		}
	}
	return *this;
}

Date Date::operator+(int t)
{
	Date t1 = *this;
	t1 += t;

	return t1;
}


Date& Date::operator-=(int t)
{
	if (t < 0)
		return *this += (-t);
	_day -= t;
	while ( _day<1 )
	{
		_month--;
		if (_month == 0)
		{
			_month = 12;
			_year--;
		}
		_day += GetMonthDay(*this);
	}
	return *this;
}

Date Date::operator-(int t)
{
	if (t < 0)
		return *this + (-t);
	Date tmp = *this;
	tmp -= t;

	return tmp;
}


int Date::operator-(Date& d)
{
	if (*this < d)
		return d - *this;
	
	Date t1 = *this;
	Date t2 = d;
	int t = 0;
	//一直加
	while (t1 != t2)
	{
		int c = GetMonthDay(t2);
		if (t2._day < t1._day && t1._day <= c)
		{
			
			t += t1._day - t2._day;
			t2._day = t1._day;
		}
		else 
		{
			t2._month++;
			if (t2._month == 13)
			{
				t2._year++;
				t2._month = 1;
			}
			t += c - t2._day + 1;
			t2._day = 1;
		}
	}

	return t;
}



ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

istream& operator>>(istream& in,  Date& d)
{
	in >> d._year >> d._month >> d._day;
	return in;
}








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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机Java项目|Springboot房产销售系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、Python项目、前端项目、人工智能与大数据、简…

Windows下安装Node.js、npm和electronic,并运行一个Hello, World!脚本程序

20240510 By wdhuag 目录 简介&#xff1a; 参考&#xff1a; 安装Node.js 安装npm 配置npm&#xff1a; 修改包存放目录和缓存目录 切换镜像源 使用 nrm 切换镜像源 安装Electron 运行一个Hello, World!脚本程序 安装Yarn JavaScript 指南 简介&#xff1a; Nod…

flash attention的CUDA实现探讨-V3

之前关于flash attention的实现参考添加链接描述,添加链接描述,添加链接描述 lash attention的数学变换:给定三个矩阵Q,K,V,形状都是[N,d],计算S=QK.T,然后针对dim=1做softmax,然后和V继续做矩阵乘法得到形状为[N,d]的输出矩阵O,即O=softmax(QK.T,dim=1)V。 下面本人的…

物联网设计竞赛_2_Jetson Nano中文输入法配置安装vscode

1、装ibus和ibus依赖框架 sudo apt-get install ibus ibus-clutter ibus-gtk ibus-gtk3 ibus-qt4 2、启动ibus im-config -s ibus 3、安装拼音引擎 sudo apt-get install ibus-pinyin 4、重启linux系统 shutdown -r now 5、进入ibus设置添加中文 ibus-setup 插入中文p…

四川汇昌联信:拼多多网点怎么开?大概需要多少钱?

想要开一家拼多多网点&#xff0c;你肯定很关心需要准备多少资金。下面&#xff0c;我们就来详细解答这个问题&#xff0c;并从多个角度分析开设网点的要点。 一、 开设拼多多网点&#xff0c;首要任务是确定启动资金。根据不同的经营模式和地区差异&#xff0c;成本会有所不同…

基于SpringBoot + Vue的兼职网站管理系统设计与实现+毕业论文+答辩PPT

系统介绍 本系统包含管理员、用户、企业三个角色。 管理员角色&#xff1a;前台首页、个人中心、用户管理、企业管理、兼职信息管理、职位申请管理、留言板管理、系统管理。 用户角色&#xff1a;前台首页、个人中心、职位申请管理。 企业角色&#xff1a;前台首页、个人中心、…

JUC下的ThreadLocalRandom详解

ThreadLocalRandom 是Java并发包&#xff08;java.util.concurrent&#xff09;中提供的一个随机数生成器类&#xff0c;它是从Java 7开始引入的。相较于传统的Math.random()或Random类&#xff0c;ThreadLocalRandom更适用于多线程环境&#xff0c;因为它为每个线程维护了一个…

【spring】application.yml导入额外配置文件

有时候application.yml 已经配置很多配置已经很大很乱了想把他们拆出去放在一个独立的XX.yml文件管理。这时候就用到了 spring.config.import 属性。 spring.config.import spring.config.import 是 Spring Boot 2.4 版本引入的一个配置属性&#xff0c;用于导入额外的配置数…

Java入门基础学习笔记21——Scanner

在程序中接收用户通过键盘输入的数据&#xff1a; 需求&#xff1a; 请在程序中&#xff0c;提示用户通过键盘输入自己的姓名、年龄、并能在程序中收到这些信息&#xff0c;怎么解决&#xff1f; Java已经写好了实现程序&#xff0c;我们调用即可。 API&#xff1a;Applicat…

解决 XXL-Job 端口额外占用问题 小结

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java技术栈笔记 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1. 前言 2. 问题解决 2.1. 下载源码 2.2. 启动admin服务器 2.3. 项目引入c…

MySQL-InnoDB数据存储结构

1、存储结构-页 索引结构提供了高效的索引方式&#xff0c;索引信息以及数据记录都保存在数据文件或索引文件中&#xff08;本质存储在页结构中&#xff09; 1.1、磁盘与内存交互的基本单位&#xff1a;页 在InnoDB中将数据划分为若干页&#xff0c;页的默认大小为&#xff…

OpenCV-基于累计直方图的中值滤波算法

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 实现原理 基于累计直方图的中值滤波算法是一种图像处理技术&#xff0c;用于去除图像中的噪声。它利用了像素值的频数分布&#…

LeetCode/NowCoder-链表经典算法OJ练习2

最好的&#xff0c;不一定是最合适的&#xff1b;最合适的&#xff0c;才是真正最好的。&#x1f493;&#x1f493;&#x1f493; 目录 说在前面 题目一&#xff1a;分割链表 题目二&#xff1a;环形链表的约瑟夫问题 SUMUP结尾 说在前面 dear朋友们大家好&#xff01;&…

卷积神经网络边缘识别

为什卷积神经网络能够识别图片呢&#xff1f;是基于图片相似度比较&#xff0c;两张图片的点击越大说明两张图片越像&#xff0c;比如我们那狗胡子的图片去比较&#xff0c;如果相似度很高&#xff0c;就是认为这个动物更像狗。点积越大&#xff0c;图片越相似&#xff0c;这个…

Windows2016系统禁止关闭系统自动更新教程

目录 1.输入cmd--适合系统2016版本2.输入sconfig&#xff0c;然后按回车键3.输入5&#xff0c;然后按回车键4.示例需要设置为手动更新&#xff0c;即输入M&#xff0c;然后按回车键 1.输入cmd–适合系统2016版本 2.输入sconfig&#xff0c;然后按回车键 3.输入5&#xff0c;然后…

揭秘APP广告变现:轻松赚取收益的秘密武器,你还在等什么?

在移动互联网时代&#xff0c;APP广告变现已成为许多开发者和公司获取收益的重要方式。它如同一把秘密武器&#xff0c;帮助那些掌握了其使用技巧的人轻松赚取收益。那么&#xff0c;究竟什么是APP广告变现&#xff1f;又如何通过它轻松赚取收益呢&#xff1f;接下来&#xff0…

对中介者模式的理解

目录 一、场景1、题目 【[来源](https://kamacoder.com/problempage.php?pid1094)】1.1 题目描述1.2 输入描述1.3 输出描述1.4 输入示例1.5 输出示例 二、不采用中介者设计模式1 代码2 问题 三、中介者设计模式1 代码2 更好的例子 四、个人思考 一、场景 设计模式不是银弹&am…

STM32(开篇总结)

STM32介绍 STM32是意法半导体公司基于ARM Cortex-M内核开发的32位微控制器 STM32常应用在嵌入式领域&#xff0c;如智能车、无人机、机器人、无线通信、物联网、工业控制、娱乐电子产品等 STM32功能强大、性能优异片上资源丰富、功耗低&#xff0c;是一款经典的嵌入式微控制器…

Lesson5--二叉树(超详细版)

【本节目标】 1. 树概念及结构 2. 二叉树概念及结构 3. 二叉树顺序结构及实现 4. 二叉树链式结构及实现 1.树概念及结构 1.1树的概念 树是一种 非线性&#xff08;线性结构就是顺序表链表&#xff09; 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个…

超详细比特币Brc-20部署发布:实用步骤演示,请点赞收藏!(一)

大家好&#xff0c;我是程序员大猩猩。 上一节我们讲到如何使用Remix部署智能合约到币安链&#xff0c;如下&#xff1a; 使用Remix部署智能合约到币安链&#xff08;Remix的操作介绍 币安链合约的部署&#xff09; 有很多小伙伴私信问我&#xff0c;那么BTC&#xff08;比特…