C++编写万年历,公元后日历程序,考虑了1582年前后以及该年的特殊情况。

一,万年历的基本要求

前言:万年历的创建思路

日历,要求日期与星期对应。基本格式输出就是,要求在一月内,从该月起始日到该月终止日,每一日都与星期相对应,因此,可以根据日期对天数7取余来完成对应
其次,在一年内,每月都有属于自己的日期数,比如11月有30天。每一月份对应日历相互独立,(我们不可能将11月30日与12月1日连在一起,因为实际生活中的日历就不是这样的)。然而,需要注意到的是,虽然在日历上,它们处于两个不同日历月份,但在日期上他们只差一天,在星期上,它们也是两个相连的星期。因此,我们可以确定两个基本思路:
1.每一月份要规定最大日期,避免溢出,也规范了输出。
2.要确定某一日为参照日,用目标日减去参照日,得到距离日期,就可以做到本月末与下月初日期相连。
自然,要创作公元后日历,我们选用公元一年一月一日作为参照日,为1 。 这样我们确定了基本思路。
规定公元1年1月1日为1后,查找它对应的星期可以得到,为星期六,我们的两个起始点都确定,下面可以根据思路具体实现。

1.公元天数与日期

      在确定了参照日后,我们假设要计算某一年某一月某一日的日数,
比如1900年5月21日,那么,我们必须用1900年以前所有年包含的日数,
加上前4月的所有日期数,再加上21,就得到了距离天数,再拿距离天数
加上某一特定数字(该数字作用是得到正确星期,因为参照日为星期六 )
对7取余,就可以得到该日的正确星期。 

1.日期输入问题

首先,我们创造了一个日期转换函数,作用是得到某年某日某月距离参照日的日期。因此,参数输入为 年,月,日;返回参数为日期。

int Date_to_day(int y, int m, int d)

那我们定义该函数的第一件事,就是规避错误输入 ,避免后续错误发生的可能。错误输入就包括:年份,月份,日期不能为负数,不能超过对应最大值。
因此,先设立两个枚举,其中包括除二月份外每一月份的天数最大值,以及二月份在平闰年的天数最大值。

//月份天数最大值
	enum Month_d 
	{ 
		Jan_d = 31, Mar_d = 31, 
		Apri_d = 30, May_d = 31, 
		Jun_d = 30, Jul_d = 31, 
		Aug_d = 31, Sep_d = 30, 
		Oct_d = 31, Nov_d = 30, Dec_d = 31
	};
	enum Month_leap_d { Feb_d = 28, Feb_ld = 29 };
//枚举创建数组
	static int month_darray[11] = 
	{
		Jan_d,Mar_d,Apri_d,May_d,
		Jun_d,Jul_d,Aug_d,Sep_d,
		Oct_d,Nov_d,Dec_d
	};

在函数内设立输入判断条件:

//排除基本输入错误
		if (y < 1 || m < 1 || m>12 || d < 1 || d>31)
		{
			cout << "输入错误.程序结束.\n";
			exit(EXIT_FAILURE);
		}
		//排除平年输入错误
		if (y % 4 != 0&&m==2)
			if (d > Feb_d)
			{
				cout << "输入错误.程序结束.\n";
				exit(EXIT_FAILURE);
			}

		//补丁(排除定日期月份超出限额问题)
		if (m == 1)
		{
			if (d > month_darray[0])
			{
				cout << "输入日期不符实际,超出月份上限,程序结束。\n";
				exit(EXIT_FAILURE);
			}
		}
		else if (m > 2)
		{
			if (d > month_darray[m - 2])
			{
				cout << "输入日期不符实际,超出月份上限,程序结束。\n";
				exit(EXIT_FAILURE);
			}
		}

由于不能被4整除的年份一定是平年,因此在开头,我们先在开头排除了平年对程序的影响。在讨论闰年平年定义时,我们再对不足进行进一步补全。

2.闰年与平年的数目

