首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言問答

C 語言經典習題:計算某年某月某日是當年的第幾天

     編輯:C 語言問答

題目重述

輸入年、月、日,輸出該日期是當年的第幾天。需正確處理閏年與各月天數。

閏年判斷規則

// 宏定義:能被 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;
}

解法二:Zeller 公式 / 積日法(進階,無需迴圈)

利用數學公式直接計算,適合嵌入式無迴圈需求:

// 以 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 版本的缺陷與修正

原回答使用 switch 卻缺少 break,導致「貫穿」效果雖然湊巧算對,但極易維護出錯。且 scanf 缺少 & 取址符,dec 常數寫錯 (12 應為 31)。

工程化建議

  1. 輸入驗證:檢查月份 1-12、日期合法性(含閏年 2 月 29 日)。
  2. 錯誤處理:scanf 回傳值檢查,非數字輸入時清空緩衝區。
  3. 模組化:將核心邏輯封裝為函數,方便單元測試。
  4. 測試用例:
    2024-01-01 → 1
    2024-02-29 → 60 (閏年)
    2023-02-28 → 59 (平年)
    2024-12-31 → 366
    2023-12-31 → 365
    

避坑提醒
❌ 不要手寫 12 個 case 硬算,維護噩夢。
✅ 用靜態常數陣列 + 迴圈/查表,代碼量減 80%,可讀性強。
✅ 宏定義閏年判斷加括號,防止運算子優先級陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved