C语言实现简易万年历

本文为“从零开始的万年历”专栏第三篇,记录我从零开始编译万年历的全过程。

第一篇:2015年中每一天是星期几        http://t.csdnimg.cn/vQ6yq

第二篇:公元年每一天是星期几        http://t.csdnimg.cn/jeU8C

目录

1 前言 

2 系统需求分析

2.1 功能需求

2.2 性能需求

3 难点分析

3.1 判断公元年每一天是星期几

3.2 将查询结果按日历格式打印出来

4 后续优化方向

4.1 功能完善

4.2 算法优化

4.3 体验优化

5 手机版


1 前言 

有兴趣的朋友可以从第一篇文章开始看,可以在三篇文章中看到我是如何一步步尝试用C语言编译出一个简单的万年历系统(黑框框系统)。使用的方法全部为独立思考,每一个方法皆为原创,当然,这些方法绝对是前人已经使用过的,而且很明显这种算法并不优越,不是现有万年历的主流算法,仅供诸位参考吧。

2 系统需求分析

2.1 功能需求

一个简单的万年历系统能够满足以下两点就基本足够:

(1)公历日期的查询与显示

(2)用户友好的交互界面

这两点可以说是一个万年历系统最本质最核心的两点,满足这两点后续升级和优化也会非常方便。

2.2 性能需求

算法尽可能的好,空间占用尽可能的小,运算时间尽可能的少。

3 难点分析

3.1 判断公元年每一天是星期几

这是实现万年历最本质的问题。

很明显我们需要一个可以计算每天是星期几的算法。

我的方法为:(计算指定日期至公元元年1月1日的总天数+初始星期数-1)求余7

注:格里历也就是现在的公历默认公元元年1月1日为星期一,所以可以直接忽略,不用加了

公元1582年10月15前使用的儒略历默认公元元年1月1日为星期六,所以要加5,减1是因为当天还没过。

思考过程:

如何判断2015年每一天是星期几?

(计算指定日期至2015年1月1日的总天数+初始星期数-1)求余7

如何计算指定日期至2015年1月1日的总天数?

上个月最后一天至2015年1月1号的天数+指定年月日中日的值

如何计算上个月最后一天至2015年1月1号的天数?

判断2015年是平年还是闰年,平年2月28,闰年2月29,让计算机记住每一个月的总天数再相加,一直加到指定月份上一个月,如指定7月,那就将1月至6月的总天数相加。

如何判断平年润年?

四年一闰,百年不闰,四百年再闰。

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

能被4整除但不能被100整除或能被400整除的年份为润年。

如何知道2015年1月1日是星期几?

 查询发现2015年1月1日是星期四。

至此,判断2015年中每一天是星期几已全部解决。

如何判断公元年每一天是星期几?

计算指定日期至公元元年1月1日的总天数+初始星期数-1)求余7

如何计算指定日期至公元元年1月1日的总天数?

公元元年1月1日至指定年份前一年的总天数+指定年份1月1日至指定月份前一月的总天数+指定日

公元元年初始星期数?

星期一

如何计算公元元年1月1日至指定年份前一年的总天数?

公元元年至指定年份前一年年数*365+闰年数,例:指定2015年,(2015-1)*365+闰年数

其它部分同2015年判断方法,至此判断公元年每一天是星期几已全部解决。

3.2 将查询结果按日历格式打印出来

两点要求:

(1)准确根据起始星期数确定每月1日的起始打印位置

(2)在起始打印位置随机的情况下在每周六精确换行

 准确根据起始星期数确定每月1日的起始打印位置?

我的方法是定义一个循环体,让这个循环体从1 循环至当月1号的起始星期数,每次循环在该星期数前打印两个空格,通过空格的数量控制起始打印位置

在起始打印位置随机的情况下在每周六精确换行?

我在观察日历中发现,每月日历的第一行,当天日期加每月 1 号起始星期 数小于等于8,也就是每到当天日期加起始星期数大于等于7时需要换行, 一周七天,日历的一行也为七列,每至下一行我将起始星期数减七,继续 与当天日期相加,仍可正确得出换行位置

 至此打印问题解决。

主要的逻辑难点就是这些了,算法上的问题也都基本解决,剩下的就是代码的实现,还有问题的铁子可以评论,我看到后会尽力解答,当然,我的代码水平极为有限。

