【C++】日期类函数(时间计数器)从无到有实现

news2024/11/13 10:17:49


风铃.gif

欢迎来到Harper·Lee的学习笔记!
博主主页传送门:Harper·Lee的博客主页
个人语录:他强任他强,清风拂山岗!

CSDN成就一亿技术人.gif
image.png


一、前期准备

1.1 检查构造的日期是否合法

bool Date::CheckDate()
{
	if (_month < 1 || _month > 12
		|| _day < 1 || _day > GetMonthDay(_year, _month))
	{
		return false;
	}
	else
	{
		return true;
	}
}


Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
	//防止构造的日期有问题
	if (!CheckDate())
	{
		cout << "非法日期:" << endl;
		Print();
	}
}

1.2 获取某年的某月的总天数

  • 建议直接写在类里面作为成员函数:定义在类里面的成员函数默认是内联inline,而且该函数不仅短小,还会被频繁调用;
	int GetMonthDay(int year, int month)
	{
        assert(month > 0 && month < 13);//避免出现非法月份??????
		static int GetMonthDayArray[13] = { -1,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;//闰年
		}
		return GetMonthDayArray[month];
	}

1.3 打印函数

void Date::Print()
{
	cout << _year << "年" << _month << "月" << _day << "日" << endl;
}

二、日期+天数

2.1 operator+=

  • 进位:时间在向前先直接相加,日期不合法,减天加月,月满加年,直至日期合法。
  • 返回值:返回*this,所以使用引用返回。
  • 注意:这里是+=,而不是+a+1:a本身不变;a+=1:a本身是会变的。
//日期+天数:d1+=100
Date& Date::operator+= (int day)
{
	//正常+:2024/7/12+10=2024/7/22
	_day += day;
	while (_day > GetMonthDay(_year, _month))//判断日期是否非法
	{
		//时间在前进:
		_day -= GetMonthDay(_year, _month);//先减天
		++_month;//再加月,判断是否满月,满月进年
		if (_month == 13)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;
}

2.2 operator+

  • 传值返回
  • 直接写:
//d1 + 100
Date Date::operator+ (int day)
{
	Date tmp = *this;//这里拷贝一份出来
	tmp._day += day;
	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
	{
		tmp._day -= GetMonthDay(tmp._year, tmp._month);
		++tmp._month;
		if (tmp._month == 13)
		{
			tmp._year++;
			tmp._month = 1;
		}
	}
	return tmp;//这里就不能使用引用返回了,局部对象,出作用域就会销毁
}
  • 上面的是直接写的,也可以在写了operator+=后,+复用+=
//d1 + 100
Date Date::operator+ (int day)
{
	Date tmp = *this;//这里拷贝一份出来
	tmp += day;//复用+=
    
	return tmp;//这里就不能使用引用返回了,局部对象,出作用域就会销毁
}

三、日期-天数

3.1 operator-=

//d1 -= 100
Date& Date::operator-=(int day)
{
	_day -= day;
	while (_day <= 0)//判断出非法日期
	{
		--_month;//先借月
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);//加上借来的
	}
	return *this;
}

3.2 operator-

  • 直接实现:
Date Date::operator-(int day)
{
	Date tmp = *this;
	tmp._day -= day;
	while (tmp._day<=0)
	{
		--tmp._month;
		if (tmp._month == 0)
		{
			tmp._month = 12;
			--tmp._year;
		}
		tmp._day += GetMonthDay(tmp._year, tmp._month);
	}
	return tmp;
}
  • -复用-=
//d1 - 100
Date Date::operator-(int day)
{
	Date tmp = *this;
	tmp -= day;
	return tmp;
}

3.3 两种复用对比image.png

  1. -复用-=(相对较好)
//d1 -= 100
Date Date::operator-(int day)
{
	Date tmp = *this;//拷贝1
	tmp -= day;
	return tmp;//拷贝2
}

