【C++】日期计算机

news2024/10/6 0:35:54

个人主页:救赎小恶魔

欢迎大家来到小恶魔频道

好久不见,甚是想念

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

引言:

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

今天几月几号?过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,看到这里,我们本节内容就彻底结束。

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

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

相关文章

Python读写文本URL蓝牙WIFI自动连接电子名片位置坐标智能海报等NDEF标签

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?id615391857885&spma1z10.5-c.w4002-21818769070.11.60ad789erlonvk 近场通信&#xff08;Near Field Communication&#xff0c;简称NFC&#xff09;&#xff0c;是一种新兴的技术&…

实验:使用apache + yum实现自制yum仓库

实验准备 Web服务器端&#xff1a;cenos-1&#xff08;IP&#xff1a;10.9.25.33&#xff09; 客户端&#xff1a;centos-2 保证两台机器网络畅通&#xff0c;原yum仓库可用&#xff0c;关闭防火墙和selinux Web服务器端 ①安装httpd并运行&#xff0c;设置开机自启动 安装…

【人工智能基础】人工神经网络

一、人工神经网络的三要素 人工神经元数理模型 MP模型是世界上第一个神经计算模型&#xff0c;为神经网络理论提供了基础 MP模型功能 对树突输入u的线性加权求和对净输入的非线性转换\ 作用函数的功能作用函数的功能 MP神经元模型的作用函数是单位阶跃函数。当x≥0时f(x)…

实现Node.js安装与配置。

一 、Node.js简介 Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;用于构建高性能、可扩展的网络应用程序。它发布于2009年5月&#xff0c;由Ryan Dahl开发&#xff0c;允许使用JavaScript进行服务器端编程&#xff0c;使开发者能够在前后端都使用同一种编程…

ASP.NET教务平台—学籍管理模块开发与设计

摘 要 教务平台之学籍管理模块是一个典型的教务信息管理系统(MIS)&#xff0c;其开发主要包括后台数据库的建立和前端应用程序的开发两个方面。对于后台数据库要求实现数据的完整性、一致性和安全性&#xff1b;对于前台应用程序开发则要求模块功能完备、界面友好、易使用等特…

进程状态和优先级(进程第2篇)【Linux复习篇】

目录 一、进程状态 1、进程有什么状态&#xff1f; 2、 Linux下的进程状态有什么&#xff1f; 二、进程优先级 1、进程优先级是什么&#xff1f; 2、为什么要有优先级 3、怎么改进程优先级&#xff1f;要改吗&#xff1f; 4、操作系统如何根据优先级开展调度的&#xff…

Spring MVC和Spring Boot

上节已经提到过请求&#xff0c;这次梳理响应。 响应 响应基本上都要被Controller所托管&#xff0c;告诉Spring帮我们管理这个代码&#xff0c;我们在后面需要访问时&#xff0c;才可以进行访问&#xff0c;否则将会报错。并且其是由RestController分离出来的&#xff0c;Re…

【MCU】栈溢出问题

项目场景&#xff1a; 硬件&#xff1a;STM32F407&#xff0c;操作系统&#xff1a;rt_thread master分支 问题描述 问题栈溢出 id 499 ide 00 rtr 00 len 8 9 Function[rt_completion_wait] shall not be used in ISR (0) assertion failed at function:rt_completion_wait,…

MATLAB实现蚁群算法栅格路径优化

蚁群算法是一种模拟自然界中蚂蚁觅食行为的优化算法&#xff0c;常用于解决路径规划问题。在栅格路径优化中&#xff0c;蚁群算法可以帮助找到从起点到终点的最优路径。以下是蚁群算法栅格路径优化的基本流程步骤&#xff1a; 初始化参数&#xff1a; (1)设置蚂蚁数量&#xff…

【错题集-编程题】数组中的最长连续子序列(排序 + 模拟)

牛客对应链接&#xff1a;数组中的最长连续子序列_牛客题霸_牛客网 (nowcoder.com) 一、分析题目 排序 模拟。 注意&#xff1a;值连续&#xff0c;位置可以不连续&#xff01;小心处理数字相同的情况。 二、代码 //值得学习的代码 class Solution { public:int MLS(vecto…