4 后续优化方向

这是给我自己看的。

4.1 功能完善

可以在原代码上增加以下功能:

(1)节假日标注

(2)农历的查询与显示

(3)图形界面

我有一些想法,后续可能会加上去,挺菜的,一般都是瞎琢磨。

4.2 算法优化

如果你仔细看过我的代码就会发现大量重复部分,有很大删减优化空间,并且在循环体中有大量重复性判定,完全可以将判定挪至循环体最外层或是直接挪出循环体,只做一次判定,可以极大的降低算力消耗,如果完美优化的话大概100行代码就够了吧,我用了300行,主要是年月日三个部分,很多代码都重复写了三遍,用了三百行,优化空间还是很大的。

以下几点:

(1)重复性运算部分删减,降低空间占用,算力消耗

(2)算法结构优化,降低算力消耗

4.3 体验优化

以下几点:

(1)增加循环层级,避免用户查询相同年份日期时做重复性输入

(2)合并日期输入,年月日分开输还按三次回车好像有点麻烦

(3)消除输入限制,解决一下负值、非数字等错误输入导致的程序异常终止、死循环等问题

完整版代码如下

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include<windows.h>
int main()
{
	while (1)
	{
		system("cls");
		int number = 0;
		printf("\n         万年历系统         \n"
			   "\n----------------------------\n"
			   "\n|    1.查询某年日历        |\n"
			   "\n|    2.查询某月日历        |\n"
			   "\n|    3.查询某日是星期几    |\n"
			   "\n----------------------------\n");
		printf("\n欢迎使用万年历系统\n");
		printf("\n输入项目编号查询指定项目,输入0则返回上一级(最高级无效)\n");
		printf("\n请输入您要查询项目的项目编号:");
		number = _getche();
		//printf("%d",number);查看数字编号的ASCII编码
		printf("\n");//换行
		switch (number)
		{
		case 48:break;
		case 49:
			while (1)
			{
				long long int year, sumday, week, sumleapyear = 0;
				//定义存储闰年个数的变量
				printf("请输入要查询的年份:");
				scanf_s("%lld", &year);
				if (year == 0)
					break;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
							sumleapyear++;
					}
				}
				else
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0)
							sumleapyear++;
					}
					sumleapyear+=5;//1582年的儒略历中公元元年不是星期一,为星期六,比周一多五天故加五
					//将算法改为儒略历算法发现星期比正确天数多了两天,也就是按元年元日为周一算多两天,往前两天,得儒略历元年元日为周六
					//但是往前减二的话会导致元年元月的日期计算出错,故我们往前加五
					//算法改为儒略历计算1582年10月4日得星期六,而正确日期为星期四,故多了两天
				}
				//统计公元元年至去年中有多少个闰年
				sumday = (year - 1) * 365 + sumleapyear;
				//统计公元元年1月1日至指定年份12月31日共有多少天,公元元年至指定年份年数*365+闰年数
				//printf("%d ",sumday);用于临时验证天数准确性
				int February;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
						February = 29;
					else
						February = 28;
				}
				else
				{
					if (year % 4 == 0)
						February = 29;
					else
						February = 28;
				}
				//区分润年及平年2月的天数
				int a[13] = { 0,31,February,31,30,31,30,31,31,30,31,30,31 };
				//定义数组存储1~12月每月天数
				for (int month = 1; month <= 12; month++)
				{
					sumday += a[month - 1];
					//printf("%d ",sumday);用于临时验证天数准确性
					int day = 1;
					if (year == 1582 && month == 11)
						sumday += 11;//这里为何不加10?
					week = (sumday + day) % 7;
					//公元1月1日至指定年份总天数求余7,公式为:星期数=(总天数+当月第一天)%7
					//printf("\n%d\n",week);用于临时验证星期数准确性
					printf("%d月\n", month);
					printf("\n------------------ %lld 年 %d 月 ---------------------\n\n", year, month);
					printf("日	一	二	三	四	五	六\n\n");
					for (int j = 1; j <= week; j++)
					{
						printf("	 ");
					}
					//通过打印空格控制当月第一天起始星期数
					if (year == 1582 && month == 10)
					{//如果是1582年10月则删除5号到14号这10天
						for (int j = 1; j <= a[month]; j++)
						{
							printf("%d	 ", j);
							if ((week + j) >= 7)
							{
								printf("\n\n");
								week -= 7;
							}
							if (j == 4)
							{
								j += 10;
								week -= 10;
							}

						}
					}
					else
					{
						for (int j = 1; j <= a[month]; j++)
						{
							printf("%d	 ", j);
							if ((week + j) >= 7)
							{
								printf("\n\n");
								week -= 7;
							}

						}
					}
					//打印当月日历
					printf("\n------------------------------------------------------\n\n");
				}
				/*if (week != 0)
					printf("%d年%d月%d日是星期%d\n", year, month, day, week);
				else
					printf("%d年%d月%d日是星期日\n", year, month, day);用于临时验证星期*/
			}
			break;
		case 50:
			while (1)
			{
				int year, sumday, week, month, sumleapyear = 0;
				//定义存储闰年个数的变量
				printf("请输入要查询的年份:");
				scanf_s("%d", &year);
				if (year == 0)
					break;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
							sumleapyear++;
					}
				}
				else
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0)
							sumleapyear++;
					}
					sumleapyear += 5;//1582年的儒略历中公元元年不是星期一,为星期六,比周一多五天故加五
					//将算法改为儒略历算法发现星期比正确天数多了两天,也就是按元年元日为周一算多两天,往前两天,得儒略历元年元日为周六
					//但是往前减二的话会导致元年元月的日期计算出错,故我们往前加五
					//算法改为儒略历计算1582年10月4日得星期六,而正确日期为星期四,故多了两天
				}
				//统计公元元年至去年中有多少个闰年
				sumday = (year - 1) * 365 + sumleapyear;
				//统计公元元年1月1日至指定年份12月31日共有多少天,公元元年至指定年份年数*365+闰年数
				//printf("%d ",sumday);用于临时验证天数准确性
				int February;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
						February = 29;
					else
						February = 28;
				}
				else
				{
					if (year % 4 == 0)
						February = 29;
					else
						February = 28;
				}
				//区分润年及平年2月的天数
				int a[13] = { 0,31,February,31,30,31,30,31,31,30,31,30,31 };
				//定义数组存储1~12月每月天数
				printf("请输入要查询的月份:");
				scanf_s("%d",&month);
				if (month == 0)
					break;
				for (int i = 1; i <= month; i++)
				{
					sumday += a[i - 1];
					//printf("%d ",sumday);用于临时验证天数准确性
				}
				if (year == 1582 && month == 11 || year == 1582 && month == 12)
					sumday += 11;//这里为何不加10?
				int day = 1;
				week = (sumday + day) % 7;
				//公元1月1日至指定年份总天数求余7,公式为:星期数=(总天数+当月第一天)%7
				//printf("\n%d\n",week);用于临时验证星期数准确性
				printf("\n------------------ %d 年 %d 月 ---------------------\n\n",year,month);
				printf("日	一	二	三	四	五	六\n\n");
				for (int j = 1; j <= week; j++)
				{
					printf("	 ");
				}
				//通过打印空格控制当月第一天起始星期数
				if (year == 1582 && month == 10)
				{//如果是1582年10月则删除5号到14号这10天
					for (int j = 1; j <= a[month]; j++)
					{
						printf("%d	 ", j);
						if ((week + j) >= 7)
						{
							printf("\n\n");
							week -= 7;
						}
						if (j == 4)//如果是1582年10月则删除5号到14号这10天
						{
							j += 10;
							week -= 10;
						}

					}
				}
				else
				{
					for (int j = 1; j <= a[month]; j++)
					{
						printf("%d	 ", j);
						if ((week + j) >= 7)
						{
							printf("\n\n");
							week -= 7;
						}

					}
				}
				//打印当月日历
				printf("\n------------------------------------------------------\n\n");
				/*if (week != 0)
					printf("%d年%d月%d日是星期%d\n", year, month, day, week);
				else
					printf("%d年%d月%d日是星期日\n", year, month, day);用于临时验证星期*/
			}
			break;
		case 51:
			while (1)
			{
				int year, month, day, sumday, week, sumleapyear = 0;
				printf("请输入年:");
				scanf_s("%d", &year);
				if (year == 0)
					break;
				//统计公元元年至去年中有多少个闰年
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
							sumleapyear++;
					}
				}
				else
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0)
							sumleapyear++;
					}
					sumleapyear += 5;//1582年的儒略历中公元元年不是星期一,为星期六,比周一多五天故加五
					//将算法改为儒略历算法发现星期比正确天数多了两天,也就是按元年元日为周一算多两天,往前两天,得儒略历元年元日为周六
					//但是往前减二的话会导致元年元月的日期计算出错,故我们往前加五
					//算法改为儒略历计算1582年10月4日得星期六,而正确日期为星期四,故多了两天
				}
				//统计公元元年至去年中有多少个闰年
				sumday = (year - 1) * 365 + sumleapyear;
				//统计公元元年1月1日至指定年份12月31日共有多少天,公元元年至指定年份年数*365+闰年数
				//printf("%d ",sumday);用于临时验证天数准确性
				int February;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
						February = 29;
					else
						February = 28;
				}
				else
				{
					if (year % 4 == 0)
						February = 29;
					else
						February = 28;
				}
				//区分润年及平年2月的天数
				int a[13] = { 0,31,February,31,30,31,30,31,31,30,31,30,31 };
				printf("请输入月:");
				scanf_s("%d", &month);
				if (month == 0)
					break;
				//统计公元元年1月1日至去年12月31日总天数+今年1月1日至今年上一个月最后一天的总天数
				for (int i = 1; i <= month - 1; i++)
					sumday += a[i];
				if (year == 1582 && month == 11 || year == 1582 && month == 12)
					sumday += 11;//这里为何不加10?
				printf("请输入日:");
				scanf_s("%d", &day);
				if (day == 0)
					break;
				if (year == 1582 && month == 10 && day > 4 && day < 15)
				{
					printf("历法变更,不存在这一天!\n\n");
					//_sleep(1000);
					continue;
				}
				//公元1月1日至今的总天数求余7
				if (year == 1582 && month == 10 && day >= 15)
					week = (sumday + day - 10) % 7;//历法变更删除10天
				else
					week = (sumday + day) % 7;
				if (week != 0)
					printf("%d年%d月%d日是星期%d\n\n", year, month, day, week);
				else
					printf("%d年%d月%d日是星期日\n\n", year, month, day);
			}
			break;
		default:printf("输入错误请重新输入");
		}
	}
	return 0;
}
//某一天是星期几的判断方法:指定日期至公元元年1月1日的总天数%7
//指定日期至公元元年1月1日的总天数的计算方法:指定年份前一年至公元元年1月1日总天数*365+指定年份前一年至公元元年中闰年总数+
											//指定年份1月1日至指定月份前一月总天数+指定日期

