当前位置: 首页 > news >正文

C++日期类的基本实现

前言

对于许多出初学C++的同学来说首先接触的第一个完整的类便是日期类,这个类能有效的帮助我们理解C++中有关类的初始化以及重载的相关知识,帮助我们轻松上手体验C++的魅力。

文章目录

  • 前言
  • 一、日期类整体初概
  • 二、构造
    • 2.1 判断日期是否合法
    • 2.2 构造函数
  • 三、关系判断
    • 3.1 大于(>)运算符
    • 3.2 等于(=)运算符
    • 3.3 其余运算符重载
  • 四、日期的加减运算
    • 4.1 +/+=运算符
    • 4.2 -/-=运算符
    • 4.3 日期相减
    • 4.4 推算当日星期
  • 五、前置++与后置++运算符
    • 5.1 前置++运算符
    • 5.2 后置++运算符
  • 六、流插入和流提取操作符重载

一、日期类整体初概

完成一个类,我们首先需要了解这个类需要完成什么任务,需要哪些函数来进行实现,以下是一个日期类的模板框架。

class Date
{//检查日期合法bool CheckDate();//获取每月天数int GetMonthDay(int year, int month);//构造函数Date(int year = 1900, int month = 1, int day = 1);//关系判断操作符重载bool operator>(const Date& d1);bool operator== (const Date& d2);bool operator>=(const Date& d1);bool operator<(const Date& d1);bool operator<=(const Date& d1);bool operator!=(const Date& d1);//日期类的加减操作Date& operator +=(int day);Date operator +(int day);Date& operator-=(int day);Date operator-(int day);//日期减去日期int operator- (const Date& d);//计算当前天数为星期几void WeekDay();//前置、后置操作符Date& operator++();Date operator++(int);Date& operator--();Date operator--(int);//流插入和流提取操作符重载friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
};

二、构造

在确认基本框架后,第一步是为我们的自定义类创建一个合适的构造函数,对于日期类而言,我们则需要在最开始实例化类的时候对日期进行一个判断,判断日期的合法性,例如年份大于1,月份在1-12之间,天数在对于的月份天数之内,具体的是实现如下:

2.1 判断日期是否合法

//获取当前月份的日期
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;
}// 检查日期是否合法
bool CheckDate()
{if (_year < 1 || _month>13 || _month < 1 || _day<1 || _day>GetMonthDay(_year, _month))return false;return true;
}

2.2 构造函数

