C++实战项目:日期计算器的实现

前言

Hello,小伙伴们,经过了前面对C++基础知识的学习,我们今天就着重运用一下前面学习到的知识,来通过类和对象以及运算符重载的部分知识来实现,来完成我们的日期计算器。

日期计算器,顾名思义,就是可以通过日期和天数来进行年、月、日的转换、计算。

1.可以实现具体日期与天数的加减,并得到加减计算后的日期。

2.可以实现两个具体日期之间的加减,计算两日期之间相差的天数。

功能不是特别的复杂,我们现在就可以着手尝试了。

好,按例三连上车不迷路,开始我们今天的内容。

在看这篇文章的时候,强烈推荐大家先看看我之前的这两篇文章,来学习一下C++类和对象的基础:
http://t.csdnimg.cn/OY9mJ

http://t.csdnimg.cn/ZK1sA

1.日期类的定义

首先我们要定义一个日期类,运用我们刚学习的C++知识,我们这里直接看代码:

案例,我们还是先创建3个文件来实现我们的目的

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
class Date
{
public:
	Date(int year = 2024, int month = 8, int day = 16);
	//~Date();

private:
	int _year;
	int _month;
	int _day;
};

在这里,我们先来解决构造函数和析构函数的问题:

构造函数:

我们在Date.cpp文件中实现他的功能:

cpp 复制代码
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

由于在日期类中,我们没有申请内存空间,也就是该类中不存在深度拷贝,因此我们就不需要自己单独实现析构函数。

2.日期类的打印(DatePrint)

完成构造函数后,我们就可以通过打印函数来显示我们定义的日期类的值:

首先我们要完成日期打印函数的声明:

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
class Date
{
public:
	Date(int year = 2024, int month = 8, int day = 16);
	//~Date();
    void DatePeint();//日期打印
private:
	int _year;
	int _month;
	int _day;
};

接下来我们来实现日期类打印函数的功能:

cpp 复制代码
void Date::DatePrint()
{
	cout << _year << "/" << _month << "/" << _day << endl;
}

接下来我们来展示一下这个函数的功能:

3.比较运算符的重载

前面我们学习了运算符重载方面的知识,我们接下来就设计及应用一下:

比较运算符的种类有很多,但是在运算符重载上实现的方法基本一样,这里借用我们前面学到的知识很容易就能实现:

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
class Date
{
public:
	Date(int year = 2024, int month = 8, int day = 16);
	//~Date();
    void DatePeint();//日期打印
//比较大小运算符的重载
bool operator==(Date& d);
bool operator!=(Date& d);
bool operator>(Date& d);
bool operator<(Date& d);
bool operator<=(Date& d);
bool operator>=(Date& d);
private:
	int _year;
	int _month;
	int _day;
};

代码实现:

cpp 复制代码
bool Date::operator==(Date& d)
{
	return _year == d._day 
		&& _month == d._month
		&& _day == d._day;
}
Date& Date::operator=(const Date& d1)
{
	
		_year = d1._year;
		_month = d1._month;
		_day = d1._day;

	return *this;

}

bool Date::operator!=(Date& d)
{
	return !(*this == d);
}
bool Date::operator>(Date& d)
{
	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;
	}
	return false;
}
bool Date::operator<(Date& d)
{
	return !(*this >= d);
}
bool Date::operator<=(Date& d)
{
	return *this < d || *this == d;
}
bool Date::operator>=(Date& d)
{
	return *this > d || *this == d;
}

运算符重载的实现逻辑十分的灵活,我们只需要实现几种基本的运算符重载,其他的我们就能够根据已知的运算关系,并运用或且非的逻辑关系来实现其余的运算符重载。

4.日期+= 和 +操作(日期加天数)的实现

首先我们还是先来定义这个运算符的重载:

要实现日期与天数的加操作,我们就好要得到每个月的天数:

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
class Date
{
public:
	Date(int year = 2024, int month = 8, int day = 16);
	//~Date();
    void DatePeint();//日期打印
//比较大小运算符的重载
bool operator==(Date& d);
bool operator!=(Date& d);
bool operator>(Date& d);
bool operator<(Date& d);
bool operator<=(Date& d);
bool operator>=(Date& d);
//获取每个月的天数
int GetMonthDay(int year, int month)
{
	assert(month >= 1 && month <= 12);
	//因为这个数组会高频·的进行调用,所以使用静态数组就能极大地提高效率
	static int MonthDay[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;
	}
	return MonthDay[month];
}
Date& operator+=(int day);//日期与天数的加运算
Date operator+(int day);
private:
	int _year;
	int _month;
	int _day;
};

实现的逻辑也十分的简单,我们先来看看代码:

cpp 复制代码
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)
{
	Date tmp = *this;
	tmp += day;
	return tmp;
}

接下来我们来看看效果

接下来,我们使用网上的日期运算器来验证一下答案是否正确:

5.日期-=和 -操作(日期减天数)的实现

日期与天数的想减得到日期的算法和前面的相加算法也相似。

