萬年曆的核心在於任意給定年、月、日,快速計算該日是星期幾,以及該月份天數。關鍵演算法包括:
w = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7(月份視 3=3月…14=翌年2月,1、2 月視為上一年 13、14 月)。// 各月標準天數,索引 0 代表 1 月
int monthDays[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
// 閏年時 2 月調整為 29 天
int getMonthDays(int year, int month) {
if (month == 2 && isLeapYear(year)) return 29;
return monthDays[month-1];
}
#include <stdio.h>
#include <stdlib.h>
// 閏年判斷
int isLeapYear(int year) {
return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}
// 取得某年某月天數
int getMonthDays(int year, int month) {
static const int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
if (month == 2 && isLeapYear(year)) return 29;
return days[month-1];
}
// 蔡勒公式計算星期 (0=日, 1=一, ..., 6=六)
int getWeekDay(int year, int month, int day) {
if (month < 3) { month += 12; year--; }
int w = (day + 2*month + 3*(month+1)/5 + year + year/4 - year/100 + year/400) % 7;
return (w + 7) % 7; // 確保非負
}
// 列印指定年月曆表
void printMonthCalendar(int year, int month) {
const char *weekNames[] = {"日","一","二","三","四","五","六"};
int firstWeekDay = getWeekDay(year, month, 1);
int days = getMonthDays(year, month);
printf("\n %d 年 %2d 月\n", year, month);
printf("===========================\n");
for (int i=0; i<7; i++) printf("%3s", weekNames[i]);
printf("\n");
// 印出第一天前的空格
for (int i=0; i 12) {
printf("月份錯誤!\n");
return 1;
}
printMonthCalendar(year, month);
return 0;
}
printMonthCalendar,加入分頁邏輯。(w%7+7)%7 修正。