精華區beta C_and_CPP 關於我們 聯絡資訊
/******************************************************************** Program: 萬年曆 Version: 1.3 File: HK0214D.cpp HomeWork_02 1.4 Description compiler: Turbo c++ 3.0 Author: 龍龍 (Dick Guan) B86506057 Date: 11/6/1997 Description: 已知: 西元一年一月一日為 Sat 1752為特殊的一年(曆法上有點兒更改) 1752之前為四年一閏 1752之9月只有19天 (1.2.14.15.......)沒有3~13號 1752以後之閏年規則為:是4的倍數,不是100的倍數而是400的倍數 ex. 1800不是閏年(100的倍數)但2000是閏年(因是400的倍數) 思考: 利用我們的星期是連續的,且是七個一循環 假設使用者輸入year年month月,我們可寫個函數 算出由西元元年一月一日至year年month月1日共隔了幾天 (當然,必須再寫個函數用來判定這一連下來的年有無閏年(1752前後不一樣判定法) 或是特殊的1752年9月___只有19天!!!) 將結果加上6(因為一年一月一日是Sat),再將結果除以7 所得結果即為year年month月1日是星期幾 研析: 1年1月1日是Sat 2年1月1日是Sum 加1 3年1月1日是Mon 加1 4年1月1日是Tue 加1 5年1月1日是Thu 加2....!!! 有沒有發覺,如果當年不是閏年,則下一年的同一天其星期數會加一天, 閏年則加兩天 因為 365(沒有閏年) / 7 ......1 366(閏年) / 7 ......2 so.....................可藉此特性來算出 由1年1月1日至year年1月1日累計了多少天(而不是多少個365或366天) 這樣比較快的 :> ********************************************************************/ #include <stdio.h> #include <conio.h> #include <ctype.h> enum {Sum, Mon, Tue, Wed, Thu, Fri, Sat}; enum {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; enum {Normal_Feb=1, Leap_Feb=2, Special_Sep=5}; const char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; //const char *Week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; int Month_Days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int Special_Day[12][32]; void display_calendar(int year, int month, int first_day, int x, int y, int color); int find_day(int year, int month, int day); int leap(int year); void input_data(int &year, int &month, int &start_month); void set_special_day(void); void main(void) { const int x_skip_space = 24; const int y_skip_space = 10; int year; int month; int day = 1; // default day = 1 int first_day; int start_month; int color; set_special_day(); do{ input_data(year, month, start_month); for(int i=0; i<6; i++) { if(start_month == month) color = WHITE; else color = LIGHTGRAY; first_day = find_day(year, start_month, day); display_calendar(year, start_month++, first_day, (i%3)*x_skip_space+1, (i/3)*y_skip_space+3, color); // 下行為恢復一般二月份的正常天數 Month_Days[Feb] = 28; } printf("\nContinue..? [Y/N] :"); }while(toupper(getch()) == 'Y'); } void input_data(int &year, int &month, int &start_month) { do{ clrscr(); printf("Please Input the year and the month : "); scanf("%d %d", &year, &month); if(year>0 && month>0 && month<13) break; printf("Input error...!!!\n"); getch(); }while(1); month--; // Because array starts at 0 , not 1 start_month = ((month>=6) ? Jul : Jan); } void set_special_day(void) { Special_Day[Jan][1] = 1; Special_Day[Feb][14] = 1; Special_Day[Aug][8] = 1; Special_Day[Sep][28] = 1; Special_Day[Oct][10] = 1; Special_Day[Oct][25] = 1; Special_Day[Oct][31] = 1; Special_Day[Nov][4] = 1; // my birthday Special_Day[Nov][12] = 1; Special_Day[Dec][25] = 1; } /************************************************************************ Function: display_calendar(int year, int month, int first_day) 用來顯示月曆,需注意1752年9月 又顯示方式可利用一個迴圈由1號至月底 並設一個變數day來代表是星期幾 當day遞增至星期六時,將day改為星期日(即為數值上的0)並執行換行程式 ************************************************************************/ void display_calendar(int year, int month, int first_day, int x, int y, int color) { int number; int day = first_day; int flag = 0; /*判斷旗標,判斷是否為1752/9*/ if(year == 1752 && month == Sep) flag = 1; textcolor(color); gotoxy(x, y); cprintf(" %4d %s\n",year, Month[month]); gotoxy(x, ++y); cprintf(" Su Mo Tu We Th Fr Sa\n"); gotoxy(x+first_day*3, ++y); /*依續由1號至月底(Month_Days[month])跑下來 flag是用來檢查特例的1752/9用*/ for (number=1; number<=Month_Days[month]; number++) { if(flag) if(number > 2 && number < 14) continue; /*因1752/9沒有3~13所以跳過*/ if(day==Sum) textcolor(LIGHTRED); else if(day==Sat) textcolor(LIGHTBLUE); if(Special_Day[month][number]) textcolor(YELLOW); cprintf("%3d",number); /*以四格為單位位移量*/ day++; /*星期數遞增*/ textcolor(color); if(day > Sat) /*如超過Sat,則還原為Sum,且換行*/ { day = Sum; gotoxy(x, ++y); } } printf("\n"); } /*************************************************************************** Function: int find_day(int year, int month, int day) 回傳值為year年month月day日是星期幾 在此題中,day已內設為1(參考main中) *****************************************************************************/ int find_day(int year, int month, int day) { long delta_days = Sat; int first_day; int i = 1; for(; i < year; i++) delta_days += leap(i); /*算出由西元一年一月一日至(year-1)年所累計的天數*/ /*以下為再算出year年的年初至month月1日所經過的天數 其中,先判斷year年是否為閏年 接著判斷是否為怪怪的1752 第三部分則為將值加起來囉*/ if(leap(year) == Leap_Feb) Month_Days[Feb] = 29; if(year == 1752) { Month_Days[Feb] = 29; /*小心!1752年亦是閏年唷...!!*/ Month_Days[Sep] = 19; } for(i=0; i<(month); i++) delta_days += Month_Days[i]; Month_Days[Sep] = 30; /*以下四行可不加,因此程式還可用來求year年month月day日是星期幾 if的那一段是因為1752年9月沒有3~13號,所以要特別的計算*/ if(year == 1752 && month == Sep && day > 13) delta_days += day-12; else delta_days += day-1; /*除以7,可得星期幾*/ first_day = (int)(delta_days % 7); return(first_day); } /***************************************************************************** Function: int leap(int year) 用來判斷year年是否為閏年(要分1752年前後)或是特殊的1752年9月 ****************************************************************************/ int leap(int year) { if(year > 1752) { if(year%4 == 0 && (year%100 != 0 || year%400 == 0)) return(Leap_Feb); } else if(year < 1752) { if(year%4 == 0) return(Leap_Feb); } else if(year == 1752) { return(Special_Sep); /*Special_Sep = 5, 因為1752年是閏年,但9月只有19天(少11天) so... 1752年為 [365(一般) + 1(閏年) - 11(9月)]除以7餘5囉..^_^ */ } return(Normal_Feb); } -- 龍龍 你是一位聰明人嗎?如果是,你該記住,你的聰明是跟那些人學來的, 然後在適當的地點,適當的時間,輕輕的對那人說:這是你教我的。 聲音要輕,而且只告訴他一個人。 摘錄自"牧羊少年奇幻之旅" -- ※ 發信站: 批踢踢實業坊(ptt.twbbs.org) ◆ From: DickG.m5.ntu.edu