使用C/C++来解决日期问题

本文介绍几种常见日期问题模板,为大家提供帮助,也方便日后复习

最近在打蓝桥杯,发现日期问题在蓝桥杯中经常出现,为大家总结常见模板,希望大家和自己再次遇到日期问题时可以拿捏(啥?你说蓝桥杯日期问题可以用win10的计算器水过去?好吧,但我更推荐你能了解其中的原理,能够随机应变,毕竟技多不压身是吧hh)

这里为大家总结了:

  1. 得到某年某月的天数
  2. 判断给定日期的合法性
  3. 查找两个日期之间有多少个回文日期
  4. 给定年月日,求经过n天后的日期

得到某年某月的天数

这个问题比较简单,但是非常重要,在日期问题以及其它的模板中使用的频率很高

int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

// 得到某年某月的天数
int get(int y, int m) 
{
    if(m != 2) return days[m];
    else
    {
        //特判 2 月 
        int leap = (y % 4 == 0 && y % 100 != 0 || y % 400 == 0);
        return days[m] + leap;
    }
}

简单解释一下数组b[]:首先这个数组存储了下标对应的月份的天数(先假设为非闰年),例如days[1] = 31的下标为1表示一月份最多有31天,其次是为啥没有写出数组的长度,这是因为:如果给全部元素赋值,则在数组说明中,可以不给出数组元素的个数,例如:

int a[5] = {1,2,3,4,5};

也可写为

int a[] = {1,2,3,4,5};

再来说一下变量leap:当使用布尔类型为整型赋值时true对应1,false对应0
这个问题明白后为大家解释一下什么是闰年,闰年分为两种:

  1. 普通闰年:年份是4的倍数,但不是100的倍数(如2004,2020)
  2. 世纪闰年:是400的倍数(如1900不是世纪闰年,2000是)
    写成伪码就是:
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
	是闰年;
else
	不是;

这里再简单解释一下因为&&的运算优先级是比||的运算优先级高所以判断是否是普通闰年时可以不用加括号,对于对优先级不太熟练或者求稳的同学写成

(year % 4 == 0 && year % 100 != 0) || year % 400 == 0

也是可以的!

判断给定日期的合法性

bool check_valid(int date) //形如20210305
{
    int y = date / 10000;//分离出年份
    int m = date % 10000 / 100;//分离出月份
    int d = date % 100;//分理出日

    if(m < 1 || m > 12) return false;//如果月份不合法
	if(d < 1 || d > get(y,m)) return false; 
	//如果日不合法,还记得get(y,m)吗,前面有提到过这是一个很重要的用法

    return true;//年份一般是不需要检查的(视题意而定),如果月份,日都符合条件则日期合法
}

查找两个日期之间有多少个回文日期

回文日期:形如20211202等,回文日期的年份一定是四位数

int solve(int date1, int date2)
{
    int ans = 0;
    for(int i = 1000; i <= 9999; i++)//枚举每一个四位数的年份  
    {
        int date = i, x = i;
        for(int j = 0; j < 4; j++)//根据年份构造出一个形如20211202的回文日期 
		{
			date = date * 10 + x % 10;//注释1
			x /= 10; //根据年份构造出回文日期 
		}
        if(date1 <= date && date <= date2 && check_valid(date)) ans++; 
    }

    return ans;
}

注释1:这个地方其实特别简单,只需要模拟一遍即可,这里我们再次以2021为例子:

初始时 date = 2021,x = 2021
第一次执行内存循环体时分理出x的个位,并处理date
即 date = 2021 * 10 + 2021 % 10 = 20211
第二次:20211 * 10 + 202 % 10 = 202112
第三次:202112 * 10 + 20 % 10 = 2021120
第四次:2021120 * 10 + 2 % 10 = 20211202

这样就可以根据年份来的到回文日期,之后再判断这个日期是否合法并是否处于给定区间内即可 0

给定年月日,求经过n天后的日期

// 给定年月日,经过n天后对应的日期 
void pass(int y, int m, int d, int n)
{
    while(n--)
    {
        d++;
        if(d > get(y, m)) m++, d = 1;//注释1
        if(m > 12) y++, m = 1;//注释2
    }
    printf("%d-%02d-%02d\n", y, m, d);
}

这个模板实际上有一点类似于进制:
注释1:当日大于本月的最大月份时再更新月和日的值
注释2:当月份大于12时更新月和年的值
最后再以特定格式输出即可

好了,这篇文章暂时介绍到这里,以后遇到本文未涉及的问题时会继续回来更新文章。

如果您喜欢这篇文章,就点个赞吧,这样就能让更多的人看到这篇文章

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值