现在日历上对闰年的定义为四年一闰百年不闰,每四百年再一闰。因此我们可以根据输入年数,该年(包括该年)以前共有多少闰年,多少平年。
再根据数目将年数转化为天数


		//得到1~y年的闰年平年数目
		int lead_y1 = y / 4;
		int lead_y2 = y / 100;
		int lead_y3 = y / 400;
		int total_lead = 0;

	
		total_lead = lead_y1 - lead_y2 + lead_y3+(JUDE_Y/100-JUDE_Y/400);


		//得到平年年数数目;
		int total_com = y - total_lead;

		//之前的年数转化为日(包括今年)
		int total_yday = total_lead * leap_year_day + total_com * year_day;

其中,上述代码块设定了常量值:

//声明使用常量
	static const int leap_year_day = 366;
	static const int year_day = 365;

在根据四年一闰百年不闰,每四百年再一闰的定义,对闰年判断,得到目标天数。
月份转化为天数:

//月份转化为日(不包括2月以及本月)
		int total_mday = 0;
		if (2 == m)
			total_mday += month_darray[m - 1];
		else
		{
			for (int i = 0; i < m - 2; i++)//不能加上本月份
				total_mday += month_darray[i];
		}
	if ((0 == y % 4) && (0 != y % 100) || (0 == y % 400))//闰年
			{
				total_yday -= leap_year_day;
				if (m > 2)
					total_mday += Feb_ld;
				fe = 1;
			}
			else
			{
				total_yday -= year_day;
				if (m > 2)
					total_mday += Feb_d;
				fe = 0;
			}


			//补丁(排除二月份日期溢出的问题)
			if (m == 2 && 0 == fe)
			{
				if (d > Feb_d)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}
			else if (2 == m && 1 == fe)
			{
				if (d > Feb_ld)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}


			//年月日对应的日数
			int total_day = total_mday + total_yday + d;

总天数:

//年月日对应的日数
			int total_day = total_mday + total_yday + d;

3.日历的输出问题

1.日数转化为星期

至此,我们得到了基本正确的目标天数,可以将它加上一个数字对7取余,便得到了对应的星期数:

//日期转星期换算
	int day_to_weekday(int n)
	{
		//公元1年1月1日是星期六
		static const int pud_day = 5;
		int weekday =(pud_day+n)%7;
		return weekday;
	}

设立一个数组保存需要输出星期日期。

const char weekDay[16] = { "日一二三四五六" };

然后再制作一个函数,输出该日期对应的星期:

//星期输出问题
	void weekday(int n)
	{
		std::cout << "该日期为:星期" << weekDay[n * 2] << weekDay[n * 2 + 1] << std::endl;
	}

需要注意的是,汉字储存需要两个字节连续储存,因此输出时也因连续输出两个字节。
至此,日期得到对应星期的工作基本完成。
运行截图如下:
该图片为最终代码运行输出与实况并不相同
该图片为最终代码运行输出与实况并不相同

2.日历月份开头

日历的表头一般是”日一二三四五六“。
因此可以创建一个表头函数,在每次显示日历时在函数中调用该表头。

//日历表头
	void Cal_week()
	{
		std::cout << "日\t一\t二\t三\t四\t五\t六\n";
	};

同时,根据得到的函数取余返回值,可以利用循环得到日历表前空白:

Cal_week();//表头
			for (int j = 0; j < week_day; j++)
				cout << " \t";//表首

此时,输出的具体日历,需要根据该年的闰平年情况进行判断,因此设立变量作为判断返回结果:

	if ((0 == n % 4) && (0 != n % 100) || (0 == n % 400))//闰年
				fe = 1;
			else
				fe = 0;

然后根据每个月,月初距离参照日的目标天数对七取余的返回值,以及该月份最大值,便可输出得到日历:

部分参数设定:

//平年
	static int month_D[12] =
	{
		Jan_d,Feb_d,Mar_d,Apri_d,May_d,
		Jun_d,Jul_d,Aug_d,Sep_d,
		Oct_d,Nov_d,Dec_d
	};
	//闰年
	static int month_LD[12] =
	{
		Jan_d,Feb_ld,Mar_d,Apri_d,May_d,
		Jun_d,Jul_d,Aug_d,Sep_d,
		Oct_d,Nov_d,Dec_d
	};

