C++入门——日期类的实现

前言

生活中,我们时不时会遇到算天数的问题:高考倒计时、考研倒计时、过年倒计时......

想解决这些问题无非就是实现一个年月日的计算器,那要怎么来实现呢?

下面就让我们来探究一下。

1.了解日期计算器的需求

1.1 表面需求

实现日期计算器无非有以下这些需求:

日期+天数得到新日期(原日期不变)

Date& operator+=(int day);

日期-天数得到新日期(原日期不变)

Date& operator-=(int day);

日期+天数,得到新日期(原日期改变)

Date operator+(int day);

日期-天数,得到新日期(原日期改变)

Date operator-(int day);

以及最常用的:两个日期相减,算天数

int operator-(const Date& d);

1.2 潜在需求

要想实现以上几个需求,我们还必须要存在判断两个日期是否相等的函数存在:

判断两个日期是否等于

bool operator==(const Date& x);

判断两个日期是否不等于

bool operator!=(const Date& x);

判断两个日期是否大于

bool operator>(const Date& x);

判断两个日期是否小于

bool operator<(const Date& x);

判断两个日期是否大于等于

bool operator>=(const Date& x);

判断两个日期是否小于等于

bool operator<=(const Date& x);

前置++ ,前置--

Date& operator++();
Date& operator--();

 后置++,后置--

Date operator++(int);
Date operator--(int);

以及一个最重要的接口函数:判断大小月、闰平月

int GetMonthDay(int year, int month);

2. 需求实现

构造函数实现

Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;if (_year < 1 || _month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month)){//assert(false);//如果日期输入错误,暴力中断程序Print();cout << "日期错误" << endl;//如果日期输入错误,温柔地警告日期错误}
}

打印函数实现

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

接口函数,判断大小月、润平月函数实现

int Date::GetMonthDay(int year, int month)
{assert(year >= 1 && month >= 1 && month <= 12);//检查日期是否合法//定义一个数组存储12个月int arrmonth[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//如果是闰年2月,返回29天if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)){return 29;}return arrmonth[month];
}

赋值运算符重载函数实现

判断两个日期是否等于、不等于、大于、小于、大于等于、小于等于

//赋值运算符重载函数实现
//d1==d2
bool Date::operator==(const Date& x)
{return _year == x._year && _month == x._month && _day == x._day;
}
//d1!=d2
bool Date::operator!=(const Date& x)
{return !(*this == x);//*this为d1,x为d2,这里相当于调用了operator==
}
//d1>d2
bool Date::operator>(const Date& x)
{if (_year > x._year){return true;}else if (_year == x._year && _month > x._month){return true;}else if (_year == x._year && _month == x._month && _day > x._day){return true;}return false;
}
//d1<d2
bool Date::operator<(const Date& x)
{return !(*this >= x);//复用operator==和operator>
}
//d1>=d2
bool Date::operator>=(const Date& x)
{return *this == x || *this > x;//复用operator==和operator>
}
//d1<=d2
bool Date::operator<=(const Date& x)
{return !(*this > x);//复用operator>
}

运算符重载函数实现

日期+天数得到新日期实现(+=原日期不变)

//日期+天数得到新日期实现(+=原日期不变)
Date& Date::operator+=(int day)
{if (day < 0)//避免输入负数{return *this -= (-day);//这里operator+=与operator-=互相调用}_day += day;while (_day > GetMonthDay(_year, _month))//当_day<=一个月的天数时,终止循环{_day -= GetMonthDay(_year, _month);//每减过一个月的天数,month就+1++_month;if (_month == 13){_year++;_month = 1;}}return *this;
}

日期-天数得到新日期实现(-=原日期不变)

//日期-天数得到新日期实现(-=原日期不变)
Date& Date::operator-=(int day)
{if (day < 0)//避免输入正数{return *this += (-day);//这里operator+=与operator-=互相调用}_day -= day;while (_day <= 0)//当_day>0时,终止循环{--_month;//每进一次循环month就-1if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);//计算完year与month后,令day加这个月天数}return *this;
}

