C++函数重载完成日期类相关计算

news2024/11/14 15:09:03

在这里插入图片描述

本文内容如下:

  • 1.创建类以及函数的声明
  • 2.日期加减天数
    • 1.月份天数
    • 2.函数实现
  • 3.日期比较大小
  • 4.日期减日期
    • 1.日期的前置和后置加加
    • 2.日期减日期的实现
  • 5.内置类型的cout和cin
      • 本文代码如下:

要完成日期类的相关计算要创建自定义的类型,然后用函数重载来完成

1.创建类以及函数的声明

我们先来定义一个Date的类

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1);
	void Print();
private:
	int _year;
	int _month;
	int _day;
};

完成类的创建和打印:

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

void Date::Print()
{
	cout << _year << "/" << _month << "/" << _day << endl;
}

2.日期加减天数

先来声明函数:

class Date
{
public:
	//日期加减天数
	Date operator+(int day);
	Date operator+=(int day);
	Date operator-(int day);
	Date operator-=(int day);
private:
	int _year;
	int _month;
	int _day;
};

1.月份天数

我们要想知道进行计算日期的天数加减难点在于:
如何区分2月小月和大月,而二月又要区分平年和闰年
我们可以通过封装一个函数来解决这个问题:

	int GetMonthDay(int year, int month)
	{
		assert(month > 0 && month < 13);
		static int GetMonthDayArray[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;
		}
		else
			return GetMonthDayArray[month];
	}

这里运用了数组取值的方法来实现
为了不频繁的创建数组将GetMonthDayArray 定于为全局变量
2月的判断优先判断 month == 2 来提升效率

2.函数实现

这里要注意的是:+= 和 + 的区别在于:

	int a = 1;
	int b = 1;
	int c = a + 1;      //a不改变
	b += 1;             //b直接改变

那么实现的方法就是先将天数直接加上,如果 _day 超出当前月的天数就让其减去当前月的天数直到合理即可
代码实现如下:

Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_month++;
		if (_month == 13)
		{
			_year++;
			_month = 1;
		}
		_day -= GetMonthDay(_year, _month);
		
	}
	return *this;
}

写完这个那么 + 就很好实现了,直接调用即可:

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

同理 - 和 -=

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

