#include <stdio.h> int main() { int Year,Month; /*判断输入年份是否是闰年*/ _Bool isLeapYear(int); /*判断每月天数*/ int monthDays(int,int); /*判断某个日期是星期几*/ int getWeekDay(int,int,int); /*判断输入年份一月一日星期几*/ int yearstartday(int); /*输出某年某月的日历*/ void outMonthDays(int,int); /*输出1582年某月日历*/ void outMonthDays1582(int,int); printf("请输入年份(公元前用负数表示):"); scanf("%d",&Year); if(Year == 0) { printf("输入错误,没有公元零年"); }else { if(Year > 0) { printf(" 公元%d年日历为:\n",Year); } else{ printf(" 公元前%d年日历为:\n",-Year); } printf("=====================================\n"); if(Year != 1582) //为计算及表达简略,不在输出中加入修正,单独编写1582年输出函数 { for(Month=1;Month<=12;Month++) { outMonthDays(Year,Month); } } else { for(Month=1;Month<=12;Month++) { outMonthDays1582(Year,Month); } } } return 0; } /*判断输入年分一月一日星期几*/ int yearstartday(int Year) { int detayear,corday,weekstartday,detaday; detayear = Year - 2000; //以2000年为参考计算每年一月一日星期几 2000.01.01周六 if(detayear>0) { corday = 2; detayear -= 1; //这个corday和detayear一起解释,这是修正了一个计算错误,计算的时候2000年是闰年,应该 //让detaday为2,又因为计算2000年以后的年份时,比如计算2020年,只需要计算到2019在内 //要间隔多少天,一月一日不需要计算2020年内的天数对星期的影响,所以就让detayear减1 //让corday赋值为2 }else{ corday = 0; //大于1582年小于2000年的时候不需要修正 if (detayear <= -418) { corday = -3; //大于等于0001年小于等于1582年,做一次修正 //1582年由于历史原因,10月少了10天,当年只有355天 if(detayear <= -2000) { corday = -1; //公元零年不存在,按照计算公式,如果这一年存在的话,它应该是闰年 } //闰年每年相隔两天,剔除这两天的误差 } } detaday = (detayear / 400) * 2 - detayear / 100 + detayear / 4 + detayear + corday;//相隔天数 //下面解释一下detaday计算公式的计算方式 //平年有365天,365除以7余1;闰年有366天,366除以7余2.这样我们就可以,先取一个参考年份, //然后用这个年份一月一日星期几来推算别的年份,为了计算方便,我选择2000年 //相隔年份里面,如果是平年,应该记为一天;如果是闰年,则应该是两天 //(detayear / 400) * 2 - detayear / 100 + detayear / 4 这些计算出了相隔年份里有多少闰年 // 后面detayear把不管是闰年还是平年都计算上了,那么再加上闰年有几个就可以,也就是前面的那些 //corday做计算公式的修正,不同年份区域有不同值 weekstartday = (6 + detaday % 7) % 7; //6是2000年一月一日为周六,detaday % 7先将计算出的“相隔天数 ”进行周期处理,也可以不用, //即使用后面的式子:weekstartday = (6 + detaday) % 7; //最后也取余7了,同样进行了周期处理 return weekstartday; //weekstartday即为一月一日周几,0代表周日 } /*判断闰年函数的具体实现*/ _Bool isLeapYear(int Year) //布尔函数 { if(Year%4==0 && Year%100!=0 || Year%400==0) { return 1; }else return 0; } /*判断每月天数的具体实现*/ int monthDays(int Year,int Month){ if(Month == 1 || Month == 3 || Month == 5 || Month == 7 || Month == 8 || Month == 10 || Month == 12) { return 31; }else if(Month == 4 || Month == 6 || Month == 9 || Month == 11) { return 30; }else{ if(isLeapYear(Year)) { return 29; }else return 28; } } /*判断某年某月某号是周几的具体实现*/ int getWeekDay(int Year,int Month,int Day){ int i,temp,weekday,Days=0; for(i=1;i<=Month-1;i++) { Days += monthDays(Year,i); //也可以定义全局数组解决 } Days = Days + Day-1; //weekstartday里面包含了开始那天,这里剔除一天 temp = yearstartday(Year)+Days; weekday = temp % 7; //weekday即为周几,0代表周日 if(Year==1582&&Month>10) //1582年10月后面少了10天,10 % 7 = 3 { weekday -= 3; } return weekday; } /*输出某年某月日历的具体实现*/ void outMonthDays(int Year,int Month){ int i,j,weekday; printf(" %d月日历\n",Month); printf(" 日 一 二 三 四 五 六\n"); weekday = getWeekDay(Year,Month,1); for(i=0;i<weekday;i++) { printf(" "); } for(j=1;j<=monthDays(Year,Month);j++) { printf("%4d",j); if((j+weekday)%7==0) { printf("\n"); } } printf("\n"); printf("-------------------------------------\n"); } /*输出1582年某月日历的具体实现*/ void outMonthDays1582(int Year,int Month){ int i,j,weekday; printf(" %d月日历\n",Month); printf(" 日 一 二 三 四 五 六\n"); weekday = getWeekDay(Year,Month,1); for(i=0;i<weekday;i++) { printf(" "); } for(j=1;j<=monthDays(Year,Month);j++) { if(Month == 10) { if(j>4&&j<15) { //这里为空,是为了提示从4号以后删除了10天 }else { printf("%4d",j); if(j==16||j==23||j==30) //没有再写函数约束,通过查到的日历直接定义换行 { printf("\n"); } } } else { printf("%4d",j); if((j+weekday)%7==0) { printf("\n"); } } } printf("\n"); printf("-------------------------------------\n"); }
C语言编写万年历,解决1582年历史问题
最新推荐文章于 2023-05-22 11:03:28 发布