在学习C++类的时候,日期类是最基础也是最重要的一个类。简单的日期类并不复杂,但在实现的过程中主要会涉及一些C++的基本成员函数。这个代码的难度主要在于如何判断日期类的合法性,比如月份如果大于12,天数也要合法,比如二月不能闰年不能超过30天,平年28天。在自增和自减的时候,也要考虑到年份、月份和天数的变化。
下面给出类的定义:
class Date
{
friend ostream& operator <<(ostream& _cout, const Date& date);
friend istream& operator >>(istream& _cin, Date& date);
public:
Date(int year = 1990, int month = 1, int day = 1);
Date(const Date& date);
Date& operator=(const Date& date);
Date& operator++();
Date operator++(int);
Date operator+(int day);
Date operator-(int day);
Date& operator--();
Date operator--(int);
bool operator>(const Date& date);
bool operator<(const Date& date);
bool operator==(const Date& date);
bool operator!=(const Date& date);
bool operator>=(const Date& date);
bool operator<=(const Date& date);
private:
bool IsLeapYear(int year)
{
return((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0));
}
int GetMonthDay(int year, int month)
{
assert(month > 0 && month < 13);
static int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int day = days[month];
if ((month == 2) && (IsLeapYear(year)))
{
day += 1;
}
return day;
}
private:
int _year;
int _month;
int _day;
};
在写这个代码的过程中,有两个地方是我考虑得比较多的地方。在考虑到自增的问题时,Date& operator++()和Date operator+(int day)有相似的地方,在写代码的时候,我是先写的++。代码如下:
Date& Date::operator++()
{
int days = GetMonthDay(_year, _month);
if (_day < days)
{
_day++;
}
else if (_day == days)
{
_day = 1;
if (_month < 12)
{
_month++;
}
else
{
_month = 1;
_year++;
}
}
else
{
assert(false);
}
return *this;
}
在写到Date operator+(int day)时,我是直接在日期类直接加上来的。比如,今天是2017年1月16日,在加上30天,也就是2017年1月46日,当然46日是不符合日期合法性的。1月一共31天,那么用46-31天,即2017年2月15日,15日符合2月的日期合法性,即是所求的日期。代码实现如下:
Date Date::operator +(int day)
{
Date tmp = *this;
if (day<0)
{
day = -day;
return tmp - day;
}
tmp._day += day;
while (tmp._day>GetMonthDay(tmp._year,tmp._month))
{
tmp._day -= GetMonthDay(tmp._year, tmp._month);
if (tmp._month < 12)
tmp._month++;
else
{
tmp._year++;
}
}
return tmp;
}
然而写完后我发现,++可以通过+1来实现也就是说:
Date& Date::operator++()
{
Date tmp = *this;
(*this) =(*this) + 1;
return *this;
}
加法和减法是一样的,这里就不赘余了。有兴趣的同学,可以按照步骤去实现一下。下面给出所有的功能代码:
ostream& operator <<(ostream& _cout, const Date& date)
{
_cout << date._year << "/" << date._month << "/" << date._day << endl;
return _cout;
}
istream& operator >>(istream& _cin, Date& date)
{
_cin >> date._year >> date._month >> date._day;
return _cin;
}
Date::Date(int year, int month, int day)
{
if (year > 0
&& ((month > 0) && (month<13))
&& ((day>0) && (day <= GetMonthDay(year, month))))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "the date is illegal!" << endl;
}
}
Date::Date(const Date& date)
:_year(date._year)
, _month(date._month)
, _day(date._day)
{}
Date& Date::operator=(const Date& date)
{
if (this != &date)
{
_year = date._year;
_month = date._month;
_day = date._day;
}
return *this;
}
Date& Date::operator++()
{
Date tmp = *this;
(*this) =(*this) + 1;
return *this;
}
Date Date::operator++(int)
{
Date tmp = *this;
++(*this);
return tmp;
}
Date Date::operator +(int day)
{
Date tmp = *this;
if (day<0)
{
day = -day;
return tmp - day;
}
tmp._day += day;
while (tmp._day>GetMonthDay(tmp._year,tmp._month))
{
tmp._day -= GetMonthDay(tmp._year, tmp._month);
if (tmp._month < 12)
tmp._month++;
else
{
tmp._year++;
}
}
return tmp;
}
Date Date::operator-(int day)
{
Date tmp = *this;
tmp._day -= day;
while (tmp._day <=0)
{
if (tmp._month == 1)
{
tmp._year--;
tmp._month = 12;
}
else
{
tmp._month--;
}
tmp._day += GetMonthDay(tmp._year, tmp._month);
}
return tmp;
}
Date& Date::operator--()
{
(*this) = (*this) - 1;
return *this;
}
Date Date::operator--(int)
{
Date tmp = *this;
(*this) = (*this) - 1;
return tmp;
}
bool Date::operator>(const Date& date)
{
if ((_year > date._year)
|| ((_year == date._year) &&( _month > date._month) )
|| ((_year == date._year) && (_month == date._month) && (_day > date._day)))
return true;
else
return false;
}
bool Date::operator<(const Date& date)
{
if ((_year < date._year)
|| ((_year == date._year) && (_month < date._month))
|| ((_year == date._year) && (_month == date._month) || (_day < date._day)))
return true;
else
return false;
}
bool Date::operator==(const Date& date)
{
return ((_year == date._year) && (_month == date._month) && (_day == date._day));
}
bool Date::operator!=(const Date& date)
{
return !(*this == date);
}
bool Date::operator>=(const Date& date)
{
if ((*this) < date)
return false;
else
return true;
}
bool Date::operator<=(const Date& date)
{
if ((*this) > date)
return false;
else
return true;
}
void Test()
{
Date d1(2017, 1, 23);
Date d2(2017, 1, 23);
cout << ++d1;
cout << d1++;
cout << d1 + 30;
cout << d1 - 207 ;
cout << --d1;
cout << d1--;
cout << (d1 > d2) << endl;
cout << (d1 < d2) << endl;
cout << (d1 == d2) << endl;
cout << (d1 != d2) << endl;
cout << (d1 <= d2) << endl;
cout << (d1 >= d2) << endl;
}
int main()
{
Test();
system("pause");
}
整个日期类的代码实现就这么多,在写代码的过程中还是难免会遇到一些奇奇怪怪的问题,比如在写最后几个函数时,函数逻辑没一点问题,但是测试函数写得有问题,所以整个程序也就有点问题。总而言之,在写代码的时候要多考虑一些,把能简化的地方尽量简化。