神解登场——带你用C语言速算还有几天过年

寒暄

今天是2024年11月22日,小雪气节,你的家乡下雪了吗?作为一名身在南方,家在北方万千游子之一,不禁想到,还有多久才到年假啊!今天就教大家如何用C语言编写新年倒计时的代码。在这里插入图片描述

步入正题

我们知道,编写一个新年倒计时的代码还是比较困难的,因为每一个月份的天数不同,有31天的,有30天的,每一年也不同,有366的,有365的,而且闰年与平年的还十分复杂!

闰年判断条件

1必须是的倍数(但有特例)
2不能100的倍数(还有特例)
3能被400整除的是闰年。

没学过的小朋友现在是不是这种心情。
在这里插入图片描述
我最初也是这样
那么,废话不多说,接下来我将带大家感受一下史上最令大家期盼的代码。


法一:最长的代码

int main()
{
    int y,m,d;
    int D=0;
    scanf("%d-%d-%d",&y,&m,&d);
    if(y%4==0&&y%100!=0||y%400==0)//闰年判断为真为366天
    {
        if(m>1)
        D+=31;
        if(m>2)
        D+=29;
        if(m>3)
        D+=31;
        if(m>4)
        D+=30;
        if(m>5)
        D+=31;
        if(m>6)
        D+=30;
        if(m>7)
        D+=31;
        if(m>8)
        D+=31;
        if(m>9)
        D+=30;
        if(m>10)
        D+=31;
        if(m>11)
        D+=30;
    D=366-D-d+1;
    printf("还有%d天到新年",D);
    }
    else//否则为假为平年为365天
    {
        if(m>1)
        D+=31;
        if(m>2)
        D+=28;
        if(m>3)
        D+=31;
        if(m>4)
        D+=30;
        if(m>5)
        D+=31;
        if(m>6)
        D+=30;
        if(m>7)
        D+=31;
        if(m>8)
        D+=31;
        if(m>9)
        D+=30;
        if(m>10)
        D+=31;
        if(m>11)
        D+=30;
    D=365-D-d+1;
    printf("还有%d天到新年",D);
    }
    return 0;
}

相同的目的地,你写的比别人长,只可能一点:你没动脑子,这也是为什么有些人看起来勤勤恳恳兢兢业业,但最终结果却不怎么好,因为他没动脑子,只是在靠时间,用最原始的方法,只能能走最长的路。
当然了,上面的代码还有许多地方是值得肯定的,比如他巧妙地运用了if而不是else if,使得正确判断每个月的天数。所以,凡是都有两面性,有些看起来笨的方法其实是最好的。


法二(真假与一零的巧妙运用)

int main()
{
    int y,m,d;
    int D=0;
    int leap=(y%4==0&&y%100!=0||y%400==0);
//巧妙使用局部变量leap,为真leap=1,否则leap=0,无需将闰年平年分开计算,从而减少工作量
    scanf("%d-%d-%d",&y,&m,&d);
        if(m>1)
        D+=31;
        if(m>2)
        D+=28+leap;
        if(m>3)
        D+=31;
        if(m>4)
        D+=30;
        if(m>5)
        D+=31;
        if(m>6)
        D+=30;
        if(m>7)
        D+=31;
        if(m>8)
        D+=31;
        if(m>9)
        D+=30;
        if(m>10)
        D+=31;
        if(m>11)
        D+=30;
    D=365+leap-D-d+1;
    printf("还有%d天到新年",D);
    return 0;
}

上面的方法是不是绝妙,巧妙借助真假与一零的关系,将代码减少了一半,这种思想可供大家在其他各种代码中奔跑,解放你的双手。


法三(改用switch)

int main()
{
    int y,m,d;
    int D=0;
    int leap=(y%4==0&&y%100!=0||y%400==0);
 //巧妙使用局部变量leap,为真leap=1,否则leap=0,无需将闰年平年分开计算,从而减少工作量
    scanf("%d-%d-%d",&y,&m,&d);
        switch(m)
        {
        case 1:
        D+=31;
       case 2:
        D+=28+leap;
       case 3:
        D+=31;
        case 4:
        D+=30;
        case 5:
        D+=31;
        case 6:
        D+=30;
        case 7:
        D+=31;
        case 8:
        D+=31;
        case 9:
        D+=30;
        case 10:
        D+=31;
        case 11:
        D+=30;
        case 12:
        D+=31;
        }
    D-=d;
    printf("还有%d天到新年",D+1);
    return 0;
}

殊途同归,if也可替换成case,而且借助了switch的特殊性用法——已经开启,非遇break不关闭,同时此解与上解的思想也不同,一个是反推,一个是正推。


法四(数组循环组合拳)

int main()
{
	int y,m,d,cg=0;
	scanf("%d-%d-%d",&y,&m,&d);
	int D[][13] ={ { 0,31,28,31,30,31,30,31,31,30,31,30,31 },{ 0,31,29,31,30,31,30,31,31,30,31,30,31 }};
	//前面添个零使数组下标与月份相对应。
	int leap=(y%4==0&&y%100!=0||y%400==0);
		//用leap来确定行数从而确定平年闰年;加一个零使得月份与列数对应;
    for(m;m<=12;m++)
        cg+=D[leap][m];
	printf("还有%d天到新年",cg+1-d);
	return 0;
}

数组循环一套组合拳下来,让你的代码再短一截,但如果知道这里就不能被称为史上最令大家期盼的代码,我也相信,大家学了数组之后都能想到。这代码肯定有值得改进的地方,提示一下,解放CPU最好的方法——减少循环次数,所以…


神解登场(只用数组)!!!

int main()
{
	int y,m,d,cg=0;
	scanf("%d-%d-%d",&y,&m,&d);
	int D[][13] ={ {0,0,3,3,4,4,5,5,5,6,6,7,7},{ 0,0,2,2,3,3,4,4,4,5,5,6,6}};
	int leap=(y%4==0&&y%100!=0||y%400==0);
	 //用leap来确定行数从而确定平年闰年;加一个零使得月份与列数对应;
    cg=365+leap+1-(d+31*(m-1)-D[leap][m-1]);
    //假设每月都按31天算,再减去到前一个月为止多算的天数,再加上这个月的天数,就是过去的总天数啦!
	printf("还有%d天到新年",cg);
	return 0;
}

反向优化

int main()
{
	int y,m,d,cg=0;
	scanf("%d-%d-%d",&y,&m,&d);
	int D[][13] ={ {0,7,7,4,4,3,3,2,2,2,1,1,0},{0,6,6,4,4,3,3,2,2,2,1,1,0}};
	int leap=(y%4==0&&y%100!=0||y%400==0);
		//用leap来确定行数从而确定平年闰年;加一个零使得月份与列数对应;
    cg=(13-m)*31-D[leap][m]+1-d;
	printf("还有%d天到新年",cg);
	return 0;
}

总结

今天,我们一共用了六种方法,领略新年倒计时与C语言的魅力,可谓收获满满不要忘了点赞收藏关注,我是第一步,我将持续更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值