Date(int year=1900,int month=1,int day=1){_year = year;_month = month;_day = day;//检查生成的日期是否非法if (!CheckDate()){cout << "日期非法:" ;Print();//退出程序,正常退出exit(0),非法退出exit(非0);exit(-1);}}

三、关系判断

3.1 大于(>)运算符

bool operator>(const Date& d1)
{if ((_year > d1._year)|| (_year >= d1._year && _month > d1._month)|| (_year >= d1._year && _month >= d1._month && _day > d1._day)){return true;}return false;
}

3.2 等于(=)运算符

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

3.3 其余运算符重载

在上面我们实现了 > 、 = 两个运算符重载。为了方便和提高可读性,对于剩下的>=、< 、 <= 、!= 这四个运算符我们可以复用的方式实现,利用> 、 = 两个运算符的逻辑组合来进行实现。

bool operator>=(const Date& d1)
{return (*this > d1) || (*this == d1);
}bool operator<(const Date& d1)
{return !(*this >= d1);
}bool operator<=(const Date& d1)
{return !(*this > d1);
}bool operator!=(const Date& d1)
{return !(*this == d1);
}

四、日期的加减运算

4.1 +/+=运算符

思路上我们选择一个日期加上具体天数之后,采取逐一加天数的方式,每次加完之后进行判断,当前天数是否大于当月天数,同时当月数进一的时候判断当前月数是否大于十二,依次进位。

Date operator +(int day)
{//如果day 是负数 调用-操作符重载if (day < 0){return *this - (-day);}Date d1(*this);//直接加到_day上,直到_day合法。d1._day += day;while (d1._day > GetMonthDay(d1._year, d1._month)){d1._day -= GetMonthDay(d1._year, d1._month);++d1._month;if (d1._month == 13){d1._month = 1;d1._year++;}}return d1;
}// 直接复用 "+" 运算符即可
Date& operator +=(int day)
{*this = *this + day;return *this;
}

4.2 -/-=运算符

思路上和日期加天数是一样的,但是不同的地方在于,当前天数小于1时,我们采取月份减一的方式,依次借位。

Date& operator-=(int day)
{//如果减去负天数 ,则调用 +=if (day < 0){return *this += -day;}//直接减去_day -= day;//借位减去天数,直到天数合法while (_day <= 0){--_month;if (_month == 0){--_year;_month = 12;}//加上天数_day += GetMonthDay(_year, _month);}return *this;
}// 复用顺序不重要
Date operator-(int day)
{Date temp(*this);temp -= day;return temp;
}

4.3 日期相减

我们在上面已经实现了日期加上天数以及两个日期之间是否相等的判断,在此可以直接复用,默认前一个日期大于后一个日期,将较小的日期天数逐次加一,当加到和较大天数相等时,此时加一的次数就是日期之间相差的天数。

//两个日期相减
int  operator- (const Date & d)
{//先假设 *this > dint flag = 1;Date max = *this;Date min = d;if (*this < d){max = d;min = *this;flag = -1;}int count = 0;while (min != max){	++min;++count;}return count * flag;
}

4.4 推算当日星期

由于1900年1月1日正好是周一,因此我们计算某个日期减去1900年1月1日得到的天数并对七取模即可。

//判断当前日期是周几
void WeekDay( )
{Date statr(1900, 1, 1);//求相差的天数int n = *this - statr;//5相当于是周6int weekday = 0;weekday += n;cout << "周" << weekday % 7 + 1 << endl;
}

五、前置++与后置++运算符

对于前置++和后置++运算符两者之间似乎操作数一样,但是不同之处在于后置++重载时有一个操作数,同时需要注意后置++运算符返回值应是修改前的值,对于 “–” 运算符与 “++“ 运算符基本一致,不在此列出。

5.1 前置++运算符

Date& operator++()
{return *this += 1;
}

5.2 后置++运算符

Date operator++(int)
{Date temp(*this);*this += 1;return temp;
}

六、流插入和流提取操作符重载

相比于其他的运算符,流插入和流提取则有一丝不同,我们知道运算符重载时默认第一位是 this 指针,但是流插入和流提取第一个操作数明显是流插入运算符或流提取运算符,因此必须将其设为全局函数

此时又会遇到另一个问题,全局函数如何访问类的私有成员,此时就需提前将其声明为友元函数在进行重载

ostream& operator<<(ostream& out,const Date& d) 
{out << d._year << '/' << d._month << '/' << d._day;return out;
}istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;//检查输入格式是否正确assert(d.CheckDate());return in;
}

相关文章:

C++日期类的基本实现

前言 对于许多出初学C的同学来说首先接触的第一个完整的类便是日期类&#xff0c;这个类能有效的帮助我们理解C中有关类的初始化以及重载的相关知识&#xff0c;帮助我们轻松上手体验C的魅力。 文章目录 前言一、日期类整体初概二、构造2.1 判断日期是否合法2.2 构造函数 三、…...

第六章:数据结构与算法-part3:数据结构算法提升

文章目录 一、排序算法1.1 插入排序1、直接插入排序2、折半插入排序3、希尔排序 1.2、交换排序法1、起泡排序2、快速排序 1.3 选择类排序1、简单选择排序 二、业务逻辑算法设计2.1 基本概念和术语2.2 静态查找表2.3、有序表的查找 一、排序算法 排序是数据处理过程中经常使用的…...

keras深度学习框架通过卷积神经网络cnn实现手写数字识别

昨天通过keras构建简单神经网络实现手写数字识别&#xff0c;结果在最后进行我们自己的手写数字识别的时候&#xff0c;准确率堪忧&#xff0c;只有60%。今天通过卷积神经网络来实现手写数字识别。 构建卷积神经网络和简单神经网络思路类似&#xff0c;只不过这里加入了卷积、池…...

Springboot启动异常 Command line is too long

Springboot启动异常 Command line is too long Springboot启动时直接报异常 Command line is too long. Shorten command line for xxxxxApplication or also for Spring Boot default解决方案: 修改 SystemApplication 的 Shorten command line&#xff0c;选择 JAR manife…...

PXE 装机(五十)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、PXE是什么 二、PXE的组件 三、配置vsftpd 四、配置tftp 五、准备pxelinx.0文件、引导文件、内核文件 ​六、配置dhcp 七、创建default文件 八、配置pxe无人值守…...

C++ 虚函数与纯虚函数

目录 1. 虚函数 2. 纯虚函数 C 中的虚函数和纯虚函数都是实现多态的重要机制。多态可以让不同的对象以相同的方式进行操作&#xff0c;从而简化代码的编写和维护。 1. 虚函数 虚函数是一种在基类中声明的函数&#xff0c;可以在派生类中进行重写。在运行时&#xff0c;根据对…...

警告:Provides transitive vulnerable dependency maven:org.yaml:snakeyaml:1.30

