【C++手撕系列】——设计日期类实现日期计算器
【C++手撕系列】——设计日期类实现日期计算器😎
- 前言🙌
- C嘎嘎类中六大护法实现代码:
- 获取每一个月天数的函数源码分享
- 构造函数源码分享
- 拷贝构造函数源码分享
- 析构函数源码分享
- 赋值运算符重载函数源码分享
- 取地址和const取地址运算符重载函数源码分享
- 各种比较(> , >= ,< , <= , == , !=)运算符重载函数源码分享
- 各种运算的 运算符重载函数源码分享
- 流插入(cout)和流提取(cin)运算符重载函数源码分享
- 日期 - 日期 函数源码分享
- Date 日期类头文件源码:
- Date 日期类功能文件源码:
- Date 日期类测试文件源码:
- 测试截图证明:
- TestDate1函数的测试结果
- TestDate2函数的测试结果
- TestDate3函数的测试结果
- TestDate4函数的测试结果
- 小结语:
- 总结撒花💞
😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!
😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘
前言🙌
哈喽各位友友们😊,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下! 都是精华内容,可不要错过哟!!!😍😍😍
最近学习了C++的类和对象这部分的内容,然后自己手痒痒,就在空闲的时候手撕了一个日期类,按照网页版日期计算器有的功能进行一个一一的实现。纯粹分享,如果大家对日期计算器感兴趣的话也可以去实现一个自己的日期计算器,也可以借鉴我写的代码,有不懂的也可以来问我哦~废话不多说,咋们开始啦!!!
C嘎嘎类中六大护法实现代码:
在C嘎嘎中,有六大护法一直守护我们的类。分别是:
- 构造函数
- 析构函数
- 拷贝构造函数
- 赋值运算符重载函数
- 取地址重载函数
- const取地址重载函数
获取每一个月天数的函数源码分享
这里要注意的就是闰年和平年的2月天数的确定。闰年2月是29,平年是28天。
//获取每一个月的天数
int Date::GetMonthDay(int year, int month) const
{int DateArray[13] = { 0, 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;}return DateArray[month];
}
构造函数源码分享
这里需要注意的就是输入非法日期的情况,所以这里要给个检查,当输入非法日期就报错!!!
//构造函数
Date:: Date(int year, int month , int day):_year(year),_month(month),_day(day)
{if (month < 1 || month > 12 || day < 1|| day > GetMonthDay(_year, _month)){cout << "输入日期非法" << endl;}
}
拷贝构造函数源码分享
这里可以不用写拷贝构造,编译器可以默认生成。
//拷贝构造函数
Date:: Date(const Date& d):_year(d._year), _month(d._month), _day(d._day)
{}
析构函数源码分享
这里可以不用写析构,编译器可以默认生成。
//析构函数
Date:: ~Date()
{}
赋值运算符重载函数源码分享
这里要避免 d1 = d1(自己给自己赋值)情况,所以加一个检查。其实也不用自己显示实现,编译器默认生成的赋值重载函数就可以了满足需求了~
//赋值运算符重载
Date& Date::operator=(const Date& d)
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;
}
取地址和const取地址运算符重载函数源码分享
一般这两个函数不用写,编译器默认生成的就可以了。这里知识闲着无聊先出来看看而已。
//取地址和const取地址运算符重载
Date* Date:: operator&()
{return this;
}const Date* Date:: operator&()const
{return this;
}
各种比较(> , >= ,< , <= , == , !=)运算符重载函数源码分享
//d1 < d2
bool Date::operator<(const Date& d) const
{if (_year < d._year){return true;}else if (_year == d._year && _month < d._month){return true;}else if (_year == d._year && _month == d._month && _day < d._day){return true;}else{return false;}
}//d1 == d2
bool Date::operator==(const Date& d) const
{if (_year == d._year && _month == d._month&& _day == d._day){return true;}return false;
}//d1 <= d2
bool Date::operator<=(const Date& d) const
{return (*this < d) || (*this == d);
}//d1 > d2
bool Date::operator>(const Date& d) const
{return !((*this) <= d);
}//d1 >= d2
bool Date::operator>=(const Date& d) const
{return !((*this) < d);
}//d1 != d2
bool Date::operator!=(const Date& d) const
{return !((*this) == d);
}
各种运算的 运算符重载函数源码分享
这里写好了+= ,然后复用 += 实现 + ;同理,写好了 -= ,我们就可以复用 -= 来实现 - 。前置++和后置++,区别是后置++参数列表加一个int进行占位,用于区分前置和后置++;同理前置- -与后置- -也是这样规定实现的。
// d1 += d2
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) const
{Date tem(*this);tem += day;return tem;
}Date& 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 Date::operator-(int day) const
{Date tem(*this);tem -= day;return tem;
}Date& Date::operator++()
{*this += 1;return *this;
}Date Date::operator++(int)
{Date tem(*this);++(*this);return tem;
}
Date& Date::operator--()
{(*this) -= 1;return *this;
}
Date Date::operator--(int)
{Date tem(*this);(*this) -= 1;return tem;
}
流插入(cout)和流提取(cin)运算符重载函数源码分享
ostream& operator<< (ostream& out,const Date& d)
{out << d._year << "/" << d._month << "/" << d._day << endl;return out;
}istream& operator>>(istream& in, Date& d)
{in >> d._year;in >> d._month;in >> d._day;return in;
}
日期 - 日期 函数源码分享
这个函数实现比较难想出来。这里先是确定出两个日期的大小关系,然后让小的日期不断++,n记录加的次数(也就是两个日期相隔的天数,当两个日期相等时,n*flag 就是结果。这里的flag是一个关键,当一开始是小日期 - 大日期时,flag 就是-1,计算出的答案自然是负数;当是大日期减小日期,flag就是1,答案自然就是正数。
int Date::operator-(const Date& d) const
{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 日期类头文件源码:
#pragma once#include<iostream>
using namespace std;class Date
{// 友元声明friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);public:int GetMonthDay(int year, int month) const;Date(int year = 1, int month = 1, int day = 1);//void Print() const;Date(const Date& d);~Date();// 只读函数可以加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;// 函数重载// 运算符重载// ++d1 -> d1.operator++()Date& operator++();// d1++ -> d1.operator++(0)// 加一个int参数,进行占位,跟前置++构成函数重载进行区分// 本质后置++调用,编译器进行特殊处理Date operator++(int);Date& operator--();Date operator--(int);Date& operator=(const Date& d);int operator-(const Date& d) const;// 日常自动生成的就可以// 不想被取到有效地址Date* operator&();const Date* operator&() const;
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);
Date 日期类功能文件源码:
#define _CRT_SECURE_NO_WARNINGS 1
#include"Date.h"//获取每一个月的天数
int Date::GetMonthDay(int year, int month) const
{int DateArray[13] = { 0, 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;}return DateArray[month];
}//构造函数
Date:: Date(int year, int month , int day):_year(year),_month(month),_day(day)
{if (month < 1 || month > 12 || day < 1|| day > GetMonthDay(_year, _month)){cout << "输入日期非法" << endl;}
}//拷贝构造函数
Date:: Date(const Date& d):_year(d._year), _month(d._month), _day(d._day)
{}//析构函数
Date:: ~Date()
{}//赋值运算符重载
//避免 d1 = d1(自己给自己赋值)情况
Date& Date::operator=(const Date& d)
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;
}//取地址和const取地址运算符重载
Date* Date:: operator&()
{return this;
}const Date* Date:: operator&()const
{return this;
}//d1 < d2
bool Date::operator<(const Date& d) const
{if (_year < d._year){return true;}else if (_year == d._year && _month < d._month){return true;}else if (_year == d._year && _month == d._month && _day < d._day){return true;}else{return false;}
}//d1 == d2
bool Date::operator==(const Date& d) const
{if (_year == d._year && _month == d._month&& _day == d._day){return true;}return false;
}//d1 <= d2
bool Date::operator<=(const Date& d) const
{return (*this < d) || (*this == d);
}//d1 > d2
bool Date::operator>(const Date& d) const
{return !((*this) <= d);
}//d1 >= d2
bool Date::operator>=(const Date& d) const
{return !((*this) < d);
}//d1 == d2
bool Date::operator!=(const Date& d) const
{return !((*this) == d);
}// d1 += d2
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) const
{Date tem(*this);tem += day;return tem;
}Date& 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 Date::operator-(int day) const
{Date tem(*this);tem -= day;return tem;
}ostream& operator<< (ostream& out,const Date& d)
{out << d._year << "/" << d._month << "/" << d._day << endl;return out;
}istream& operator>>(istream& in, Date& d)
{in >> d._year;in >> d._month;in >> d._day;return in;
}Date& Date::operator++()
{*this += 1;return *this;
}Date Date::operator++(int)
{Date tem(*this);++(*this);return tem;
}
Date& Date::operator--()
{(*this) -= 1;return *this;
}
Date Date::operator--(int)
{Date tem(*this);(*this) -= 1;return tem;
}int Date::operator-(const Date& d) const
{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 日期类测试文件源码:
#define _CRT_SECURE_NO_WARNINGS
#include"Date.h"//6大默认成员函数测试
void TestDate1()
{//构造测试Date d1;//拷贝构造测试Date d2(2023, 8, 11);//流插入运算符重载测试cout << d1;cout << d2;//流提取运算符重载测试cin >> d1;cout << d1;//取地址运算符重载测试cout << &d1 << endl;cout << &d2;}//测试日期大小比较以及计算日期往后或者往前几天的日期是多少
void TestDate2()
{Date d1(2003, 8, 23);Date d2(2023, 8, 11);/*cout << (d1 < d2) << endl;cout << (d1 <= d2) << endl;cout << (d1 > d2) << endl;cout << (d1 >= d2) << endl;cout << (d1 == d2) << endl;cout << (d1 != d2) << endl;*///cout << d1;//d1 += 10000;//cout << d1;//d2 = d1 + 10000;//cout << d1;//cout << d2;//d1 += -1000;//cout << d1;//d1 = d2 + -1000;//cout << d1;/*d1 -= 11000;d2 = d1 - 1000;cout << d1;cout << d2;*/}void TestDate3()
{Date d1(2003, 8, 23);Date d2(2023, 8, 11);/*cout << d1;++d1;cout << d1;*//*cout << d1;d2 = d1++;cout << d1;cout << d2;*//*cout << d1;d2 = d1--;cout << d1;cout << d2;*//*cout << d1;d2 = ++d1;cout << d1;cout << d2;*//*cout << d1;d2 = --d1;cout << d1;cout << d2;*/
}void TestDate4()
{Date d1(2003, 8, 23);Date d2(2023, 8, 11);cout << (d2 - d1) << endl;cout << (d1 - d2) << endl;
}int main()
{//TestDate1();//TestDate2();//TestDate3();TestDate4();return 0;
}
测试截图证明:
TestDate1函数的测试结果

TestDate2函数的测试结果
TestDate3函数的测试结果

TestDate4函数的测试结果

与网页版日期计算器测试结果一致!!!!!

小结语:
上述测试案例我只写了比较常规的,并没有做会更加仔细的测试。大家也可以帮我用链接: 网页版日期计算器测试一下我的程序有没有bug,我好及时更正!!!
总结撒花💞
本篇文章旨在分享的是用C++ 设计日期类实现日期计算器的知识。希望大家通过阅读此文有所收获!
😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘
相关文章:
【C++手撕系列】——设计日期类实现日期计算器
【C手撕系列】——设计日期类实现日期计算器😎 前言🙌C嘎嘎类中六大护法实现代码:获取每一个月天数的函数源码分享构造函数源码分享拷贝构造函数源码分享析构函数源码分享赋值运算符重载函数源码分享取地址和const取地址运算符重载函数源码分…...
FFmpeg常见命令行(四):FFmpeg流媒体
前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》,结合我自己的工作学习经历,我准备写一个音视频系列blog。本文是音视频系…...
ftp访问ubuntu文件系统
ftp访问ubuntu文件系统 安装vsftpd服务器 sudo apt-get install vsftpd启动ftp服务 sudo service vsftpd start编辑vsftdp的配置文件 sudo vim /etc/vsftpd.conf找到write_enable字段并修改, 设定可以进行写操作,保存并退出 write_enable=YES从新启动ftp服务...
网络防御(6)
密码学综合应用 定义: 密码学综合应用是指将密码学的理论和技术应用于各种场景中,以保障信息的安全性、完整性和可靠性。密码学的应用范围非常广泛,包括通信安全、网络安全、电子商务、数字签名、认证、密钥管理等。 密码学综合应用的实例…...
【Nginx15】Nginx学习:HTTP核心模块(十二)内嵌变量
Nginx学习:HTTP核心模块(十二)内嵌变量 关于内嵌变量,其实就是 Nginx 开放给我们的在配置文件中可以使用的变量。源码中无非就是替换成真实的代码变量进行操作。这些变量可以帮助我们做很多事情。之前的文章中其实也有不少地方用到…...
2023年中国HPV宫颈癌疫苗需求量、竞争格局、市场规模及行业细分产品规模分析[图]
HPV宫颈癌疫苗也是人乳头瘤病毒疫苗,由重组表达的HPV主要衣壳蛋白L1病毒样颗粒制备而成,可以预防由HPV感染及其引起的各种疾病,包括宫颈癌、阴道癌、肛门癌和口咽癌等癌症,及相关癌前病变。 目前中国在售的HPV疫苗包括万泰生物的二…...
基于LMK2572的FPGA逻辑实现
项目背景: 在时钟同步或类似时钟方案系统,需要用到一些时钟芯片,LMK2572就是一款频率带宽覆盖广的芯片。 项目介绍: LMK2572该器件是一个低功耗、高性能的宽带合成器,可生成 13MHz 到 6.4GHz 的任何频率,而无需使用内部倍频器。该 PLL 可提供优异的性能,而 3.3V 单电源…...
数据通信——VRRP
引言 之前把实验做了,结果发现我好像没有写过VRRP的文章,连笔记都没记过。可能是因为对STP的记忆,导致现在都没忘太多。 一,什么是VRRP VRRP全名是虚拟路由冗余协议,虚拟路由,看名字就知道这是运行在三层接…...
第二章:CSS基础进阶-part2:CSS过渡与动画
文章目录 CSS3 过渡动画一、transition属性二、transform属性-2D变换2.1 tanslate : 移动2.2 rotate-旋转2.3 scale-变形2.4 skew-斜切2.5 transform-origin: 变换中心点设置 三、CSS3关键帧动画四、CSS3-3D变换4.1 perspective 定义3D元素距视图距离4.2 transform-…...
华为OD真题---玩牌高手--带答案
2023华为OD统一考试(AB卷)题库清单-带答案(持续更新)or2023年华为OD真题机考题库大全-带答案(持续更新) 玩牌高手 给定一个长度为n的整型数组,表示一个选手在n轮内可选择的牌面分数。选手基于规…...
案例14 Spring MVC文件上传案例
基于Spring MVC实现文件上传: 使用commons-fileupload实现上传文件到本地目录。 实现上传文件到阿里云OSS和从阿里云OSS下载文件到本地。 1. 创建项目 选择Maven快速构建web项目,项目名称为case14-springmvc03。 2. 配置Maven依赖 <?xml ver…...
如何用Python实现多线程
1 问题 线程是操作系统能够进行运算调度的最小单位。进程被包含在进程中,是进程中实际处理单位。一条线程就是一堆指令集合。一条线程是指进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。那么如何用pyt…...
Chrome浏览器导出插件并安装到其他电脑浏览器上的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
对话即数据分析,网易数帆ChatBI做到了
大数据产业创新服务媒体 ——聚焦数据 改变商业 在当今数字化快速发展的时代,数据已经成为业务经营与管理决策的核心驱要素。无论是跨国大企业还是新兴创业公司,正确、迅速地洞察数据已经变得至关重要。然而,传统的BI工具往往对用户有一定的…...
简单记录牛客top101算法题(初级题C语言实现)BM17 二分查找 BM21 旋转数组的最小数字 BM23 二叉树的前序遍历
1. BM17 二分查找 要求:给定一个 元素升序的、无重复数字的整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标(下标从 0 开始),否则返回 -1。 输入:…...
日常BUG——Java使用Bigdecimal类型报错
😜作 者:是江迪呀✒️本文关键词:日常BUG、BUG、问题分析☀️每日 一言 :存在错误说明你在进步! 一、问题描述 直接上代码: Test public void test22() throws ParseException {System.out.p…...
为Windows Terminal设置背景图片
直接通过界面上选项无法达到修改背景图片的目的,后再在官网,和git上找到通过修改配置文件来更改背景图片 首先打开设置界面 点击左下角打开settings.json文件 在json中profiles关键字default选项相面增加几个key,就像下面 修改前修改后 修改后的termin…...
【Spring】-Spring中Bean对象的存取
作者:学Java的冬瓜 博客主页:☀冬瓜的主页🌙 专栏:【Framework】 主要内容:往spring中存储Bean对象的三大方式:XML方式(Bean标签);五大类注解;方法注解。从spring中取对象的两种方式…...
机器人CPP编程基础-03变量类型Variables Types
机器人CPP编程基础-02变量Variables 全文AI生成。 C #include<iostream>using namespace std;main() {int a10,b35; // 4 bytescout<<"Value of a : "<<a<<" Address of a : "<<&a <<endl;cout<<"Val…...
或许有用的开源项目平台——物联网、区块链、商城、CMS、客服系统、低代码、可视化、ERP等
摘自个人印象笔记Evernote Export wumei-smart-物美智能开源物联网平台 官网:https://wumei.live/ gitee:https://gitee.com/kerwincui/wumei-smart 一个简单易用的物联网平台。可用于搭建物联网平台以及二次开发和学习。适用于智能家居、智慧办公、智慧…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

