(1)可以建立具有指定日期(指定年、月、日)的Date对象,默认的日期是1949.10.1;
(2)可以从输入流读一个日期到一个Date对象,日期的输人格式是:年.月.日,其中年可以是4位数字也可以是2位数字(即可省略20),月、日可以是2位数字也可以是1位数字;
(3)可以通过输出流输出一个Date对象,格式与输入同;
(4)可以用==、!=、<、<=、>和>=等运算符对两个Date对象进行比较;
(5)可以用++、--(前缀及后缀)、+=、-=等运算符完成增减1天或若干天的操作;
(6)可以用+、-将一个Date对象与一个表示天数的整数相加减,其结果是一个表示若干天前或若干天后的日期的Date对象。
cpp
class Date
{
private:
int year, month, day;
//校验闰年 返回day = 29
bool isLeapYear()const
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int getDaysOfMonth()const
{
int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (month == 2 && isLeapYear())
{
return 29;
}
//返回月份对应的天数
return days[month];
}
bool isValidDate()const
{
//校验日期合法性
if (year < 1 || month < 1 || month > 12 || day < 1)
{
return false;
}
return day <= getDaysOfMonth();
}
//返回四位数年份
int normalizeYear(int y)const
{
if (y>=0 && y<100)
{
return 2000 + y;
}
return y;
}
void adjustDatr()
{
while (day < 1)
{
if (--month < 1)
{
month = 12;
year--;
}
day += getDaysOfMonth();
//成功+=后跳出循环
}
while (day > getDaysOfMonth())
{
day -= getDaysOfMonth();
if (++month > 12)
{
month = 1;
year++;
}
}
}
//问题1 可以建立具有指定日期(指定年、月、日)的Date对象,默认的日期是1949.10.1;
public:
Date(int y = 1949, int m = 10, int d = 1) :year(normalizeYear(y)), month(m), day(d)
{
//非法日期自动重置为默认值,符合指定日期的不会进入这里,不符合才会重置
if (!isValidDate())
{
year = 1949;
month = 10;
day = 1;
}
}
//流运算符 << 输出运算符
friend ostream& operator<<(ostream& out, const Date& date)
{
//sprintf 是把内容输出到内存中的字符串数组里。
char buf[20];
sprintf(buf, "%d.%d.%d", date.year, date.month, date.day);
out << buf;
return out;
}
//流运算符 >> 输入流运算符
//支持2位/4位年份,1/2位月,日
friend istream& operator>>(istream& in, Date& date2)
{
string s;
in >> s;
int y, m, dy;
//将s的字符串的内容通过s_str()转换成C风格,因为sscanf只接纳C风格
//"%d.%d.%d" 通过这样的形式输入提取三个整数数据,看看是否等于3,如果是2026/2/19,提取的整数数据小于3
if (sscanf(s.c_str(),"%d.%d.%d",&y,&m,&dy) == 3)
{
date2.year = date2.normalizeYear(y);
date2.month = m;
date2.day = dy;
//如果确实是提取到三个整数,成功进入if循环,如果赋值中发现整数非法,恢复默认值
if (!date2.isValidDate())
{
date2.year = 1949;
date2.month = 10;
date2.day = 1;
}
}
return in;
}
//关系运算符 返回值必须是bool,关系运算符的结果只有真假且作为成员函数只有一个形参
bool operator==(const Date& other)const
{
return this->year == other.year && this->month == other.month && this->day == other.day;
}
bool operator!=(const Date& other)const
{
//其中==是基于已经实现好的"=="来实现比较的
return !(*this == other);
}
bool operator<(const Date& other)const
{
//不是不相等就要返回other大于this的,是判断这样的结果是true还是false
if (this->year != other.year)
{
return this->year < other.year;
}
if (this->month != other.month)
{
return this->month < other.month;
}
return this->day < other.day;
}
bool operator<=(const Date& other)const
{
//其中< == 是基于已经实现好的代码来进行比较的
return *this < other || *this == other;
}
bool operator>(const Date& other)const
{
// !<= 反过来就是this > other
return !(*this <= other);
}
bool operator>=(const Date& other)const
{
//!< 反过来就是this >= other
return !(*this < other);
}
//++,--,+=,-+
//前置++
Date& operator++()
{
this->day++;
//检验是否因为+1天而产生月份/年份增加
adjustDatr();
return *this;
}
//后置++
Date operator++(int)
{
//拷贝
Date temp = *this;
//基于已实现的++来处理
++(*this);
return temp;
}
//前置--
Date& operator--()
{
this->day--;
adjustDatr();
return *this;
}
//后置--
Date operator--(int)
{
Date temp = *this;
--(*this);
return temp;
}
//日期+天数
Date operator+(int days)const
{
Date d = *this;
d.day += days;
d.adjustDatr();
return d;
}
//日期 - 天数
Date operator-(int days)const
{
Date d = *this;
d.day -= days;
d.adjustDatr();
return d;
}
//日期+=天数
Date operator+=(int days)
{
*this = *this + days;
return *this;
}
//日期 -= 天数
Date operator-=(int days)
{
*this = *this - days;
return *this;
}
//两日期相减,差->天数
int toTotalDays(const Date& d)const
{
int total = 0;
//累加之前所有年份的天数
for (int y = 1; y < d.year; y++)
{
if ((year%4 == 0 && year%100 != 0) || (year%400 == 0))
{
total += 366;
}
else
{
total += 365;
}
}
//累加当年的之前月份的天数
for (int m = 1; m < d.month; m++)
{
//创建一个临时Date对象,用于调用getDaysOfMonth
Date temp(d.year, m, 1);
total += temp.getDaysOfMonth();
}
//累加当月天数
total += d.day;
return total;
}
int operator-(const Date& date)const
{
return toTotalDays(*this) - toTotalDays(date);
}
//析构函数
~Date() = default;
};
int main()
{
//【第一问】
//默认输出日期
Date d1;
cout << "默认日期:" << d1 << endl;
////自定义日期
Date d2(2026, 2, 19);
cout << "自定义日期:" << d2 << endl;
////两位数年份
Date d3(26, 2, 19);
cout << "补充四位数年份:" << d3 << endl;
////非法日期恢复默认日期
Date d4(-1, 2, 19);
cout << "非法日期恢复默认值" << d4 << endl;
//【第二问】
Date d5;
cout << "请输入日期(格式:年.月.日,支持2 / 4位年、1 / 2位月日):";
cin >> d5;
cout << "你输入的日期解析后:" << d5 << endl;
//【第三问】
//在第一第二问实现时候顺带实现了
//就是通过friend ostream& operator<<(ostream& out, const Date& date)实现
//【第四问】
//关系运算符
// 太多例子了都是一样的,就实现一个比较符,其他的都一样
Date d6(2026, 2, 19);
Date d7(2025, 5, 5);
if (d6 < d7)
{
cout << "d6 < d7" << endl;
}
else {
cout << "d6 > d7" << endl;
}
//【第五问】
Date d8(2026, 12, 31);
cout << d8++ << endl;
cout << d8 << endl;
// -- 如出一辙
// += -=
Date d9(2026, 2, 23);
d9.operator+=(10);
cout << d9;
d9.operator-=(3);
cout << d9;
//【第六问】
Date d10(2026, 2, 23);
Date d11(2025, 10, 10);
int result = d10 - d11;
cout << "两日期相减天数差为:" << result << endl;
return 0;
}