中图分类号:TP3文献标识码:A摘要:本文介绍了根据已知日期推算星期几的思路和算法,并给出了运用C语言中的多分支选择结构——switch语句实现这一功能的具体方法及程序代码。
关键词:C语言 ;switch语句;推算星期;程序设计
我们在日常生活中经常会遇到这样的问题,忘记了某年某月某日是星期几,特别是一些重大节日或是一些值得纪念的日子,这就是星期的推算问题。学过程序设计语言的人都知道:在VB和VFP中,都有实现这个功能的函数,而C语言中却没有这样的函数。那么,在C语言中如何设计出一个函数来实现星期的推算呢?本文拟就这一问题加以分析,并给出在C语言中实现的具体解决办法和程序代码,可以很方便地转化为其他高级语言的程序代码,供大家在学习其他程序设计语言时作为参考。
根据已知日期推算星期几,人们一般会采用这样的方法:从一个已知星期几的某天开始推算,先计算出已知星期几的这一天距要推算的那天相差多少天,由于星期是7天一个轮回,故可将相差的天数除以7取余数,再用已知的那天的星期数加上余数,就可以计算出要推算的这天是星期几了。例如:已知1月1日是星期日,那么5月1日是星期几呢?通过计算可知,5月1日距1月1日相差121天,121除以7商17余2,即以上两个日期相差17周多两天,故5月1日是星期二。
在此,我们也采用类似的方法进行推算,但可应用的日期范围更加广泛。已知公元元年1月1日是星期一,那么只需计算出从公元元年1月1日到要推算的这一天总共有多少天,再用总天数除以7取余,余0则说明正好够整数个星期,则要推算的这一天正好就是星期日;余1则说明整数个星期还多一天,那么要推算的这一天就是星期一了,以此类推,余2就是星期二,余3就是星期三,……。但是我们在计算天数时会发现由于中间会经历平年(365天)、闰年(366天),每年的不同月份天数也不相同(公历的平年和闰年只有2月份的天数不同,平年2月份28天,闰年2月份29天,其它相应月份的天数是一样的,与是否闰年无关,1、3、5、7、8、10、12这七个月份固定有31天,而4、6、9、11这四个月份固定有30天),这样算来计算量是很大的,计算也十分不便。有没有改进的方法呢?不妨这样来考虑:如果一个年份是平年,则该年有365天,也就是52个星期多一天;如果是闰年,则该年有366天,也就是52个星期多两天;于是,对于以前的年份,如果是平年,则只计为一天(扣除其中的整数个星期),同理,如果是闰年,则计为两天。如此计算则计算量大大减少。
那么,什么样的年份是闰年呢?查阅资料可知,如果一个年份是闰年,则必满足这样的条件:年份是4的整数倍但不是100的整数倍或者年份是400的整数倍。
只要年份能满足上述条件,便可判定是闰年,否则不是。于是,不难写出判断一个年份是否闰年的函数如下:
Char leap(int year) //判断是否闰年函数
{ return (year%4==0&&year%100!=0||year%400==0); }
该函数若返回1则说明年份year是闰年,否则不是闰年。
再进一步,把要推算的日期所在年份之前的所有年份都先按平年计算,则之前有多少年,就计多少天(因为一个平年只计一天,其中的整数个星期已扣除)。设要推算的年份为y,则之前有y-1个年份,就计为y-1天。其中y-1个年份中有若干个年份是闰年,由于闰年比平年多一天,则需再加上闰年的个数。根据上述闰年的条件,于是可以写出y年之前的天数为(y-1)+(y-1)/4-(y-1)/100+(y-1)/400。注意:这个表达式是先把之前y-1个年份中凡是4的整数倍的年份都暂按闰年计算,然后再去掉是100的整数倍的年份,再加上400的整数倍的年份,即可算出y年之前扣除整数个星期之后所有的天数了。
余下的工作就是要计算出要推算的日期是当年的第多少天。这个不难计算。我们可以先根据要推算的日期所在的月份计算出该月份之前当年已经历了多少天,再加上要推算的这一天是当月的第几天,就可以计算出要推算的日期是当年的第多少天了。如果要推算的日期在该年的前两个月,则与该年是否闰年无关;如果是2月份以后的月份,可以先按平年计算,如果是闰年,则需再加上一天。由于各个月份的天数不同,每个月份之前当年已经历了多少天,情况也各不相同,需用具有多分支选择功能的语句来实现。C语言中的switch语句正好具有这样的功能,我们可以运用它来对要推算的日期所在的月份进行测试,并按各种情况计算出要推算的日期所在月份之前当年已经历了多少天,再加上要推算的日期是当月的第几天,就可以计算出要推算的日期是当年的第多少天了。用之前所算出的当年之前的总天数加上要推算的这一天是当年的多少天,如此计算出总天数,再用这个总天数除以7取余数,所得余数即星期几:余0则是星期日,余1则是星期一,余2则是星期二,……依次类推。
综上所述,由已知日期推算星期几的函数的源代码设计如下:
char calc_week(int y, char m, char d)
{ int s; //变量s用于存放总天数
switch (m)
{
case 1: s=0; break;
//1月份之前当年没有天数
case 2: s=31;break;
//2月份之前当年已过31天
case 3: s=59; break;
//3月份之前当年已过59天,此处暂按平年计算,下同
case 4: s=90;break;
case 5: s=120; break;
case 6: s=151;break;
case 7: s=181; break;
case 8: s=212;break;
case 9: s=243; break;
case 10: s=273;break;
case 11: s=304; break;
case 12: s=334;break;
}
if(m>2 && leap(y)) s=s+1;
s=s+d+(y-1)+(y-1)/4-(y-1)/100+(y-1)/400;
return (s%7);
}
程序的主函数设计如下:
main( )
{ char week[7][3]={"日","一","二","三","四","五","六"};
int y; char m,d;
printf("请输入日期: (格式为:yyyy-mm-dd)\n");
scanf("%d-%d-%d",&y,&m,&d);
printf("%d年%d月%d日是星期%s.",y,m,d,week[calc_week(y,m,d)]);
}
结束语:在由已知日期推算星期几时,需要用户计算出已知星期几的某天到要推算的这天的总天数,再用总天数除以7取余,即可推算出这一天是星期几了。如何计算这期间的总天数是解决这个问题的关键所在。其中在计算每个月份之前当年已经历多少天时,可巧妙利用C语言中的多分支选择结构——switch语句来实现。不同的程序语言语法不同而已,但编程的思路与算法是基本相同的,都可以用上述思路来实现,不同的只是语法规定的书写方式不同而已。读者只要理解掌握了这样的思路,问题就不难解决了。
参考文献:
[1] 沈祥玖编著.VB程序设计(第2版)[M].北京:高等教育出版社,
[2] 谭浩强编著.C程序设计(第4版)[M].北京:清华大学出版社,