在刚开始学习C++的时候,曾经封装过一个时间类,里面实现了一些接口,包括判断该年是否为闰年,计算某个月的天数,计算截止这个日期总共过了多少天等等。
可能很多学C++的人都写过这种东西,大多数人的写法可能和我最开始的时候写的一样,都是通过if,else语句和switch,case语句来进行判断,github上也有很多这种实现。
代码
判断闰年
bool IsLeapYear(int _year) const
{
if (_year % 4 == 0 && _year % 100 != 0 || _year % 400 == 0)
return true;
else
return false;
}
获取某月天数
int DayOfMonth(int year,int month)
{
int day = 0;
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
day = 31;
break;
case 4:
case 6:
case 9:
case 11:
day = 30;
break;
case 2:
day = 28 + IsLeapYear(year);
break;
}
return day;
}
这样实现起来是没有问题的,但是还有更简洁的代码可以只用一行代码就实现这些功能。
我们知道在C和C++中有一种运算符叫做选择运算符(三目运算),它的形式为“表达式1?表达式2:表达式3”,它的作用是当表达式一为真时计算表达式二,否则计算表达式三。
例如:a>b?c=1:c=0;当a大于b为真时c就为1,a小于b时c就为0。
其实选择运算符就有判断的操作在里面,我们可以把他巧妙的运用到上面两个函数里面。
判断闰年函数只需三个选择运算符嵌套使用就可以让它在一句代码中完成。
代码
bool IsLeapYear(int _year) const
{
return _year % 400 ? (_year % 100 ? (_year % 4 ? (false) : (true)) : (false)) : true;
}
这里使用选择表达式比使用if语句要更优越,原因是使用if语句,CPU会对代码进行分支预测,会更多地消耗CPU的时钟周期。
获取月份天数的函数里也可以用选择表达式来代替switch和case语句,同样可以做到一句代码完成。但是我们需要对这个问题进行进一步的分析。
如图,经过观察12个月份中的大月(31天的月份)在七月之前是奇数月,在七月以后是偶数月。
那么我们就可以以七月为分界线,用月份减一去模上2,这个时候奇数月就会得到0,偶数月得到1,再用31减去这个的结果,就可以得到这个月的天数。
七月之前的可以这样计算,那么七月之后的又应该怎么计算呢?
如图,我们在这个地方可以对月份模上一个七,这样就巧妙的使七月以后的月份又从一开始计算,正好对上了奇数为31天,偶数为30天的结果。同时也不影响七之前的运算。
代码
int DayOfMonth(int year, int month)
{
return 31 - ((month == 2) ?
(3 - IsLeapYear(year)) : ((month - 1) % 7 % 2));
}
这样实现计算月份天数相比于第一种实现要简洁很多,但是可读性没有第一种高,两者在效率上的差距也并不是很大。所以更多的时候我们还是选择第一种实现,第二种只是给大家分享另一种新奇的思路。