/* * Based on the year 2000/01/01,when is Saturday to finger out the Y/M/01 's weekday,if we know this,we * can print all that month's weekdays. */
#include "stdio.h"
#define USHORT unsigned short #define ULONG unsigned long
USHORT DaysOfEachMonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31};/* the common days of each month,not the leap year */ USHORT Total[12] = {0,31,59,90,120,151,181,212,243,273,304,334}; USHORT M = 0;/* month */ ULONG Y = 0;/* Year */
USHORT IsLeapYear(ULONG year); /* Judge the year is a leep year(return 1) or not(return 0) */ USHORT WeakDayOfYM1();/* Count the weakday of Y/M/1 */ void Print(USHORT space);
unsigned short IsLeapYear(ULONG year) { return((year%4 == 0 && year%100) || year%400 == 0)?1:0; }
USHORT WeakDayOfYM1() { ULONG Range_Y = 0, Sub_N = 0; USHORT Div_Y = 0, Div_M = 0, Space = 0, TotalDays = 0, Flag = 0; short Div = 0;/* use unsigned short Div may < 0 */
Flag=(Y==2000)?0:((Y>2000 || IsLeapYear(Y))?2:1);/* we donot Judge the year Y, if Y=2000,we Flag=0 * if the year>2000 or the year is a leep year * Flag=2,else Flag=1 * this is the key!! */ Range_Y = (Y>2000)?(Y-2001):((Y<2000)?(2000-Y-1):0); /* not include the year Y */ Sub_N = Range_Y/4 - Range_Y/100 + Range_Y/400;/* num of leap year */ Div_Y = 2*Sub_N%7 + (Range_Y - Sub_N + Flag)%7;/* offset between 2000/01/01 and Y/01/01, * eacn leap year has 366 days the offset is 366%7=2, * so we use 2*Sub_N, and the other years which are not * leap year, the offset is 365%7=1,so we use Range_Y-Sub_N * do not use Div_Y = (2*Sub_N + Range_Y - Sub_N + Flag)%7; * defend overflow. */ TotalDays=Total[M-1];/* the total days from January to Month M */ if(IsLeapYear(Y) && M>=3) TotalDays++; /* Yet we donot Judge the year Y, now we do it,if Y is a leap year and M is big * than 29,Februray, we increase the totaldays,because the default days of Feb is * 28 */ Div_M=TotalDays%7;/* offset between Y/01/01 and Y/M/01 */ Div=(Y>2000)?(Div_M+Div_Y)%7:(Div_M-Div_Y)%7; /* offet between 2000/01/01 and Y/01/01 * there is a puzzle puzzled me so long,when * Y=1900,M=1 or 2 or 3 ...,u will see Div_M=0,Div_Y=5,but * the result of Div=4!!! this happend in Turbo C 2.0 * but in gcc and Dev-C++ and VS 2005 that's OK,so surprised thing!!! */ Space=(6 + Div)%7;/* the number 6 is the weekday of 2000/01/01-Saturday,also is the init offset */ return Space;/* return the result offset we do want */ }
void Print(USHORT space) { USHORT days=DaysOfEachMonth[M-1],i=0,j=0;
printf("\t\t********==== Calendar ====********\n"); printf("\t\t*************F.U.Moon*************\n");
printf("\t\t\t %lu/%-2hu \n\n",Y,M); printf("\tSun\tMon\tTue\tWen\tThu\tFri\tSat\n"); for(i=0;i<space;i++) printf("\t"); if(IsLeapYear(Y) && M == 2) days=29; for(j=1;j<=days;j++) { printf("\t%3d",j); if((space + j)%7 == 0) printf("\n"); } }
int main(int argc, char* argv[]) { USHORT space = 0; printf("Input Year and Month:"); scanf("%lu%hu",&Y,&M);/* we do not check the input */ space = WeakDayOfYM1(); Print(space); fflush(stdin);/* flush the stdin,if not do this some compile need two getchar(); */ getchar(); return 0; }
|