7-27 计算天数及星期值

题目描述:

你知道你生日那天是星期几吗,你知道你爸爸生日那天是星期几吗?你可能会说:可以查万年历啊。然而,不查万年历你能计算出来吗?编程序实现:输入任意一个日期的年、月、日的值,求出从公元1年1月1日到该日期前一年的年末总共有多少天,到该日期前一个月的月末总共有多少天,到这一天总共有多少天,并求出这一天是星期几(用英文表示)。假定从公元第一天开始,就实施格里高利历法,并且公元1年1月1日为星期一。格里高利历法的置闰规则是400年97闰,也可以概括为:四闰百不闰,四百闰。提示:可以将每个月的天数存入一个数组中。

输入格式:

输入年、月、日的值,数据之间以空格分隔。

输出格式:

数据之间以换行符分隔。

输入样例:

2012 3 31

输出样例:

734502
734562
734593
Saturday

原代码:

#include<stdio.h>
int main ()
{
   
	int a[12]={
   31,28,31,30,31,30,31,31,30,31,30,31};
	char b[7][10]={
   "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
	int n,y,r,i,s1=0,s2=0,s3=0;
	scanf("%d %d %d",&n,&y,&r);
	for(i=1;i<n;i++)
        if((i%4==0&&i%100!=0)||i%400==0) s1+=366;
        else s1+=365;
	if((n%4==0&&n%100!=0)||n%400==0) a[1]=29;
    s2=s1;
	for(i=0;i<y-1;i++)
		s2+=a[i];
	s3=s2+r;
	printf("%d\n%d\n%d\n%s\n",s1,s2,s3,b[s3%7]);
}

总结:

1、该代码是通过求出总天数再对7求余实现求算星期几的,余数只会是0,1,2,3,4,5,6,所以数组b的元素顺序应为"Sunday",“Monday”,“Tuesday”,“Wednesday”,“Thursday”,“Friday”,“Saturday”。
2、非常重要的一点:月份对应的下标为(月份数-1),所以“计算公元1年1月1日到该日期前一个月的月末的天数”的for循环的控制条件为(>=0&&<该月-1),1月份下标为0,2月份下标为1。

微调1(基姆拉尔森公式求星期几):

基姆拉尔森计算公式:W= (d+2m+3(m+1)/5+y+y/4-y/100+y/400+1)%7

#include<stdio.h>
int main ()
{
   
	int a[12]={
   31,28,31,30,31,30,31,31,30,31,30,31};
	char b[7][10]={
   "Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
	int n,y,r,i,s1=0,s2=0,s3=0;
	scanf("%d %d %d",&n,&y,&r);
	for(i=1;i<n;i++)
        if((i%4==0&&i%100!=0)||i%400==0) s1+=366;
        else s1+=365;
	if((n%4==0&&n%100!=0)||n%400==0) a[1]=29;
    s2=s1;
	for(i=0;i<y-1;i++)
		s2+=a[i];
	s3=s2+r;
    int w=(r+2*y+3*(y+1)/5+n+n/4-n/100+n/400)%7;
	printf("%d\n%d\n%d\n%s\n",s1,s2,s3,b[w]);
}

与原代码的区别:

因为基姆拉尔森计算式直接求出的就是星期几,所以w的取值只可能是1~7,分别对应"Monday",“Tuesday”,“Wednesday”,“Thursday”,“Friday”,“Saturday”,“Sunday”。
所以数组b的元素位置要进行调换。

微调2:

#include<stdio.h>
int main ()
{
   
	int a[13]={
   0,31,28,31,30,31,30,31,31,30,31,30,31};
	char b[7][10]={
   "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
	int n,y,r,i,s1=0,s2=0,s3=0;
	scanf("%d %d %d",&n,&y,&r);
	for(i=1;i<n;i++)
        if((i%4==0&&i%100!=0)||i%400==0) s1+=366;
        else s1+=365;
	if((n%4==0&&n%100!=0)||n%400==0) a[2]=29;
    s2=s1;
	for(i=1;i<y;i++)
		s2+=a[i];
	s3=s2+r;
	printf("%d\n%d\n%d\n%s\n",s1,s2,s3,b[s3%7]);
}

与原代码的区别:

储存月份天数的数组月份对应下标的改变,使月份数等于下标。
看似只需改动一处,实则还改变了“计算公元1年1月1日到该日期前一个月的月末的天数”的for循环的控制条件,由于当月的天数不用计算在内,故范围为(>=1&&<该月)。同时计算二月份对应数组位置变为a[2]。

微调3:

#include<stdio.h>
int main ()
{
   
	int a[12]={
   31,28,31,30,31,30,31,31,30,31,30,31};
	char b[7][10]={
   "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
	int n,y,r,i,s1=0,s2=0,s3=0,temp,j;
	scanf("%d %d %d",&n,&y,&r);
	for(i=1;i<n;i++)
    {
   
        temp=0;
        if((i%4==0&&i%100!=0)||i%400==0) a[1]=29;
        else a[1]=28;
        for(j=0;j<12;j++)
            temp+=a[j];
        s1+=temp;
    }
	if((n%4==0&&n%100!=0)||n%400==0) a[1]=29;
    else a[1]=28;
    s2=s1;
	for(i=0;i<y-1;i++)
		s2+=a[i];
	s3=s2+r;
	printf("%d\n%d\n%d\n%s\n",s1,s2,s3,b[s3%7]);
}

与原代码的区别:

改变了“从公元1年1月1日到该日期前一年的年末的天数”的计算方式。
采用for循环,利用临时变量存储每一年的天数,再加到总天数里。由于每次循环后2月份的天数a[1]都会发生改变,所以不只要有if,也要有else,即

if((n%4==0&&n%100!=0)||n%400==0) a[1]=29;
    else a[1]=28;

又因为计算“从公元1年1月1日到该日期前一年的年末的天数”的for循环结束后,a[1]的并不确定,所以在进行“计算公元1年1月1日到该日期前一个月的月末的天数”时也要有else,即

if((n%4==0&&n%100!=0)||n%400==0) a[1]=29;
    else a[1]=28;

微调4:

#include<stdio.h>
int main ()
{
   
	int a[12]={
   31,28,31,30,31,30,31,31,30,31,30,31};
	char b[7][10]={
   "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
	int n,y,r,i,s1=0,s2=0,s3=0;
	scanf("%d %d %d",&n,&y,&r);
	s1=(n-1)*365+(n-1)/4-(n-1)/100+(n-1)/400;//每一年都当成365天,再加上闰年的个数,由于当年不计算在内,故总年数为n-1 
	if((n%4==0&&n%100!=0)||n%400==0) a[1]=29;
    s2=s1;
	for(i=0;i<y-1;i++)
		s2+=a[i];
	s3=s2+r;
	printf("%d\n%d\n%d\n%s\n",s1,s2,s3,b[s3%7]);
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-27 10:28
点赞 评论 收藏
分享
11-27 12:43
已编辑
门头沟学院 C++
点赞 评论 收藏
分享
点赞 评论 收藏
分享
威猛的小饼干正在背八股:挂到根本不想整理
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务