摘要:[C/C++] 程式語言作業-時空旅人的萬年曆
題目的敘述如下:
倘若在宇宙中某一個異次元世界當中,有一個星球的曆法和地球一樣,包括閏年規則、每個月天數、每周天數都一樣。唯一不同的是,它們的星期幾和地球有平行的差異,舉例來說,地球的星期一在那邊可能是星期三,星期二是星期四,以此類推 (有一個等差,但不見得完全相同)。
為了方便時空旅人,於是你要寫一個給他們用的萬年曆程式,只要輸入那個世界當中某西元年 (>=1)、月 (1~12)、日 (1~當月最大天數) 與星期幾 (0~6,0表示星期天)。然後就可以透過輸入西元年和月,得知在當地該月份的月曆。
看到這樣的萬年曆變形題,我的解題概念是計算地球跟外星的offset,然後再用普通印萬年歷的方法即可完成。
除了main()以外,我定義了4個function
//判斷是否為閏年
int isLeapYear(int year);
//傳回這一天是星期幾
int getWeekday(int year, int month, int day);
int getWeekday(int year, int month, int day, int offset);
//根據輸入的year, month以及offset印出月歷
int printMonthCalendar(int year, int month, int offset);
其中判斷閏年的方法我參考閏年 - 維基百科的邏輯,在此就不贅述
int isLeapYear(int year) {
return (year%400==0) || ((year%4==0) && (year%100!=0));
}
計算星期幾的公式也是網路上找的:
W = [Y-1] + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D
int getWeekday(int year, int month, int day, int offset) {
//12個月各月的天數
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//如果是閏年,2月就多加1天變成29天
days[1] += isLeapYear(year);
//計算這一天是一年中的第幾天
int d, i;
d = day;
for (i=0; i<month-1; i++) {
d += days[i];
}
//根據公式去計算這一天是星期幾
year--;
d += year + (year/4) - (year/100) + (year/400);
d += offset + 7; //此處+7是避免d算出來是負值的情況
d %= 7; //算出星期幾
return d;
}
完整的程式碼如下
#include <stdio.h>
//判斷是否為閏年
int isLeapYear(int year);
//傳回這一天是星期幾
int getWeekday(int year, int month, int day);
int getWeekday(int year, int month, int day, int offset);
//根據輸入的year, month以及offset印出月歷
int printMonthCalendar(int year, int month, int offset);
//判斷是否為閏年
int isLeapYear(int year) {
return (year%400==0) || ((year%4==0) && (year%100!=0));
}
//傳回這一天是星期幾
int getWeekday(int year, int month, int day) {
return getWeekday(year, month, day, 0);
}
//傳回這一天是星期幾
int getWeekday(int year, int month, int day, int offset) {
//12個月各月的天數
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//如果是閏年,2月就多加1天變成29天
days[1] += isLeapYear(year);
//計算這一天是一年中的第幾天
int d, i;
d = day;
for (i=0; i<month-1; i++) {
d += days[i];
}
//根據公式去計算這一天是星期幾
year--;
d += year + (year/4) - (year/100) + (year/400);
d += offset + 7; //此處+7是避免d算出來是負值的情況
d %= 7; //算出星期幾
return d;
}
//根據輸入的year, month以及offset印出月歷
int printMonthCalendar(int year, int month, int offset) {
//12個月各月的天數
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//如果是閏年,2月就多加1天變成29天
days[1] += isLeapYear(year);
//計算這個月第一天是星期幾
int weekday = getWeekday(year, month, 1, offset);
//開始印出月歷
int i, count;
printf(" SUN MON TUE WED THU FRI SAT\n");
//印出第一週的空白
for (i=0; i<weekday; i++) {
printf("%4s", " ");
}
//印出每一天
for (i=1, count=weekday+1; i<=days[month-1]; i++, count++) {
printf("%4d", i);
//處理換行
if (count % 7 == 0) {
printf("\n");
}
}
//如果最後一天是星期六就不要再多印換行,以保持輸出的資料沒有多餘的空行
if ((count-1) %7 != 0) {
printf("\n");
}
return 0;
}
int main() {
//輸入資料
int year, month, day, weekday;
printf("輸入年月日(以空白分開): ");
scanf("%d %d %d", &year, &month, &day);
printf("輸入星期幾(0為星期日,1~6為星期一~六): ");
scanf("%d", &weekday);
//計算位移
int offset = weekday - getWeekday(year, month, day);
//讓程式可以重複輸入資料
while (1) {
printf("輸入年份和月份(輸入0 0以結束): ");
scanf("%d %d", &year, &month);
//輸入0 0就結束
if (!year & !month) {
break;
}
//印出月歷
printMonthCalendar(year, month, offset);
}
return 0;
}
文章內容僅提供技術分享,如有錯誤還請不吝指教。