輸入年、月、日,輸出該日期是當年的第幾天。需正確處理閏年與各月天數。
// 宏定義:能被 400 整除,或能被 4 整除但不能被 100 整除
#define IS_LEAP(year) (((year) % 400 == 0) || ((year) % 4 == 0 && (year) % 100 != 0))
#include <stdio.h>
int day_of_year(int year, int month, int day) {
static const int mdays[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, // 平年
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} // 閏年
};
int leap = IS_LEAP(year);
int doy = day;
for (int m = 1; m < month; ++m) {
doy += mdays[leap][m];
}
return doy;
}
int main() {
int y, m, d;
printf("請輸入日期 (年 月 日):");
if (scanf("%d %d %d", &y, &m, &d) != 3) return 1;
// 簡易合法性檢查
if (m < 1 || m > 12 || d < 1 || d > 31) {
printf("日期格式錯誤\\n");
return 1;
}
printf("%d-%02d-%02d 是 %d 年的第 %d 天\\n", y, m, d, y, day_of_year(y, m, d));
return 0;
}
利用數學公式直接計算,適合嵌入式無迴圈需求:
// 以 3/1 為年初(將 1、2 月視為上一年的 13、14 月)
int day_of_year_zeller(int y, int m, int d) {
static const int offset[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
int doy = offset[m - 1] + d;
if (m > 2 && IS_LEAP(y)) doy++; // 閏年 3 月後加 1
return doy;
}
原回答使用 switch 卻缺少 break,導致「貫穿」效果雖然湊巧算對,但極易維護出錯。且 scanf 缺少 & 取址符,dec 常數寫錯 (12 應為 31)。
scanf 回傳值檢查,非數字輸入時清空緩衝區。2024-01-01 → 1
2024-02-29 → 60 (閏年)
2023-02-28 → 59 (平年)
2024-12-31 → 366
2023-12-31 → 365
避坑提醒
❌ 不要手寫 12 個case硬算,維護噩夢。
✅ 用靜態常數陣列 + 迴圈/查表,代碼量減 80%,可讀性強。
✅ 宏定義閏年判斷加括號,防止運算子優先級陷阱。