#include <time.h>
#include <stdlib.h>
// 打印當年的日歷,輸出到以自己學號命名的文件夾下面的文件名稱
const char OUTPUT_FILE_NAME[] = "calendar.txt";
/*表示星期的常量*/
const int SUN = 0;
const int MON = 1;
const int TUE = 2;
const int WED = 3;
const int THU = 4;
const int FRI = 5;
const int SAT = 6;
const char WEEK_NAME_SHORT[][4]={"SUN","MON","TUE","WED","THU","FRI","SAT"};
const char WEEK_NAME[][10]={"SUNDAY","MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY"};
// 表示月份的常量
const int JAN = 0;
const int FEB = 1;
const int MAR = 2;
const int APR = 3;
const int MAY = 4;
const int JUN = 5;
const int JUL = 6;
const int AUG = 7;
const int SEP = 8;
const int OCT = 9;
const int NOV = 10;
const int DEC = 11;
const char MONTH_NAME[][10]=
{
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
/*
設定壹個最小的系統日期,並且指定改天是星期幾
*/
/*最小的系統日期年份,默認是 2000 年*/
const int START_YEAR = 2000;
/*日最小的系統日期月份,默認是 1 月*/
const int START_MONTH = 1;
/*最小的系統日期,默認是 1 號*/
const int START_DAY = 1;
/*最小的系統日期所在的星期,默認是星期六(2000年1月1日是星期六)*/
const int START_WEEK_DAY = SAT;
/*
功能:計算壹年中指定月份的天數
*/
int getDaysOfMonth(int year ,int month)
{
const int daysOfMonth[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
if( month == 2 && ( (year%4==0 && year%100!=0) || year %400==0 ))
{
return daysOfMonth[month] +1;
}
else
{
return daysOfMonth[month];
}
}
/*
功能:
計算 year 年 month 月 day 日
距離
START_YEAR 年 START_MONTH 月 START_DAY 日
的天數
*/
int getDiffDays(int year ,int month , int day)
{
int diffDays = 0 ;
int y,m,d;
// 同年
if(year == START_YEAR)
{
// 同年同月
if(month == START_MONTH)
{
diffDays = day - START_DAY;
}
// 同年不同月
else
{
/*加上當月剩余天數*/
diffDays += getDaysOfMonth(START_YEAR,START_MONTH) - START_DAY + 1;
/*加上整月的天數*/
for(m = START_MONTH + 1 ; m < month ; m ++)
{
diffDays += getDaysOfMonth(START_YEAR,m);
}
/*加上當月剩余天數*/
diffDays += day -1;
}
}
// 不同年
else
{
/*加上當月剩余天數*/
diffDays += getDaysOfMonth(START_YEAR,START_MONTH) - START_DAY + 1;
/*加上整月的天數*/
for(m = START_MONTH + 1 ; m <= 12 ; m ++)
{
diffDays += getDaysOfMonth(START_YEAR,m);
}
/*加上整年的天數*/
for(y = START_YEAR+1 ; y < year ; y ++)
{
/*如果是閏年*/
if((y%4==0%y%100!=0) || y%400==0)
{
diffDays += 366;
}
else
{
diffDays += 365;
}
}
/*加上整月的天數*/
for(m = 1 ; m < month ; m ++)
{
diffDays += getDaysOfMonth(year,m);
}
/*加上當月的天數*/
diffDays += ( day - 1 );
}
return diffDays;
}
/*
功能:計算 year 年 month 月第壹天所在的星期
*/
int getFirstDayOfMonthInWeekDay(int year ,int month)
{
int days = getDiffDays(year,month,1);
return (days % 7 + START_WEEK_DAY) % 7;
}
/*
功能:輸出 year 年 month 月日歷
*/
void printMonthCalendar(int year,int month)
{
int firstDayOfMonthInWeekDay = 1;
int daysOfMonth;
int daysCounter;
int d,i;
/*檢查輸入的年份*/
if(year < START_YEAR || year > 9999)
{
printf("Illegal year : %d ! The year must range [%d,9999]!\n",year,START_YEAR);
return ;
}
/*檢查輸入的月份*/
if(month < 0 || month > 12)
{
printf("Illegal month : %d ! The month must range [0,12]");
return;
}
/********************開始打印日歷********************/
/*日歷年月頭部*/
printf("Calendar %d-%02d\n",year,month);
/*日歷星期頭部*/
for(i=0;i<7;i++)
{
printf("%s ",WEEK_NAME_SHORT[i]);
}
printf("\n");
for(i=0;i<4*7;i++)
{
printf("_");
}
printf("\n");
/*月中每日星期排列*/
//每月的第壹天所在的星期
firstDayOfMonthInWeekDay = getFirstDayOfMonthInWeekDay(year,month);
//當月的天數
daysOfMonth = getDaysOfMonth(year,month);
//輸出每月開頭空出的星期,並統計空白的星期
for(d = 0 ,daysCounter = 0; d < firstDayOfMonthInWeekDay ; d ++)
{
printf("%4s"," ");
daysCounter ++;
}
//輸出每月的天,根據所在的星期
for( d = 1 ; d <= daysOfMonth; d ++)
{
if(daysCounter % 7 ==0)
{
printf("\n");
}
printf("%3d ",d);
daysCounter++;
}
printf("\n");
for(i=0;i<4*7;i++)
{
printf("_");
}
printf("\n");
}
/*
功能:輸出 year 年歷 ,每行最多顯示 maxShowMonthNumPerLine 個月份
*/
void printYearCalendar(int year,int maxShowMonthNumPerLine)
{
int *firstDayOfMonthInWeekDay = (int*)malloc(sizeof(int)*maxShowMonthNumPerLine);
int *daysOfMonth = (int*)malloc(sizeof(int)*maxShowMonthNumPerLine);
int *daysCounter = (int*)malloc(sizeof(int)*maxShowMonthNumPerLine);
int i,d,month,startMonth,showMonthNumPerLine;
int showMonthCounterPerLine;
/*檢查輸入的年份*/
if(year < START_YEAR || year > 9999)
{
printf("Illegal year : %d ! The year must range [%d,9999]!\n",year,START_YEAR);
return ;
}
/********************開始打印日歷********************/
/*日歷年頭部*/
printf("Calendar %d\n",year);
for(startMonth=1;startMonth<=12;startMonth+=showMonthNumPerLine)
{
showMonthNumPerLine = (startMonth+maxShowMonthNumPerLine )<=12 ? maxShowMonthNumPerLine : (12 - startMonth + 1);
/*1年歷的月頭部*/
for(month=startMonth;month<(startMonth+showMonthNumPerLine);month++)
{
printf("%-28s ",MONTH_NAME[month-1]);
}
printf("\n");
/*2年歷的星期頭部*/
for(month=startMonth;month<(startMonth+showMonthNumPerLine);month++)
{
for(i=0;i<7;i++)
{
printf("%s ",WEEK_NAME_SHORT[i]);
}
printf(" ");
}
printf("\n");
// 分割線
for(month=startMonth;month<(startMonth+showMonthNumPerLine);month++)
{
for(i=0;i<4*7;i++)
{
printf("_");
}
printf(" ");
}
printf("\n");
/* 數據初始化 */
for(month=startMonth;month<(startMonth+showMonthNumPerLine);month++)
{
//每月的第壹天所在的星期
firstDayOfMonthInWeekDay[month-startMonth] = getFirstDayOfMonthInWeekDay(year,month);
//當月的天數
daysOfMonth[month-startMonth] = getDaysOfMonth(year,month);
// 已經輸出的天計數器
daysCounter[month-startMonth] = -firstDayOfMonthInWeekDay[month-startMonth]+1;
}
/*3日歷每天排列*/
showMonthCounterPerLine = 0;
while(showMonthCounterPerLine < showMonthNumPerLine)
{
for(month=startMonth;month<(startMonth+showMonthNumPerLine);month++)
{
for(i=0;i<7;i++)
{
if(daysCounter[month-startMonth]<=0 || daysCounter[month-startMonth] > daysOfMonth[month-startMonth])
{
printf("%4s"," ");
}
else
{
printf("%3d ",daysCounter[month-startMonth]);
}
daysCounter[month-startMonth] ++;
if(daysCounter[month-startMonth] > daysOfMonth[month-startMonth] )
{
showMonthCounterPerLine++;
}
}
printf(" ");
}
printf("\n");
}
// 分割線
for(month=startMonth;month<(startMonth+showMonthNumPerLine);month++)
{
for(i=0;i<4*7;i++)
{
printf("_");
}
printf(" ");
}
printf("\n");
}
}
int main(int argc, char *argv[])
{
int year,month;
time_t t = time(NULL);
struct tm* now = localtime(&t);
int choice;
/*
1
顯示任意年月的月歷
每行兩個月的格式輸出當年的年歷
每行兩個月的格式輸出任意年的年歷
*/
while(1)
{
printf("×××××××××××××××\n");
printf("1輸出當月月歷 1\n");
printf("2輸出當年年歷 2\n");
printf("3指定任意年月的月歷 3\n");
printf("4指定任意年的年歷 4\n");
printf("5退出 5\n");
printf("×××××××××××××××\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
printMonthCalendar(now->tm_year+1900,now->tm_mon+1);
break;
case 2:
printYearCalendar(now->tm_year+1900,2);
break;
case 3:
printf("輸入年和月(YYYY-MM):");
scanf("%d-%d",&year,&month);
printMonthCalendar(year,month);
break;
case 4:
printf("輸入年(YYYY):");
scanf("%d-%d",&year);
printYearCalendar(year,2);
break;
case 5:
exit(0);
default:
printf("選擇錯誤,請重新選擇\n"); ;
};
}
return 0;
}