日历输出代码块:

	for (int i = 0; i < 12; i++)
		{
			int week_day = Date_to_day(n, Month_array[i], 1);
			//制作日历表
			cout << '\t' << i + 1 << "月\n";
			Cal_week();//表头
			for (int j = 0; j < week_day; j++)
				cout << " \t";//表首
			if (fe == 1)
			{
				for (int n = 1; n <= month_LD[i]; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day) % 7)
						cout << endl;
				}
			}
			else
			{
				for (int n = 1; n <= month_D[i]; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day) % 7)
						cout << endl;
				}
			}
			cout << endl;
		};

至此,输出万年历的基本操作完成。
以下为运行截图:
在这里插入图片描述
该图片为最终代码运行输出与实况并不相同
但如果我们细心观察,就会发现,日历与星期对不上,并且差距较大。这是为什么呢?
并不是程序运行出了什么差错,而是,闰年的定义经过了变更。
为保证万年历的正确性,下面我们要讨论闰年的定义补充。

二,万年历正确性的额外补丁

凡公历中有闰日(2月29日)的年份,阴阳历中有闰月的年份。
1582年以来公历的置闰规则:
普通闰年:公历年份是4的倍数,且不是100的倍数的,为闰年
(如2004年、2020年等就是闰年)。
世纪闰年:公历年份是整百数的,必须是400的倍数才是闰年
(如1900年不是闰年,2000年是闰年)。
1582年以前的惯例:四年一闰;

也就是说,如果我们按1582年以来的闰年定义来得到公元1年以后的日历的话,偏差会越来越大。
因此为了解决这个偏差,我们对日期转化函数进行了分段更进
以1583前为一段,以1583开始为一段。

1.1582年闰年定义的变更解决

对闰年定义分段,则会得到两种闰年和平年的数目。
如果在转化函数内对日期分段,再将得到的日期转化为星期。在第一步的分段分析,再将数字相加将会很麻烦。
因此,我们不妨如同将公元1年1月1日作为参照日那样,将1583年1月1日作为参考日,即:
1.在1583年以前(输入年数小于1583),用四年一闰的方法,判断闰年数可以得到正确日期。
2.在1583年以后,输入的年份用现在定义的闰年方法定义(此时得到的日期数是错误的),减去用现在定义的闰年方法定义的1583年以前的错误日期(此时得到的1583年以前的日期也是错误的),就得到了1583年以后的日期相对于1583年1月1日的正确的距离天数。
即抛弃之前的错误,使用参照日为1583年1月1日的正确天数。
改进后代码块:
(1)平闰年数目以及年月转化:

//得到1~y年的闰年平年数目
		int lead_y1 = y / 4;
		int lead_y2 = y / 100;
		int lead_y3 = y / 400;
		int total_lead = 0;

		if (y < 1583)
			total_lead = lead_y1;
		else
			total_lead = lead_y1 - lead_y2 + lead_y3+(JUDE_Y/100-JUDE_Y/400);
	
		//得到平年年数数目;
		int total_com = y - total_lead;

		//之前的年数转化为日(包括今年)
		int total_yday = total_lead * leap_year_day + total_com * year_day;


		//月份转化为日(不包括2月以及本月)
		int total_mday = 0;
		if (2 == m)
			total_mday += month_darray[m - 1];
		else
		{
			for (int i = 0; i < m - 2; i++)//不能加上本月份
				total_mday += month_darray[i];
		}

(2)1583年以前日期转化为天数:

