最近在看《The C Programing Language》,进一步加深了自己对于指针赋值的理解,现在看来关于日期,天数这类的题目很是简单,但是遥想当年大一的时候自己去参加计算机学院的编程大赛,五个问题只是求解出来一个,而没解答出的问题中就包含关于日期天数的一个问题,今天为了弥补一下以前的遗憾,就把这个程序再写一写吧。(话说程序还就需要多写多练,本来以为自己看书的时候想枚举,多维数组,局部变量初始化等问题都是很简单的,但是自己写起来还是很费劲,说明自己写的代码还是少,需要加强训练啊。)
#include <stdio.h> #include <stdlib.h> int monthday[2][12]= { {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31} }; char *Month[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; int year_days(int year,int month,int day) { int leap,yeardays,i; yeardays = 0; leap = ((year%4==0 && year%100!=0) || (year%400==0)); for(i=0;i<month-1;i++) yeardays += monthday[leap][i]; yeardays = yeardays+day; return yeardays; } void month_day(int year,int yeardays,int* pmonth,int* pday) { int leap,i; leap = ((year%4==0 && year%100!=0) || (year%400==0)); for(i=0;yeardays>monthday[leap][i];i++) yeardays -= monthday[leap][i]; *pmonth = i; *pday = yeardays; } int main() { int year = 1997; int month = 3; int day = 1; int *pmonth; int *pday; int yeardays = year_days(year,month,day); pmonth = (int*)malloc(sizeof(int)); pday = (int*)malloc(sizeof(int)); month_day(year,yeardays,pmonth,pday); printf("The yeardays is %d\n",yeardays); printf("The Month is %s, The Date is %d \n",Month[*pmonth],*pday); return 0; }
对于程序的完美运行需要进行用户输入的合法性判断,下面是另外一个版本:
#include <stdio.h> static char daytab[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}, }; /* day_of_year: set day of year from month & day */ int day_of_year(int year, int month, int day) { int i, leap; if (year < 1752 || month < 1 || month > 12 || day < 1) return -1; leap = (year%4 == 0 && year%100 != 0) || year%400 == 0; if (day > daytab[leap][month]) return -1; for (i = 1; i < month; i++) day += daytab[leap][i]; return day; } /* month_day: set month, day from day of year */ int month_day(int year, int yearday, int *pmonth, int *pday) { int i, leap; if (year < 1752 || yearday < 1) return -1; leap = (year%4 == 0 && year%100 != 0) || year%400 == 0; if ((leap && yearday > 366) || (!leap && yearday > 365)) return -1; for (i = 1; yearday > daytab[leap][i]; i++) yearday -= daytab[leap][i]; *pmonth = i; *pday = yearday; return 0; } /* main: test day_of_year and month_day */ int main(void) { int year, month, day, yearday; for (year = 1970; year <= 2000; ++year) { for (yearday = 1; yearday < 366; ++yearday) { if (month_day(year, yearday, &month, &day) == -1) { printf("month_day failed: %d %d\n", year, yearday); } else if (day_of_year(year, month, day) == yearday) { printf("bad result: %d %d\n", year, yearday); printf("month = %d, day = %d\n", month, day); } } } return 0; }
下面是根据年月日求解当天星期几的代码
#include <stdio.h> char *name[] = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" }; int main() { int d, m, y, a; printf("Day: "); scanf("%d",&d); printf("Month: "); scanf("%d",&m); printf("Year: "); scanf("%d",&y); // 1213,14 if (m == 1 || m == 2) { m += 12; y--; } // 175293 if ((y < 1752) || (y == 1752 && m < 9) || (y == 1752 && m == 9 && d < 3)) a = (d + 2*m + 3*(m+1)/5 + y + y/4 +5) % 7; else a = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400)%7; printf("it's a %s\n", name[a]); return 0; }
根据代码可以发现1752年9月3日是一个转折点。说明那天发生了什么大事,
现行的公历是格利戈里历法,这个历法的是1582年教皇格利戈里根据恺撒大帝引进的算法改进的。它采用的是闰年制也就是现行的制度,不过有一个需要注意的地方就是,这个历法并不是连续的,中间缺少了11天。1752年9月2日之后的那一天并不是1752年9月3日,而是1752年9月14日。也就是说,从1752年9月3日到1752年9月13日的11天并不存在。抹掉这11天是由英国议会做出的决定。所以要计算某年每个月的天数的,除了要考虑是否是闰年以外,还要考虑1752年的9月。