【王道机试】| | 日期类问题

题目描述:

有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天

输入:

有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD

输出:

每组数据输出一行,即日期差值

做题思路:

样例输入:

20110412
20110422

样例输出:

11

对于日期类:年月日,就像学生信息一样,用结构体处理。

struct Date{
	int year;
	int month;
	int day;
	status fun();//待添加
}

这里提出一个新的概念:预处理
首先无论输入的两行数字是什么,我们不妨都初始化一个日期init_date:如0000年1月1日,分别计算输入的两个日期离init_date的日期差值,然后再将这两个差值相减,即得到结果。举个栗子。小A就是初始化Init_people,他的年龄是0岁0月,小B的年龄是7岁10个月,小C的年龄是15岁2个月,问小B与小C的月份之差。显然,计算直接计算其实有点点的绕(毕竟不是十进制,像我这种直白的人类处理起来就是容易搞错),如果先计算小B与小A的月份差: 7 ∗ 12 + 10 − 0 = 94 ( m o n t h ) 7*12+10-0 = 94(month) 712+100=94(month) 小C与小A的月份差: 15 ∗ 12 + 2 − 0 = 182 ( m o n t h ) 15*12+2-0=182(month) 1512+20=182month) 所以小B与小C月份差: ∣ 94 − 182 ∣ = 88 ( m o n t h ) |94-182|=88(month) 94182=88(month)

上面就是解决本题的一个大体思路,但显然本题还有很多的细节和难点:

  1. 闰年
  2. 每个月份的天数

首先对于闰年的判断,是每个人学习C语言入门必备的一个知识点:闰年是4的倍数但不能是100的倍数,或者是400的倍数。就是公元100年不是闰年,但公元4年,400年是闰年。

bool isLeap(int year)
{
	if( (year%4 == 0&&year%100 != 0 )||year%400 == 0 )
		return true;
	else
		return false;
}

其次,判断完闰年,我们可以开始处理每个月份的天数了,众所周知,只有2月摇摆不定,所以我们不妨建立一个二维数组:int daysOfMonth[13][2]

int daysOfMonth[13][2]={{0,0},
				 {31,31},
				 {28,29},//闰年是29天~
				 {31,31},
				 {30,30},
				 {31,31},
				 {30,30},
				 {31,31},
				 {31,31},
				 {30,30},
				 {31,31},
				 {30,30},
				 {31,31}
				}		

现在就可以开始进行预处理部分了:
假设此时我们简化问题:计算某一天的明天的日期。这里要考虑到天数是否超过了30(31,28,29),月数是否超过12?

void nextDay()
{
	Day++;
	if(Day>DaysOfMonth[Month][isLeap(Year}]//月份加1
	{
		Day-=DaysOfMonth[Month][isLeap(Year}];//Day = 1;
		Month++;
	}
	if(Month>12)
	{
		Month-=12;//Month = 1;
		Year++;
	}	

接下来我们定义一个三维数组:int date[year][month][days]
具体来说,先设定一个范围(输入的年份在0~5000年)则可定义为:int date[5001][13][32](不用下标零)
所谓预处理就是先填充这个数组,如某个数组单元date[y0][m0][d0]填充的内容就是y0年m0月d0日离初始0000年1月1日的GapDays.

gapDays = 0;//天数计时器
Date tmp;
tmp.year=0;
tmp.month = tmp.day = 1;
while(tmp.year!=5001)//日期不超过5001年
{
	date[tmp.year][tmp.month][tmp.day]=gapDays;
	tmp.nextDay();
	gapDays++;//时间差
}

有了上述预处理的过程,我们就可以根据输入的时间从三维数组里直接找到(记起了学数据结构的时候,老师一直强调的数组具有随机存取的特性。)其对应的gapDays,然后两个相减就可以了。

结合上述分析,就可以写程序了。

//2_3日期差值 
//针对此类问题,我们要量化每个月的天数 
#include<stdio.h>
bool isLeap(int d)
{
	if((d%4==0&&d%100!=100)||d%400==0)
		return true;
	else
		return false;
}
int abs(int a)
{
	return a>0?a:(-a);
}
int daysOfMonth[13][2]={
	             0,0,
				 31,31,
				 28,29,
				 31,31,
				 30,30,
				 31,31,
				 30,30,
				 31,31,
				 31,31,
				 30,30,
				 31,31,
				 30,30,
				 31,31
				};
struct Date{
	int year;
	int month;
	int day;
	void nextDay()
	{
		day++;
		if(day>daysOfMonth[month][isLeap(year)])
		{
			day = 1;
			month++;
			if(month > 12)
			{
				month = 1;
				year++;
			}
		 } 
	}
};		
int date[5001][13][32];
int main()
{
	Date tmp;
	tmp.year = 0;
	tmp.month = 1;
	tmp.day = 1;
	int gapDays= 0;
	while(tmp.year!=5001)
	{
		date[tmp.year][tmp.month][tmp.day]=gapDays;
		tmp.nextDay();
		gapDays++;
	}	
	int y1,y2,
		m1,m2,
		d1,d2;
	while(scanf("%4d%2d%2d",&y1,&m1,&d1)!=EOF)
	{
		scanf("%4d%2d%2d",&y2,&m2,&d2);
		int ans;
		ans = abs(date[y1][m1][d1]-date[y2][m2][d2]);
		printf("%d\n",ans+1);//相邻两天记作两天 
	}
	return 0;
 } 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值