检查日期是否合法
//检查日期是否合法的函数
bool CheckDate()
{
if (_month < 1 || _month>12
|| _day< 1 || _day>GetMonthDay(_year, _month))
{
return false;
}
}
获取每个月的天数
//获取每个月的天数——该函数使用最为频繁,故直接放到类里作内联函数。
int GetMonthDay(int year, int month)
{
//保证月份在正确的区间
assert(month > 0 || month < 13);
//把数组放到静态区
//原因:由于频繁调用,为避免其每次进入函数都反复创建空间
static int MonthArr[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };//将第0个位置空出来
//闰年的二月情况单独
if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
return 29;
}
return MonthArr[month];
}
友元函数(以便全局函数(流输入输出函数)使用私有)
//友元函数的声明:
// 作用:可以在类访问私有
friend ostream& operator<<(ostream& out, const Date& d);//流输出
friend istream& operator>>(istream& in, Date& d);//流输入
//流输入这里是不能加const的,因为我们提取的值要写到对象d里面去
运算符重载功能:比较大小
//运算符重载功能
// operator传值注意:
// d1(对应operator)的地址,d2(对应参数列表第一个参数)的地址
//比较大小
//应学会的技巧:复用函数~
bool Date::operator > (const Date& d)
{
//从day开始比较
//天大就大
if(_day > d._day)
{
return true;
}
//天相等,月大就大
else if(_day == d._day && _month > d._month)
{
return true;
}
//天、月相等,年大就大
else if (_day == d._day && _month == d._month && _year > d._year)
{
return true;
}
return false;
}
bool Date::operator == (const Date& d)
{
return _day == d._day && _month == d._month && _year == d._year;
}
// == 的函数取反(!),就是 != 的函数
bool Date::operator != (const Date& d)
{
return !(*this == d);
}
// d1 >= d2
//this是d1的地址,d是d2的地址
//
// >= 重载,直接结合 > 和 = 的运算符重载函数
bool Date::operator >= (const Date& d)
{
//注意:此处的this是指针,改变其数值要使用*this
// 而d是引用,改变值直接使用d
return *this > d || *this == d;
}
// >= 的函数取反(!),就是 < 的函数
bool Date::operator < (const Date& d)
{
return !(*this >= d);
}
// > 的函数取反(!),就是 < 的函数
bool Date::operator <= (const Date& d)
{
return !(*this > d);
}
日期类加减
//日期类的加减
//日期加日期无意义,日期加整型(如天数)有意义
// += 是天数直接赋值到对象,会改变对象的值,故使用引用Date&
// + 是算以后多少天的日期,不改变数值,故直接Date
Date& Date::operator += (int day)
{
//d1 += -100, d1 = d1-100
if (day < 0)
{
//d1 - (-100) = d1 + 100
return *this -= -day;
}
_day += day;
//天数大于当月天数
while (_day > GetMonthDay(_year, _month))
{
//月份进一位,天数减掉当月天数
_day -= GetMonthDay(_year,_month);
++_month;
//月份大于12,说明这一年过去了
if (_month == 13)
{
//年份进一位,月份更新为来年一月
_year++;
_month = 1;
}
}
return *this;
}
//此前提是已经有+= 运算符重载函数
//注意: + 是不改变对象的
Date Date::operator + (int day)
{
//调用拷贝构造,拷贝this指向的对象
Date tmp = *this;
//赋值给tmp
tmp += day;
//返回tmp,不会改变原对象的值
return tmp;
}
Date& Date::operator -= (int day)
{
//d1 -= -100 ,d1 = d1 + (-100)
if (day < 0)
{
//d1 + (-100) == d1 - 100;
return *this += -day;
}
//原来的天数减去要减的天数
_day -= day;
while (_day <= 0)
{
-- _month;
if (_month == 0)
{
//说明到上一年12月了
--_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)
{
//传入默认 d1 - d2
Date max = *this;//默认假设d1大
Date min = d;
int flag = 1;
if (*this < d)
{
//此时d1 - d2 是负数,故flag要变-1 避免返回负数
max = d;
min = *this;
flag = -1;
}
//计数器count
int count = 0;
while (min != max)
{
min++;
count++;
}
return count * flag;//避免返回负数
}
日期自定义格式流输出和输入
//流输出
ostream& operator <<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "日" << d._day << "日" << endl;
}
//流输入
istream& operator >> (istream& in,Date& d)
{
//这里要注意输入的日期可能不合法
while (1)//用循环,直至输入合法日期可跳出循环
{
cout << "请输入正确的日期:" << endl;
in >> d._year >> d._month >> d._day;
if (d.CheckDate())
{
break;
}
else
{
cout << "日期非法,请重新输入" << endl;
}
}
return in;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include<assert.h>
using namespace std;
class Date
{
public:
//友元函数的声明:
// 作用:可以在类访问私有
friend ostream& operator<<(ostream& out, const Date& d);//流输出
friend istream& operator>>(istream& in, Date& d);//流输入
//流输入这里是不能加const的,因为我们提取的值要写到对象d里面去
Date(int year = 1999, int month = 1, int day = 1);
//void point (const Date* const this) const; 传参列表有隐藏的this指针
//调用是会将引用对象的地址传给this指针(if你调用的是d1.print() ,便将d1地址传过去)
void print() const;//函数后面加const的作用如上
//检查日期是否合法的函数
bool CheckDate()
{
if (_month < 1 || _month>12
|| _day< 1 || _day>GetMonthDay(_year, _month))
{
return false;
}
}
//获取每个月的天数——该函数使用最为频繁,故直接放到类里作内联函数。
int GetMonthDay(int year, int month)
{
//保证月份在正确的区间
assert(month > 0 || month < 13);
//把数组放到静态区
//原因:由于频繁调用,为避免其每次进入函数都反复创建空间
static int MonthArr[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };//将第0个位置空出来
//闰年的二月情况单独
if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
return 29;
}
return MonthArr[month];
}
//————————————————————————————————————————————————————————
//运算符重载功能
//比较大小
bool operator > (const Date& d);
bool operator < (const Date& d);
bool operator >= (const Date& d);
bool operator <= (const Date& d);
bool operator == (const Date& d);
bool operator != (const Date& d);
//————————————————————————————————————————————————————————
//日期类的加减
//日期加日期无意义,日期加整型(如天数)有意义
// += 是天数直接赋值到对象,会改变对象的值,故使用引用Date&
// + 是算以后多少天的日期,不改变数值,故直接Date
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);
//————————————————————————————————————————————————————————
//流输出和流输入
//即需要重载<< >>,此时重载必须为全局函数
//若重载为成员函数,this指针默认抢占第一个形参位置,即变成 this对象 << cout
//而我们正常应该是 cout << this对象
//注意:由于是在全局函数,无法访问类内私有的_year _month _day
//此时我们在Date类开头加友元函数声明这个全局函数(即流输入输出函数)
//————————————————————————————————————————————————————————
private:
int _year;
int _month;
int _day;
};
//流输出
ostream& operator <<(ostream& out, const Date& d);
//流输入
//流输入这里传参列表是不能加const的,因为我们提取的值要写到对象d里面去
istream& operator >>(istream& in,Date& d);
#define _CRT_SECURE_NO_WARNINGS 1
#include "Date.h"
//Date:: 的作用
// 在某个类的外面定义它的成员函数,要指定类域,否则无法知道是否是某个类的成员函数
//即不知道你_year那些是哪来的(它默认只在全局找,不特定标明他不会特地去类域找)
//为啥声明里(Date.h)有缺省值,定义(Date.cpp)没有?
// (参数列表中初始定义传入的参数为某个数值,如 int year = 10)
// 复习一下!缺省值 在声明和定义都存在时,只在声明中标明。
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//注:Date::在函数名前加!别在返回值前加!
void Date::print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
//————————————————————————————————————————————————————————
//运算符重载功能
// operator传值注意:
// d1(对应operator)的地址,d2(对应参数列表第一个参数)的地址
//比较大小
//应学会的技巧:复用函数~
bool Date::operator > (const Date& d)
{
//从day开始比较
//天大就大
if(_day > d._day)
{
return true;
}
//天相等,月大就大
else if(_day == d._day && _month > d._month)
{
return true;
}
//天、月相等,年大就大
else if (_day == d._day && _month == d._month && _year > d._year)
{
return true;
}
return false;
}
bool Date::operator == (const Date& d)
{
return _day == d._day && _month == d._month && _year == d._year;
}
// == 的函数取反(!),就是 != 的函数
bool Date::operator != (const Date& d)
{
return !(*this == d);
}
// d1 >= d2
//this是d1的地址,d是d2的地址
//
// >= 重载,直接结合 > 和 = 的运算符重载函数
bool Date::operator >= (const Date& d)
{
//注意:此处的this是指针,改变其数值要使用*this
// 而d是引用,改变值直接使用d
return *this > d || *this == d;
}
// >= 的函数取反(!),就是 < 的函数
bool Date::operator < (const Date& d)
{
return !(*this >= d);
}
// > 的函数取反(!),就是 < 的函数
bool Date::operator <= (const Date& d)
{
return !(*this > d);
}
//————————————————————————————————————————————————————————
//日期类的加减
//日期加日期无意义,日期加整型(如天数)有意义
// += 是天数直接赋值到对象,会改变对象的值,故使用引用Date&
// + 是算以后多少天的日期,不改变数值,故直接Date
Date& Date::operator += (int day)
{
//d1 += -100, d1 = d1-100
if (day < 0)
{
//d1 - (-100) = d1 + 100
return *this -= -day;
}
_day += day;
//天数大于当月天数
while (_day > GetMonthDay(_year, _month))
{
//月份进一位,天数减掉当月天数
_day -= GetMonthDay(_year,_month);
++_month;
//月份大于12,说明这一年过去了
if (_month == 13)
{
//年份进一位,月份更新为来年一月
_year++;
_month = 1;
}
}
return *this;
}
//此前提是已经有+= 运算符重载函数
//注意: + 是不改变对象的
Date Date::operator + (int day)
{
//调用拷贝构造,拷贝this指向的对象
Date tmp = *this;
//赋值给tmp
tmp += day;
//返回tmp,不会改变原对象的值
return tmp;
}
Date& Date::operator -= (int day)
{
//d1 -= -100 ,d1 = d1 + (-100)
if (day < 0)
{
//d1 + (-100) == d1 - 100;
return *this += -day;
}
//原来的天数减去要减的天数
_day -= day;
while (_day <= 0)
{
-- _month;
if (_month == 0)
{
//说明到上一年12月了
--_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)
{
//传入默认 d1 - d2
Date max = *this;//默认假设d1大
Date min = d;
int flag = 1;
if (*this < d)
{
//此时d1 - d2 是负数,故flag要变-1 避免返回负数
max = d;
min = *this;
flag = -1;
}
//计数器count
int count = 0;
while (min != max)
{
min++;
count++;
}
return count * flag;//避免返回负数
}
//————————————————————————————————————————————————————————
//流输出
ostream& operator <<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "日" << d._day << "日" << endl;
}
//流输入
istream& operator >> (istream& in,Date& d)
{
//这里要注意输入的日期可能不合法
while (1)//用循环,直至输入合法日期可跳出循环
{
cout << "请输入正确的日期:" << endl;
in >> d._year >> d._month >> d._day;
if (d.CheckDate())
{
break;
}
else
{
cout << "日期非法,请重新输入" << endl;
}
}
return in;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"Date.h"
int main()
{
//Date d1(2024, 8, 10);
//d1.Print();//2024-8-10
///*d1 += 100;
//d1.Print();*///2024-11-18
//Date d2 = d1 + 100;
//d2.Print();
//d1.Print();//那么这里的d1就没有被改变了
///*int i = 1;
//i + 100;*/
///*
//如果是单纯的+的话,原先的对象是不会被改变的,但是现在我们的对象已经被改变了
//由此可知我们在这里实现的是+=的操作符
//*/
//d1 += 100;
//d1.Print();
//d1 -= 100;
//d1.Print();
//Date ret1=++d1;
//d1.Print();
//Date ret2 = d1++;
//d1.Print();
//ret1.Print();
//ret2.Print();
Date d1(2024, 2, 29);
Date d2(2024, 8, 20);
cout << d1 - d2 << endl;
cout << d2 - d1 << endl;
/*cout << d1;*/
/*d1 << cout;*///我们只有这么写才能正确打印出来日期
//d1对应的就是隐含的this指针,cout对应的就是后面的参数
//但是这种写法很怪
//那么我们是否有方法将这个进行改变呢
/*
重载<<和>>时,需要重载为全局函数
然后我们的ostream/iostream就能放到第一个参数了
然后第二个参数就是我们的对象了*/
cout << d1;
operator<<(cout, d1);//本质
//那么到这里我们就不支持了
cout << d1<<d2<<endl;
//我们这里是从左往右进行结合
//对于cout << d1这个我们的返回值应该是cout 然后cout和d2
//再次返回cout 和endl
//所以流插入是需要返回cout的
cin >> d1 >> d2;
cout << d1 << d2 << endl;
return 0;
}
希望对你有帮助