#include<iostream>
using namespace std;
class date
{
public:
date(int year=1990,int month=1,int day=1)
:_year(year)
,_month(month)
,_day(day)
{
if(isinvalid(year,month,day))
cout<<"date right"<<endl;
else
cout<<"date error"<<endl;
}
date(const date &d)
{
_year=d._year;
_month=d._month;
_day=d._day;
}
void print()
{
cout<<_year<<"-";
cout<<_month<<"-";
cout<<_day<<endl;
}
bool isLeapyear(int year)
{
if((year%4==0)&&(year%100!=0))
{
return true;
}
else
{
if(year%400==0)
return true;
else
return false;
}
}
int Getmonthday(int year,int month)
{
int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapyear(year)&&month==2)
return a[month-1]+1;
else
return a[month-1];
}
bool isinvalid(int year,int month,int day)
{
if(year>=1900)
{
if(month>0&&month<=12)
{
if(day>0&&(day<=Getmonthday(year,month)))
return true;
else
return false;
}
else
return false;
}
else
return false;
}
bool operator ==(const date &d)
{
if(_year==d._year)
{
if(_month==d._month)
{
if(_day==d._day)
return true;
else
return false;
}
return false;
}
else
return false;
}
bool operator !=(const date &d)
{
return !(*this==d);
}
bool operator >(const date &d)
{
if(_year>d._year)
{
return true;
}
else
{
if(_month>d._month)
return true;
else
{
if(_day>d._day)
return true;
else
return false;
}
}
}
date operator +(int day)
{
int nowday=_day+day;
while(nowday>=Getmonthday(_year,_month))
{
nowday=nowday-Getmonthday(_year,_month);
if(_month==12)
{
_year++;
_month=1;
}
else
{
_month++;
}
}
_day=nowday;
return (*this);
}
date operator -(int day)
{
int sumday=_day;
while(sumday<day)
{
sumday=sumday+Getmonthday(_year,_month);
if(_month==1)
{
_month=12;
_year--;
}
else
{
_month--;
}
}
_day=sumday-day;
return (*this);
}
int operator -(date const &d)
{
int count=0;
if(*this>d)
{
while(*this!=d)
{
count++;
*this=*this-1;
}
}
else
{
while(*this!=d)
{
count++;
*this=*this+1;
}
}
return count;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
int count=0;
date A(2018,6,29);
A.print();
date B(2000,2,19);
B.print();
count=A-B;
cout<<count<<" days"<<endl;
return 0;
}
今天给大家介绍的是日期计算器也就是日期类的操作,这里我写的并不是很完全,有些功能还没有完全实现,例如日期类的++,--等。
其实这个类并不复杂,需要注意的是一些思想,比如假如现在让你计算两个日期之间的有多少天,这个问题不用仔细想你就会发现很难来计算,比如有一个大问题就是中间隔了几年,这几年中有几个是闰年有几个是平年,月份每个月份含有的天数都是不一样的。
这里先从简单的函数来说起
date(int year=1990,int month=1,int day=1)
:_year(year)
,_month(month)
,_day(day)
{
if(isinvalid(year,month,day))
cout<<"date right"<<endl;
else
cout<<"date error"<<endl;
}
date(const date &d)
{
_year=d._year;
_month=d._month;
_day=d._day;
}
这两个函数分别是这个类的构造函数和拷贝构造函数,这里我并没有写析构函数,因为这里的成员变量都是简单的int类型,没有所要开辟空间等等问题。
这里在构造函数的时候采用的是缺省值,也就是说当你定义一个类变量的时候,如果不给他初值他将用函数中设定好的缺省值来赋值,并且在赋值的时候采用了初始化列表,这种方式在我们这个类中是几乎没有差别的,在内置类型例如float、int等等是几乎没有差别的,但是当你用的是自定义类型来操作的话就会有很大的区别,这里不再去验证了简单的说一下,当你对自定义类型赋值的时候,这里会比普通的赋值函数来说,少一个构造函数,并且在初始化列表定义的时候,并不是按你在初始化列表所书写的顺序来进行的,而是通过你在类中定义的顺序来进行的。这里就简单的介绍一下。
当对数据进行赋值结束之后,会对数据进行判断是不是合法的,通过isinvalid函数来实现。
bool isinvalid(int year,int month,int day)
{
if(year>=1900)
{
if(month>0&&month<=12)
{
if(day>0&&(day<=Getmonthday(year,month)))
return true;
else
return false;
}
else
return false;
}
else
return false;
}
返回类型是bool类型,符合就返回真不符合就返回假,通过年月日一个一个来判断,因为不同年份不同月份来说2月份到底有多少天是不固定的。所以通过调用一个函数来返回当前年份当前月的天数,其实并不难因为改变的只有二月份,其他每个月的时间都是固定的。
int Getmonthday(int year,int month)
{
int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapyear(year)&&month==2)
return a[month-1]+1;
else
return a[month-1];
}
这个函数在我看来我认为有两个需要注意的地方,一个是如果你传入的月份是闰年的二月这时候返回的是你数组的数值加上1,这里注意不能返回a[month-1]++,因为这样你会修改原本数组中的数值,还有就是返回的时候要记着month-1,因为数组是从0开始的。
bool isinvalid(int year,int month,int day)
{
if(year>=1900)
{
if(month>0&&month<=12)
{
if(day>0&&(day<=Getmonthday(year,month)))
return true;
else
return false;
}
else
return false;
}
else
return false;
}
判断非法值这些都是很简单的思维方式。
bool operator ==(const date &d)
{
if(_year==d._year)
{
if(_month==d._month)
{
if(_day==d._day)
return true;
else
return false;
}
return false;
}
else
return false;
}
bool operator !=(const date &d)
{
return !(*this==d);
}
这里将这两个函数放在一起来说,因为一个是等于一个是不等于,等于思维逻辑也是很简单,函数里的==就是库所提供的内置基本类型的比较,去看不等于,这里不等于就是调用了等于函数然后取反,这样设计很巧妙因为你已经写了等于了,那不等于就是他的取反,同样这样还可以应用的很多方面。
bool operator >(const date &d)
{
if(_year>d._year)
{
return true;
}
else
{
if(_month>d._month)
return true;
else
{
if(_day>d._day)
return true;
else
return false;
}
}
}
这是大于,那大于等于就是大于和等于都可以,小于等于就是大于的取反等等,这里我并没有再去一个一个写,但是这种也是有一定的坏处的那就是当一个错了可能会大面积出现错误。
date operator +(int day)
{
int nowday=_day+day;
while(nowday>=Getmonthday(_year,_month))
{
nowday=nowday-Getmonthday(_year,_month);
if(_month==12)
{
_year++;
_month=1;
}
else
{
_month++;
}
}
_day=nowday;
return (*this);
}
date operator -(int day)
{
int sumday=_day;
while(sumday<day)
{
sumday=sumday+Getmonthday(_year,_month);
if(_month==1)
{
_month=12;
_year--;
}
else
{
_month--;
}
}
_day=sumday-day;
return (*this);
}
之后是日期类的加减,这里的加减参数是day天数也就是时间,时间类的加减有两种,第一个就是一个日期加上多少多少天,或者减去多少多少天,另一个是两个日期类的加减,这里首先写的是,一个日期加减一定的时间,这两个函数只是思想上有那么一点点的不同。都需要注意的是临界值,也就是当你的月份是1月或者12月的时候就需要通过从年借位或者进位来继续往下走。
int operator -(date const &d)
{
int count=0;
if(*this>d)
{
while(*this!=d)
{
count++;
*this=*this-1;
}
}
else
{
while(*this!=d)
{
count++;
*this=*this+1;
}
}
return count;
这里就是两个日期类的加减,这里我的思想是找到两个日期类中小的那个,然后让他不断的加1,直到它等于大的那个日期类,再通过一个计数器没加1,计数器也加上1,最后返回你的count就可以了,但是这样也是有缺点的,这样更改了你本身传进来的参数,如果有介意的话,可以在我的程序上进行修改,在函数开始拷贝构造一个date 类的temp。
很多日期类中还有对运算符++,--前置后置两种运算符的更改,++,——就是通过去调用我们之前所写的+运算符重载来实现的,很简单,但是怎么来区分前置和后置两个概念呢?大家都知道C++中的重载,之前我也介绍过
https://blog.csdn.net/hanani_jia/article/details/80645958
通过参数不同就可以区分两个不同的函数,所以这里为了区分两个,我在后置++中传了一参数date operator -(int) 而在前置中并没有传入参数date operator -(),这里哪个传参哪个不传参可以自己决定,没必要一定按着别人的来,这两个函数内部也是有一定的区别的。平时大家看很多在两个都一样的时候,很多大佬都会选择前置的因为前置的运算速度是相对来说比较快的。为了完完全全的模仿,后置++需要在定义一个变量最后返回的是定义的这个变量,这个变量的值就是在以前的基础上加了1,而前置并没有这个中间变量。
这里就先对日期类介绍这么多,日期类并不复杂,这里要了解运算符重载等等这些C++特性东西的一些应用。