if (y < 1583)
		{
			if (0 == y % 4)//闰年
			{
				total_yday -= leap_year_day;
				if (m > 2)
					total_mday += Feb_ld;
				fe = 1;
			}
			else
			{
				total_yday -= year_day;
				if (m > 2)
					total_mday += Feb_d;
				fe = 0;
			}


			//补丁(排除二月份日期溢出的问题)
			if (m == 2 && 0 == fe)
			{
				if (d > Feb_d)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}
			else if (2 == m && 1 == fe)
			{
				if (d > Feb_ld)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}
//年月日对应的日数
			int total_day = total_mday + total_yday + d;

(3)1583年后:

//定义的常量:
static const int JUDE_YEAR = 1582 / 4 * leap_year_day + (1582 - 1582 / 4) * year_day;
	static const int JUDE_Y = 1582;

else
		{
			//闰年新制定的日历方法
			total_yday -= JUDE_YEAR;
			if ((0 == y % 4) && (0 != y % 100) || (0 == y % 400))//闰年
			{
				total_yday -= leap_year_day;
				if (m > 2)
					total_mday += Feb_ld;
				fe = 1;
			}
			else
			{
				total_yday -= year_day;
				if (m > 2)
					total_mday += Feb_d;
				fe = 0;
			}


			//补丁(排除二月份日期溢出的问题)
			if (m == 2 && 0 == fe)
			{
				if (d > Feb_d)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}
			else if (2 == m && 1 == fe)
			{
				if (d > Feb_ld)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}


			//年月日对应的日数
			int total_day = total_mday + total_yday + d;

如同定义公元1年1月1日那样,定义它:

//1582年后
	int day_to_weekday_new(int n)
	{
		//公元1583年1月1日是星期六
		static const int Pud_day = 5;
		int weekday = (Pud_day + n) % 7;
		return weekday;
	}

再调用该函数即可:

//年月日对应的日数
			int total_day = total_mday + total_yday + d;

			//调用函数
			int wday = day_to_weekday_new(total_day);
			cout << "公元" << y << "年" << m << "月" << d << "日\t";
			weekday(wday);

这样,分段处理后,再搭配日历输出函数,便可以输出精准正确的星期与日历。

2.1582年消失的十天

下面,是1582年10月日历上消失的十天。
在这里插入图片描述
按照上述程序,程序以及可以完美实现公元后任意一年的日历输出。
但1582年有特殊情况:1582年10月5~14号并不存在,因此,要进行一下操作改进程序:
1.规避输入: 使程序判断输入该日期时,结果为false

//判断是否在1582年后
		int Jude_year = 1582;


		//补丁:
		//特殊情况: 1582年10月5~14输入为错误,消失的十天
		
		if(y==Jude_year&&m==Oct)
			if (4< d && d < 15)
			{
				cout << "1582年10月" << d << "日不存在于日历中。\n";
				exit(EXIT_FAILURE);
			}

2.输出日期对应星期: 1582年十月消失10天,因此,10月5日以前可以使用四年一闰的方法得到正确日期,而10月14日以后,得到日期的总数要减去10。
因此,加一个判断条件(加在y<1583的条件语句块里):

//年月日对应的日数
			int total_day = total_mday + total_yday + d;

			//平年判断补丁
			//补丁(1582年特殊情况)
			if (y == Jude_year && m == Oct)
			{
				if (d > 14)
				{
					total_day -= 10;
				}
			}
			else if (y == Jude_year && m > Oct)
			{
				total_day -= 10;
			}
				//调用函数
			int wday = day_to_weekday(total_day);
			cout << "公元" << y << "年" << m << "月" << d << "日\t";
			weekday(wday);

这样可以得到正确星期。

3.输出正确日历:
辅助函数:

	//1582年11月1日为星期一
	int day_to_weekday_1582(int n)
	{
		//公元1583年11月1日是星期一
		static const int Pud_day = 5;
		if (n == Nov)
		{

			int weekday = (Pud_day + 3) % 7;
			return weekday;
		}
		//12月1日是星期三
		else if (n == Dec)
		{
			int weekday = (Pud_day + 5) % 7;
			return weekday;
		}//10月1日为星期一
		else if (n == Oct)
		{
			int weekday = (Pud_day + 3) % 7;
			return weekday;
		}
	}

输出日历部分:

if (n == 1582)
		{
			fe = 0;

			//1~9月份的日期
			for (int i = 0; i < 9; i++)
			{
				int week_day = Date_to_day(n, Month_array[i], 1);
				//制作日历表
				cout << '\t' << i + 1 << "月\n";
				Cal_week();//表头
				for (int j = 0; j < week_day; j++)
					cout << " \t";//表首
					for (int n = 1; n <= month_D[i]; n++)
					{
						cout << n << '\t';
						if (0 == (n + week_day) % 7)
							cout << endl;
					}
				cout << endl;
			};

			//10月
			{
				int week_day = day_to_weekday_1582(Oct);
				cout << "公元" << JUDE_Y << "年" << Oct<< "月" << 1 << "日\t";
				weekday(week_day);
				cout << '\t' << Oct << "月\n";
				Cal_week();//表头
				for (int j = 0; j < week_day; j++)
					cout << " \t";//表首
				for (int n = 1; n <= 4; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day) % 7)
						cout << endl;
				}
				for (int n = 15; n <= 31; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day-10) % 7)
						cout << endl;
				}
				cout << endl;
			};

			//11~12月
			for (int i = 10; i < 12; i++)
			{
				int week_day = day_to_weekday_1582(i + 1);
				cout << "公元" << JUDE_Y << "年" << i+1 << "月" << 1 << "日\t";
				weekday(week_day);
				//制作日历表
				cout << '\t' << i + 1 << "月\n";
				Cal_week();//表头
				for (int j = 0; j < week_day; j++)
					cout << " \t";//表首
				for (int n = 1; n <= month_D[i]; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day) % 7)
						cout << endl;
				}
				cout << endl;
			};

			return;//结束进程
		}

