UVA602 日期计算(2)+模拟+细节

1 题意

两种日历计算对应的日期的星期几?

刚开始理解错题意了,不是说以1752年9.2与1752.9.14作为分界线,计算天数时,查询日期在分界线前的天数计算用旧历闰年规则计算;查询日期在后面的、日期就分成两半,界线前的按旧历、界线后的按新历闰年规则计算,不是这样的。如果这样那么新历的延后几天用来弥补之前的误差就没有了意义,而是说:
查询日期在1752.9.2之前的,计算天数用旧历的计算闰年的规则;查询日期在1752.9.14之后的,计算天数直接全用新历的计算闰年的规则,这样题目中说的弥补误差才是有意义的。也就是说,本质上,问题是两种日历计算对应的日期的星期几。

2分析

有很多坑。上面的题意算一个。
其次,检查无效日期,分两类,一类是错误的即比如1月“89日”2013年的这种,而对应不同月份,比如1月和2月,上限分别是31天和30天,而对于是否闰年的2月,也同样有不一样的上限;其次,另一类是对应题意的无效日期,即1752.9.3~1752.9.13是不存在的,是新历和旧历都不存在的,旧历按照Sample Output,是从最初(公元1年)到1752.9.2,而新历是从1752.9.14到现在或者未来。
而计算星期几,网上有这样的计算公式。这里没有用公式,是用的从公元1年1月1日(包括这一天)到所查日期(包括所查日期)一共多少天,week[day%7]就是周几,而week数组是从0开始的,week[0]对应周日,week[1]对应周一......week[6]对应周六。但要注意,这样的计算方式是用新历来算(因为旧历有误差),这样算出的对于1752.9.2之前的数算出的周几再和Sample Output给出的对应日期的周几相比较(题目中可用的是,2 11 1732、9 2 1752),从而得出新历和旧历转换的规律,old_week=(new_week+5)%7。
因为细节比较多,所以代码个部分实现的顺序也要注意,不然因为之前各个变量有初始化的原因,可能计算出错误的结果。

3学习

1 凡是与日期转换有关,应学习关于闰年的处理方式,单独一个函数判断闰年( int run_year() )&&二维数组来存储有关闰年的天数选择:
int year_day[2]={365,366};
int month_day[2][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};
2 计算天数:是从公元1年1月1日到查询日期(包括在内)有多少天,day%7即周几,而week数组是从0到6分别对应周天、周一......周六,当然对应其他的日期开始也可以只要知道开始日期对应的周几,此方法仅对于新历有效(闰年计算规则:被4整除但不被100整除的,以及被400整除的)。

4

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
using namespace std;

int year_day[2]={365,366};
int month_day[2][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};
char month_name[][20]={"", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
char week_name[][20]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int sum,year,month,day,week;
int old;

int run_year(int temp){ ///Note!!!  根据题意,历史原因,前后的闰年定义不一样!!!
    if(!old){   //history,
        //return (temp%4 == 0) ? true : false;
        if(temp%4==0)   return 1;
        else       return 0;
    }
    else{       //new,
        //return (temp%100 == 0)?(temp%400 == 0?true:false):(temp%4 == 0?true : false);
        if( ( temp%4==0&&temp%100!=0 )|| (temp%400==0) )    return 1;
        else    return 0;
    }
}
int Judge(){
    if(year<1)     return 0;
    if(month<1||month>12)   return 0;
    if(day<1)   return 0;///Note!!! fenlei
    if(day>month_day[run_year(year)][month])    return 0;
    if(year==1752&&month==9&&(2<day&&day<14))   return 0;   ///Note!!!
    return 1;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    while(~scanf("%d%d%d",&month,&day,&year)){
        if(month==0&&day==0&&year==0)   break;
        old=0;
        sum=0;
        if(year>1752||(year==1752&&month>9)||(year==1752&&month==9&&day>2)){///Note!!!  if(year>=1752&&month>=9&&day>=2)
            old=1;
        }
        if(Judge()==0){
            printf("%d/%d/%d is an invalid date.\n",month,day,year);
            continue;
        }
        for(int i=1;i<year;i++){//历史上,从公元1年开始的,没有公元0年
            sum+=year_day[run_year(i)];
        }
        for(int i=1;i<month;i++){
            sum+=month_day[run_year(year)][i];
        }
        sum+=day;
        week=sum%7;
        if(!old){    //new,
            week=(week+5)%7;
        }
        //cout<<old<<endl;
        //cout<<sum<<endl;
        //cout<<week<<endl;
        printf("%s %d, %d is a %s\n",month_name[month],day,year,week_name[week]);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值