运行结果如下

5 手机版

推荐使用“C语言编译器”:C语言编译器官方下载-C语言编译器 app 最新版本免费下载-应用宝官网 (qq.com) 

运行效果如下 

手机版完整代码如下 

#include <stdio.h>
#include <stdlib.h>
//#include <conio.h>
//#include<windows.h>
int main()
{
	while (1)
	{
		system("cls");
		int number = 0;
		printf("\n         万年历系统         \n"
			   "\n----------------------------\n"
			   "\n|    1.查询某年日历        |\n"
			   "\n|    2.查询某月日历        |\n"
			   "\n|    3.查询某日是星期几    |\n"
			   "\n----------------------------\n");
		printf("\n欢迎使用万年历系统\n");
		printf("\n输入项目编号查询指定项目,输入0则返回上一级(最高级无效)\n");
		printf("\n请输入您要查询项目的项目编号:");
		scanf("%d",&number);
		//printf("%d",number);查看数字编号的ASCII编码
		printf("\n");//换行
		switch (number)
		{
		case 0:break;
		case 1:
			while (1)
			{
				int year, sumday, week, sumleapyear = 0;
				//定义存储闰年个数的变量
				printf("请输入要查询的年份:");
				scanf("%d", &year);
				if (year == 0)
					break;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
							sumleapyear++;
					}
				}
				else
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0)
							sumleapyear++;
					}
					sumleapyear+=5;//1582年的儒略历中公元元年不是星期一,为星期六,比周一多五天故加五
					//将算法改为儒略历算法发现星期比正确天数多了两天,也就是按元年元日为周一算多两天,往前两天,得儒略历元年元日为周六
					//但是往前减二的话会导致元年元月的日期计算出错,故我们往前加五
					//算法改为儒略历计算1582年10月4日得星期六,而正确日期为星期四,故多了两天
				}
				//统计公元元年至去年中有多少个闰年
				sumday = (year - 1) * 365 + sumleapyear;
				//统计公元元年1月1日至指定年份12月31日共有多少天,公元元年至指定年份年数*365+闰年数
				//printf("%d ",sumday);用于临时验证天数准确性
				int February;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
						February = 29;
					else
						February = 28;
				}
				else
				{
					if (year % 4 == 0)
						February = 29;
					else
						February = 28;
				}
				//区分润年及平年2月的天数
				int a[13] = { 0,31,February,31,30,31,30,31,31,30,31,30,31 };
				//定义数组存储1~12月每月天数
				for (int month = 1; month <= 12; month++)
				{
					sumday += a[month - 1];
					//printf("%d ",sumday);用于临时验证天数准确性
					int day = 1;
					if (year == 1582 && month == 11)
						sumday += 11;//这里为何不加10?
					week = (sumday + day) % 7;
					//公元1月1日至指定年份总天数求余7,公式为:星期数=(总天数+当月第一天)%7
					//printf("\n%d\n",week);用于临时验证星期数准确性
					printf("%d月\n", month);
					printf("\n------------------ %lld 年 %d 月 ---------------------\n\n", year, month);
					printf("日	一	二	三	四	五	六\n\n");
					for (int j = 1; j <= week; j++)
					{
						printf("	 ");
					}
					//通过打印空格控制当月第一天起始星期数
					if (year == 1582 && month == 10)
					{//如果是1582年10月则删除5号到14号这10天
						for (int j = 1; j <= a[month]; j++)
						{
							printf("%d	 ", j);
							if ((week + j) >= 7)
							{
								printf("\n\n");
								week -= 7;
							}
							if (j == 4)
							{
								j += 10;
								week -= 10;
							}

						}
					}
					else
					{
						for (int j = 1; j <= a[month]; j++)
						{
							printf("%d	 ", j);
							if ((week + j) >= 7)
							{
								printf("\n\n");
								week -= 7;
							}

						}
					}
					//打印当月日历
					printf("\n------------------------------------------------------\n\n");
				}
				/*if (week != 0)
					printf("%d年%d月%d日是星期%d\n", year, month, day, week);
				else
					printf("%d年%d月%d日是星期日\n", year, month, day);用于临时验证星期*/
			}
			break;
		case 2:
			while (1)
			{
				int year, sumday, week, month, sumleapyear = 0;
				//定义存储闰年个数的变量
				printf("请输入要查询的年份:");
				scanf("%d", &year);
				if (year == 0)
					break;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
							sumleapyear++;
					}
				}
				else
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0)
							sumleapyear++;
					}
					sumleapyear += 5;//1582年的儒略历中公元元年不是星期一,为星期六,比周一多五天故加五
					//将算法改为儒略历算法发现星期比正确天数多了两天,也就是按元年元日为周一算多两天,往前两天,得儒略历元年元日为周六
					//但是往前减二的话会导致元年元月的日期计算出错,故我们往前加五
					//算法改为儒略历计算1582年10月4日得星期六,而正确日期为星期四,故多了两天
				}
				//统计公元元年至去年中有多少个闰年
				sumday = (year - 1) * 365 + sumleapyear;
				//统计公元元年1月1日至指定年份前一年12月31日共有多少天,公元元年至指定年份前一年年数*365+闰年数
				//printf("%d ",sumday);用于临时验证天数准确性
				int February;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
						February = 29;
					else
						February = 28;
				}
				else
				{
					if (year % 4 == 0)
						February = 29;
					else
						February = 28;
				}
				//区分润年及平年2月的天数
				int a[13] = { 0,31,February,31,30,31,30,31,31,30,31,30,31 };
				//定义数组存储1~12月每月天数
				printf("请输入要查询的月份:");
				scanf("%d",&month);
				if (month == 0)
					break;
				for (int i = 1; i <= month; i++)
				{
					sumday += a[i - 1];
					//printf("%d ",sumday);用于临时验证天数准确性
				}
				if (year == 1582 && month == 11 || year == 1582 && month == 12)
					sumday += 11;//这里为何不加10?
				int day = 1;
				week = (sumday + day) % 7;
				//公元1月1日至指定年份总天数求余7,公式为:星期数=(总天数+当月第一天)%7
				//printf("\n%d\n",week);用于临时验证星期数准确性
				printf("\n------------------ %d 年 %d 月 ---------------------\n\n",year,month);
				printf("日	一	二	三	四	五	六\n\n");
				for (int j = 1; j <= week; j++)
				{
					printf("	 ");
				}
				//通过打印空格控制当月第一天起始星期数
				if (year == 1582 && month == 10)
				{//如果是1582年10月则删除5号到14号这10天
					for (int j = 1; j <= a[month]; j++)
					{
						printf("%d	 ", j);
						if ((week + j) >= 7)
						{
							printf("\n\n");
							week -= 7;
						}
						if (j == 4)//如果是1582年10月则删除5号到14号这10天
						{
							j += 10;
							week -= 10;
						}

					}
				}
				else
				{
					for (int j = 1; j <= a[month]; j++)
					{
						printf("%d	 ", j);
						if ((week + j) >= 7)
						{
							printf("\n\n");
							week -= 7;
						}

					}
				}
				//打印当月日历
				printf("\n------------------------------------------------------\n\n");
				/*if (week != 0)
					printf("%d年%d月%d日是星期%d\n", year, month, day, week);
				else
					printf("%d年%d月%d日是星期日\n", year, month, day);用于临时验证星期*/
			}
			break;
		case 3:
			while (1)
			{
				int year, month, day, sumday, week, sumleapyear = 0;
				printf("请输入年:");
				scanf("%d", &year);
				if (year == 0)
					break;
				//统计公元元年至去年中有多少个闰年
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
							sumleapyear++;
					}
				}
				else
				{
					for (int i = 1; i <= year - 1; i++)
					{
						if (i % 4 == 0)
							sumleapyear++;
					}
					sumleapyear += 5;//1582年的儒略历中公元元年不是星期一,为星期六,比周一多五天故加五
					//将算法改为儒略历算法发现星期比正确天数多了两天,也就是按元年元日为周一算多两天,往前两天,得儒略历元年元日为周六
					//但是往前减二的话会导致元年元月的日期计算出错,故我们往前加五
					//算法改为儒略历计算1582年10月4日得星期六,而正确日期为星期四,故多了两天
				}
				//统计公元元年至去年中有多少个闰年
				sumday = (year - 1) * 365 + sumleapyear;
				//统计公元元年1月1日至指定年份12月31日共有多少天,公元元年至指定年份年数*365+闰年数
				//printf("%d ",sumday);用于临时验证天数准确性
				int February;
				if (year > 1582)//通过年份判断将公历和儒略历分开
				{
					if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
						February = 29;
					else
						February = 28;
				}
				else
				{
					if (year % 4 == 0)
						February = 29;
					else
						February = 28;
				}
				//区分润年及平年2月的天数
				int a[13] = { 0,31,February,31,30,31,30,31,31,30,31,30,31 };
				printf("请输入月:");
				scanf("%d", &month);
				if (month == 0)
					break;
				//统计公元元年1月1日至去年12月31日总天数+今年1月1日至今年上一个月最后一天的总天数
				for (int i = 1; i <= month - 1; i++)
					sumday += a[i];
				if (year == 1582 && month == 11 || year == 1582 && month == 12)
					sumday += 11;//这里为何不加10?
				printf("请输入日:");
				scanf("%d", &day);
				if (day == 0)
					break;
				if (year == 1582 && month == 10 && day > 4 && day < 15)
				{
					printf("历法变更,不存在这一天!\n\n");
					//_sleep(1000);
					continue;
				}
				//公元1月1日至今的总天数求余7
				if (year == 1582 && month == 10 && day >= 15)
					week = (sumday + day - 10) % 7;//历法变更删除10天
				else
					week = (sumday + day) % 7;
				if (week != 0)
					printf("%d年%d月%d日是星期%d\n\n", year, month, day, week);
				else
					printf("%d年%d月%d日是星期日\n\n", year, month, day);
			}
			break;
		default:printf("输入错误请重新输入");
		}
	}
	return 0;
}
//某一天是星期几的判断方法:指定日期至公元元年1月1日的总天数%7
//指定日期至公元元年1月1日的总天数的计算方法:指定年份前一年至公元元年1月1日总天数*365+指定年份前一年至公元元年中闰年总数+
											//指定年份1月1日至指定月份前一月总天数+指定日期

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值