Date& Date::operator-=(int day)
{
	_day -= day;
	while (_day < 1)
	{
		_month--;
		if (_month < 1)
		{
			_month = 12;
			_year--;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

3.日期比较大小

函数声明:

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1);
	void Print();
	int GetMonthDay(int year, int month)
	{
		assert(month > 0 && month < 13);
		static int GetMonthDayArray[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;
		}
		else
			return GetMonthDayArray[month];
	}
	//日期加减天数
	Date operator+(int day);
	Date& operator+=(int day);
	Date operator-(int day);
	Date& operator-=(int day);

	//日期比较大小
	bool operator>(const Date& d1) const;
	bool operator==(const Date& d1) const;
	bool operator!=(const Date& d1) const;
	bool operator<(const Date& d1) const;
	bool operator>=(const Date& d1) const;
	bool operator<=(const Date& d1)const;
private:
	int _year;
	int _month;
	int _day;
};

比较就很简单了,先比年后月 日:

bool Date::operator>(const Date& d1)const
{
	if (_year > d1._year)
	{
		return true;
	}
	else if (_year==d1._year)
	{
		if (_month > d1._month)
		{
			return true;
		}
		else if (_month == d1._month)
		{
			return _day > d1._day;
		}
	}
	else
	{
		return false;
	}
}

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

将这两个写好后,后续比较直接调用这两个就行

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

bool Date::operator>=(const Date& d1)const
{
	return (*this > d1 || *this == d1);
}

bool Date::operator<=(const Date& d1)const
{
	return (*this < d1 || *this == d1);
}

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

4.日期减日期

1.日期的前置和后置加加

C++中重载函数区别前置与后置的区别在于:
后置加加有int参数

class Date
{
public:
	//日期的前置和后置加加
	Date& operator++();
	Date operator++(int);
private:
	int _year;
	int _month;
	int _day;
};

实现起来就直接调用 + 或 += 就行
区别就在于返回值,而且后置加加要多几次拷贝

Date& Date::operator++()
{
	*this += 1;
	return *this;
}

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

2.日期减日期的实现

声明:

class Date
{
public:
	//日期的前置和后置加加
	Date& operator++();
	Date operator++(int);
	
	//日期减日期计算天数
	int operator-(Date& d1);
private:
	int _year;
	int _month;
	int _day;
};

有了加加日期的实现就变简单了
运用判断和加加结合就可以直接算出相差的天数
虽然效率慢了点,但是过程相对简单:

int Date::operator-(Date& d1)
{
	//假设法找小的日期
	int flag = 1;
	if (*this > d1)
	{
		Date tmp = *this;
		*this = d1;
		d1 = tmp;
		flag = -1;
	}
	int day = 0;
	while (*this != d1)
	{
		++*this;
		day++;
	}
	return day * flag;
}

5.内置类型的cout和cin

因为如果再类里面因为*this 默认写前面而导致 cin和cout无法写在前面从而写成这样:

	d1 << cout;

为了解决这样的问题我们只能将函数写在外面:
声明:

istream& operator>>(istream& in, Date& d1);
ostream& operator<<(ostream& out, Date& d1);

由于要访问Date 的私有要在类里面用friend 函数:

class Date
{
	friend istream& operator>>(istream& in, Date& d1);
	friend ostream& operator<<(ostream& out, Date& d1);
public:
	//....
private:
	int _year;
	int _month;
	int _day;
};

先完成日期的输入判断是否正确:

bool Date::CheckDate()
{
	if (_month < 1 || _month > 12
		|| _day < 1 || _day > GetMonthDay(_year, _month))
	{
		return false;
	}
	else
		return true;
}

cin的实现:

istream& operator>>(istream& in, Date& d1)
{
	cout << "请依次输入年月日:->";
	in >> d1._year >> d1._month >> d1._day;
	if (!d1.CheckDate())
	{
		cout << "非法日期!!!请重新输入" << endl;
	}
	return in;
}

cout的实现:

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

这样就可以实现直接输入输出自定义类型了
后续进行测试就行,这里就不演示了

本文代码如下:

Date.h

#pragma once

#include<iostream>
using namespace std;

#include <assert.h>

class Date
{
	friend istream& operator>>(istream& in, Date& d1);
	friend ostream& operator<<(ostream& out, Date& d1);
public:
	bool CheckDate();
	Date(int year = 1900, int month = 1, int day = 1);
	void Print();
	int GetMonthDay(int year, int month)
	{
		assert(month > 0 && month < 13);
		static int GetMonthDayArray[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;
		}
		else
			return GetMonthDayArray[month];
	}
	//日期加减天数
	Date operator+(int day);
	Date& operator+=(int day);
	Date operator-(int day);
	Date& operator-=(int day);

	//日期比较大小
	bool operator>(const Date& d1) const;
	bool operator==(const Date& d1) const;
	bool operator!=(const Date& d1) const;
	bool operator<(const Date& d1) const;
	bool operator>=(const Date& d1) const;
	bool operator<=(const Date& d1)const;
	
	//日期的前置和后置加加
	Date& operator++();
	Date operator++(int);

	//日期减日期计算天数
	int operator-(Date& d1);
private:
	int _year;
	int _month;
	int _day;
};

//输入和输出
istream& operator>>(istream& in, Date& d1);
ostream& operator<<(ostream& out, Date& d1);

Date.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include "Date.h"

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

void Date::Print()
{
	cout << _year << "/" << _month << "/" << _day << endl;
}

Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_month++;
		if (_month == 13)
		{
			_year++;
			_month = 1;
		}
		_day -= GetMonthDay(_year, _month);
		
	}
	return *this;
}

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

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

