【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/27d1.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.mzph.cn/bicheng/2770.shtml

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

相关文章

MySQL你想知道序列当前生成的值,你可以使用SHOW TABLE STATUS命令或者查询information_schema数据库

在MySQL中&#xff0c;如果你想知道序列当前生成的值&#xff08;例如&#xff0c;自增主键的当前值&#xff09;&#xff0c;你可以使用SHOW TABLE STATUS命令或者查询information_schema数据库。 使用SHOW TABLE STATUS命令&#xff1a; 这个命令可以显示关于表的各种信息&…

比特币中的符文是什么?

比特币中的符文是什么&#xff1f; 比特币符文是存在于比特币区块链上的独特的、可替代的代币。它们旨在代表具有独特特征和元数据的可替代资产。 Ordinals 协议的创建者 Casey Rodamor 最近放弃了一项替代 BRC-20 可替代代币协议的提案&#xff0c;该替代方案被称为 Runes。 破…

【k8s】Kubernetes 1.29.4离线安装部署(总)

&#xff08;一&#xff09;kubernetes1.29.4离线部署之-安装文件准备 &#xff08;二&#xff09;kubernetes1.29.4离线部署之-镜像文件准备 &#xff08;三&#xff09;kubernetes1.29.4离线部署之-环境初始化 &#xff08;四&#xff09;kubernetes1.29.4离线部署之-组件安装…

掌握Linux Shell脚本函数:提高脚本效率与可维护性

目录标题 1、什么是Shell函数&#xff1f;2、如何定义Shell函数&#xff1f;3、Shell函数参数4、返回值5、实例&#xff1a;使用函数进行文件备份6、为什么使用函数&#xff1f;7、最佳实践 在编写Linux shell脚本时&#xff0c;函数是组织和重用代码的重要手段。本文将介绍如何…

Python实现定时任务的八种方式

在实际的软件开发过程中,经常需要执行定时任务,比如定时备份数据、定时发送邮件、定时清理缓存等。Python作为一种功能强大的编程语言,提供了多种方式来实现定时任务。本文将介绍Python实现定时任务的八种常用方法,并提供相应的代码示例。 1. 使用​​time.sleep()​​函数…

rt1052 模拟hard fault

uint32_t u32Addr ((uint32_t)0x5FFFFFFF); //定义一个单片机不存在的地址 uint32_t u32StackTop *((__IO uint32_t *)u32Addr); //读取这个不存在的地址 //会进入 void HardFault_Handler(void) 中断

现货白银价格走势分析别走弯路!

参与现货白银投资离不开对其价格走势的分析&#xff0c;虽然相关的分析方法有很多种&#xff0c;但说到直观高效的方法&#xff0c;技术分析就是很多专业投资者所钟爱的选择。投资者可以通过平台交易软件所自带的技术指标和画线工具&#xff0c;来辅助自己的分析&#xff0c;实…

移动端js事件、zeptojs、swiper、bootstrap、正则表达式、前端性能优化

移动端场景下的js事件&#xff0c;制作移动端特效常用的js库&#xff0c;介绍移动端常用开发框架Bootstrap 一、移动端js事件 移动端的操作方式和PC端是不同的&#xff0c;移动端主要用手指操作&#xff0c;所以有特殊的touch事件&#xff0c;touch事件包括如下几个事件&…

前缀和 求数列的子序列的K倍区间

(直接截图比复制文字要好多了) 不会做的时候我去看了之前做的关于这道题目的笔记&#xff0c; &#xff08;Ak 1&#xff09;% k 1 &#xff08;Ak 1 Ak&#xff09;% k 1 只要发现了同余数的情况就说明有一个区间满足了题目的要求。 这个方法的精妙之处就在于前缀和包括了…

嵌入式Linux driver开发实操(二十一):linux device driver basic设备驱动程序基础