Date& Date::operator-=(int day)//无拷贝
{
	_day -= day;
	while (_day <= 0)//判断出非法日期
	{
		--_month;//先借月
		if (_month == 0)
		{
			_month = 12;
			--_year;
		}
		_day += GetMonthDay(_year, _month);//加上借来的
	}
	return *this;
}
  1. -=复用-
Date Date::operator-(int day)
{
	Date tmp = *this;//拷贝1
	tmp._day -= day;
	while (tmp._day<=0)
	{
		--tmp._month;
		if (tmp._month == 0)
		{
			tmp._month = 12;
			--tmp._year;
		}
		tmp._day += GetMonthDay(tmp._year, tmp._month);
	}
	return tmp;//拷贝2
}

Date& Date::operator-=(int day)//一次赋值拷贝
{
	/*Date tmp = *this - day;
	*this = tmp;*/

	*this = *this - day;//赋值也是一种拷贝

	return *this;
}
// 拷贝的次数比第一种多
  • 两种operator-的拷贝次数一样;
  • 第一种的-=是自己实现的,全程无拷贝;但是第二种-=复用-:前面-的两次拷贝再加上自己本身的一次赋值拷贝。因此第一种相对较好。

四、日期比较

4.1 operator<

//d1 < d2
bool Date::operator<(const Date& d)
{
	//true为一类
	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;
			}
		}
	}
	//false为一类
	return false;
}

4.2 operator==

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

4.3 其他关系比较

在写了operator<(或者operator>)和operator=两个之后,就可以根据去翻等个侯总逻辑关系表示出其他的关系符。

//d1 <= d2
bool Date::operator<=(const Date& d)
{
	//在写了前面两个之后:
	return *this < d || *this == d;
}

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

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

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