运行结果截图:
在这里插入图片描述
至此,程序结束,万年历制作完成。

三,万年历程序的组成函数

 代码部分仅供参考

1.程序使用常量的设定

//声明使用常量
	static const int leap_year_day = 366;
	static const int year_day = 365;
	//补丁
	static const int JUDE_YEAR = 1582 / 4 * leap_year_day + (1582 - 1582 / 4) * year_day;
	static const int JUDE_Y = 1582;

	enum Month{ZERO,Jan, Feb, Mar, Apri, May, Jun, Jul, Aug, Sep, Oct, Nov,Dec };
	
	//月份天数最大值
	enum Month_d 
	{ 
		Jan_d = 31, Mar_d = 31, 
		Apri_d = 30, May_d = 31, 
		Jun_d = 30, Jul_d = 31, 
		Aug_d = 31, Sep_d = 30, 
		Oct_d = 31, Nov_d = 30, Dec_d = 31
	};
	enum Month_leap_d { Feb_d = 28, Feb_ld = 29 };

	//声明使用数组
	static int Month_array[12] = 
	{Jan, Feb, Mar, Apri, May, Jun, Jul, Aug, Sep, Oct, Nov,Dec};
	static int month_darray[11] = 
	{
		Jan_d,Mar_d,Apri_d,May_d,
		Jun_d,Jul_d,Aug_d,Sep_d,
		Oct_d,Nov_d,Dec_d
	};
	//平年
	static int month_D[12] =
	{
		Jan_d,Feb_d,Mar_d,Apri_d,May_d,
		Jun_d,Jul_d,Aug_d,Sep_d,
		Oct_d,Nov_d,Dec_d
	};
	//闰年
	static int month_LD[12] =
	{
		Jan_d,Feb_ld,Mar_d,Apri_d,May_d,
		Jun_d,Jul_d,Aug_d,Sep_d,
		Oct_d,Nov_d,Dec_d
	};


	const char weekDay[16] = { "日一二三四五六" };

2.辅助函数

表头函数:

//日历表头
	void Cal_week()
	{
		std::cout << "日\t一\t二\t三\t四\t五\t六\n";
	};

输出星期函数:

//星期输出问题
	void weekday(int n)
	{
		std::cout << "该日期为:星期" << weekDay[n * 2] << weekDay[n * 2 + 1] << std::endl;
	}

换算日历函数(3个):

