【C++手撕系列】——设计日期类实现日期计算器

【C++手撕系列】——设计日期类实现日期计算器😎

  • 前言🙌
    • C嘎嘎类中六大护法实现代码:
      • 获取每一个月天数的函数源码分享
      • 构造函数源码分享
      • 拷贝构造函数源码分享
      • 析构函数源码分享
      • 赋值运算符重载函数源码分享
      • 取地址和const取地址运算符重载函数源码分享
      • 各种比较(> , >= ,< , <= , == , !=)运算符重载函数源码分享
      • 各种运算的 运算符重载函数源码分享
      • 流插入(cout)和流提取(cin)运算符重载函数源码分享
      • 日期 - 日期 函数源码分享
    • Date 日期类头文件源码:
    • Date 日期类功能文件源码:
    • Date 日期类测试文件源码:
    • 测试截图证明:
      • TestDate1函数的测试结果
      • TestDate2函数的测试结果![在这里插入图片描述](https://img-blog.csdnimg.cn/f38c9207a79a4ef98f9eb94b84c7e049.png)
      • 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++ 设计日期类实现日期计算器的知识。希望大家通过阅读此文有所收获
   😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

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

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

相关文章

远程RDP、远控手机、双屏控双屏,向日葵“瓜子会员”妥妥的真香

最近儿有点“小感冒”&#xff0c;没去公司在家歇着&#xff0c;居家归居家&#xff0c;砖还是要搬的&#xff0c;突然来活了也得及时的处理掉&#xff0c;这种时候我一般用远程桌面的方式&#xff0c;之前就一直用的向日葵远程控制。 为啥用远程桌面呢&#xff1f;主要原因是家…

CAD绘制法兰、添加光源、材质并渲染

首先绘制两个圆柱体&#xff0c;相互嵌套 在顶部继续绘制圆柱体&#xff0c;这是之后要挖掉的部分 在中央位置绘制正方形 用圆角工具&#xff1a; 将矩形的四个角分别处理&#xff0c;效果&#xff1a; 用拉伸工具 向上拉伸到和之前绘制的圆柱体高度齐平 绘制一个圆柱体&#…

以太网ICMP协议(九)

目录 一、概述 二、ICMP消息类型 2.1 ICMP类型0和类型8&#xff1a;Ping功能 2.2 ICMP类型3&#xff1a;目标不可达 2.3 ICMP类型5&#xff1a;重定向 2.4 ICMP类型11&#xff1a;超时 三、报文格式 一、概述 由于IP协议是不可靠的通信协议&#xff0c;需要有其他协议的…

Python:Spider爬虫工程化入门到进阶(2)使用Spider Admin Pro管理scrapy爬虫项目

Python&#xff1a;Spider爬虫工程化入门到进阶系列: Python&#xff1a;Spider爬虫工程化入门到进阶&#xff08;1&#xff09;创建Scrapy爬虫项目Python&#xff1a;Spider爬虫工程化入门到进阶&#xff08;2&#xff09;使用Spider Admin Pro管理scrapy爬虫项目 目录 1、使…

MacBook触控板窗口管理 Swish for Mac

Swish for Mac是一款用于通过手势来控制mac应用窗口的软件&#xff0c;你可以通过这款软件在触控板上进行手势控制&#xff0c;你可以在使用前预设好不同手势的功能&#xff0c;然后就能直接通过这些手势让窗口按照你想要的方式进行变动了 Swish 支持 Haptick Feedback 震动反…

用excel格式书写的接口用例执行脚本

创建测试用例和测试结果集文件夹&#xff1a; excel编写的接口测试用例如下&#xff1a; 1 encoding 响应的编码格式。所测项目大部分是utf-8&#xff0c;有一个特殊项目是utf-8-sig 2 params 对应requests的params 3 data&#xff0c;对应requests的data 有些参数是动态的&a…

安卓中常见的字节码指令介绍

问题背景 安卓开发过程中&#xff0c;经常要通过看一些java代码对应的字节码&#xff0c;来了解java代码编译后的运行机制&#xff0c;本文将通过一个简单的demo介绍一些基本的字节码指令。 问题分析 比如以下代码&#xff1a; public class test {public static void main…

SpringCloud源码探析(九)- Sentinel概念及使用

1.概述 在微服务的依赖调用中&#xff0c;若被调用方出现故障&#xff0c;出于自我保护的目的&#xff0c;调用方会主动停止调用&#xff0c;并根据业务需要进行对应处理&#xff0c;这种方式叫做熔断&#xff0c;是微服务的一种保护方式。为了保证服务的高可用性&#xff0c;…

IntelliJ IDEA 2021/2022关闭双击shift全局搜索

我这里演示的是修改&#xff0c;删除是右键的时候选择Remove就好了 IDEA左上角 File-->Settings 找到Navigate -->Search Everywhere &#xff0c;右键添加快捷键。 OK --> Apply应用

GPT-3.5 人工智能还是人工智障?——西红柿炒钢丝球!!

人工智能还是人工智障&#xff1f;——西红柿炒钢丝球 西红柿炒钢丝球的 基本信息西红柿炒钢丝球的 详细制作方法材料步骤 备注幕后花絮。。。。。。。。。关于GPT-3.5&#xff0c;你的看法&#xff1a; 西红柿炒钢丝球的 基本信息 西红柿炒钢丝球是一道具有悠久历史的传统中式…

构建高性能的MongoDB数据迁移工具:Java的开发实践

随着大数据时代的到来&#xff0c;数据迁移成为许多企业和组织必须面对的挑战之一。作为一种非关系型数据库&#xff0c;MongoDB在应用开发中得到了广泛的应用。为了满足数据迁移的需求&#xff0c;我们需要一个高性能、稳定可靠的MongoDB数据迁移工具。下面将分享使用Java开发…

lc15.三数之和

暴力解法&#xff1a;三层for循环&#xff0c;每个循环指向一个变量&#xff0c;求所有的和为零的情况 时间复杂度&#xff1a;O(n3) 空间复杂度&#xff1a;O(1) 双指针 1、对数组进行排序 2、外层循环控制第一个数 i&#xff1b;第一个数的范围必须保证小于等于0&#xf…

docker 部署mysql 5.6集群

docker搭建mysql的集群&#xff08;一主双从&#xff09; 1.拉取镜像 docker pull mysql:5.6 2.启动master容器 docker run -it -d --name mysql_master -p 3306:3306 --ip 192.168.162.100 \ -v /data/mysql_master/mysql:/var/lib/mysql \ -v /data/mysql_master/conf.d…

vue报错‘vue-cli-service‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

运行我的后台管理项目的时候报错&#xff1a;‘vue-cli-service’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 查看自己package.json中是否有vue 或者vue-cli-service 查看自己项目目录下有没有node_module文件夹&#xff0c;如果有删除&#xff0c;然后…

拥抱AIGC浪潮,亚信科技将如何把握时代新增量?

去年底&#xff0c;由ChatGPT带起的AIGC浪潮以迅雷不及掩耳之势席卷全球。 当互联网技术的人口红利逐渐消退之际&#xff0c;AIGC就像打开通用人工智能大门的那把秘钥&#xff0c;加速开启数智化时代的到来。正如OpenAI CEO Sam Altman所言&#xff1a;一个全新的摩尔定律可能…

android ndk clang交叉编译ffmpeg动态库踩坑

1.ffmpeg默认使用gcc编译&#xff0c;在android上无法使用&#xff0c;否则各种报错&#xff0c;所以要用ndk的clang编译 2.下载ffmpeg源码 修改configure文件&#xff0c;增加命令 cross_prefix_clang 修改以下命令 cc_default"${cross_prefix}${cc_default}" cxx…

Vue.js2+Cesium1.103.0 八、动态光墙效果

Vue.js2Cesium1.103.0 八、动态光墙效果 Demo <template><divid"cesium-container"style"width: 100%; height: 100%;"/> </template><script> /* eslint-disable no-undef */ import /utils/dynamicWallMaterialProperty.js exp…

【脚踢数据结构】

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言,Linux基础,ARM开发板&#xff0c;软件配置等领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff01;送给自己和读者的一句鸡汤&#x1f914;&…

服务器时钟同步

服务器时钟同步 文章目录 服务器时钟同步背景windows时钟同步Linux机器上的时钟同步Centos时钟同步Ubuntu系统时钟同步 查看是否同步的命令 背景 运维&#xff0c;XXX服务器慢了2秒&#xff0c;导致XXX业务没有正常执行&#xff0c;请立即排查为啥会有时钟不同步的问题。 首先…

neo4j终端操作

1】进入容器 (base) xiaokkkxiaokkkdeMacBook-Pro ~ % docker exec -it 77ed5fe2b52e /bin/bash 2】启动、停止neo4j root77ed5fe2b52e:/var/lib/neo4j/bin# ./neo4j start Neo4j is already running (pid:7). Run with --verbose for a more detailed error message.root7…