【C++】日期计算机

个人主页:救赎小恶魔

欢迎大家来到小恶魔频道

好久不见,甚是想念

今天我们要讲述的是一个日期类计算机的代码实现

引言:

我们日常生活中可能会有一个烦恼。

今天几月几号?过n天后又是几月几号?某年某月某天和x年x月x天相差几天?你和男/女朋友的相识了几天?等等。这些问题好麻烦,我不想去算,所以我们的日期计算机也就油然而生了。

头文件的准备

头文件的声明代码:

#pragma once
#include<iostream>
#inclu<assert.h>
using namespace std;
class Date
{
public:
	// 获取某年某月的天数
	int GetMonthDay(int year, int month)
	{
		static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31,30,31 };
		int day = days[month];
		if (month == 2 &&
			(year & 4 == 0 && year % 100 != 0) || (year % 400 == 0))
		{
			day += 1;
		}
		return day;
	}
	//打印函数
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1);
	// 拷贝构造函数
  // d2(d1)
	Date(const Date& d);
	// 赋值运算符重载
  // d2 = d3 -> d2.operator=(&d2, d3)
	Date& operator=(const Date& d);
	// 析构函数
	~Date();
	// 日期+=天数
	Date& operator+=(int day);
	// 日期+天数
	Date operator+(int day);
	// 日期-天数
	Date operator-(int day);
	// 日期-=天数
	Date& operator-=(int day);
	// 前置++
	Date& operator++();
	// 后置++
	Date operator++(int);
	// 后置--
	Date operator--(int);
	// 前置--
	Date& operator--();
	// >运算符重载
	bool operator>(const Date& d);
	// ==运算符重载
	bool operator==(const Date& d);
	// >=运算符重载
	bool operator >= (const Date& d);
	// <运算符重载
	bool operator < (const Date& d);
	// <=运算符重载
	bool operator <= (const Date& d);
	// !=运算符重载
	bool operator != (const Date& d);
	// 日期-日期 返回天数
	int operator-(const Date& d);
private:
	int _year;
	int _month;
	int _day;
};

函数代码的实现

1.某年某月天数的获取

第一个函数,我们定义在了头文件中

// 获取某年某月的天数
int GetMonthDay(int year, int month)
{
	assert(month > 0 && month < 13);
	static int DayA[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31,30,31 };
	int day = DayA[month];
	if (month == 2 &&
		(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		day += 1;
	}
	return day;
}

这里我们直接建立一个数组,存储的是每月的天数。

第一个我们存储为0,毕竟第一个月我们没有经历满。

这里的数组我们前边加上了static,使其成为了全局变量。这里设置为全局变量是为了方便后边的使用/调用。

不要忽略了这里闰年的判定,最后返回我们的天数

2.全缺省的构造函数

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

这个函数就比较简单了,就是赋值。

值得注意的是:这里是源文件,我们在头文件声明是已经使用了缺省参数,所以在源文件中就不需要使用了。

3.拷贝构造函数

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

这个函数也比较简单,我们这里利用了this指针,所以传参只需要传递一个就可以了。也不过多讲解了。

4.七个运算符的重载

首先是==的重载

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

然后再写一个 < 的重载

bool Date::operator<(const 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<=(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);
}

赋值运算符重载

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

这个我们在之前也讲解过,就不过多叙述了

5.四个日期计算函数

第一个:月份日期增加天数

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;
}

 首先先获取天数

如果天数大于月份的天数,我们就减去当前月份的天数,然后让月份加一。如果月份大于13了,我们就让年去加一。

写完+=,那么+就会好写很多

Date Date::operator+(int day)
{
	Date ret = *this;
	ret += day;
	return  ret;
}

这里我们也用到了+=的重载。

但这两个都是用来加天数的,两者有什么不同呢?

首先呢,第一个重载的是运算符+=的重载,他们的本质是在原有的基础上进行改变,改变了*this指针的值

举个例子

int main()
{
	Date d1(2024, 4, 24);
	d1 += 3;//这里的d1应该是2024/4/27
	d1.Print();
	return 0;
}

利用+=我们改变了d1原本的数值

再看一看+

 虽然d1加了3,但是并没有改变d1原本的数值

总结:

  • Date& Date::operator+=(int day)  他的返回类型是Date的引用们可以进行链式操作,调用+=,是在原有的基础上进行增加天数,会改变原有变量的数值。
  • Date Date::operator+(int day) 他的返回类型是一个新的Date,需要去利用变量去接受。调用+,返还的对象实在原有的基础上进行增加得到结果,不会改变原有变量的数值

那么问题又来了?

我这里显示写出+=,然后再+中去调用+=。

那么如果我们先写出+后,再重在+=中去调用+会怎么样呢???

这里就直接说结论了 