//日期转星期换算
	int day_to_weekday(int n)
	{
		//公元1年1月1日是星期六
		static const int pud_day = 5;
		int weekday =(pud_day+n)%7;
		return weekday;
	}

	//1582年后
	int day_to_weekday_new(int n)
	{
		//公元1583年1月1日是星期六
		static const int Pud_day = 5;
		int weekday = (Pud_day + n) % 7;
		return weekday;
	}

	//1582年11月1日为星期一
	int day_to_weekday_1582(int n)
	{
		//公元1583年11月1日是星期一
		static const int Pud_day = 5;
		if (n == Nov)
		{

			int weekday = (Pud_day + 3) % 7;
			return weekday;
		}
		//12月1日是星期三
		else if (n == Dec)
		{
			int weekday = (Pud_day + 5) % 7;
			return weekday;
		}//10月1日为星期一
		else if (n == Oct)
		{
			int weekday = (Pud_day + 3) % 7;
			return weekday;
		}
	}

3.天数转化星期(其中有函数调用)

//日期换算
	int Date_to_day(int y, int m, int d)
	{
		using  std::cout;
		using std::endl;
		using std::cin;
		//排除基本输入错误
		if (y < 1 || m < 1 || m>12 || d < 1 || d>31)
		{
			cout << "输入错误.程序结束.\n";
			exit(EXIT_FAILURE);
		}
		//排除平年输入错误
		if (y % 4 != 0&&m==2)
			if (d > Feb_d)
			{
				cout << "输入错误.程序结束.\n";
				exit(EXIT_FAILURE);
			}

		//补丁(排除定日期月份超出限额问题)
		if (m == 1)
		{
			if (d > month_darray[0])
			{
				cout << "输入日期不符实际,超出月份上限,程序结束。\n";
				exit(EXIT_FAILURE);
			}
		}
		else if (m > 2)
		{
			if (d > month_darray[m - 2])
			{
				cout << "输入日期不符实际,超出月份上限,程序结束。\n";
				exit(EXIT_FAILURE);
			}
		}


		//得到1~y年的闰年平年数目
		int lead_y1 = y / 4;
		int lead_y2 = y / 100;
		int lead_y3 = y / 400;
		int total_lead = 0;

		if (y < 1583)
			total_lead = lead_y1;
		else
			total_lead = lead_y1 - lead_y2 + lead_y3+(JUDE_Y/100-JUDE_Y/400);


		//得到平年年数数目;
		int total_com = y - total_lead;

		//之前的年数转化为日(包括今年)
		int total_yday = total_lead * leap_year_day + total_com * year_day;


		//月份转化为日(不包括2月以及本月)
		int total_mday = 0;
		if (2 == m)
			total_mday += month_darray[m - 1];
		else
		{
			for (int i = 0; i < m - 2; i++)//不能加上本月份
				total_mday += month_darray[i];
		}

		//判断本年是否为闰年
		int fe = 0;
		//判断是否在1582年后
		int Jude_year = 1582;


		//补丁:
		//特殊情况: 1582年10月5~14输入为错误,消失的十天
		
		if(y==Jude_year&&m==Oct)
			if (4< d && d < 15)
			{
				cout << "1582年10月" << d << "日不存在于日历中。\n";
				exit(EXIT_FAILURE);
			}


		//得到年月的总日数

		//1583年以前的闰年规则
		if (y < 1583)
		{
			if (0 == y % 4)//闰年
			{
				total_yday -= leap_year_day;
				if (m > 2)
					total_mday += Feb_ld;
				fe = 1;
			}
			else
			{
				total_yday -= year_day;
				if (m > 2)
					total_mday += Feb_d;
				fe = 0;
			}


			//补丁(排除二月份日期溢出的问题)
			if (m == 2 && 0 == fe)
			{
				if (d > Feb_d)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}
			else if (2 == m && 1 == fe)
			{
				if (d > Feb_ld)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}



			//年月日对应的日数
			int total_day = total_mday + total_yday + d;

			//平年判断补丁
			//补丁(1582年特殊情况)
			if (y == Jude_year && m == Oct)
			{
				if (d > 14)
				{
					total_day -= 10;
				}
			}
			else if (y == Jude_year && m > Oct)
			{
				total_day -= 10;
			}

			//调用函数
			int wday = day_to_weekday(total_day);
			cout << "公元" << y << "年" << m << "月" << d << "日\t";
			weekday(wday);
			return wday;
		}
		//1583年后的闰年规则
		else
		{
			//闰年新制定的日历方法
			total_yday -= JUDE_YEAR;
			if ((0 == y % 4) && (0 != y % 100) || (0 == y % 400))//闰年
			{
				total_yday -= leap_year_day;
				if (m > 2)
					total_mday += Feb_ld;
				fe = 1;
			}
			else
			{
				total_yday -= year_day;
				if (m > 2)
					total_mday += Feb_d;
				fe = 0;
			}


			//补丁(排除二月份日期溢出的问题)
			if (m == 2 && 0 == fe)
			{
				if (d > Feb_d)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}
			else if (2 == m && 1 == fe)
			{
				if (d > Feb_ld)
				{
					cout << "输入日期不符实际,超出月份上限,程序结束。\n";
					exit(EXIT_FAILURE);
				}
			}


			//年月日对应的日数
			int total_day = total_mday + total_yday + d;

			//调用函数
			int wday = day_to_weekday_new(total_day);
			cout << "公元" << y << "年" << m << "月" << d << "日\t";
			weekday(wday);
			return wday;
		}
	}