1. 警告 SpringBoot 的 validation 依赖包含有易受攻击的依赖 snakeyaml。 警告信息如下&#xff1a; Provides transitive vulnerable dependency maven:org.yaml:snakeyaml:1.30 意思是&#xff1a;提供了可传递的易受攻击依赖 maven:org.yaml:snakeyaml:1.30 2. 警告示例 …...

中文命名实体识别

本文通过people_daily_ner数据集&#xff0c;介绍两段式训练过程&#xff0c;第一阶段是训练下游任务模型&#xff0c;第二阶段是联合训练下游任务模型和预训练模型&#xff0c;来实现中文命名实体识别任务。 一.任务和数据集介绍 1.命名实体识别任务 NER&#xff08;Named En…...

WPF CommunityToolkit.Mvvm Messenger通讯

文章目录 环境WeakReferenceMessenger方法介绍无回调订阅发送Token区分有回调订阅发送 环境 CommunityToolkit.Mvvm Messenger 十月的寒流: 如何使用 CommunityToolkit.Mvvm 中的 Messenger 来进行 ViewModel 之间的通信 WeakReferenceMessenger 我这里只讲简单的弱Messenger…...

【杂言】写在研究生开学季

这两天搬进了深研院的宿舍&#xff0c;比中南的本科宿舍好很多&#xff0c;所以个人还算满意。受台风 “苏拉” 的影响&#xff0c;原本的迎新计划全部打乱&#xff0c;导致我现在都还没报道。刚开学的半个月将被各类讲座、体检以及入学教育等活动占满&#xff0c;之后又是比较…...

渗透测试漏洞原理之---【任意文件读取漏洞】

文章目录 1、概述1.1、漏洞成因1.2、漏洞危害1.3、漏洞分类1.4、任意文件读取1.4.1、文件读取函数1.4.2、任意文件读取 1.5、任意文件下载1.5.1、一般情况1.5.2、PHP实现1.5.3、任意文件下载 2、任意文件读取攻防2.1、路径过滤2.1.1、过滤../ 2.2、简单绕过2.2.1、双写绕过2.2.…...

合宙Air724UG LuatOS-Air LVGL API控件-图片 (Image)

图片 (Image) 图片IMG是用于显示图像的基本对象类型&#xff0c;图像来源可以是文件&#xff0c;或者定义的符号。 示例代码 -- 创建图片控件 img lvgl.img_create(lvgl.scr_act(), nil) -- 设置图片显示的图像 lvgl.img_set_src(img, "/lua/luatos.png") -- 图片…...

仿京东 项目笔记2(注册登录)

这里写目录标题 1. 注册页面1.1 注册/登录页面——接口请求1.2 Vue开发中Element UI的样式穿透1.2.1 ::v-deep的使用1.2.2 elementUI Dialog内容区域显示滚动条 1.3 注册页面——步骤条和表单联动 stepsform1.4 注册页面——滑动拼图验证1.5 注册页面——element-ui组件Popover…...

Spark与Flink的区别

分析&回答 &#xff08;1&#xff09;设计理念 1、Spark的技术理念是使用微批来模拟流的计算,基于Micro-batch,数据流以时间为单位被切分为一个个批次,通过分布式数据集RDD进行批量处理,是一种伪实时。 2、Flink是基于事件驱动的&#xff0c;是面向流的处理框架, Flink基于…...

未来智造:珠三角引领人工智能产业集群

原创 | 文 BFT机器人 产业集群是指产业或产业群体在地理位置上集聚的现象&#xff0c;产业集群的研究对拉动区域经济发展&#xff0c;提高区域产业竞争力具有重要意义。 从我国人工智能产业集群形成及区域布局来看&#xff0c;我国人工智能产业发展主要集聚在京津冀、长三角、…...

【Unity db】sqlite

背景 最近使用unity&#xff0c;需要用到sqlite&#xff0c;记录下使用过程 需要的动态库 Mono.Data.Sqlite.dll&#xff0c;这个文件下载参考下面链接 SqliteConnection的Close和Open 连接的概念&#xff1a; 在数据库编程中&#xff0c;连接是一个重要的概念&#xff0c…...

Linux 指令心法(四)`touch` 创建一个新的空文件

文章目录 命令的概述和用途命令的用法命令行选项和参数的详细说明命令的示例命令的注意事项或提示 命令的概述和用途 touch 是一个用于在 Linux 和 Unix 系统中创建空文件或更改现有文件的访问和修改时间的命令。如果指定的文件不存在&#xff0c;touch会创建一个新的空文件&a…...

分类算法系列②:KNN算法

