1. 程式人生 > >機試演算法講解: 第3題 求兩個日期相差的天數

機試演算法講解: 第3題 求兩個日期相差的天數

/*
問題:求兩個日期相差的天數,連續2天預設為一天。日期形式:YYYYMMDD
輸入:
20110412
20110422
輸出:
11

思路:方法1:將2個日期都應該化為絕對秒數,然後相減,用絕對秒數之差然後除以24*3600即可

易錯點:
time_t mktime(struct tm* tmptr)
double difftime(time_t time1,time_t time2)
char* strncpy(char* strDest,const char* stdSource,size_t count)返回的是strDest
void* memset(void* dest,int i,size_t count)

方法2:
建立一個日期結構體,判斷閏年:能被4整除且不能被100整除,或者能被400整除,
建立月份:1,3,5,7,8,10,12有31天
         4,6,9,11有30天
		 2月:閏年29天,平年28天


if( (i/4==0 && i/100!=0) || i/400==0 )

20140122
19891005
8875(正確) 8870錯誤
年與年相減得diffYear,每一年按照是否是閏年加366或365
小日期的月做減法:依次減去上一個的天數
大日期的月做加法: 依次加上上一個月的天數
小日期的日做減法:依次減去日期
大日期的日做加法:依次加上日期

易錯點:
1結構體內不能給陣列賦值
2採用加減法計算日期,不需要最終再加上1
3while(scanf("%4d%2d%2d",&y1,&m1,&d1)) 來讀取前4位給年,後2位給月

*/


#include <stdio.h>
#include <string.h>
#include <time.h>
#include <memory.h> //memset
#include <stdlib.h> //atoi

//#define leap(y) ((y/4==0 && y/100!=0) || y/400==0),寫錯了是%而不是/
#define leap(y) ((y%4==0 && y%100!=0) || y%400==0)

typedef struct Date
{
	bool operator < (Date& date)
	{
		if(iYear != date.iYear)
		{
			return iYear < date.iYear;
		}
		else
		{
			if(iMon != date.iMon)
			{
				return iMon < date.iMon;
			}
			else
			{
				return iDay < date.iDay;
			}
		}
	}
	void operator = (Date& date)
	{
		iYear = date.iYear;
		iMon = date.iMon;
		iDay = date.iDay;
	}
	//int iMonArr[2][12] = { {0,31,28,31,,30,31,30,31,31,30,31,30},{0,31,29,31,30,31,30,31,31,30,31,30} };//用兩個花括號括起來,結構體內不能賦值
	int iYear;
	int iMon;
	int iDay;
}Date;

void toDate(char* sDate,Date& date)
{
	char sStr[4];
	memset(sStr,0,4);
	strncpy(sStr,sDate,4);
	//Date date;
	date.iYear = atoi(sStr);
	memset(sStr,0,4);
	strncpy(sStr,sDate+4,2);
	date.iMon = atoi(sStr);
	memset(sStr,0,4);
	strncpy(sStr,sDate+6,2);
	date.iDay = atoi(sStr);
	//return date;
}

int Days(Date& date1,Date& date2)
{
	int iMonArr[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} };
	Date dateMax;
	Date dateMin;
	if(date2 < date1)
	{
		dateMax = date1;
		dateMin = date2;
	}
	else
	{
		dateMax = date2;
		dateMin = date1;
	}
	int iDiffDays = 0,i;
	for( i = dateMin.iYear ; i < dateMax.iYear ; i++ )
	{
		iDiffDays += leap(i) ? 366:365;
	}
	for( i = 1 ; i < dateMax.iMon ; i++)
	{
		//iDiffDays += iMonArr[leap(dateMax.iYear)][i-1];
		iDiffDays += iMonArr[leap(dateMax.iYear)][i];
	}
	//iDiffDays += dateMax.iDay ;
	iDiffDays += dateMax.iDay -1;
	for( i = 1 ; i < dateMin.iMon ; i++)
	{
		//iDiffDays -= iMonArr[leap(dateMax.iYear)][i-1];
		iDiffDays -= iMonArr[leap(dateMax.iYear)][i];//已經沒有取當前月的天數了
	}
	//iDiffDays -= dateMin.iDay;
	iDiffDays -= dateMin.iDay -1;
	//return(iDiffDays+1);//這裡不需要加1,因為求出來的就是兩天之差
	return iDiffDays;
}

//using namespace std;
time_t mk_time(char* sDate)
{
	struct tm tTm;
	char sStr[4];
	//memset(sStr,0,4);
	//memset(tTm,0,sizeof(tm));
	memset(&tTm,0,sizeof(tTm));
	memset(&sStr,0,4);
	tTm.tm_year = atoi(strncpy(sStr,sDate,4)) - 1900;

	memset(&sStr,0,4);
	tTm.tm_mon = atoi(strncpy(sStr,sDate+4,2)) - 1;

	memset(&sStr,0,4);
	tTm.tm_mday = atoi(strncpy(sStr,sDate+6,2)) + 1;//連續2天算兩天之差

	return mktime(&tTm);
}

int main(int argc,char* argv[])
{
	//char sDate1[9];
	//char sDate2[9];
	Date date1,date2;
	//int y1,m1,d1,y2,m2,d2;
	//while(EOF!=scanf("%s %s",sDate1,sDate2))
	while(EOF!=scanf("%4d%2d%2d",&date1.iYear,&date1.iMon,&date1.iDay))
	{
		scanf("%4d%2d%2d",&date2.iYear,&date2.iMon,&date2.iDay);
		//time_t tTime1 = mk_time(sDate1);
		//time_t tTime2 = mk_time(sDate2);
		//time_t diffTime = (time_t)difftime(tTime1,tTime2);
		//int iDays = (int)( diffTime > 0 ? diffTime/(3600*24) : (-1)*diffTime/(3600*24) );
		//printf("%d",iDays);
		//Date date1,date2;
		
		//toDate(sDate1,date1);
		//toDate(sDate2,date2);
		int iDays = Days(date1,date2);
		printf("%d",iDays);
	}
	getchar();
	return 0;
}