最近在看《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月。