目录 KNN算法 1、简介 2、原理分析 数学原理 相关公式及其过程分析 距离度量 k值选择 分类决策规则 3、API 4、⭐案例实践 4.1、分析 4.2、代码 5、K-近邻算法总结 &#x1f343;作者介绍&#xff1a;准大三网络工程专业在读&#xff0c;努力学习Java&#xff0c;涉…...

12. 微积分 - 梯度积分

Hi,大家好。我是茶桁。 上一节课,我们讲了方向导数,并且在最后留了个小尾巴,是什么呢?就是梯度。 我们再来回看一下但是的这个式子: [ f x f y...

Large Language Models and Knowledge Graphs: Opportunities and Challenges

本文是LLM系列的文章&#xff0c;针对《Large Language Models and Knowledge Graphs: Opportunities and Challenges》的翻译。 大语言模型和知识图谱&#xff1a;机会与挑战 摘要1 引言2 社区内的共同辩论点3 机会和愿景4 关键研究主题和相关挑战5 前景 摘要 大型语言模型&…...

Python操作Excel教程(图文教程,超详细)Python xlwings模块详解,

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 xlwings模块详解 1、快速入门1、打开Excel2、创建工作簿2.1、使用工作簿2.2、操作…...

Java入门

Java导入包 import 主要用于导入在使用类前准备好了Import 关键字可以多次使用&#xff0c;导入多个包Import 关键字可以多次使用&#xff0c;导入多个类如果同一个包中需要大量的类&#xff0c;那么可以使用通配符进行导入如果Import了不同包&#xff0c;相同名称的类&#x…...

深度解析BERT:从理论到Pytorch实战

本文从BERT的基本概念和架构开始&#xff0c;详细讲解了其预训练和微调机制&#xff0c;并通过Python和PyTorch代码示例展示了如何在实际应用中使用这一模型。我们探讨了BERT的核心特点&#xff0c;包括其强大的注意力机制和与其他Transformer架构的差异。 关注TechLead&#x…...

小程序数据导出文件

小程序josn数据生成excel文件 先从下载传送门将xlsx.mini.min.js拷贝下来&#xff0c;新建xlsx.js文件放入小程序项目文件夹下。 const XLSX require(./xlsx)//在需要用的页面中引入// 定义导出 Excel 报表的方法exportData() {const that thislet newData [{time:2021,val…...

hadoop1.2.1伪分布式搭建

0.使用host-only方式 将Windows上的虚拟网卡改成跟Linux上的网卡在同一网段 注意&#xff1a;一定要将widonws上的WMnet1的IP设置和你的虚拟机在同一网段&#xff0c;但是IP不能相同 1.Linux环境配置&#xff08;windows下面的防火墙也要关闭&#xff09; 1.1修改主…...

【校招VIP】前端JavaScript语言之跨域

考点介绍&#xff1a; 什么是跨域&#xff1f;浏览器从一个域名的网页去请求另一个域名的资源时&#xff0c;域名、端口、协议任一不同&#xff0c;都是跨域。跨域是前端校招的一个重要考点&#xff0c;在面试过程中经常遇到&#xff0c;需要着重掌握。本期分享的前端算法考点之…...

mysql调优小计

1.选择最合适的字段属性&#xff1a;类型、⻓度、是否允许NULL等&#xff1b;尽量把字段设为not null&#xff0c;⼀⾯查询时对⽐是否为null&#xff1b; 2.要尽量避免全表扫描&#xff0c;⾸先应考虑在 where 及 order by 涉及的列上建⽴索引。 3.应尽量避免在 where ⼦句中对…...

AI:04-基于机器学习的蘑菇分类

蘑菇是一类广泛分布的真菌,其中许多种类具有重要的食用和药用价值,但也存在着一些有毒蘑菇。因此,准确地区分可食用和有毒的蘑菇对于保障人们的食品安全和健康至关重要。本研究旨在基于机器学习技术开发一种蘑菇分类系统,以实现对蘑菇的自动分类和识别。通过构建合适的数据…...

算法——排序

排序 下面的代码会用到宏定义&#xff0c;因为再C中没有swap交换函数&#xff0c;所以对于swap的宏定义代码如下&#xff1a; #define swap(a, b) {\__typeof(a) __a a; a b; b __a;\ } 稳定排序&#xff1a; 1.插入排序&#xff1a; 插入排序会将数组&#xff0c;分位两个部…...

leetCode动态规划“不同路径II”

迷宫问题是比较经典的算法问题&#xff0c;一般可以用动态规划、回溯等方法进行解题&#xff0c;这道题目是我昨晚不同路径这道题趁热打铁继续做的&#xff0c;思路与原题差不多&#xff0c;只是有需要注意细节的地方&#xff0c;那么话不多说&#xff0c;直接上coding和解析&a…...