C语言求两个日期之间间隔的天数

求解方法有很多,这里用小学生翻日历的笨方法。大致思路如下:定义三个变量year、month、day,用来记录日期,再定义一个变量days,用来计算天数。现在有一本日历放在面前,假设当前日期是2005年3月5日,开始翻日历,翻一页,变量day就加1,日期变成2005年3月6日,继续翻……,翻到了2005年3月31日,此时变量month是3,day是31,继续翻页,变成了3月32日,这时候,我们发现32大于3月份的天数(31),于是,将month加1,并且day置为1。特殊情况,如果是2005年12月31日,如果翻一页日历,就会变成2005年12月32日,先变为2005年13月1日(month加1,并且day置为1),然后变为2006年1月1日(year加1,并且month置为1)。

为什么不整年整年的366或者365天累加呢?那样程序运行效率明显高很多。原因有三:

(1)上面这种原始的写法的好处是很容易把它改成火星上的程序,只需要修改三处:MONTH的值、daysOfMonth的值、IsLeapYear函数体,程序其它逻辑不需要做任何修改。

(2)以上这种很笨的写法,循环体执行一次的时间是纳秒(10的负9次方秒)级别的,即使一百万年的间隔,循环几亿次(10的8次方),整个程序运行时间也不需要1秒钟。

(3)这种一页一页翻日历的思路,不但可以求两天的时间间隔,还可以求从某一天开始往前或者往后经过若干天的日期。前者(求两天的时间间隔)用while循环,后者(从某一天开始往前或者往后经过若干天的日期)用for循环,循环体里的逻辑基本完全一致。

进一步的,这种面向过程的写法可以改成面向对象的,如果利用C++的运算符重载,重载减号运算符,求某两天的间隔天数的形式将非常简单,像下面这样:Date(2023, 9, 29) - Date(2005, 3, 5)。

面向过程的代码如下:

#include 
using namespace std;

#define MONTH 12

int daysOfMonth[2][MONTH + 1] = { {-1,31,28,31,30,31,30,31,31,30,31,30,31},			//每行多定义一个元素,第一个元素不用
								  {-1,31,29,31,30,31,30,31,31,30,31,30,31} };	

struct Date
{
	int year, month, day;
};

int DateDiff(Date beginDate, Date endDate);
int IsLeapYear(int year);

int main()
{
	Date date1 = { 2005,3,5 };
	Date date2 = { 2023,9,29 };

	cout << "间隔" << DateDiff(date1, date2) << "天" << endl;

	return 0;
}

int DateDiff(Date beginDate, Date endDate)
{
	int year = beginDate.year;
	int month = beginDate.month;
	int day = beginDate.day;
	int days = 0;

	while (!(year == endDate.year && month == endDate.month && day == endDate.day)) 
	{
		day++;

		if (day > daysOfMonth[IsLeapYear(year)][month])	
		{
			day = 1;
			month++;

			if (month > MONTH)	
			{
				month = 1;
				year++;
			}
		}

		days++;
	}

	return days;
}

int IsLeapYear(int year)
{
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
		return 1;
	else
		return 0;
}

你可能感兴趣的:(c语言,c++,算法)