首页 > 编程语言 >C++:日期类的实现

C++:日期类的实现

时间:2024-10-30 08:48:11浏览次数:3  
标签:实现 year C++ month int 日期 ._ Date day

  

目录

一.日期类

1.类的构造函数和拷贝构造

2.日期的比较

3.日期加减一个天数

1.日期加天数

2.日期减天数

4.日期的++与--

1.日期的++

2.日期的--

5.日期减日期

6.日期的输入和输出

二.整体代码

1.Date.h

2.Date.cpp


      在前面几节的内容中,我们学习了类的基本知识,其中比较重要的是类的6个默认成员函数,在这节中我们主要对前几节的内容进行实际应用,实现一个简单的日期类

一.日期类

1.类的构造函数和拷贝构造

对于一个日期类,我们首先能够想到的便是初始化一个日期和日期的复制

Date::Date(int year = 0, int month = 1, int day = 1) :_year(year), _month(month), _day(day)
{
	_year = year;
	_month = month;
	_day = day;	
}

Date::Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

        我们很容易可以写出上面的构造函数,但是有一个问题是我们可以输入各种日期,即便是2024年55月56日这种不合法的日期,所以我们需要对其进行范围的限定,对于年和月的范围我们可以通过year>=0,month>=1&&month<=12进行控制,但是日却不好控制,因为1个月中有30,31,28,29这种情况,所以我们可以写一个函数来获取每月的日数

int Date::GetMonthDay(int year, int month)
{
	static int monthDays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

	//4年一闰,100年不闰,400年一闰
	if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
	{
		return 29;
	}

	return monthDays[month];
}

构造函数可以修改为

Date::Date(int year = 0, int month = 1, int day = 1) :_year(year), _month(month), _day(day)
{
	if (year >= 0 && month >= 1 && month <= 12 && day >= 1 && day <= GetMonthDay(year, month))
	{
		_year = year;
		_month = month;
		_day = day;
	}
	else
	{
		cout << "日期错误" << endl;
	}
}

2.日期的比较

我们可以比较两个日期的大小,是否相等其他操作,比如<,>,==,<=,>=,!=

bool Date::operator==(const Date& d)
{
	return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator<(const 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<=(const Date& d)
{
	return *this < d || *this == d;
}

对于>,我们可以选择对年,月,日依次比较,也可以选择取反<=

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

>=对<取反即可

bool Date::operator>=(const Date& d)
{
	/*return *this > d || *this == d;*/
	return !(*this < d);
}

!=对==取反

bool Date::operator!=(const Date& d)
{
	return !(*this == d);
}

3.日期加减一个天数

1.日期加天数

        对于加上一个天数,我们需要考虑的便是月和年的进位,所以我们只需要将天数加上,与当前月份天数比较,如果大于就将其减去,月份++,直到天数小于当前月份天数,如果月份加到13,就年++,将月份置为1

注意:如果我们不希望原来的天数发生改变,就需要用一个临时变量来记录,若不记录的话,如d2=d1+100,我们只希望改变d2,但是d1也会改变

Date Date::operator+(int day)
{
	Date ret(*this);
	ret._day += day;
	while (ret._day > GetMonthDay(ret._year, ret._month))
	{
		ret._day -= GetMonthDay(ret._year, ret._month);
		ret._month++;

		if (ret._month == 13)
		{
			ret._year++;
			ret._month = 1;
		}
	}
	return ret;
}

实现了+,那么+=直接复用即可

Date Date::operator+=(int day)
{
	Date ret(*this);
	*this =*this+ day;
	return *this;
}

2.日期减天数

        对于减去一个天数,原理与加天数相似,只是天数<=0的时候,月份减1,当月份减到0,年份减1,月份置为12

Date Date::operator-(int day)
{
	Date ret(*this);
	ret._day -= day;

	while (ret._day <= 0)
	{
		ret._month--;

		if (ret._month == 0)
		{
			ret._year--;
			ret._month = 12;
		}
		ret._day += GetMonthDay(ret._year, ret._month);
	}
	return ret;
}

对于-=复用-即可

Date Date::operator-=(int day)
{
	Date ret(*this);
	*this = *this - day;
	return *this;
}

4.日期的++与--

1.日期的++

前置++

对与前置++,+=1即可

//前置++
Date Date::operator++()
{
	*this += 1;
	return *this;
}

后置++

因为后置++,需要用完在+,所以需要一个临时变量记录

//后置++;
Date Date::operator++(int)
{
	Date ret(*this);
	*this += 1;
	return ret;
}

2.日期的--

前置--

//前置--
Date Date::operator--()
{
	*this -= 1;
	return *this;
}

后置--

//后置--
Date Date::operator--(int)
{
	Date ret(*this);
	*this -= 1;
	return ret;
}

5.日期减日期

我们有时需要知道两个日期之间相差几天,所以写一个函数会更方便

        创建两个日期对象max和min,分别指向当前对象(*this)和参数对象(d).使用flag来确定结果的符号,使用operator<来判断哪个日期更早.如果*this < d,则交换max和min的值,并将flag设为-1,表示结果是负的,使用一个循环,不断增加min,直到其大于或等于max,同时计数n,表示经过的天数,返回n * flag,得到两个日期之间的差值

//日期减日期
int Date::operator-(const Date& d)
{
	Date max = *this;
	Date min = d;
	int flag = 1;
	if (*this < d)
	{
		flag = -1;
		max = d;
		min = *this;
	}
	int n = 0;
	while (min < max)
	{
		min++;
		n++;
	}
	return n * flag;
}

6.日期的输入和输出

        当我们在类中使用<<和>>显示没有合适的构造函数匹配,我们尝试重载,但是发现没有办法重载为成员函数,因为cout和this指针在抢第一个参数位置,所以我们重载为全局函数,却无法访问私有成员,这时候就需要用到友元

ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

istream& operator>>(istream& in, Date& d)
{
	while (1)
	{
		in >> d._year >> d._month >> d._day;
		if (d._year >= 0 && d._month >= 1 && d._month <= 12 && d._day >= 1 && d._day <= d.GetMonthDay(d._year, d._month))
			break;
		else
			cout << "非法日期,请重新输入" << endl;
	}
	return in;
}

二.整体代码

1.Date.h

#pragma once
#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year, int month, int day);
	Date(const Date& d);
	int GetMonthDay(int month, int year);
	bool operator==(const Date& d);
	bool operator<(const Date& d);
	bool operator>(const Date& d);
	bool operator<=(const Date& d);
	bool operator>=(const Date& d);
	bool operator!=(const Date& d);
	Date operator+(int day);
	Date operator-(int day);
	Date operator+=(int day);
	Date operator-=(int day);
	int operator-(const Date & d);
	Date operator++();
	Date operator++(int);
	Date operator--();
	Date operator--(int);
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);
private:
	int _year;
	int _month;
	int _day;
};

