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

news2025/3/18 2:16:35

【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.coloradmin.cn/o/864016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何写一篇吸引人的新闻稿?揭秘新闻稿写作的技巧!

一篇高质量的新闻稿不仅能够吸引读者的眼球&#xff0c;还能提高文章的曝光量。下面&#xff0c;伯乐网络传媒将给大家揭秘新闻稿写作的十大技巧&#xff0c;帮助大家写出更有吸引力的新闻稿。 1. 选择热门而有吸引力的话题或爆点 要想写出一篇吸引人的新闻稿&#xff0c;首先…

【前端】CSS水平居中的6种方法

左右两边间隔相等的居中 文章目录 flex绝对定位margin:auto绝对定位margin:负值定位transformtext-align: center;margin: 0 auto;思维导图 flex display: flex;justify-content: center; <div classparent><div class"son"></div> </div>…

【VUE】7、VUE项目中集成watermark实现页面添加水印

在网站浏览中&#xff0c;常常需要网页水印&#xff0c;以便防止用户截图或录屏暴露敏感信息后&#xff0c;方便追踪用户来源。 1、安装 watermark 在 package.json 文件 dependencies 节点增加 watermark-dom 依赖 "watermark-dom": "2.3.0"然后执行命…

fastadmin 自定义搜索分类和时间范围

1.分类搜索&#xff0c;分类信息获取----php 2.对应html页面&#xff0c;页面底部加搜索提交代码&#xff08;这里需要注意&#xff1a;红框内容&#xff09; 图上代码----方便直接复制使用 <script id"countrySearch" type"text/html"><!--form…

初识鸿蒙跨平台开发框架ArkUI-X

HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。在传统的单设备系统能力基础上&#xff0c;HarmonyOS提出了基于同一套系统能力、适配多种终端形态的分布式理念&#xff0c;能够支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备&#xff0c;提供全场景&#…

vue项目里面有多个模块的服务,前端处理url转发

先看下vue的代理配置里面&#xff1a; 现在是在 /pca 基础上增加了 2个模块的服务&#xff1a; /dca、 /api 现在服务器的nginx 没有在/pca 服务里面做转发接受 /dca、 /api的服务&#xff0c;所以需要前端自己去配置每个服务模块对应的 URL 先拿登录的api 做示例吧: 先定义…

多用户微商城多端智慧生态电商系统搭建

多用户微商城多端智慧生态电商系统的搭建步骤如下&#xff1a; 系统规划&#xff1a;在搭建多用户微商城多端智慧生态电商系统之前&#xff0c;需要进行系统规划。包括确定系统的目标、功能、架构、技术选型、开发流程等方面。市场调研&#xff1a;进行市场调研&#xff0c;了…

解决createRoot is not a function

报错&#xff1a; 出现的原因&#xff1a;在于把react18使用的vite构建&#xff0c;在开发中因react版本太高与其他库不兼容&#xff0c;而在降级的时候&#xff0c;出现以上dom渲染出现报错。 解决&#xff1a;将 src/index.j文件改成如下 import React from react; import…

玩转C链表

链表是C语言编程中常用的数据结构&#xff0c;比如我们要建一个整数链表&#xff0c;一般可能这么定义&#xff1a; struct int_node {int val;struct int_node *next;}; 为了实现链表的插入、删除、遍历等功能&#xff0c;另外要再实现一系列函数&#xff0c;比如&#xff1a…

微星游戏本旗舰性价比爆款:泰坦GP68 HX新品开启预售

微星游戏本金字塔尖的旗舰泰坦系列&#xff0c;讲究的就是一个“极致的性能释放”&#xff1a;除了机皇泰坦GT&#xff0c;旗舰性能的泰坦GE以外&#xff0c;泰坦GP则成为了泰坦系列中、甚至所有旗舰游戏本产品中的“旗舰游戏本的守门员”&#xff0c;让更多性能控玩家&#xf…

linux pwn 基础知识

环境搭建 虚拟机安装 镜像下载网站为了避免环境问题建议 22.04 &#xff0c;20.04&#xff0c;18.04&#xff0c;16.04 等常见版本 ubuntu 虚拟机环境各准备一份。注意定期更新快照以防意外。虚拟机建议硬盘 256 G 以上&#xff0c;内存也尽量大一些。硬盘大小只是上界&#…

Mongodb:业务应用(1)

环境搭建参考&#xff1a;mongodb&#xff1a;环境搭建_Success___的博客-CSDN博客 需求&#xff1a; 在文章搜索服务中实现保存搜索记录到mongdb 并在搜索时查询出mongdb保存的数据 1、安装mongodb依赖 <dependency><groupId>org.springframework.data</groupI…

rknn3588如何查看npu使用情况

cat /sys/kernel/debug/rknpu/load在Linux中&#xff0c;你可以使用一些工具和命令来绘制某一进程的实时内存折线图。一个常用的工具是gnuplot&#xff0c;它可以用来绘制各种图表&#xff0c;包括折线图。 首先&#xff0c;你需要收集进程的实时内存数据。你可以使用pidstat命…

餐馆包厢隔断装修该怎么去设计

餐馆包厢隔断装修设计需要综合考虑以下几个方面&#xff1a; 1. 功能布局&#xff1a;根据包厢的面积和形状来确定餐桌、椅子、电视等家具的摆放方式&#xff0c;保证客人的用餐舒适度和便利性。 2. 音响设备&#xff1a;安装合适的音响设备&#xff0c;提供一定的音乐背景&…

商城-学习整理-基础-库存系统(八)

一、整合ware服务 1、配置注册中心 2、配置配置中心 3、配置网关&#xff0c;重启网关 二、仓库维护 http://localhost:8001/#/ware-wareinfo 在前端项目module中创建ware文件夹保存仓库系统的代码。 将生成的wareinfo.vue文件拷贝到项目中。 根据功能&#xff0c;修改后台接…

电感与磁珠

电感最重要的公式&#xff1a; 它说明了电感的很多特性。比如&#xff1a; 电感电流不能突变 电感的储能大小 电感的电流与电压的相位关系 还有电感的阻抗为什么是jwL。 电感电流不能突变 电感电流为什么不能突变呢&#xff1f;来看这个公式&#xff0c;U等于负的L乘以di…

「C/C++」C/C++正则表达式

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C」C/C程序设计「Win」Windows程序设计「DSA」数据结构与算法「File」数据文件格式 目录 术语介绍…

opencv基础60-用分水岭算法cv2.distanceTransform()实现图像分割与提取原理及示例

在图像处理的过程中&#xff0c;经常需要从图像中将前景对象作为目标图像分割或者提取出来。例如&#xff0c;在视频监控中&#xff0c;观测到的是固定背景下的视频内容&#xff0c;而我们对背景本身并无兴趣&#xff0c;感兴趣的是背景中出现的车辆、行人或者其他对象。我们希…

CSP复习每日一题(四)

树的重心 给定一颗树&#xff0c;树中包含 n n n 个结点&#xff08;编号 1 ∼ n 1∼n 1∼n&#xff09;和 n − 1 n−1 n−1条无向边。请你找到树的重心&#xff0c;并输出将重心删除后&#xff0c;剩余各个连通块中点数的最大值。 重心定义&#xff1a; 重心是指树中的一…

C++初阶语法——类和对象

前言&#xff1a;C语言中的结构体&#xff0c;在C有着更高位替代者——类。而类的实例化叫做对象。 本篇文章不定期更新扩展后续内容。 目录 一.面向过程和面向对象初步认识二.类1.C中的结构体2.类的定义类的两种定义方式 3.类的访问限定符及封装访问限定符说明 4.类的实例化对…