C++实现日期类Date(超详细)
个人主页:平行线也会相交💪
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【C++之路】💌
本专栏旨在记录C++的学习路线,望对大家有所帮助🙇
希望我们一起努力、成长,共同进步。🍓
目录
- 日期类(Date.cpp)成员函数的实现
- 构造函数
- bool类型的运算符重载
- 得到该月有几天GetMonthDay
- 运算符重载+=和+
- 运算符重载-=和-
- 运算符重载前置++和后置++
- 运算符重载前置--后置--
- 两个日期相差几天
- 日期类(Date.h)
- 日期测试
- TestDate1()
- TestDate2()
- TestDate3()
- TestDate4()
- TestDate5()
- TestDate6()
日期类(Date.cpp)成员函数的实现
//构造函数,声明和定义分析不能同时给缺省参数,一般是声明给缺省参数
Date::Date(int year, int month, int day)
{if (month > 0 && month < 13 && day>0 && day <= GetMonthDay(year, month)){_year = year;_month = month;_day = day;}else{cout << "非法日期" << endl;}
}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;
}bool Date::operator==(const Date& x)
{return _year == x._year&& _month == x._month&& _day == x._day;
}bool Date::operator<=(const Date& x)
{return *this < x || *this == x;
}bool Date::operator>(const Date& x)
{return !(*this <= x);
}bool Date::operator>=(const Date& x)
{return !(*this < x);
}bool Date::operator!=(const Date& x)
{return !(*this == x);
}int Date::GetMonthDay(int year, int month)
{//由于要频繁调用daysArr,所以我们把daysArr放到静态区static int daysArr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) && month == 2)if (month == 2 && ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))){return 29;}else{return daysArr[month];}return daysArr[month];
}//+=复用+
//Date& Date::operator+=(int day)
//{
// *this = *this + day;
// return *this;
//}Date& Date::operator+=(int day)
{if (day < 0){return *this -= -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)
{Date tmp(*this);tmp += day;/*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;*///出了作用域后tmp销毁,所以不能用引用返回return tmp;
}Date& Date::operator -=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){--_month;if (_month == 0){_month = 13;--_year;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date:: operator-(int day)
{Date tmp = *this;//这里是拷贝构造tmp -= day;return tmp;
}//前置++
Date& Date::operator++()
{*this += 1;return *this;
}//后置++
//增加int参数并不是为了接收具体的值,这里仅仅是占位,为了就是跟前置++构成重载
Date Date::operator++(int)
{Date tmp = *this;*this += 1;return tmp;
}//前置--
Date& Date::operator--()
{*this -= 1;return *this;
}//后置--
Date Date::operator--(int)
{Date tmp = *this;*this -= 1;return tmp;
}//两个日期相差几天
int Date::operator-(const Date& d)
{//默认认为第一个日期大,第二个小Date max = *this;Date min = d;int flag = 1;if (*this < d){max = d;min = *this;flag = -1; }int n = 0;while (min != max){++min;++n;}return n * flag;
}
构造函数
Date::Date(int year, int month, int day)
{if (month > 0 && month < 13 && day>0 && day <= GetMonthDay(year, month)){_year = year;_month = month;_day = day;}else{cout << "非法日期" << endl;}
}
bool类型的运算符重载
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;
}bool Date::operator==(const Date& x)
{return _year == x._year&& _month == x._month&& _day == x._day;
}bool Date::operator<=(const Date& x)
{return *this < x || *this == x;
}bool Date::operator>(const Date& x)
{return !(*this <= x);
}bool Date::operator>=(const Date& x)
{return !(*this < x);
}bool Date::operator!=(const Date& x)
{return !(*this == x);
}
得到该月有几天GetMonthDay
int Date::GetMonthDay(int year, int month)
{//由于要频繁调用daysArr,所以我们把daysArr放到静态区static int daysArr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) && month == 2)if (month == 2 && ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))){return 29;}else{return daysArr[month];}return daysArr[month];
}
运算符重载+=和+
这里有两种方式来写+=和+的赋值运算符重载。
先来看第一种:+=复用+的方式,请看:
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)
{Date tmp(*this);tmp += day;/*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;*///出了作用域后tmp销毁,所以不能用引用返回return tmp;
}
现在来看第二种写法,+=复用+
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;}}//出了作用域后tmp销毁,所以不能用引用返回return tmp;
}//+=复用+
Date& Date::operator+=(int day)
{*this = *this + day;return *this;
}
现在这两种写法哪一种好呢?对于每种方式的+的赋值运算符重载
没啥太大的区别(都要都要创建两个对象,一个是Date tmp(*this);
,另外一个就是return tmp
);但是对于+=的赋值运算符重载
,第一种方式并没有创建对象,而第二种方式的+=的符重运算符重载
由于又调用了一次+的赋值运算符重载函数
(即多创建了两个对象)。所以最终第一种方式(+复用+=
)显然更好一些,第二种方式差就差再+=复用+
的时候多创建了两个对象。
运算符重载-=和-
Date& Date::operator -=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){--_month;if (_month == 0){_month = 13;--_year;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date:: operator-(int day)
{Date tmp = *this;//这里是拷贝构造tmp -= day;return tmp;
}
运算符重载前置++和后置++
//前置++
Date& Date::operator++()
{*this += 1;return *this;
}//后置++
//增加int参数并不是为了接收具体的值,这里仅仅是占位,为了就是跟前置++构成重载,方便区分
Date Date::operator++(int)
{Date tmp = *this;*this += 1;return tmp;
}
运算符重载前置–后置–
//前置--
Date& Date::operator--()
{*this -= 1;return *this;
}//后置--
Date Date::operator--(int)
{Date tmp = *this;*this -= 1;return tmp;
}
两个日期相差几天
//两个日期相差几天
int Date::operator-(const Date& d)
{//默认认为第一个日期大,第二个小Date max = *this;Date min = d;int flag = 1;if (*this < d){max = d;min = *this;flag = -1; }int n = 0;while (min != max){++min;++n;}return n * flag;
}
日期类(Date.h)
class Date
{
public://构造函数Date(int year = 22, int month = 5, int day = 20);//不需要写拷贝构造函数,所以下面可以选择直接注释掉Date (const Date& d){cout << "Date(const Date& d)" << endl;_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}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);int GetMonthDay(int year, int month);Date& operator+=(int day);Date operator+(int day);Date& operator -=(int day);Date operator-(int day);Date& operator++();//前置++Date operator++(int);//后置++Date& operator--();//前置--Date operator--(int);//后置++//计算两个日期相差多少天int operator-(const Date& d);
private:int _year;int _month;int _day;
};
日期测试
TestDate1()
void TestDate1()
{Date da1(23, 5, 20);da1 += 100;da1.Print();Date da2(23, 5, 20);Date da3(da2 + 100);da2.Print();da3.Print();//用一个已经存在的对象初始化另一个对象,即拷贝构造函数//拷贝构造的意义就是赋值初始化Date da4 = da2;//等价于Date da4(da2);//均为拷贝构造函数,是等价的//而赋值重载的意义纯粹的就是拷贝//已经存在的两个对象之间进行复制拷贝,即运算符重载函数da4 = da1;
}
这里指的注意的是Date da4 = da2;
是等价于Date da4(da2);
,因为这里实在用一个已经存在的对象初始化另外一个对象,所以这里调用的是拷贝构造函数,而不是调用=的赋值运算符重载
。
如下如:
TestDate2()
{Date da1(2021, 5, 21);//无论前置还是后置++都需要++//前置++就返回++以后的对象,后置++就返回++之前的对象//编译器这里成全一个同时委屈一个,为了区分这里的重载++da1;//da1.operator++()da1++;//da1.operator++(0)Date da2(2024, 5, 20);Date da3(2023, 3, 14);bool ret1 = da2 < da3;//自定义类型转换为对应的函数int i = 0, j = 2;bool ret2 = i < j;//内置类型编译器知道怎么比较,故编译器会自动处理内置类型的重载
}
TestDate3()
//测试日期类的-=
void TestDate3()
{Date da1(2023, 5, 20);da1 -= 50;da1.Print();Date da2(2023, 5, 21);da2 -= 88;da2.Print();Date da3(2023, 5, 25);da3 -= 100;da3.Print();Date da4(2024, 5, 20);da4 -= 10000;da4.Print();
}
TestDate4()
void TestDate4()
{Date d1(2020, 5, 20);d1 += 100;d1.Print();Date da2(2023, 5, 21);da2 += -100;da2.Print();Date da3(2023, 5, 5);da3 -= -100;da3.Print();
}
TestDate5()
void TestDate5()
{Date da1(2023, 5, 5);Date ret1 = da1--;//调用da1.operator(&da1,0);ret1.Print();da1.Print();Date da2(2023, 5, 5);Date ret2 = --da2;//调用da1.operator++(&da1);ret2.Print();da2.Print();
}
TestDate6()
void TestDate6()
{Date da1(2023, 5, 20);Date da2(2022, 5, 21);Date da3(1949, 10, 1);Date da4(2023, 5, 20);cout << da1 - da2 << endl;cout << da2 - da1 << endl;cout << da3 - da4 << endl;cout << da4 - da3 << endl;
}
好了,以上就是用C++来实现日期类。
就到这里,再见啦各位!!!
相关文章:

C++实现日期类Date(超详细)
个人主页:平行线也会相交💪 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C之路】💌 本专栏旨在记录C的学习路线,望对大家有所帮助🙇 希望我们一起努力、成长&…...

实验室检验系统源码,集检验业务、质量控制、报告、统计分析、两癌等模块于一体
云 LIS 系统针对区域化 LIS 而设计,依托底层云架构,将传统的 LIS 功能模块进行“云化”。 该系统是集检验业务、科室管理、质量控制、报告、统计分析、两癌等模块于一体的数据检验信息平台。通过计算机联网,实现各类仪器数据结果的实时自动接…...

学习RHCSA的day.03
目录 2.6 Linux系统的目录结构 2.7 目录操作命令 2.8 文件操作命令 2.6 Linux系统的目录结构 1、Linux目录结构的特点 分区加载于目录结构: 使用树形目录结构来组织和管理文件。整个系统只有一个位于根分区的一个根目录(树根)、一棵树。…...

电子邮件协议(SMTP,MIME,POP3,IMAP)
SMTP 关键词: 电子邮件协议:SMTP简单邮件传输协议,负责将邮件上传到服务器,采用TCP的25端口,C/S工作。仅传送ASCII码文本 详细介绍: SMTP是一种提供可靠且有效的电子邮件传输的协议。SMTP是建立在FTP文件传输服务上…...

Golang笔记:使用embed包将静态资源嵌入到程序中
文章目录 目的使用演示//go:embed 指令在WebServer中应用总结 目的 Golang编译程序默认是静态编译,会把相关的库都打包到一起,这在分发部署使用时非常方便。不过如果项目中用到的外部的静态资源文件,通常就需要将这些资源和程序一起拷贝分发…...
ImportError: cannot import name ‘OldCsv‘ from ‘pyflink.table.descriptors‘
我最近开始使用flink用于数据处理。 当我尝试执行table api 用于计数时 我不能导入OldCsv and FileSystem from pyflink.table.descriptors. I have also downloaded apache-flink using: pip install apache-flink [rootmaster flink]# pip3 list | grep flink apache-fli…...

YouCompleteMe(YCM)安装
vim在各个linux版本中是个比较好编辑器,反正nano我是用不惯。但这个ycm的安装也是不断的在变,现在的安装比之前要简单的多,基本个几命令就搞定了,而且 也不用关心系统里有没有vim,ycm已经可以自动安装。具体安装步骤如下ÿ…...

day33_css
今日内容 零、 复习昨日 一、CSS 零、 复习昨日 见代码 一 、引言 1.1CSS概念 层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文…...

10个最流行的向量数据库【AI】
矢量数据库是一种将数据存储为高维向量的数据库,高维向量是特征或属性的数学表示。 每个向量都有一定数量的维度,范围从几十到几千不等,具体取决于数据的复杂性和粒度。 推荐:用 NSDT场景设计器 快速搭建3D场景。 矢量数据库&…...

vite3+vue3 项目打包优化二 —— 依赖分包策略
在没有配置构建工具的分包功能时,构建出来的文件将无比巨大且是独立的一个 js 和 css 文件(如下图),这样本地加载文件时会存在巨大的压力。 默认情况下,浏览器重复请求相同名称的静态资源时,会直接使用缓存…...

中国社科院与美国杜兰大学金融管理硕士——与时间赛跑,充分利用每一分钟
不管你愿不愿意,时间总是在不经意间流去。林清玄在《和时间赛跑》中写道:“虽然我知道人永远跑不过时间,但是可以比原来快跑几步。那几步虽然很小很小,但作用却很大很大”。是的,我们需要与时间赛跑,充分利…...
什么是Dirichlet分布?
Dirichlet分布是一种概率分布,用于描述多维随机变量的概率分布。它是一个连续分布,通常用于处理具有多种可能取值的离散型随机变量。在LDA模型中,Dirichlet分布通常被用作先验分布,用来表示主题的概率分布和单词的概率分布。 Dir…...

web前端开发需要哪些技术?学前端顺序千万千万不要搞错啦!
宝子们,下午好,之前给大家分享了前端岗位的前景规划,小源看的出来,还是有不少宝子想入行前端的! 那除了会面试,还要有充足丰富的知识储备,需要什么技术,怎么样做才能找到高薪工作呢&…...

【AFNetWorking源码(二)AFURLSessionManger和AFHTTPSessionManager】
前言 学习了Mananger的初始化和以GET请求为例的过程,发现整个过程离不开AFHTTPSessionManager和AFURLSessionManger的某些方法。这两个是AFN的重要的网络通信模块内容,对它们作揖详细的学习。 AFURLSessionManager和AFHTTPSessionManager都是AFNetwork…...

编程不头秃,Google「AI程序员」来了,聊天就能敲代码
上周 Google 在 I/O 大会宣布了一个能够辅助编程的聊天机器人 Codey,现在它终于上线 Google Colab 啦! 🌟 Codey 是基于 Google 目前最新的大语言模型 PaLM 2 运行,有着强大的语言理解和编程能力。 Codey 有这些功能࿱…...

【数据结构与算法】基础数据结构
文章目录 数组概述动态数组二维数组局部性原理越界检查 链表概述单向链表单向链表(带哨兵)双向链表(带哨兵)环形链表(带哨兵) 队列概述链表实现环形数组实现 栈概述链表实现数组实现应用 双端队列概述链表实…...

k8s系列(四)——资源对象
k8s系列四——资源对象 pod概念 思考:为什么k8s会引出pod这个概念,容器不能解决么? 我的理解:一组密切相关的服务使用容器的话,如果他们的镜像不在一个容器里的话,那么就需要配置反向代理进行通信…...
JavaScript如何使用for循环
JavaScript 是一门非常有趣的编程语言,它可以让我们在浏览器中创建交互式的 Web 应用程序。在 JavaScript 中,我们可以使用 for 循环来迭代一个数组或对象,从而执行一系列的操作。下面是一些关于 for 循环的有趣的用法和例子。 为什么要使用…...

(浙大陈越版)数据结构 第三章 树(上) 3.1 树和树的表示
目录 3.1.1 引子(顺序查找) 什么是树 查找 3.1.2 引子 二分查找例子(BinarySearch) 二分查找 3.1.3 引子 二分查找实现 二分查找代码 二分查找的启示 3.1.4 树的定义 一些基本术语: 3.1.5 树的表示 3.1.1 引子(顺序查找…...

平抑风电波动的电-氢混合储能容量优化配置(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...