当前位置: 首页 > news >正文

【C++】日期类的实现

在上篇博客中我们已经学习了C++中的运算符重载,我们说,操作符只能对于内置类型进行操作,对自定义类型我们需要自己定义函数去实现一系列的操作
那么这篇博客我们就专门把日期这个类单独拿出来写一下它都有哪些有意义的可以重载的运算符,这个函数我们要放到类里面为了访问私有的成员变量,但是函数声明和定义可以分到两个文件中写,只需要标识一下它属于哪个类就行。还有我们之前说过的一点,缺省参数只能声明给,定义不用给,因为编译器怕你给的不一样。
下面一个类当中首先是成员变量年月日我就不说了,下面是构造函数,我们就写一个全缺省的函数,默认不传参数年月日都是一,但是我们要判断传过来的数字是否合法,不合法要做出提醒,可以assert断言,也可以就打印一下。

//声明
Date(int year = 1, int month = 1, int day = 1);
//定义
Date::Date(int year, int month , int day ) {_year = year;_month = month;_day = day;if (_year < 1 || _month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month)) {cout << _year << "年" << _month << "月" << _day << "日";cout << "日期非法" << endl;}
}

下面比较两个日期的大小和是否相等其实逻辑就比较简单了,写上一个后边的直接赋用就行
比如说

bool Date:: operator==(const Date& n) {return _year == n._year && _month == n._month && _day == n._day;
}bool Date::operator!=(const Date& n) {return !(*this == n);
}

写了等于那么不等于不就是它的相反嘛
下面的大于小于也是同理

bool Date:: operator<(const Date& n) {if (_year < n._year) {return true;}if (_year == n._year && _month < n._month) {return true;}if (_year == n._year && _month == n._month && _day < n._day) {return true;}return false;
}bool Date::operator<=(const Date& n) {return ((*this < n) || (*this == n));
}bool Date::operator>(const Date& n) {return !(*this <= n);
}bool Date:: operator>=(const Date& n) {//return *this > n || *this == n;return !(*this < n);
}

下面是加减运算,首先日期加日期是没有意义的,但是日期加减天数是有意义的,这个该如何去加减呢?我们可以先把天数加到年月日的日数上,如果合法就不用动了,如果多余本月的该有的天数就进位到月上。为了方便就得有一个得到该年该月的天数的一个函数

int Date :: GetMonthDay(int year, int month) {assert(year >= 1 && month >= 1 && month <= 12);int monthArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if ((month == 2) && (((year % 400) == 0) || ((year % 4) == 0 && (year % 100) != 0))) {return 29;}return monthArray[month];
}

下边就是日期加减一个天数

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

我们先看第一种情况,加等其实是不需要进行拷贝的,而加则需要拷贝两次。第二种情况,加要拷贝两次,而加等要拷贝三次,所以我们可以看出第一种情况更好一些
我们这里的加等还有一个问题,如果我们写的是加等一个负数或者说减等一个负数时就会有问题,这时就会有问题,我们只需要转到相反的就行了,就类似这样:

Date& Date:: operator-=(int day) {if (day < 0) {return *this -= (-day);}

下面就是++了,但是++有前置,有后置,这时我们就规定后置++要在形参上写上一个int,写别的不行

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

下面的日期减日期也是有意义的,就是相差的天数
简单的话就是从小的日期一直加直到大的日期,看一共加了多少回

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

要想效率更高些就要整年整年的加,后面的零碎的天数就从1月1日开始数,大的日期就加上,小的日期就减去

int Date::operator-(const Date& d) {int flag = 1;Date max = *this;Date min = d;if (*this < d) {max = d;min = *this;flag = -1;}int n = 0;int y = min._year;while (y != max._year) {if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) {n += 366;}else {n += 365;}y++;}int m1 = 1;int m2 = 1;while (m1 < max._month) {n += GetMonthDay(max._year, m1);m1++;}while (m2 < min._month) {n -= GetMonthDay(min._year, m2);m2++;}n = n + max._day - min._day;return n;
}

下面是Date.h中所有代码


#include<iostream>
#include<assert.h>
using namespace std;
class Date {
public:Date(int year = 1, int month = 1, int day = 1);void Print();int GetMonthDay(int year, int month);bool operator==(const Date& n);bool operator!=(const Date& n);bool operator<(const Date& n);bool operator<=(const Date& n);bool operator>(const Date& n);bool operator>=(const Date& n);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;
};