我们还是先来定义相减运算:

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
class Date
{
public:
	Date(int year = 2024, int month = 8, int day = 16);
	//~Date();
    void DatePeint();//日期打印
//比较大小运算符的重载
bool operator==(Date& d);
bool operator!=(Date& d);
bool operator>(Date& d);
bool operator<(Date& d);
bool operator<=(Date& d);
bool operator>=(Date& d);
//获取每个月的天数
int GetMonthDay(int year, int month)
{
	assert(month >= 1 && month <= 12);
	//因为这个数组会高频·的进行调用,所以使用静态数组就能极大地提高效率
	static int MonthDay[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;
	}
	return MonthDay[month];
}
Date& operator+=(int day);//日期与天数的加运算
Date operator+(int day);
Date& operator+=(int day);//日期与天数的减运算
Date operator+(int day);
private:
	int _year;
	int _month;
	int _day;
};

减运算符重载的实现与加运算符的实现逻辑基本相同,我们直接看代码:

cpp 复制代码
Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		return (*this += -day);
	}
	_day -= day;
	while (_day <= 0)
	{
		_day += GetMonthDay(_year, _month);
		_month--;
		while (_month <= 0)
		{
			_year--;
			_month = 12;
		}
	}
	return *this;
}
Date Date::operator-(int day)
{
	Date tmp = *this;
	tmp -= day;
	return tmp;
}

接下来我们来测试一下运行效果:

让我们用日期计算器来验算一下日期的计算结果是否正确:

6. 前置++(--)与后置++(--)

根据我们前面的基础知识,我们知道前置++(--)和后置++(--)的冲在式定义就是根据是否有参数来判断的,所以本质上他们的实现就与+=(-=)和-=(-) 相似。

首先来看定义:

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
class Date
{
public:
	Date(int year = 2024, int month = 8, int day = 16);
	//~Date();
    void DatePeint();//日期打印
//比较大小运算符的重载
bool operator==(Date& d);
bool operator!=(Date& d);
bool operator>(Date& d);
bool operator<(Date& d);
bool operator<=(Date& d);
bool operator>=(Date& d);
//获取每个月的天数
int GetMonthDay(int year, int month)
{
	assert(month >= 1 && month <= 12);
	//因为这个数组会高频·的进行调用,所以使用静态数组就能极大地提高效率
	static int MonthDay[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;
	}
	return MonthDay[month];
}
Date& operator+=(int day);//日期与天数的加运算
Date operator+(int day);
Date& operator-=(int day);//日期与天数的减运算
Date operator-(int day);

//前置和后置的区别就是看式子中是不是有参数
Date& operator++();
Date& operator++(int );
Date& operator--();
Date& operator--(int);
private:
	int _year;
	int _month;
	int _day;
};

我们直接来代码:

cpp 复制代码
Date& Date::operator++()
{
	return (*this += 1);
}
Date& Date::operator++(int)
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

Date& Date:: operator--()
{
	return (*this -= 1);
}
Date& Date::operator--(int)
{
	Date tmp(*this);
	*this -= 1;
	return tmp;
}

简单的来看看效果,单独看这个的用处好像是不大,但是结合到接下来我们要实现的功能,这个重载式就会发挥很大的作用:

7.两日期之间相差的天数

首先我们还是先来定义这个重载式:

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
class Date
{
public:
	Date(int year = 2024, int month = 8, int day = 16);
	//~Date();
    void DatePeint();//日期打印
//比较大小运算符的重载
bool operator==(Date& d);
bool operator!=(Date& d);
bool operator>(Date& d);
bool operator<(Date& d);
bool operator<=(Date& d);
bool operator>=(Date& d);
//获取每个月的天数
int GetMonthDay(int year, int month)
{
	assert(month >= 1 && month <= 12);
	//因为这个数组会高频·的进行调用,所以使用静态数组就能极大地提高效率
	static int MonthDay[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;
	}
	return MonthDay[month];
}
Date& operator+=(int day);//日期与天数的加运算
Date operator+(int day);
Date& operator-=(int day);//日期与天数的减运算
Date operator-(int day);

//前置和后置的区别就是看式子中是不是有参数
Date& operator++();
Date& operator++(int );
Date& operator--();
Date& operator--(int);

//计算两个日期之间的天数差
int operator-(const Date&  d);
private:
	int _year;
	int _month;
	int _day;
};

大家在这个时候可以来想想,用什么方法能得到两个日期之间的天数差异:

想要实现这个方法其实十分的简单,我们先找到小的那个日期,再让这个日期++,记录他++的次数,直到他与那个较大的日期相等为止,记录得到的次数就是相差的天数。

接下来我们来实现一下代码:

cpp 复制代码
int Date::operator-(const Date& d)
{
	Date small =d ;
	Date big = *this;
	int flag = 1;
	if (big < small)
	{
		big = d;
		small = *this;
		flag *= -1;
	}
	int count = 0;
	while (small < big)
	{
		small++;
		++count;
	}
	return (count - 1) * flag;
}

我们实现了代码,接下来我们来测试一下代码的效果:

我们就简单测试一下从 8 月16号,到今年国庆节之间的天数差,然后我们就在网上的日期计算器上验算一下我们得结果:

8.代码展示