linux的架构框图: 内核空间是内核(即操作系统的核心)执行(即运行)并提供其服务的地方。 用户空间是执行用户应用程序的地方。 内核模块是可以根据需要加载和卸载到内核中的代码片段。它们扩展了内核的功能,而无需重新启动系统。自定义代码可以通过两种方法添加到Linux内…

C++ —— 继承

什么是继承&#xff1f; 继承是指一种代码可以被复用的机制&#xff0c;在一个类的基础上进行扩展&#xff0c;产生的新类叫做派生类&#xff0c;被继承的类叫基类。&#xff08;也可称为子类和父类&#xff09; 继承的写法&#xff1a; class B : 继承方式 A (…

Java高级阶段面试题库(Redis数据库、MQ消息队列、kafka、SpringBoot + SpringCloud、MySQL、JVMJUC、其它)

文章目录 1. Redis数据库篇(忽略)1.1 简单介绍一下redis1.2 单线程的redis为什么读写速度快?1.3 redis为什么是单线程的?1.4 redis服务器的的内存是多大?1.5 为什么Redis的操作是原子性的&#xff0c;怎么保证原子性的&#xff1f;1.6 你还用过其他的缓存吗&#xff1f;这些…

学习Django

1.python安装是会有几个主要目录&#xff1a; 2.如果某个路径加入了环境变量&#xff0c;那么在命令行直接输入他下面的文件就能找到&#xff0c;不用输入完整路径 2.过程 &#xff08;1&#xff09;安装 &#xff08;2&#xff09;建项目 在终端&#xff1a; &#xff08;…

快速回复app是什么样

在电商领域&#xff0c;掌握一些必备的软件工具是提高工作效率、优化运营流程以及提升用户体验的关键。本文将为您介绍做电商必备的几个软件&#xff0c;帮助您更好地开展电商业务。 ​ 快速回复APP&#xff1a;重新定义沟通效率 在快节奏的现代社会中&#xff0c;人们对于沟通…

ZeRO论文阅读

一.前情提要 1.本文理论为主&#xff0c;并且仅为个人理解&#xff0c;能力一般&#xff0c;不喜勿喷 2.本文理论知识较为成体系 3.如有需要&#xff0c;以下是原文&#xff0c;更为完备 Zero 论文精读【论文精读】_哔哩哔哩_bilibili 二.正文 1.前言 ①为什么用该技术&…

性能测试工具一——gprof(采样测试与插桩测试结合的混合测试)

gprof只适用于Linux平台&#xff0c;不支持MacOS和Windows。 使用前提&#xff1a;在编译指令中加入-pg即可。也可添加其它编译选项&#xff0c;但-pg是核心&#xff0c;-Og -g -pg或-D NDEBUG -Og -g -pg。 例如在Makefile中g -Og -g -pg。或在CMakeLists.txt中set(CMAKE_CX…

Linux网络设置

将Linux主机接入到网络&#xff0c;需要配置网络相关设置 一般包括&#xff1a;主机名&#xff1b;IP/netmask&#xff1b;路由&#xff1a;默认网关&#xff1b;DNS服务器&#xff1a;主DNS服务器&#xff0c;次DNS服务器&#xff0c;第三个DNS服务器 网卡的配置文件在&…

java:观察者模式

java&#xff1a;观察者模式 1 前言 观察者模式&#xff0c;又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;他定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时&#xff0c;会通知所…

C语言-atoi函数的使用和实现

atoi是C语言中常见的函数。大家可能对于他不太熟悉&#xff0c;其主要还是因为学校可能没有讲到。其实有很多函数像atol、atof都是一样的&#xff0c;本篇文章以atoi为例&#xff0c;剩余大家如果感兴趣可以再去了解。 目录 1.函数介绍 2.代码演示 3.atoi函数的模拟实现 4…

【Pyhton爬虫实战】爬取京东商城的商品信息

爬取京东商城的商品信息&#xff0c;并将数据以Dataframe形式展示 from selenium.webdriver import Chrome, ChromeOptions import re import pymysql from selenium.webdriver.common.by import By import collections import pandas as pdclass Spider():def __init__(self)…