寒暄
今天是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语言的魅力,可谓收获满满不要忘了点赞收藏关注,我是第一步,我将持续更新。