不论是先写+=再写+,还是先写+再写+=,结果都是一样的,但是唯一不同的就是代码的书写量以及效率的高低。在这里我比较推荐我的写法,先写+=,再写+会提高一定的效率。

 写完+有关的,我们开始写-有关的

接下来是月份日期的减少

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)
{
	Date tmp = *this;
	tmp -= day;

	return tmp;
}

6.前置/后置的加加减减

这里需要注意的是,为了区分时前置和后置的区别,我们在传参时需要加入一个int

加入int参数的就是后置++

这里代码如下:

Date& Date::operator++()
{
	_day += 1;
	return *this;
}
Date Date::operator++(int)
{
	Date tmp(*this);
	_day += 1;
	return tmp;
}
Date& Date::operator--()
{
	_day -= 1;
	return *this;
}
Date Date::operator--(int)
{
	Date tmp(*this);
	_day -= 1;
	return tmp;
}

既然是加加就是day加一,这样的话我们也利用前边思路想法,前置我们利用引用去写,而后置我们不用引用,利用前边的运算符重载去写

7.计算两个日期之间的天数值

int Date::operator-(const Date& d)
{
	int flag = 1;
	Date max = *this;
	Date min = d;

	if (*this < d)
	{
		int flag = -1;
		max = d;
		min = *this;
	}

	int n = 0;
	while (min != max)
	{
		++min;
		++n;
	}

	return n * flag;
}

这个函数的逻辑也利用了假设法,其思路则是确定好大的日期后,让小的日期不断增加然后直至与大的日期相同。

讲解:

  • 第一个点是确确定日期的大小。我们让max确保成为大日期min确保成为小日期,这里就利用了假设法,设置完后,利用if语句,确保我们的判断是正确的,如果不正确就进行反转并让flag成为-1。
  • 第二个点就是计算两者之间差值的天数。我们通过循环,每次都让min不断增加,同时也见建立一个变量n,让它随着min增加,从而记录下两者之间的差值天数,最后n就是两者之间的差值。
  • 第三个点就是返回值。我们这里的返回值最后需要乘上flag,其原因是,我们一开始我们让this指针为大日期,如果不对的话,就说明this指针的日期小,所以两者之间差值就是负的

OK,看到这里,我们本节内容就彻底结束。

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

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

相关文章

PE文件的导入表,动态链接库中的函数应该如何导入

导入地址表IAT IAT保存的内容与windos操作系统的核心进程、内存、DLL结构有关。IAT是一种表格&#xff0c;用来记录程序正在使用哪些库中的哪些函数。 动态链接库(DLL) 常见的kernel.dll就是一个非常重要的动态链接库&#xff0c;其中包含了运行程序时需要使用到的函数&…

文件操作(1)

为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久化的…

再谈C语言——理解指针(四)

assert断⾔ assert.h 头⽂件定义了宏 assert() &#xff0c;⽤于在运⾏时确保程序符合指定条件&#xff0c;如果不符合&#xff0c;就报错终⽌运⾏。这个宏常常被称为“断⾔”。 assert(p ! NULL); 上⾯代码在程序运⾏到这⼀⾏语句时&#xff0c;验证变量 p 是否等于 NULL 。…

JavaScript 数学对象 Math

Math对象其实就是数学对象&#xff0c;它给我们提供了各种各样的数学功能。 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>首页</title> </head><body><script type"text/javascript"&g…

linux的“>”和“>>”

在Linux中&#xff0c;>和>>都是用于文件重定向的操作符&#xff0c;它们用于将命令的输出发送到文件中。 > 用于创建一个新文件或覆盖现有文件的内容。当你执行一个如 command > file.txt 的命令时&#xff0c;如果 file.txt 文件存在&#xff0c;它的内容将被…

【uniapp】引入uni-ui组件库

&#xff08;1&#xff09;新建项目的时候选择 uni-ui项目 &#xff08;2&#xff09;已经创建好的项目去官网单独安装 跳转单独安装组件 https://uniapp.dcloud.net.cn/component/uniui/quickstart.html#%E9%80%9A%E8%BF%87-uni-modules-%E5%8D%95%E7%8B%AC%E5%AE%89%E8%A3%8…

YOLOv9训练损失、精度、mAP绘图功能 | 支持多结果对比,多结果绘在一个图片(消融实验、科研必备)

一、本文介绍 本文给大家带来的是YOLOv9系列的绘图功能&#xff0c;我将向大家介绍YOLO系列的绘图功能。我们在进行实验时&#xff0c;经常需要比较多个结果&#xff0c;针对这一问题&#xff0c;我写了点代码来解决这个问题&#xff0c;它可以根据训练结果绘制损失(loss)和mA…

VBA技术资料MF144:将PDF首页作为对象插入工作表

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

【C++】如何用C++写一个日期计算器

