CPP入门:日期类的构建
目录
1.日期类的成员
2.日期类的成员函数
2.1构造和析构函数
2.2检查日期合法
2.3日期的打印
2.4操作符重载
2.4.1小于号
2.4.2等于号
2.4.3小于等于号
2.4.4大于号
2.4.5大于等于号
2.4.6不等号
2.4.7加等的实现
2.4.8加的实现
2.4.9减去一个天数的减等实现
2.4.10减去一个天数的减实现
2.4.11两个日期相减的实现
2.4.12前后置++的实现
2.4.13前后置--的实现
2.5流插入/流提取操作符
1.日期类的成员
实现一个日期类,内部的成员自然是年、月、日
class Date
{private:int _year;int _month;int _day;
};
在日期类中,我们应当是已知每个月份有多少天的,因此我们还需要在日期内中写一个成员函数来获得当月的天数。
//获得天数int GetMonthDay(int year,int month){static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };//四年一闰,百年不闰/四百年闰if (month = 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0){return 29;}else{return monthDayArray[month];}}
此外,我们的日期类还应当能够实现对日期的打印、对日期类的相关计算、输入输出的重载等成员函数。
因此,我们完整的日期类应是如下:
#pragma once
#include <iostream>
using namespace std;
#include <assert.h>
class Date
{
public://流插入or输出friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);//构造Date(int year = 1900, int month = 1, int day = 1);//获取月份天数int GetMonthDay(int year, int month){assert(month > 0 && month < 13);static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0){return 29;}else{return monthDayArray[month];}}//检查日期bool CheckDate();//打印日期void Print() const;//日期类相关计算bool operator<(const Date& d) const;bool operator<=(const Date& d) const;bool operator>(const Date& d) const;bool operator>=(const Date& d) const;bool operator==(const Date& d) const;bool operator!=(const Date& d) const;Date& operator+=(int day);Date operator+(int day) const;Date& operator-=(int day);Date operator-(int day) const;int operator-(const Date& d) const;Date& operator++();Date operator++(int);Date& operator--();Date operator--(int);
private:int _year;int _month;int _day;
};
//输入流重载
ostream& operator<<(ostream& out, const Date& d);
//输出流重载
istream& operator>>(istream& in, Date& d);
2.日期类的成员函数
2.1构造和析构函数
由于日期类的成员都是内置类型,因此我们可以显式的写一个构造函数,但不用显式定义析构函数。
Date::Date(int year = 2024, int month = 7, int day = 2)
{_year = year;_month = month;_day = day;//检查日期合法性if (!CheckDate()){cout << "日期非法" << endl;}
}
由于我们的日期具有范围,因此我们需要在构造函数中检查日期是否合法。也正是因此,我们需要实现一个检查日期合法性的函数。
2.2检查日期合法
检查日期合法,首先要确保我们输入的数是正数,
//检查日期合法性
bool Date::CheckDate()
{if (_month < 1 || _month>12|| _day<1 || _day>GetMonthDay(_year, _month)||_year < 1){return false;}else{return true;}
}
2.3日期的打印
void Date::Print() const
{cout << _year <<'-' << _month <<'-'<<_day;
}
2.4操作符重载
下面我们就需要重载一些对日期类计算有用的操作符
2.4.1小于号
由于我们不想要我们传入的参数会被修改,因此我们需要传递常量。(权限可以缩小)
另外,我们传引用有两个原因
- 可以少一次构造形参的过程,可以提高性能。
- d在函数运行结束后不会销毁,不会返回一个空引用。
因此我们的函数名为:
bool operator<(const Date& d) const
判断一个日期是否小于另一个日期,我们需要分别判断年、月、日是否小于另一个日期。
在判断日的时候,我们可以直接使用原生的<操作符判断。
bool Date::operator<(const Date& d) const
{//年if (_year < d._year){return true;}else if (_year == d._year){ //月if (_month < d._month){return true;}else if (_month == d._month){//日return _day < d._day;//if (_day < d._day)//{// return true;//}//else//{// return false;//}}}
}
2.4.2等于号
直接判断年月日是否相等即可
bool Date::operator==(const Date& d) const
{return _year == d.year&& _month == d._month&& _day == d._day;
}
2.4.3小于等于号
我们传入的第一个参数是this,因此我们解引用this即可得到第一个参数的值。
bool Date::operator<=(const Date& d)const
{return *this < d || *this == d;
}
2.4.4大于号
判断是否大于就是是否小于等于取反
bool Date::operator>(const Date& d)const
{return !(*this <= d);
}
2.4.5大于等于号
判断是否大于等于就是对判断是否小于取反
bool Date::operator>=(const Date& d)const
{return !(*this < d);
}
2.4.6不等号
判断是否不相等就是对判等取反
bool Date::operator!=(const Date& d)const
{return !(*this == d);
}
2.4.7加等的实现
对于加等,是给定一个日期和一个天数,计算日期加上这个天数之后的日期。
这里我们采取的思路是先将原天数加上需要加的天数。
之后我们一直减去当月的天数,并让月份加1,如果月份为13,则年份加1,月份赋为1。一直到天数没有当月天数大为止。
Date& Date::operator+=(int day)
{//日期加_day+= day;//月份加while (_day > GetMonthDay(_year, _month)){if (_day > GetMonthDay(_year, _month)){_month++;_day - GetMonthDay(_year, _month);if (_month == 13){_month == 1;_year += 1;}}}return *this;
}
2.4.8加的实现
首先,我们实现两数相加,是不能改变我们的原数的。
因此,我们的第一个形参为const修饰的变量。
//加
//c=a+b;
Date Date::operator+(int day) const
{Date tmp = *this;tmp += day;return tmp;
}
这里我们采取的思路是创建一个临时变量来保存*this,然后返回tmp加等day的结果即可。
这里需要注意的是,由于这个函数运行结束之后,tmp会先被销毁掉,再进行返回,因此我们如果返回值为引用的话,则会出错。
2.4.9减去一个天数的减等实现
//减去一个天数
//减等
Date& Date::operator-=(int day)
{//减去一个负数if (day < 0){return *this += (-day);}//减去一个整数_day -= day;while (_day < 0){--month;if (_month == 0){_month = 12;_year--;}_day += GetMonthDay(_year, _month);}
}
与实现加等类似的是,这里我们也是类似的步骤,通过一个循环来不断的更新年月日。
2.4.10减去一个天数的减实现
//减去一个天数
Date Date::operator-(int day)const
{Date tmp = *this;tmp -= day;return tmp;
}
这里和上面的加等相似。
2.4.11两个日期相减的实现
首先,我们要判断出哪个日期大
之后,我们让小的日期不断加1,直到他们相同。
加了多少次1,两个日期就相隔多少天。
//两个日期相减
Date Date::operator-(const Date& d)const
{//假设法判断谁大Date max = *this;Date min = d;if (min > max){max = d;min = *this;}//小的日期不断加一天,直到二者相等//设置一个计数器,计数器的值就是两个日期的差值int n = 0;while (min!+ max){min++;n++;}return n;
}
2.4.12前后置++的实现
由于我们重载++操作符时都是这么写的:
Date::operator++()//前
Date::operator++(int)//后
这样便无法判断到底是调用前置++还是后置++了。
因此,我们规定调用后置++时,形参写一个int。
Date::operator++()//前
Date::operator++(int)//后
前置++非常容易实现,这里不再赘述。
//前后置++--
Date& Date::operator++()//前
{*this += 1;return *this;
}
Date Date::operator++(int)//后
{Date tmp = *this;*this + 1;return tmp;
}
后置++是先使用后++的。因此我们创建一个临时变量来保存*this,并在返回tmp前对*this+1。
2.4.13前后置--的实现
Date& Date::operator--()//前
{*this -= 1;return *this;
}
Date Date::operator--(int)//后
{Date tmp = *this;*this - 1;return tmp;
}
2.5流插入/流提取操作符
观察下面两行代码,我们发现这两个操作符的第二个操作数才是this。
但是成员函数默认第一个操作数为this,这就产生了问题。
因此我们不能够将这两个函数声明为成员函数。
cout << n << endl;
cin << n ;
我们需要将这两个函数声明在类外,之后通过友元在类内访问即可。
//类内
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
//定义
ostream& operator <<(ostream& out, const Date& d)
{cout << d._year << '-' << d._month << '-' << d._day;return out;
}
istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;if (!d.CheckDate()){cout << "日期非法" << endl;}return in;
}
相关文章:
CPP入门:日期类的构建
目录 1.日期类的成员 2.日期类的成员函数 2.1构造和析构函数 2.2检查日期合法 2.3日期的打印 2.4操作符重载 2.4.1小于号 2.4.2等于号 2.4.3小于等于号 2.4.4大于号 2.4.5大于等于号 2.4.6不等号 2.4.7加等的实现 2.4.8加的实现 2.4.9减去一个天数的减等实现 2.4.10…...
springboot学习,如何用redission实现分布式锁
目录 一、springboot框架介绍二、redission是什么三、什么是分布式锁四、如何用redission实现分布式锁 一、springboot框架介绍 Spring Boot是一个开源的Java框架,由Pivotal团队(现为VMware的一部分)于2013年推出。它旨在简化Spring应用程序…...
【MySQL】如果表被锁可以尝试看一下事务
今天在MySQL中删除表的时候,发现无法删除,一执行drop,navicat就卡死。 通过 SHOW PROCESSLIST显示被锁了 kill掉被锁的进程后依旧被锁 最后发现是由于存在为执行完的事务 SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; kill掉这些事务以…...
Datawhale - 角色要素提取竞赛
文章目录 赛题要求一、赛事背景二、赛事任务三、评审规则1.平台说明2.数据说明3.评估指标4.评测及排行 四、作品提交要求五、 运行BaselineStep1:下载相关库Step2:配置导入Step3:模型测试Step4:数据读取Step5:Prompt设…...
【Sql-驯化】sql中对时间的处理方法技巧总结
【Sql-驯化】sql中对时间的处理方法技巧总结 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 免费获取相关内容文档关注:微信公众…...
TFD那智机器人仿真离线程序文本转换为现场机器人程序
TFD式样那智机器人离线程序通过Process Simulation、DELMIA等仿真软件为载体给机器人出离线,下载下来的文本程序,现场机器人一般是无法导入及识别出来的。那么就需要TFD on Desk TFD控制器来进行转换,才能导入现场机器人读取程序。 导入的文…...
贪心+后缀和,CF 1903C - Theofanis‘ Nightmare
一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1903C - Theofanis Nightmare 二、解题报告 1、思路分析 我们任意一种分组其实都是若干个后缀和相加 比如我们分成了三组,第一组的数被加了一次,第二组的数被加了两次,第…...
10分钟完成微信JSAPI支付对接过程-JAVA后端接口
引入架包 <dependency><groupId>com.github.javen205</groupId><artifactId>IJPay-WxPay</artifactId><version>${ijapy.version}</version></dependency>配置类 package com.joolun.web.config;import org.springframework.b…...
如何寻找一个领域的顶级会议,并且判断这个会议的影响力?
如何寻找一个领域的顶级会议,并且判断这个会议的影响力? 会议之眼 快讯 很多同学都在问:学术会议不是期刊,即使被SCI检索,也无法查询影响因子。那么如何知道各个领域的顶级会议,并对各个会议有初步了解呢…...
真的假不了,假的真不了
大家好,我是瑶琴呀,拥有一头黑长直秀发的女程序员。 最近,17岁的中专生姜萍参加阿里巴巴 2024 年的全球数学竞赛,取得了 12 名的好成绩,一时间在网上沸腾不止。 从最开始的“数学天才”,到被质疑ÿ…...
看完这篇文章你就知道什么是未来软件开发的方向了!即生成式AI在软件开发领域的革新=CodeFlying
从最早的UGC(用户生成内容)到PGC(专业生成内容)再到AIGC(人工智能生成内容)体现了web1.0→web2.0→web3.0的发展历程。 毫无疑问UGC已经成为了当前拥有群体数量最大的内容生产方式。 同时随着人工智能技术…...
HTML5五十六个民族网站模板源码
文章目录 1.设计来源高山族1.1 登录界面演示1.2 注册界面演示1.3 首页界面演示1.4 中国民族界面演示1.5 关于高山族界面演示1.6 联系我们界面演示 2.效果和源码2.1 动态效果2.2 源代码2.3 源码目录 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.ne…...
Linux_fileio实现copy文件
参考韦东山老师教程:https://www.bilibili.com/video/BV1kk4y117Tu?p12 目录 1. 通过read方式copy文件2. 通过mmap映射方式copy文件 1. 通过read方式copy文件 copy文件代码: #include <sys/types.h> #include <sys/stat.h> #include <…...
【JavaEE精炼宝库】多线程进阶(2)synchronized原理、JUC类——深度理解多线程编程
一、synchronized 原理 1.1 基本特点: 结合上面的锁策略,我们就可以总结出,synchronized 具有以下特性(只考虑 JDK 1.8): 开始时是乐观锁,如果锁冲突频繁,就转换为悲观锁。 开始是轻量级锁实现ÿ…...
【Linux进程通信】使用匿名管道制作一个简单的进程池
进程池是什么呢?我们可以类比内存池的概念来理解进程池。 内存池 内存池是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继…...
Django 多对多关系
多对多关系作用 Django 中,多对多关系模型的作用主要是为了表示两个模型之间的多对多关系。具体来说,多对多关系允许一个模型的实例与另一个模型的多个实例相关联,反之亦然。这在很多实际应用场景中非常有用,比如: 博…...
构建 Audio Unit 应用程序
构建 Audio Unit 应用程序 构建 Audio Unit 应用程序从选择设计模式开始I/O Pass ThroughI/O Without a Render Callback FunctionI/O with a Render Callback FunctionOutput-Only with a Render Callback Function其他设计模式 构建应用程序配置 audio session指定 audio uni…...
JavaScript 实用技巧
1. 使用 const 和 let 替代 var 在 ES6 之前,我们通常使用 var 声明变量。但如今,推荐使用 const 和 let,因为它们具有块级作用域,可以避免很多潜在的问题。 const PI 3.14; // 常量,无法重新赋值 let age 25; // …...
Python协作运动机器人刚体力学解耦模型
🎯要点 🎯腿式或固定式机器人模型 | 🎯网格、点云和体素网格碰撞检测 | 🎯正反向运动学和动力学 | 🎯机器人刚体力学计算 | 🎯编辑参考系姿势和路径 | 🎯软件接口实体机器人模拟 | Ἲ…...
可重入锁思想,设计MQ迁移方案
如果你的MQ消息要从Kafka切换到RocketMQ且不停机,怎么做?在让这个MQ消息调用第三方发奖接口,但无幂等字段又怎么处理?今天小傅哥就给大家分享一个关于MQ消息在这样的场景中的处理手段。 这是一种比较特例的场景,需要保…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