【数据库】Redis

文章目录 [toc]Redis终端操作进入Redis终端Redis服务测试切换仓库 String命令存储字符串普通存储设置存储过期时间批量存储 查询字符串查询单条批量查询 Key命令查询key查询所有根据key首字母查询判断key是否存在查询指定的key对应的value的类型 删除键值对 Hash命令存储hash查…

前端补充17(JS)

一、JS组成成分 JS的组成成分&#xff0c;由三部分组成 第一、ECMAScript&#xff1a;语法规则&#xff0c;如何定义变量&#xff0c;数据类型有哪些&#xff0c;如何转换数据类型&#xff0c;if判断 if-else while for for-in forEach do-while switch 数组 函数 对…

HTML表单(详解网页表单如何实现)

目录 一、表单介绍 1.概念 二、表单用法 1.HTML表单 2.HTML 表单 - 输入元素 2.1.文本域&#xff08;Text Fields&#xff09; 2.2.密码字段 2.3.单选按钮&#xff08;Radio Buttons&#xff09; 2.4.复选框&#xff08;Checkboxes&#xff09; 2.5.提交按钮(Submit)…

SAP 变更记录表查询使用逻辑简介

通常用户在遇到问题后&#xff0c;经常会问某个单据的变更记录&#xff0c;很多模块中在前台的操作界面中都根据对应的菜单栏中可以找到对应的变更记录&#xff0c;像销售订单、交货单、采购申请、采购订单都在菜单栏位中都可以查询到对应的修改记录&#xff0c;但是对于想批量…

“豪门”子刊!中科院2区SCI,收稿范围广,发文量超20000!无预警记录,极速录用见刊!

&#xff08;一&#xff09;期刊简介概况 【期刊类型】网络数据类SCIE 【出版社】SPRINGER出版社 【期刊概况】IF&#xff1a;4.0-5.0&#xff0c;JCR2区&#xff0c;中科院2区 【版面类型】正刊&#xff0c;仅10篇版面 【预警情况】2020-2024年无预警记录 【收录年份】2…

【项目】基于JDBC+MySQL的Java教务管理系统(附源码+论文说明)

摘要 随着信息技术的不断发展&#xff0c;教育管理也在向数字化、智能化方向迈进。Java作为一种广泛应用于企业级应用开发的编程语言&#xff0c;与数据库技术的结合更是为教务管理系统的开发提供了强大的支持。 本文将介绍基于JDBC&#xff08;Java Database Connectivity&a…

跨越未知,拥抱挑战——新征程

在浩瀚的IT领域里&#xff0c;每一位开发工程师都如同一位探险家&#xff0c;不断地探索、挑战和成长。作为一名新入职的Java开发工程师&#xff0c;我面临着全新的技术栈和业务领域&#xff0c;这是一次跨越未知的征程&#xff0c;也是一次自我提升的机会。 新入职 初入公司…

mac系统镜像源管理之nrm的安装与使用

之前有介绍过&#xff1a;pnpm安装和使用&#xff0c;nvm安装及使用&#xff0c;在前端开发中其实还有一个工具也会偶尔用到&#xff0c;那就是nrm&#xff0c;本文就详解介绍一下这个工具&#xff0c;非常的简单且好用&#xff5e; 文章目录 1、什么是nrm&#xff1f;2、安装3…

为什么说这些倒腾AI的方式会把自己“搞死”

在AI技术的浪潮下&#xff0c;许多基于大模型的产品涌现而出&#xff0c;但并非所有创新都能带来成功&#xff0c;有时大模型的出现还会放大AI创业公司的内部矛盾。这个时候&#xff0c;我们需要搭建与AI相配的底层思考框架。 为什么说这些倒腾AI的方式会把自己“搞死”© …

go语言并发实战——日志收集系统(五) 基于go-ini包读取日志收集服务的配置文件

实现日志收集服务的客户端 前言 从这篇文章开始我们就正式进入了日志收集系统的编写&#xff0c;后面几篇文章我们将学习到如何编写日志收集服务的客户端,话不多说,让我们进入今天的内容吧&#xff01; 需要实现的功能 我们要收集指定目录下的日志文件&#xff0c;将它们发…