2.Date.cpp

#include "Date.h"

int Date::GetMonthDay(int year, int month)
{
	static int monthDays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

	//4年一闰,100年不闰,400年一闰
	if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
	{
		return 29;
	}

	return monthDays[month];
}

Date::Date(int year = 0, int month = 1, int day = 1) :_year(year), _month(month), _day(day)
{
	if (year >= 0 && month >= 1 && month <= 12 && day >= 1 && day <= GetMonthDay(year, month))
	{
		_year = year;
		_month = month;
		_day = day;
	}
	else
	{
		cout << "日期错误" << endl;
	}
}

Date::Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

bool Date::operator==(const Date& d)
{
	return _year == d._year && _month == d._month && _day == d._day;
}

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

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

bool Date::operator>=(const Date& d)
{
	/*return *this > d || *this == d;*/
	return !(*this < d);
}

bool Date::operator!=(const Date& d)
{
	return !(*this == d);
}

Date Date::operator+(int day)
{
	Date ret(*this);
	ret._day += day;
	while (ret._day > GetMonthDay(ret._year, ret._month))
	{
		ret._day -= GetMonthDay(ret._year, ret._month);
		ret._month++;

		if (ret._month == 13)
		{
			ret._year++;
			ret._month = 1;
		}
	}
	return ret;
}

Date Date::operator+=(int day)
{
	Date ret(*this);
	*this =*this+ day;
	return *this;
}

Date Date::operator-(int day)
{
	Date ret(*this);
	ret._day -= day;

	while (ret._day <= 0)
	{
		ret._month--;

		if (ret._month == 0)
		{
			ret._year--;
			ret._month = 12;
		}
		ret._day += GetMonthDay(ret._year, ret._month);
	}
	return ret;
}

Date Date::operator-=(int day)
{
	Date ret(*this);
	*this = *this - day;
	return *this;
}

//前置++
Date Date::operator++()
{
	*this += 1;
	return *this;
}

//后置++;
Date Date::operator++(int)
{
	Date ret(*this);
	*this += 1;
	return ret;
}

//前置--
Date Date::operator--()
{
	*this -= 1;
	return *this;
}

//后置--
Date Date::operator--(int)
{
	Date ret(*this);
	*this -= 1;
	return ret;
}

//日期减日期
int Date::operator-(const Date& d)
{
	Date max = *this;
	Date min = d;
	int flag = 1;
	if (*this < d)
	{
		flag = -1;
		max = d;
		min = *this;
	}
	int n = 0;
	while (min < max)
	{
		min++;
		n++;
	}
	return n * flag;
}

ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

istream& operator>>(istream& in, Date& d)
{
	while (1)
	{
		in >> d._year >> d._month >> d._day;
		if (d._year >= 0 && d._month >= 1 && d._month <= 12 && d._day >= 1 && d._day <= d.GetMonthDay(d._year, d._month))
			break;
		else
			cout << "非法日期,请重新输入" << endl;
	}
	return in;
}