我们完成了日期计算器的, 接下来是代码展示:

Date.h

cpp 复制代码
#pragma once

#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
public:
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& out,  Date& d);
	Date(int year  = 2024, int month  = 8, int day = 16);
	///~Date();
	//日期值的打印
	void DatePrint();

	//赋值运算符的重载
	Date& operator=(const Date& d1);
	//比较大小运算符的重载
	bool operator==(Date& d);
	bool operator!=(Date& d);
	bool operator>(Date& d);
	bool operator<(Date& d);
	bool operator<=(Date& d);
	bool operator>=(Date& d);
	//获取每个月的天数
	int GetMonthDay(int year, int month)
	{
		assert(month >= 1 && month <= 12);
		//因为这个数组会高频·的进行调用,所以使用静态数组就能极大地提高效率
		static int MonthDay[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;
		}
		return MonthDay[month];
	}
	Date& operator+=(int day);
	Date operator+(int day);
	Date& operator-=(int day);
	Date operator-(int day);

	//前置++
	Date& operator++();
	Date& operator++(int );
	Date& operator--();
	Date& operator--(int);

	//计算两个日期之间的天数差
	int operator-(const Date&  d);

	bool CheckDate()
	{
		
		if (_month >= 13 || _month <= 0)
		{
			return false;
		}
		if (_day >= GetMonthDay(_year, _month)	|| _day <= 0)
		{
			return false;
		}
		return true;
	}
private:
	int _year;
	int _month;
	int _day;
};

//ostream& operator<<(ostream& out, const Date& d); 
//& operator>>(istream& out, const Date& d);

Date.cpp

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1

#include"Date.h"
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
	if (!CheckDate())
	{
		cout << "输入非法日期!!" << "->";
		cout << *this;
	}
}

void Date::DatePrint()
{
	cout << _year << "/" << _month << "/" << _day << endl;
}
bool Date::operator==(Date& d)
{
	return _year == d._day 
		&& _month == d._month
		&& _day == d._day;
}
Date& Date::operator=(const Date& d1)
{
	
		_year = d1._year;
		_month = d1._month;
		_day = d1._day;

	return *this;

}

bool Date::operator!=(Date& d)
{
	return !(*this == d);
}
bool Date::operator>(Date& d)
{
	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;
	}
	return false;
}
bool Date::operator<(Date& d)
{
	return !(*this >= d);
}
bool Date::operator<=(Date& d)
{
	return *this < d || *this == d;
}
bool Date::operator>=(Date& d)
{
	return *this > d || *this == d;
}
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)
{
	Date tmp = *this;
	tmp += day;
	return tmp;
}
Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		return (*this += -day);
	}
	_day -= day;
	while (_day <= 0)
	{
		_day += GetMonthDay(_year, _month);
		_month--;
		while (_month <= 0)
		{
			_year--;
			_month = 12;
		}
	}
	return *this;
}
Date Date::operator-(int day)
{
	Date tmp = *this;
	tmp -= day;
	return tmp;
}
Date& Date::operator++()
{
	return (*this += 1);
}
Date& Date::operator++(int)
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

Date& Date:: operator--()
{
	return (*this -= 1);
}
Date& Date::operator--(int)
{
	Date tmp(*this);
	*this -= 1;
	return tmp;
}

int Date::operator-(const Date& d)
{
	Date small =d ;
	Date big = *this;
	int flag = 1;
	if (big < small)
	{
		big = d;
		small = *this;
		flag *= -1;
	}
	int count = 0;
	while (small < big)
	{
		small++;
		++count;
	}
	return (count - 1) * flag;
}
ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

istream& operator>>(istream& in, Date& d)
{
	cout << "请依次输入有效的年月日信息" << endl;
	while (1)
	{
		in >> d._year >> d._month >> d._day;
		if (d.CheckDate())
		{
			break;
		}
		cout << "日期非法!!" << "->";
		cout << d;
	}
	return in;
}

Test.c

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1

#include"Date.h"


int  main()
{
	Date d1;
	Date d2(2024, 10, 1);
	d1.DatePrint();
	d2.DatePrint();
	cout << d2 - d1 << endl;
}

好,今天的学习就到这里了,我们下期再见,拜拜!!!

相关推荐
云空9 分钟前
《解锁 Python 数据挖掘的奥秘》
开发语言·python·数据挖掘
青莳吖19 分钟前
Java通过Map实现与SQL中的group by相同的逻辑
java·开发语言·sql
Buleall27 分钟前
期末考学C
java·开发语言
重生之绝世牛码29 分钟前
Java设计模式 —— 【结构型模式】外观模式详解
java·大数据·开发语言·设计模式·设计原则·外观模式
小蜗牛慢慢爬行35 分钟前
有关异步场景的 10 大 Spring Boot 面试问题
java·开发语言·网络·spring boot·后端·spring·面试
Algorithm157644 分钟前
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
开发语言·云原生·golang
shinelord明1 小时前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
Monly211 小时前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
boligongzhu1 小时前
DALSA工业相机SDK二次开发(图像采集及保存)C#版
开发语言·c#·dalsa
Eric.Lee20211 小时前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频