給定基準日期為 2007 年 10 月 17 日(星期六),輸入任意合法日期(年、月、日),程式需輸出該日期對應的星期幾;若輸入日期不合法,則輸出 "illegal"。輸入包含多組測試資料,每組佔一行,直到 EOF 結束。
採用標準規則:能被 4 整除但不能被 100 整除,或能被 400 整除的年份為閏年。
int isLeap(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
累加完整年份的天數、當年已過月份的天數,再加上當月日期,總和即為距離基準日的總天數。
for (k = 1; k < year; k++)
days += isLeap(k) ? 366 : 365;
for (j = 0; j < month; j++)
days += isLeap(year) ? year2[j] : year1[j];
days += day;
由於 2007/10/17 是星期六,若以公元元年 1 月 1 日為起點,需根據實際對應關係調整陣列順序。程式中直接以 days % 7 作為索引,對應 date[7] = {"星期日","星期一",...,"星期六"}。
for 迴圈內不可宣告變數(如 for(int i=0;...)),需在函數開頭宣告所有變數。year1、year2 陣列大小為 13,索引 1~12 對應月份,索引 0 置 0 以便迴圈累加。scanf(...) != EOF 讀取多組測資。#include
char date[7][7] = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
int isLeap(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main() {
int year, month, day;
int year1[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int year2[13] = {0,31,29,31,30,31,30,31,31,30,31,30,31};
int days, k, j;
char *getDate;
while (scanf("%d %d %d", &year, &month, &day) != EOF) {
// 合法性檢查
if (year <= 0 || year >= 10000 || month <= 0 || month >= 13 || day <= 0 || day >= 32) {
printf("illegal\n");
continue;
}
// 針對 2 月與閏年做額外檢查
if (month == 2) {
int maxDay = isLeap(year) ? year2[2] : year1[2];
if (day > maxDay) {
printf("illegal\n");
continue;
}
} else if (day > year1[month]) { // 平年月份天數同閏年(除 2 月外)
printf("illegal\n");
continue;
}
days = 0;
for (k = 1; k < year; k++)
days += isLeap(k) ? 366 : 365;
for (j = 0; j < month; j++)
days += isLeap(year) ? year2[j] : year1[j];
days += day;
getDate = date[days % 7];
printf("%s\n", getDate);
}
return 0;
}
文章附帶測試截圖顯示程式正確輸出星期資訊,並提醒在 C89 環境下編譯時需將迴圈變數移至函數頂部宣告,否則會報錯。