目录 前言 代码的布局 设计数据 方法声明 方法的实现 获取某年某月的天数 *全缺省的构造函数 * 拷贝构造函数 *赋值运算符重载 *析构函数 日期天数 日期天数 日期-天数 日期-天数 前置 后置 后置-- 前置-- 实现比较大小运算符重载思路 >运算符重载 运算…

盲人餐厅点餐:科技之光照亮餐桌上的美食之旅

在现代社会&#xff0c;餐厅不仅是满足口腹之欲的场所&#xff0c;更是一个社交、放松的重要空间。然而&#xff0c;对于视障人士而言&#xff0c;盲人餐厅点餐这一日常行为&#xff0c;却往往伴随着诸多不便与挑战。幸运的是&#xff0c;科技的革新正为这一群体带来前所未有的…

递归神经网络(RNN)在AI去衣技术中的深度应用

在人工智能&#xff08;AI&#xff09;技术飞速发展的今天&#xff0c;图像处理和计算机视觉领域不断取得新的突破。其中&#xff0c;AI去衣技术作为一个具有挑战性的研究方向&#xff0c;引起了广大研究者和公众的关注。递归神经网络&#xff08;RNN&#xff09;作为深度学习的…

【linux】编译器使用

目录 1. gcc &#xff0c;g 编译器使用 a. 有关gcc的指令&#xff08;g同理&#xff09; 2. .o 文件和库的链接方式 a. 链接方式 b. 动态库 和 静态库 优缺点对比 c. debug 版本 和 release 版本 1. gcc &#xff0c;g 编译器使用 a. 有关gcc的指令&#xff08;g同理&…

【第19章】spring-i8n

文章目录 前言一、准备二、Java国际化1.测试类2.测试结果 三、Spring国际化1.配置文件2.测试类3.测试结果4.占位符4.1 准备4.2 测试类4.3 测试结果 总结 前言 在Spring中实现国际化Internationalization&#xff08;i18n&#xff09;其实就是完成语言的切换&#xff0c;类似于…

4.SpringCloud基础项目搭建利用RestTemplate实现远程调用

简单的微服务架构 父pom.xml <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apa…

短信视频提取批量工具,免COOKIE,博主视频下载抓取,爬虫

痛点&#xff1a;关于看了好多市面的软件&#xff0c;必须要先登录自己的Dy号才能 然后找到自己的COOKIE 放入软件才可以继续搜索&#xff0c;并且无法避免长时间使用 会导致无法正常显示页面的问题。 有没有一种方法 直接可以使用软件&#xff0c;不用设置的COOKIE的方法呢 …

Linux驱动开发:掌握SPI通信机制

目录标题 1、SPI简介2、SPI通信机制3、Linux内核中的SPI支持4、SPI核心API5、SPI控制器驱动6、SPI设备驱动 7、编写SPI设备驱动8、调试SPI驱动 在Linux驱动开发中&#xff0c;串行外设接口(SPI)是一种常见的高速全双工通信协议&#xff0c;用于连接处理器和各种外设。本文将深入…

会声会影滤镜怎么用 会声会影滤镜效果怎么调 会声会影视频制作教程

在进行视频剪辑时&#xff0c;合理地运用滤镜效果可以提升视频的观赏性&#xff0c;使你的作品更加出彩。这篇文章便一起来学习会声会影滤镜怎么用&#xff0c;会声会影滤镜效果怎么调。 一、会声会影滤镜怎么用 使用会声会影的滤镜效果非常简单&#xff0c;以下是具体的操作…

Rust腐蚀服务器定制地图开服

Rust腐蚀服务器定制地图开服 大家好我是艾西一个做服务器租用的网络架构师。Rust腐蚀这个游戏有很多的插件mod作者&#xff0c;在地图制作这一块也是一样&#xff0c;有些好玩的地图可能大家在map网站找到了但是不知道怎么操作设置那么今天艾西给大家说下特定定制地图怎么弄。…

Penpad获Gate Labs以及Scroll联创Sandy的投资

近期&#xff0c;Scroll上的LaunchPad &聚合收益平台Penpad迎来了重磅利好&#xff0c;该平台在前不久获得了来自于Gate Las的融资&#xff0c;在此后其又获得了Scroll联合创始人Sandy的融资&#xff0c;这也让Penpad平台成为了近期Scroll生态中最值得关注的项目之一。 事实…

《生成式AI导论》学习笔记

1.课程定位 2.什么是生成式人工智慧&#xff1f; 3. 今日的生成式人工智慧厉害在哪里&#xff1f; 4.训练不了人工智慧&#xff1f;那我训练自己 5.训练不了人工智慧&#xff1f;你可以训练你自己&#xff08;中&#xff09;——拆解问题使用工具 6.大语言模型修炼史——第一阶…