int main()
{
	Date d1;
	Date d2(1999, 2, 3);
	Date d3(d1);
	cout << d1 << d2 << d3;
	cout << (d3 == d1) << endl;
	cout << (d1 < d2) << endl;
	cout << (d1 <= d2) << endl;
	cout << (d1 > d2) << endl;
	cout << (d1 >= d2) << endl;
	cout << (d1 != d2) << endl;
	d2 += 100;
	cout << d2;
	d2 -= 100;
	cout << d2;

	Date d(2024, 1, 1);
	d3 = ++d;
	cout << d3;
	cout << d;

	d3 = d++;
	cout << d3;
	cout << d;

	d3 = --d;
	cout << d3;
	cout << d;

	d3 = d--;
	cout << d3;
	cout << d;

	Date d4 = d2 + 100;
	cout << d4;
	Date d5 = d2 - 100;
	cout << d5;
	Date d6(2024, 3, 1);
	Date d7(2024, 4, 1);
	cout << d7 - d6 << endl;
	Date d8;
	cin >> d8;
	cout << d8;
}

标签:实现,year,C++,month,int,日期,._,Date,day
From: https://blog.csdn.net/w200514/article/details/143337668

相关文章

  • WPF+MVVM案例实战(十二)- 3D数字翻牌计时实现
    文章目录1、运行效果2、功能实现1、文件创建2、控件代码实现3、控件引用与菜单实现1.引用用户控件2.按钮菜单1、运行效果2、功能实现1、文件创建打开项目Wpf_Examples,在用户控件UserControlLib中创建NumberFoldingCard.xaml文件,在主程序......
  • 【C/C++】5.并发控制
    并发控制(ConcurrencyControl)是指在多线程或多进程环境中,确保多个操作在共享资源上的访问不会发生冲突或产生不一致的情况。并发控制的核心目标是在允许并发操作的同时,保证系统的正确性、数据的一致性和完整性。在并发环境下,不同的线程或进程可能会同时访问共享资源(例如变量、文......
  • Paimon lookup store 实现
    LookupStore主要用于Paimon中的LookupCompaction以及Lookupjoin的场景.会将远程的列存文件在本地转化为KV查找的格式.Hashhttps://github.com/linkedin/PalDBSorthttps://github.com/dain/leveldbhttps://github.com/apache/paimon/pull/3770整体文件结构:......
  • 每日OJ题_牛客_AB20走迷宫_BFS_C++_Java
    目录牛客_AB20走迷宫_BFS题目解析C++代码Java代码牛客_AB20走迷宫_BFS走迷宫_牛客题霸_牛客网(nowcoder.com)描述:        给定一个n×m的网格,在网格中每次在不超过边界的情况下可以选择向上、向下、向左、向右移动一格。网格中的一些格子上放置有障碍物,放有......
  • qt的c++环境配置和c++基础【正点原子】嵌入式Qt5 C++开发视频
    QTc++环境配置和c++基础c++环境配置和工程创建  1.配置步骤  2.新建qt工程目录和工程  3.重启qt后打开最近的qt项目c++基础-类和对象  1.什么是类和对象    A.类的定义    B.类的结构表示    C.类的访问权限    D.对象的定义    E.类和......
  • 【linux网络编程】| socket套接字 | 实现UDP协议聊天室
        前言:本节内容将带友友们实现一个UDP协议的聊天室。主要原理是客户端发送数据给服务端。服务端将数据再转发给所有链接服务端的客户端。所以,我们主要就是要实现客户端以及服务端的逻辑代码。那么,接下来开始我们的学习吧。    ps:本节内容建议了解so......
  • 什么时候用C而不用C++
    在选择编程语言时,我们可能会在C和C++之间犹豫。C语言通常用于低级别的系统编程、嵌入式系统开发、操作系统组件、与硬件密切相关的软件、对性能要求极高的应用以及早期使用C语言编写且维护成本较低的项目。而C++以其面向对象特性、灵活的抽象能力、类和模板等特性而广泛应用于软......
  • openssl enc内部算法实现原理
    我们都知道使用命令openssl时可以使用-enc指定算法,那么具体它的实现原理是什么呢?我们通过实验来一探究竟我们新建一个my.txt里面的内容为12345678opensslenc-aes-128-cbc-inmy.txt-outmy.enc-k"mypasswd"结果会生成my.enc文件,我们用xxd命令可以看到那么这个文件是如......
  • 基于springboot的校园管理系统的设计与实现(含源码)
    随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,校园管理系统当然也不能排除在外。校园管理系统是以实际运用为开发背景,运用软件工程原理和开发方法,采用springboot框架构建的一个管理系统。整个开发过程首先对软件系......
  • Jetson AGX Orin 实现相机雷达联合标定
    JetsonAGXOrin实现相机雷达联合标定.使用autoware标定工具,联合标定lidar和相机,计算出内外参等参数,实现点云目标映射到图像上.点云分隔目标映射图片环境安装参考:JetsonAGXOrin安装Autowarecalibration_toolkit标定工具标定雷达和相机新开终端roscore......