Date& Date::operator-=(int day)
{
	_day -= day;
	while (_day < 1)
	{
		_month--;
		if (_month < 1)
		{
			_month = 12;
			_year--;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

bool Date::operator>(const Date& d1)const
{
	if (_year > d1._year)
	{
		return true;
	}
	else if (_year==d1._year)
	{
		if (_month > d1._month)
		{
			return true;
		}
		else if (_month == d1._month)
		{
			return _day > d1._day;
		}
	}
	else
	{
		return false;
	}
}

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

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

bool Date::operator>=(const Date& d1)const
{
	return (*this > d1 || *this == d1);
}

bool Date::operator<=(const Date& d1)const
{
	return (*this < d1 || *this == d1);
}

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

Date& Date::operator++()
{
	*this += 1;
	return *this;
}

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

int Date::operator-(Date& d1)
{
	//假设法找小的日期
	int flag = 1;
	if (*this > d1)
	{
		Date tmp = *this;
		*this = d1;
		d1 = tmp;
		flag = -1;
	}
	int day = 0;
	while (*this != d1)
	{
		++*this;
		day++;
	}
	return day * flag;
}

bool Date::CheckDate()
{
	if (_month < 1 || _month > 12
		|| _day < 1 || _day > GetMonthDay(_year, _month))
	{
		return false;
	}
	else
		return true;
}

istream& operator>>(istream& in, Date& d1)
{
	cout << "请依次输入年月日:->";
	in >> d1._year >> d1._month >> d1._day;
	if (!d1.CheckDate())
	{
		cout << "非法日期!!!请重新输入" << endl;
	}
	return in;
}

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

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

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

相关文章

Java制作拼图小游戏——基础编程实战(详细代码注释与流程讲解)

目录 前言 涉及知识点 准备工具 Java开发环境 图片资源 最终效果 ——需求分析 登录界面 功能描述 需求分析 功能需求 游戏主界面 功能描述 需求分析 功能需求 游戏菜单 游戏胜利界面 框架搭建 总结 编码 编码顺序 搭建App实现程序的入口 完成User用户类和…

计算总体方差statistics.pvariance()

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 计算总体方差 statistics.pvariance() [太阳]选择题 根据给定的Python代码&#xff0c;运行结果为&#xff1f; import statistics data [1, 2, 3, 4, 5] print(f"【显示】data{…

【C++掌中宝】深入解析C++命名空间:有效管理代码的利器

文章目录 前言1. namespace 的价值2. namespace 的定义3. 命名空间的本质4. 嵌套的命名空间5. 命名空间的使用6. using 指令7. 补充结语 前言 假设这样一种情况&#xff0c;当一个班上有两个名叫 Zara 的学生时&#xff0c;为了明确区分它们&#xff0c;我们在使用名字之外&am…

2.Seata 1.5.2 集成Springcloud-alibaba

一.Seata-server搭建已完成前提下 详见 Seata-server搭建 二.Springcloud 项目集成Seata 项目整体测试业务逻辑是创建订单后&#xff08;为了演示分布式事务&#xff0c;不做前置库存校验&#xff09;&#xff0c;再去扣减库存。库存不够的时候&#xff0c;创建的订单信息数…

攻防世界Web新手练习区题目(view_source到simple_php)WP

目录 view_source​ robots​ Training-WWW-Robots PHP2​ get_post​ backup​ cookie​ disabled_button​ simple_js​ xff_referer​ weak_auth​ command_execution​ simple_php​ view_source 获取在线场景后访问题目场景 在右键不管用的情况下&#xff0…

尚品汇-秒杀成功下单接口、秒杀结束定时任务-清空缓存数据(五十四)

目录&#xff1a; &#xff08;1&#xff09;下单页面 &#xff08;2&#xff09;service-activity-client添加接口 &#xff08;3&#xff09;web-all 编写去下单控制器 &#xff08;4&#xff09;service-order模块提供秒杀下单接口 &#xff08;5&#xff09;service-or…

1份可以派上用场丢失数据恢复的应用程序列表

无论如何&#xff0c;丢失您的宝贵数据是可怕的。您的 Android 或 iOS 设备可能由于事故、硬件损坏、存储卡问题等而丢失了数据。这就是为什么我们编制了一份可以派上用场以恢复丢失数据的应用程序列表。 如果您四处走动&#xff0c;您大多会随身携带手机或其他移动设备。这些…

豆包Python SDK接入流程

模型与价格 豆包的模型介绍可以看豆包大模型介绍&#xff0c;模型价格可以看豆包定价文档里的“模型推理” - “大语言模型” - “字节跳动”部分。 推荐使用以下模型&#xff1a; Doubao-lite-32k&#xff1a;每百万 token 的输入价格为 0.3 元&#xff0c;输出价格为 0.6 元…

vue组件($refs对象,动态组件,插槽,自定义指令)

一、ref 1.ref引用 每个vue组件实例上&#xff0c;都包含一个$refs对象&#xff0c;里面存储着对应dom元素或组件的引用。默认情况下&#xff0c;组件的$refs指向一个空对象。 2.使用ref获取dom元素的引用 <template><h3 ref"myh3">ref组件</h3&g…

手机切换IP简单方法:掌握技巧,轻松实现IP变换‌

在当今的数字化时代&#xff0c;IP地址作为网络身份的重要标识&#xff0c;对于网络访问、数据传输等方面都起着至关重要的作用。然而&#xff0c;在某些特定场景下&#xff0c;我们可能需要切换手机的IP地址&#xff0c;以满足不同的网络需求。本文将为大家介绍几种手机切换IP…

Linux —— 多线程

一、本篇重点 1.了解线程概念&#xff0c;理解线程与进程区别与联系 2.理解和学会线程控制相关的接口和操作 3.了解线程分离与线程安全的概念 4.学会线程同步。 5.学会互斥量&#xff0c;条件变量&#xff0c;posix信号量&#xff0c;以及读写锁 6.理解基于读写锁的读者写…

Kafka 3.0.0集群部署教程

1、集群规划 主机名 ip地址 node.id process.roles kafka1 192.168.0.29 1 broker,controller Kafka2 192.168.0.30 2 broker,controller Kafka3 192.168.0.31 3 broker,controller 将kafka包上传以上节点/app目录下 mkdir /app 解压kafka包 tar -zxvf kafka_…

BLE 协议之链路层

目录 一、前言二、状态和角色三、Air Interface Packets1、Preamble 字段2、Access Address 字段2.1 静态地址2.2 私有地址 3、PDU 字段3.1 Advertising Channel PDU3.1.1 Header 字段3.1.2 Payload 字段 3.2 Data Channel PDU3.2.1 Header 字段3.2.2 Payload 字段 4、CRC 字段…

【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第一篇-原理】

如果想直接制作&#xff0c;请看【第二篇】内容 这次做一个这样的东西&#xff0c;通过在2DRT上实时绘制&#xff0c;生成动态的体积纹理&#xff0c;也就是可以runtime的VDB 设想的文章流程: 对原理进行学习制作体积渲染制作实时绘制 第一篇&#xff08;本篇&#xff09;是对“…

Spring MVC 基础 : 文件、cookies的接收 ,REST响应

一、接受文件 在 Spring MVC 中&#xff0c;可以使用 RequestPart 注解来接收文件。这个注解常用于处理复杂的请求&#xff0c;如同时发送 JSON 数据和文件。RequestPart 非常适用于多部分请求&#xff08;multipart requests&#xff09;&#xff0c;这在单个请求中同时发送文…

法定退休年龄计算器,看看你还有多少年退休?

最近延迟退休上了微博热搜&#xff0c;从2025年开始实行。 分享个法定退休年龄计算器&#xff0c;看看你还有多少年退休&#xff1f; 官方出品的计算器&#xff0c;网站地址 https://si.12333.gov.cn/304647.jhtml 输入出生日期和性别就可以。 当然也可以在微信的城市服务。…

基于asp.net固定资产管理系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

JZ2440开发板——S3C2440的UART

以下内容源于韦东山课程的学习与整理&#xff0c;如有侵权请告知删除。 一、UART硬件简介 UART&#xff0c;全称是“Universal Asynchronous Receiver Transmitter”&#xff0c;即“通用异步收发器”&#xff0c;也就是我们日常说的“串口”。 它在嵌入式中用途非常广泛&…

【计算机网络篇】物理层

本文主要介绍计算机网络第二章节的物理层&#xff0c;文中的内容是我认为的重点内容&#xff0c;并非所有。参考的教材是谢希仁老师编著的《计算机网络》第8版。跟学视频课为河南科技大学郑瑞娟老师所讲计网。 文章目录 &#x1f3af;一.基本概念及公式 &#x1f383;基本概念…

力扣-1035不相交的线(Java详细题解)

题目链接&#xff1a;力扣-1035不相交的线 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5.如果没有ac打印dp数组 利于debug。 每一…