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

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

😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!
😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘

前言🙌

哈喽各位友友们😊,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下! 都是精华内容,可不要错过哟!!!😍😍😍

最近学习了C++的类和对象这部分的内容,然后自己手痒痒,就在空闲的时候手撕了一个日期类,按照网页版日期计算器有的功能进行一个一一的实现。纯粹分享,如果大家对日期计算器感兴趣的话也可以去实现一个自己的日期计算器,也可以借鉴我写的代码,有不懂的也可以来问我哦~废话不多说,咋们开始啦!!!

C嘎嘎类中六大护法实现代码:

在C嘎嘎中,有六大护法一直守护我们的类。分别是:

  • 构造函数
  • 析构函数
  • 拷贝构造函数
  • 赋值运算符重载函数
  • 取地址重载函数
  • const取地址重载函数

获取每一个月天数的函数源码分享

这里要注意的就是闰年和平年的2月天数的确定。闰年2月是29,平年是28天。

cpp 复制代码
//获取每一个月的天数
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];
}

构造函数源码分享

这里需要注意的就是输入非法日期的情况,所以这里要给个检查,当输入非法日期就报错!!!

cpp 复制代码
//构造函数
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;
	}
}

拷贝构造函数源码分享

这里可以不用写拷贝构造,编译器可以默认生成。

cpp 复制代码
//拷贝构造函数
Date:: Date(const Date& d)
	:_year(d._year)
	, _month(d._month)
	, _day(d._day)
{}

析构函数源码分享

这里可以不用写析构,编译器可以默认生成。

cpp 复制代码
//析构函数
Date:: ~Date()
{}

赋值运算符重载函数源码分享

这里要避免 d1 = d1(自己给自己赋值)情况,所以加一个检查。其实也不用自己显示实现,编译器默认生成的赋值重载函数就可以了满足需求了~

cpp 复制代码
//赋值运算符重载
Date& Date::operator=(const Date& d)
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	return *this;
}

取地址和const取地址运算符重载函数源码分享

一般这两个函数不用写,编译器默认生成的就可以了。这里知识闲着无聊先出来看看而已。

cpp 复制代码
//取地址和const取地址运算符重载
Date* Date:: operator&()
{
	return this;
}


const Date* Date:: operator&()const
{
	return this;
}

各种比较(> , >= ,< , <= , == , !=)运算符重载函数源码分享

cpp 复制代码
//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进行占位,用于区分前置和后置++;同理前置- -与后置- -也是这样规定实现的。

cpp 复制代码
// 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)运算符重载函数源码分享

cpp 复制代码
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,答案自然就是正数。

cpp 复制代码
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 日期类头文件源码:

cpp 复制代码
#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 日期类功能文件源码:

cpp 复制代码
#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 日期类测试文件源码:

cpp 复制代码
#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++ 设计日期类实现日期计算器的知识。希望大家通过阅读此文有所收获!

😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

相关推荐
wkd_00716 分钟前
【开源库 | xlsxio】C/C++读写.xlsx文件,xlsxio 在 Linux(Ubuntu18.04)的编译、交叉编译
c语言·c++·xlsxio·c语言读写xlsx·c++读写xlsx·xlsxio交叉编译
IT 古月方源29 分钟前
ensp 关于ARRP 的讲解 配置
运维·开发语言·网络·tcp/ip·智能路由器
西猫雷婶34 分钟前
python学opencv|读取图像(二十二)使用cv2.polylines()绘制多边形
开发语言·python·opencv
温轻舟37 分钟前
前端开发 -- 自定义鼠标指针样式
开发语言·前端·javascript·css·html·温轻舟
xiaocaibao7771 小时前
编程语言的软件工程
开发语言·后端·golang
Ocean☾1 小时前
C语言-基因序列转换独热码(one-hot code)
c语言·开发语言
2401_858286111 小时前
117.【C语言】数据结构之排序(选择排序)
c语言·开发语言·数据结构·笔记·算法·排序算法
捕鲸叉1 小时前
C++软件设计模式之类型模式和对象型模式
开发语言·c++·设计模式
魔道不误砍柴功1 小时前
Java 中反射的高级用法:窥探 Java 世界的魔法之门
java·开发语言·python
2401_857617621 小时前
“无缝购物体验”:跨平台网上购物商城的设计与实现
java·开发语言·前端·安全·架构·php