3.日历输出函数

//输出日历
	void month_Calendar(int n)
	{
		using std::cout;
		using std::endl;
		cout << "年份:" << n << " 年\n";
		//该年是否为闰年的判断依据
		int fe;
		
		//考虑特殊情况 1582年

		if (n == 1582)
		{
			fe = 0;

			//1~9月份的日期
			for (int i = 0; i < 9; i++)
			{
				int week_day = Date_to_day(n, Month_array[i], 1);
				//制作日历表
				cout << '\t' << i + 1 << "月\n";
				Cal_week();//表头
				for (int j = 0; j < week_day; j++)
					cout << " \t";//表首
					for (int n = 1; n <= month_D[i]; n++)
					{
						cout << n << '\t';
						if (0 == (n + week_day) % 7)
							cout << endl;
					}
				cout << endl;
			};

			//10月
			{
				int week_day = day_to_weekday_1582(Oct);
				cout << "公元" << JUDE_Y << "年" << Oct<< "月" << 1 << "日\t";
				weekday(week_day);
				cout << '\t' << Oct << "月\n";
				Cal_week();//表头
				for (int j = 0; j < week_day; j++)
					cout << " \t";//表首
				for (int n = 1; n <= 4; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day) % 7)
						cout << endl;
				}
				for (int n = 15; n <= 31; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day-10) % 7)
						cout << endl;
				}
				cout << endl;
			};

			//11~12月
			for (int i = 10; i < 12; i++)
			{
				int week_day = day_to_weekday_1582(i + 1);
				cout << "公元" << JUDE_Y << "年" << i+1 << "月" << 1 << "日\t";
				weekday(week_day);
				//制作日历表
				cout << '\t' << i + 1 << "月\n";
				Cal_week();//表头
				for (int j = 0; j < week_day; j++)
					cout << " \t";//表首
				for (int n = 1; n <= month_D[i]; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day) % 7)
						cout << endl;
				}
				cout << endl;
			};

			return;//结束进程
		}



		if (n < 1583)
		{
			if (0 == n % 4)//闰年
				fe = 1;
			else
				fe = 0;
		}
		else
		{
			if ((0 == n % 4) && (0 != n % 100) || (0 == n % 400))//闰年
				fe = 1;
			else
				fe = 0;
		}
		//星期余数
		for (int i = 0; i < 12; i++)
		{
			int week_day = Date_to_day(n, Month_array[i], 1);
			//制作日历表
			cout << '\t' << i + 1 << "月\n";
			Cal_week();//表头
			for (int j = 0; j < week_day; j++)
				cout << " \t";//表首
			if (fe == 1)
			{
				for (int n = 1; n <= month_LD[i]; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day) % 7)
						cout << endl;
				}
			}
			else
			{
				for (int n = 1; n <= month_D[i]; n++)
				{
					cout << n << '\t';
					if (0 == (n + week_day) % 7)
						cout << endl;
				}
			}
			cout << endl;
		};

	}

代码如上仅供参考

如有不足,敬请指正。

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值