本文内容如下:
- 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;}elsereturn 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;}elsereturn 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;}elsereturn 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;}elsereturn 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;}elsereturn 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;
}