五、++

  • 前置++用的比较多,而且拷贝比较少。
  • 重载++运算符时,有前置++和后置++,运算符重载函数名都是``operator++,无法很好的区分。C++规定,后置++重载时,增加一个int`形参,跟前置++构成函数重载,方便区分。

5.1 前置++

//1.前置++:d1.operator++()
Date Date::operator++()//没有拷贝
{
	//Date tmp = *this;
	*this += 1;
	return *this;//使用引用返回
}

5.2 后置++

//2.后置++:d1.operator++(0)(括号里面只要求整数)
Date& Date::operator++(int)//有拷贝
{
	Date tmp = *this;
	*this += 1;
	return tmp;
}

六、-- (和++相似)

6.1 前置–

//1.前置--
Date& Date::operator--()
{
	//Date tmp = *this;
	*this -= 1;
	return *this;
}

6.2 后置–

//2.后置--
Date Date::operator--(int)
{
	Date tmp = *this;
	*this -= 1;
	return tmp;
}

八、所有代码

Date.h

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
 
class Date
{
public:
	// 获取某年某月的天数
	int GetMonthDay(int year, int month) const
	{
		assert(month > 0 && month < 13);
		// 因为该函数会经常调用,但是数组的值一直是不需要变化的,因此可以使用静态数组
		// 好处是在静态区只会创建一份变量
		static int GetMonthDayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if ((month == 2) && ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)))
			return 29;
		return GetMonthDayArray[month];
	}
	// 构造函数
	Date(int year, int month, int day);
	// 拷贝构造函数
	// d2(d1)
	Date(const Date& d);
	// 赋值运算符重载
	// d2 = d3 -> d2.operator=(&d2, d3)
		// >运算符重载
	bool operator>(const Date& d) const;
	// ==运算符重载
	bool operator==(const Date& d) const;
	// >=运算符重载
	bool operator >= (const Date& d) const;
	// <运算符重载
	bool operator < (const Date& d) const;
	// <=运算符重载
	bool operator <= (const Date& d) const;
	// !=运算符重载
	bool operator != (const Date& d) const;
 
	// 操作赋值操作符
	Date& operator=(const Date& d);
	// 日期+=天数
	Date& operator+=(int day);
	// 日期+天数
	Date operator+(int day) const;
	// 日期-天数
	Date operator-(int day) const;
	// 日期-=天数
	Date& operator-=(int day);
	// 前置++
	Date& operator++();
	// 后置++
	Date operator++(int);
	// 后置--
	Date operator--(int);
	// 前置--
	Date& operator--();
 
	// 日期-日期 返回天数
	int operator-(const Date& d) const;
private:
	int _year;
	int _month;
	int _day;
};

Date.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include "Date.h"
 
 
// 构造函数
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}
// 拷贝构造函数
// d2(d1)
Date::Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}
// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& Date::operator=(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
 
	return *this;
}
 
// >运算符重载
bool Date::operator>(const Date& d) const
{
	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==(const Date& d) const
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}
// >=运算符重载
bool Date::operator >= (const Date& d) const
{
	return *this > d || *this == d;
}
// <运算符重载
bool Date::operator < (const Date& d) const
{
	return !(*this >= d);
}
// <=运算符重载
bool Date::operator <= (const Date& d) const
{
	return !(*this > d);
}
// !=运算符重载
bool Date::operator != (const Date& d) const
{
	return !(*this == d);
}
 
 
// 日期+=天数
Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		++_month;
		if (_month == 13)
		{
			++_year;
			_month = 1;
		}
	}
	return *this;
}
// 日期+天数 ---使用前面实现的+=运算符重载实现
//Date Date::operator+(int day) const
//{
//	Date temp(*this);
//	temp += day;
//	return temp;
//}
 
// 日期+天数 ---直接实现
Date Date::operator+(int day) const
{
	Date temp(*this);
	temp._day += day;
	while (temp._day > GetMonthDay(_year, _month))
	{
		temp._day -= GetMonthDay(temp._year, temp._month);
		++temp._month;
		if (temp._month == 13)
		{
			++temp._year;
			temp._month = 1;
		}
	}
	return temp;
}
// 日期-=天数
Date& Date::operator-=(int day)
{
	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}
// 日期-天数 ---使用前面-=运算符重载实现
Date Date::operator-(int day) const
{
	//Date temp(*this);
	Date temp(*this);
	temp -= day;
 
	return temp;
}
 
 //日期-天数 ---直接实现
//Date Date::operator-(int day) const
//{
//	//Date temp(*this);
//	Date temp(*this);
//	temp._day -= day;
//	while (temp._day <= 0)
//	{
//		--temp._month;
//		if (temp._month == 0)
//		{
//			--temp._year;
//			temp._month = 12;
//		}
//		temp._day += GetMonthDay(temp._year, temp._month);
//	}
//	return temp;
//}
 
// 前置++
Date& Date::operator++()
{
	*this += 1;
	return *this;
}
// 后置++
Date Date::operator++(int)
{
	Date temp(*this);
	*this += 1;
	return temp;
}
// 后置--
Date Date::operator--(int)
{
	Date temp(*this);
	*this -= 1;
	return temp;
}
// 前置--
Date& Date::operator--()
{
	*this -= 1;
	return *this;
}
 
 
// 日期-日期 返回天数
int Date::operator-(const Date& d) const
{
	int flag = 1;
	Date max = *this;
	Date min = d;
	if (*this < d)
	{
		flag = -1;
		max = d;
		min = *this;
	}
	int n = 0;
	while (min != max)
	{
		min++;
		n++;
	}
	return n * flag;
}

喜欢的uu记得三连支持一下哦!
下雨.gif

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

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

相关文章

vercel免费在线部署TodoList网页应用

参考&#xff1a; TodoList网页应用&#xff1a;https://blog.csdn.net/weixin_42357472/article/details/140909096 1、项目首先上传github 直接vscode自带的上传项目&#xff0c;commit后在创建项目上传即可 2、vercel部署项目 1&#xff09;先注册 2&#xff09;impor…

基于PHP评论区的存储型XSS漏洞

评论区的XSS漏洞是指攻击者在评论区输入恶意脚本&#xff0c;当其他用户浏览该页面时&#xff0c;这些恶意脚本会被执行&#xff0c;从而造成安全威胁。这种漏洞通常出现在网站没有对用户输入进行充分过滤和转义的情况下&#xff0c;为存储型XSS。存储型XSS攻击是指攻击者在目标…

【MCAL】TC397+EB-tresos之SPI配置实战 - (同步/异步)

本篇文章首先从理论讲起&#xff0c;从AUTOSAR规范以及MCAL手册两个不同角度&#xff08;前者偏理论&#xff0c;后者偏实践&#xff09;介绍了SPI模块的背景概念与理论&#xff0c;帮助读者在实际配置之前能有个理论的框架。然后详细的介绍了在TC397平台使用EB tresos对SPI驱动…

数智化粮仓综合监控管理系统设计方案WORD-2023

关注智慧方案文库&#xff0c;学习9000多份智慧城市智慧医院&#xff0c;智慧水利&#xff0c;智能制造&#xff0c;数字化转型&#xff0c;智慧工厂&#xff0c;智慧矿山&#xff0c;智慧交通&#xff0c;智慧粮仓&#xff0c;工业互联网&#xff0c;数字孪生......持续更新热…

SpringCloud Alibaba】(十三)学习 RocketMQ 消息队列

目录 1、MQ 使用场景与选型对比1.1、MQ 的使用场景1.2、引入 MQ 后的注意事项1.3、MQ 选型对比 2、下载、安装 RocketMQ 及 RocketMQ 控制台2.1、下载安装 RocketMQ2.2、测试 RocketMQ 环境2.3、RocketMQ 控制台【图形化管理控制台】2.3.1、下载、安装2.3.2、验证 RocketMQ 控制…

【困难】 猿人学web第一届 第14题 备而后动-勿使有变

调试干扰 进入题目 打开开发者工具会进入一个无限 debugger; 向上查看堆栈&#xff0c;可以找到生成 debugger 的代码段 手动解混淆后可以知道 debugger 生成的方式 (function () {// 函数内的代码是不需要的&#xff0c;因为里面的代码不会执行 }[constructor](debugger)[call…

Java并发编程面试必备:如何创建线程池、线程池拒绝策略

一、线程池 1. 线程池使用 1.1 如何配置线程池大小 如何配置线程池大小要看业务系统执行的任务更多的是计算密集型任务&#xff0c;还是I/O密集型任务。大家可以从这两个方面来回答面试官。 &#xff08;1&#xff09;如果是计算密集型任务&#xff0c;通常情况下&#xff…

模型 ACT心理灵活六边形

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。接纳现实&#xff0c;灵活行动&#xff0c;追求价值。 1 ACT心理灵活六边形的应用 1.1 应对工作压力 背景&#xff1a; 在高压的工作环境中&#xff0c;员工经常面临巨大的工作压力&#xff0c;这可…

在VScode中使用Git将本地已有文件夹提交到Github仓库以便于使用版本控制进行项目开发

前置软件 VScode、Git。 Linux系统中安装Git工具请自行百度。可以通过git --version查看对应Git版本号。 Github创建空白仓库 一定要注意创建空白仓库&#xff0c;不要包含任何文件&#xff0c;包括Readme.md文件也不能有。 上面的仓库名&#xff08;Repository name&#xff…

Kaggle克隆github项目+文件操作+Kaggle常见操作问题解决方案——一文搞定,以openpose姿态估计项目为例

文章目录 前言一、Kaggle克隆仓库1、克隆项目2、查看目录 二、安装依赖三、文件的上传、复制、转移操作1.上传.pth文件到input目录2、将权重文件从input目录转移到工作目录 三、修改工作目录里的文件内容1、修改demo_camera.py内容 四、运行&#xff01; 前言 想跑一些深度学习…

【网络安全】条件竞争绕过电子邮件验证

未经许可,不得转载。 文章目录 正文正文 目标:xxx.com 使用电子邮件注册该网站并登录。接着,进入帐户设置,进入更改电子邮件功能: 请求包如下: 接着,发送两个相同的请求包到repeater,第一个中添加攻击者邮件: 第二个中添加正常的邮件: 创建组,以便能够同时发送两个…

手把手教你如果安装激活CleanMyMac X 4.15.6中文破解版

CleanMyMac X 4.15.6中文破解版可以为Mac腾出空间&#xff0c;软件已经更新到CleanMyMac X 4.15.6中文版支持最新版Macos 10.14系统。CleanMyMac X 4.15.6中文破解版具有一系列巧妙的新功能&#xff0c;可让您安全&#xff0c;智能地扫描和清理整个系统&#xff0c;删除大量未使…

NeRF: Representing Scenes asNeural Radiance Fields for View Synthesis 论文解读

目录 一、导言 二、NeRF 1、渲染和反渲染 2、NeRF的基本原理 3、采样点 4、位置编码 5、NeRF网络结构 6、体渲染 三、分层采样 1、均匀采样 2、基于σ的采样 四、损失函数 一、导言 该论文来自于ECCV2020&#xff0c;主要提到一种NeRF的方法来合成复杂场景下的新视…

创建 AD9361 的 vivado 工程,纯FPGA配置,不使用ARM程序

前言 AD9361 的配置程序&#xff0c;如果使用官方的&#xff0c;就必须用ps进行配置&#xff0c;复杂不好使&#xff0c;如果直接使用FPGA配置&#xff0c;将会特别的简单。 配置软件 创建一份完整的寄存器配置表 //*******************************************************…

续:docker 仓库数据传输加密

上一个实验&#xff1a;非加密的形式在企业中是不被允许的。 示例&#xff1a;【为Registry 提供加密传输】 因为传输也是https&#xff0c;所以与ssh一样的加密。 ## 这种方式就不用写这个了。 [rootdocker ~]# cat /etc/docker/daemon.json #{ # "insecure-registrie…

GoodSync Business - 企业级服务器同步与备份工具

现在越来越多公司会搭建服务器&#xff0c;或自建文件共享中心。那么如何才能实现对这些终端的高效管理、安全备份&#xff0c;以保障企业数据的安全呢&#xff1f; GoodSync Business 就是一款企业服务器同步与备份工具&#xff0c;适用于 Win / Mac 工作站&#xff0c;以及 …

C语言程序设计

日落有个小商店&#xff0c;贩卖着橘黄色的温柔。 7.关系操作符 > > < < ! (用于测试“不相等”) &#xff08;用于测试“相等”&#xff0c;但是不是所有的对象都可以用该符号来比较相不相等&#xff09; eg. int main ( ) { if ("abc"&q…

【AI大模型】基于docker部署向量数据库Milvus和可视化工具Attu详解步骤

&#x1f680; 作者 &#xff1a;“大数据小禅” &#x1f680; 文章简介 &#xff1a;本专栏后续将持续更新大模型相关文章&#xff0c;从开发到微调到应用&#xff0c;需要下载好的模型包可私。 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 目…

【王树森】Few-Shot Learning (2/3): Siamese Network 孪生网络(个人向笔记)

Learning Pairwise Similarity Scores Training Data 训练集有很多个类别的图片&#xff0c;每个类别的图片都有标注 Positive Sample&#xff1a;我们需要正样本来告诉神经网路什么东西是同一类 Negative Sample&#xff1a;负样本可以告诉神经网路事物之间的区别 我们用…

【笔记】数据结构04

文章目录 稀疏矩阵压缩存储三元组表示稀疏矩阵转三元组 栈的应用前缀表达式前缀表达式求值 中缀表达式后缀表达式 稀疏矩阵内容参考 强连通文章 稀疏矩阵压缩存储三元组表示 将非零元素所在的行、列以及它的值构成一个三元组&#xff08;i,j,v&#xff09;&#xff0c;然后再…