Date.cpp文件中的代码

#include"Date.h"
Date::Date(int year, int month , int day ) {_year = year;_month = month;_day = day;if (_year < 1 || _month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month)) {cout << _year << "年" << _month << "月" << _day << "日";cout << "日期非法" << endl;}
}void Date::Print() {cout << _year << "年" << _month << "月" << _day << "日" << endl;
}int Date :: GetMonthDay(int year, int month) {assert(year >= 1 && month >= 1 && month <= 12);int monthArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if ((month == 2) && (((year % 400) == 0) || ((year % 4) == 0 && (year % 100) != 0))) {return 29;}return monthArray[month];
}bool Date:: operator==(const Date& n) {return _year == n._year && _month == n._month && _day == n._day;
}bool Date::operator!=(const Date& n) {return !(*this == n);
}bool Date:: operator<(const Date& n) {if (_year < n._year) {return true;}if (_year == n._year && _month < n._month) {return true;}if (_year == n._year && _month == n._month && _day < n._day) {return true;}return false;
}bool Date::operator<=(const Date& n) {return ((*this < n) || (*this == n));
}bool Date::operator>(const Date& n) {return !(*this <= n);
}bool Date:: operator>=(const Date& n) {//return *this > n || *this == n;return !(*this < n);
}Date& Date:: operator+=(int day) {if (day < 0) {return *this -= (-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);}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) {Date tmp(*this);tmp -= day;return tmp;
}Date& Date::operator++() {*this += 1;return *this;
}Date Date:: operator++(int) {Date tmp(*this);*this += 1;return tmp;
}Date& Date::operator--() {*this -= 1;return *this;
}Date Date:: operator--(int) {Date tmp(*this);*this -= 1;return tmp;
}//int Date::operator-(const Date& d) {
//	int flag = -1;
//	Date min = *this;
//	Date max = d;
//	if (*this > d) {
//		min = d;
//		max = *this;
//		flag = 1;
//	}
//	int n = 0;
//	while (min < max) {
//		++min;
//		++n;
//	}
//	return n*flag;
//}
int Date::operator-(const Date& d) {int flag = 1;Date max = *this;Date min = d;if (*this < d) {max = d;min = *this;flag = -1;}int n = 0;int y = min._year;while (y != max._year) {if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) {n += 366;}else {n += 365;}y++;}int m1 = 1;int m2 = 1;while (m1 < max._month) {n += GetMonthDay(max._year, m1);m1++;}while (m2 < min._month) {n -= GetMonthDay(min._year, m2);m2++;}n = n + max._day - min._day;return n;
}
http://www.lryc.cn/news/247113.html

相关文章:

  • 带残差连接的ResNet18
  • 【深入解析git和gdb:版本控制与调试利器的终极指南】
  • CGAN原理讲解与源码
  • C#实体类与XML互转以及List和DataTable转XML的使用
  • uniapp的vue3的模版的setup函数内使用uniapp内置方法
  • UI自动化的基本知识
  • python实现C++简易自动压行
  • 京东数据分析(京东大数据采集):2023年线上珍珠市场销售数据采集
  • 亚信科技AntDB数据库与库瀚存储方案完成兼容性互认证
  • 现代C++之万能引用、完美转发、引用折叠
  • ELK日志收集系统-filbeat
  • Python小知识
  • 如何在Ubuntu系统上安装Redis
  • Vue2问题:如何全局使用less和sass变量?
  • Java 基础学习(四)操作数组、软件开发管理
  • git仓库如何撤销提交,恢复提交,重置版本命令
  • Java 基础学习(三)循环流程控制与数组
  • 别太担心,人类只是把一小部分理性和感性放到了AI里
  • 最新AIGC创作系统ChatGPT系统源码+DALL-E3文生图+图片上传对话识图/支持OpenAI-GPT全模型+国内AI全模型
  • 在centos7上源码安装nginx
  • Html网页threejs显示obj,ply三维图像实例
  • Windows平台下的oracle 11G-11.2.0.4补丁升级操作指南
  • MFC居中显示文字及其应用
  • 50-75GHz大功率六倍频源设计
  • Qt 软件调试(一) Log日志调试
  • docker network容器网络通信
  • CVE-2022-4886 ingress命令注入复现与分析
  • Oracle整体架构
  • webpack具体实现--未完
  • 【Git】修改提交信息(单次、批量)