前置++与前置--重载

//前置++重载
Date& Date::operator++()
{*this += 1;//这里复用operator+=//前置++,先加后用,因此返回+1之后的日期//this出作用域未销毁,因此返回this的地址,以&做返回值return *this;
}
//前置--重载
Date& Date::operator--()
{*this -= 1;return *this;
}

后置++与后置--重载

//后置++重载
Date Date::operator++(int)
{Date tmp(*this);//创建临时变量tmp,调用拷贝构造,tmp拷贝this*this += 1;//后置++,先用后加,因此返回+1之前的tmp//tmp出作用域被销毁,因此直接返回tmp的值,无需用&return tmp;
}
//后置--重载
Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}

日期+-天数,得到新日期

//日期+-天数,得到新日期,返回Date类型
Date Date::operator+(int day)
{Date tmp(*this);tmp += day;//复用operator+=return tmp;
}
Date Date::operator-(int day)
{Date tmp(*this); tmp -= day;//复用operator -=return tmp;
}

倒计时,两个日期相减,算天数

//两个日期相减,算天数,返回int类型
int Date::operator-(const Date& x)
{// 假设左大右小int flag = 1;Date max = *this;Date min = x;// 假设错了,左小右大if (*this < x){	max = x;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}

3.测试

测试d1与d2相隔多少天

int main()
{Date d1(2002, 7, 12);d1.Print();Date d2(2002, 7, 7);d2.Print();//测试d1与d2相隔多少天int ret1 = d1 - d2;cout << ret1 << endl;return 0;
}

我的结果: 

ac5bdb268ddc4ef2910600b8c9d52a1e.png

 电脑结果:

333349aada9746b49ae26cdad472beba.png

测试d1+10000天是何年何月何日

int main()
{Date d1(2002, 7, 12);d1.Print();Date d2(2002, 7, 7);d2.Print();//测试d1+10000天是何年何月何日Date ret2 = d1 + 10000;ret2.Print();return 0;
}

我的结果: 

0cda8d5bdfd44dd8bd48936dda4ceb6f.png

 电脑结果:

896afaabfacc474b8b99710d56198b91.png

测试d1-10000天是何年何月何日

int main()
{Date d1(2002, 7, 12);d1.Print();Date d2(2002, 7, 7);d2.Print();//测试d1-10000天是何年何月何日Date ret3 = d1 - 10000;ret3.Print();return 0;
}

我的结果: 

db9bfa55f47641e895cf95d5047f597c.png

 电脑结果:

7ebb8490992d4b7d89a1a511d5307104.png

测试前置++与后置++

int main()
{Date d1(2002, 7, 12);d1.Print();Date d2(2002, 7, 7);d2.Print();//测试前置++与后置++Date ret4 = ++d1;d1.Print();ret4.Print();cout << endl;Date ret5 = d1++;d1.Print();ret5.Print();return 0;
}

09b1cf431c424a5b8ba4e7fe51040bbd.png

4. 源代码

Date.h

#pragma once#include <iostream>
#include <assert.h>using namespace std;class Date
{
public://构造函数(全缺省)Date(int year = 2002, int month = 7, int day = 7);//打印函数void Print();//判断大小月、闰平月int GetMonthDay(int year, int month);//赋值运算符重载函数//bool类型,判断两个日期是否等于、不等于、大于、小于、大于等于、小于等于bool operator==(const Date& x);bool operator!=(const Date& x);bool operator>(const Date& x);bool operator<(const Date& x);bool operator>=(const Date& x);bool operator<=(const Date& x);//运算符重载函数//日期+天数得到新日期(原日期不变)Date& operator+=(int day);//日期-天数得到新日期(原日期不变)Date& operator-=(int day);//前置++与后置++重载Date& operator++();Date operator++(int);//前置--与后置--重载Date& operator--();Date operator--(int);//日期+-天数,得到新日期,返回Date类型Date operator+(int day);Date operator-(int day);//两个日期相减,算天数,返回int类型int operator-(const Date& d);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;if (_year < 1 || _month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month)){//assert(false);//如果日期输入错误,暴力中断程序Print();cout << "日期错误" << endl;//如果日期输入错误,温柔地警告日期错误}
}//打印函数实现
void Date::Print()
{cout << _year << "-" << _month << "-" << _day << endl;
}//判断大小月、润平月函数实现
int Date::GetMonthDay(int year, int month)
{assert(year >= 1 && month >= 1 && month <= 12);//检查日期是否合法//定义一个数组存储12个月int arrmonth[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//如果是闰年2月,返回29天if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)){return 29;}return arrmonth[month];
}//赋值运算符重载函数实现
//d1==d2
bool Date::operator==(const Date& x)
{return _year == x._year && _month == x._month && _day == x._day;
}
//d1!=d2
bool Date::operator!=(const Date& x)
{return !(*this == x);//*this为d1,x为d2,这里相当于调用了operator==
}
//d1>d2
bool Date::operator>(const Date& x)
{if (_year > x._year){return true;}else if (_year == x._year && _month > x._month){return true;}else if (_year == x._year && _month == x._month && _day > x._day){return true;}return false;
}
//d1<d2
bool Date::operator<(const Date& x)
{return !(*this >= x);//复用operator==和operator>
}
//d1>=d2
bool Date::operator>=(const Date& x)
{return *this == x || *this > x;//复用operator==和operator>
}
//d1<=d2
bool Date::operator<=(const Date& x)
{return !(*this > x);//复用operator>
}//运算符重载函数实现
//日期+天数得到新日期实现(+=原日期不变)
Date& Date::operator+=(int day)
{if (day < 0)//避免输入负数{return *this -= (-day);//这里operator+=与operator-=互相调用}_day += day;while (_day > GetMonthDay(_year, _month))//当_day<=一个月的天数时,终止循环{_day -= GetMonthDay(_year, _month);//每减过一个月的天数,month就+1++_month;if (_month == 13){_year++;_month = 1;}}return *this;
}
//日期-天数得到新日期实现(-=原日期不变)
Date& Date::operator-=(int day)
{if (day < 0)//避免输入正数{return *this += (-day);//这里operator+=与operator-=互相调用}_day -= day;while (_day <= 0)//当_day>0时,终止循环{--_month;//每进一次循环month就-1if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);//计算完year与month后,令day加这个月天数}return *this;
}
//前置++重载
Date& Date::operator++()
{*this += 1;//这里复用operator+=//前置++,先加后用,因此返回+1之后的日期//this出作用域未销毁,因此返回this的地址,以&做返回值return *this;
}
//后置++重载
Date Date::operator++(int)
{Date tmp(*this);//创建临时变量tmp,调用拷贝构造,tmp拷贝this*this += 1;//后置++,先用后加,因此返回+1之前的tmp//tmp出作用域被销毁,因此直接返回tmp的值,无需用&return tmp;
}
//前置--与后置--和++相同的道理
Date& Date::operator--()
{*this -= 1;return *this;
}
Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}
//日期+-天数,得到新日期,返回Date类型
Date Date::operator+(int day)
{Date tmp(*this);tmp += day;//复用operator+=return tmp;
}
Date Date::operator-(int day)
{Date tmp(*this); tmp -= day;//复用operator -=return tmp;
}
//两个日期相减,算天数,返回int类型
int Date::operator-(const Date& x)
{// 假设左大右小int flag = 1;Date max = *this;Date min = x;// 假设错了,左小右大if (*this < x){	max = x;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}

test.cpp

 

#define _CRT_SECURE_NO_WARNINGS 1
#include "Date.h"int main()
{Date d1(2002, 7, 12);d1.Print();Date d2(2002, 7, 7);d2.Print();cout << endl;//测试d1与d2相隔多少天int ret1 = d1 - d2;cout << ret1 << endl;cout << endl;//测试d1+10000天是何年何月何日Date ret2 = d1 + 10000;ret2.Print();cout << endl;//测试d1-10000天是何年何月何日Date ret3 = d1 - 10000;ret3.Print();cout << endl;//测试前置++与后置++Date ret4 = ++d1;d1.Print();ret4.Print();cout << endl;Date ret5 = d1++;d1.Print();ret5.Print();return 0;
}

 

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

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

相关文章

Tailwind CSS快速入门

文章目录 初识安装Tailwindcss试用安装快速书写技巧扩展好处Todo 初识 只需书写 HTML 代码&#xff0c;无需书写 CSS&#xff0c;即可快速构建美观的网站 Tailwind CSS 是一个功能类优先的 CSS 框架&#xff0c;它通过提供大量的原子类&#xff08;utility classes&#xff09;…

FTP协议——LightFTP安装(Linux)

1、简介 LightFTP是一个轻量级的FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#xff09;客户端软件。FTP是一种用于在网络上传输文件的标准协议&#xff0c;允许用户通过TCP/IP网络&#xff08;如互联网&#xff09;在计算机之间进行文件传输。 2、步骤…

APM2.8下载固件的方法(两种办法详解)

1.把APM飞控用安卓手机的USB线插入电脑。 选择COM口&#xff0c;不要选择auto&#xff0c;如果你没有COM口说明你驱动安装有问题。 波特率115200。点击相应的图标就可以下载固件到飞控板。 请注意&#xff1a;烧录APM必须选择INSTALL FIRMWARE LEAGACY,第一个是用于刷pixhawk的…

常用时序逻辑电路模块:移位寄存器

寄存器与移位寄存器 寄存器&#xff1a;数字系统中用来存储二进制数据的逻辑器件。存储N位二进制数据的寄存器需要N个触发器组成。 移位功能&#xff1a;存储代码在脉冲作用下依次左移或右移。 移位寄存器&#xff1a; 移位寄存器中的数据可以在移位脉冲作用下依次逐位右移…

Vue3_创建项目

目录 一、创建vue项目 1.下载vue 2.进入刚才创建的项目 3.安装依赖 4.运行项目 ​5.打包项目放入生产环境 二、vue项目组成 1.项目文件结构 2.项目重要文件 Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、C…

unity制作app(9)--拍照 相册 上传照片

1.传输照片&#xff08;任何较大的数据&#xff09;都需要扩展服务器的内存空间。 2.还需要base64编码 2.1客户端发送位置的编码 2.2服务器接收部分的代码

Visual Studio中调试信息格式参数:/Z7、/Zi、/ZI参数

一般的调试信息都保存在pdb文件中。 Z7参数表示这些调试信息保存到OBJ目标文件中&#xff0c;这样的好处是不需要单独分发PDB文件给下游。Zi就是把所有的调试信息都保存在pdb文件中&#xff0c;以缩小发布文件的大小。ZI和Zi类似&#xff0c;但是增加了热重载的能力&#xff1…

数据库|基于T-SQL向数据库数据表中添加、修改、删除数据

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 前边学习了基于T-SQL创建数据库和创建数据表&#xff0c; 《数据库|基于T-SQL创建数据库》 《数据库|基于T-SQL创建数据表》 接下来学习向创建好的数据表中添加数据&#xff0c;以下为学习笔记。 01 通过T-SQL向数据表…

1.5.3 基于Java配置方式使用Spring MVC

本实战教程主要介绍了如何使用Java配置方式来使用Spring MVC框架。相较于XML配置方式&#xff0c;Java配置方式提供了一种更为简洁和灵活的配置方法。 项目创建与配置 创建一个Jakarta EE项目&#xff0c;并设置项目名称和位置。选择Jakarta EE 10版本&#xff0c;不添加依赖&a…

【StableDiffusion】SD1.4、1.5、2.0、2.1 和 SDXL0.9-1.0、SDXL turbo 等的区别

总览 1.基础sd base model家族&#xff1a;SD1.4、SD1.5、SD1.5-LCM、SD2.0、SD2.0-768、SD2.1、SD2.1-768、SD2.1-UNCLIP 2.升级sdxl base model家族&#xff1a;SDXL0.9、SDXL1.0、SDXL1.0-LCM、SDXL-DISTILLED、SDXL-TURBO 3.专门用于视频生成的 SVD 家族&#xff1a;SVD、…

鸿蒙知识点总结

1 Stage模型应用程序包结构 在开发态&#xff0c;一个应用包含一个或者多个Module&#xff0c;可以在DevEco Studio工程中创建一个或者多个Module。Module是HarmonyOS应用/服务的基本功能单元&#xff0c;包含了源代码、资源文件、第三方库及应用/服务配置文件&#xff0c;每一…

华为CE6851-48S6Q-HI升级设备版本及补丁

文章目录 升级前准备工作笔记本和交换机设备配置互联地址启用FTP设备访问FTP设备升级系统版本及补丁 升级前准备工作 使用MobaXterm远程工具连接设备&#xff0c;并作为FTP服务器准备升级所需的版本文件及补丁文件 笔记本和交换机设备配置互联地址 在交换机接口配置IP&#…

[AIGC] Java常用的JSON库及简单示例

Java常用的JSON库及简单示例 在Java的世界里&#xff0c;JSON库广泛用于日常开发工作&#xff0c;本文将介绍几个常用的JSON库并配以简单的示例代码。 1. Gson Gson是Google提供的一个用来在Java对象和JSON数据之间进行转换的Java库。 它有一定的学习曲线&#xff0c;但一旦熟…

财务RPA机器人如何使用

随着科技的不断发展&#xff0c;自动化技术在各个领域得到了广泛应用&#xff0c;在财务领域&#xff0c;RPA机器人已经成为一种新兴的技术手段&#xff0c;帮助众多企业实现了财务流程的自动化&#xff0c;大大提高了工作效率&#xff0c;降低人力成本。 本文金智维将详细介绍…

move base全解

0. 简介 之前我们专门有一节讲到了《move_base源码学习》。主要介绍了MoveBase基类中函数的大概意思以及调用的方式。move_base是ROS下关于机器人路径规划的中心枢纽。它通过订阅激光雷达、map地图、amcl的定位等数据&#xff0c;然后规划出全局和局部路径&#xff0c;再将路径…

2024年03月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 在Python中,hex(2023)的功能是?( ) A:将十进制数2023转化成十六进制数 B:将十进制数2023转化成八进制数 C:将十六进制数2023转化成十进制数 D:将八进制数2023转化成十进制数 答案:A …

东莞MES管理系统在电子工厂的益处

东莞MES管理系统对东莞电子企业带来了许多好处&#xff0c;包括但不限于以下几点&#xff1a; 提高生产效率&#xff1a;MES系统可以优化生产计划、监控生产过程&#xff0c;提高生产效率&#xff0c;减少生产中的浪费和停机时间&#xff0c;提高产能利用率。 优化库存管理&a…

洛谷 CF1209D Cow and Snacks

题目来源于&#xff1a;洛谷 题目本质&#xff1a;并查集 解题思路&#xff1a; 我们以每种化为一个点&#xff0c;以每个客人喜欢的两朵花给两朵花连一条无向边。则会出现一定数目的连通块&#xff0c;连通块总个数为 ans。 对每个连通块进行分析&#xff1a;第一个客人买走…

指纹识别经典图书、开源算法库、开源数据库

目录 1. 指纹识别书籍 1.1《精通Visual C指纹模式识别系统算法及实现》 1.2《Handbook of Fingerprint Recognition》 2. 指纹识别开源算法库 2.1 Hands on Fingerprint Recognition with OpenCV and Python 2.2 NIST Biometric Image Software (NBIS) 3. 指纹识别开源数…

马斯克:AI时代人人高收入,不需要工作,商品服务不再短缺,可能性80%

当前人工智能现状和未来如何&#xff1f;AI时代下&#xff0c;人类未来会发生哪些变化&#xff1f; 埃隆马斯克&#xff08;Elon Musk&#xff09;在2024 VivaTech大会上分享了关于地球未来的诸多愿景。 投资作业本课代表摘录了其中的要点&#xff0c;分享给大家&#xff1a…