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

C 語言日期加一天算法:閏年判斷、月份天數表驅動與邊界條件完整處理

     編輯:關於C語言

問題:給定年月日,輸出下一天日期

核心挑戰:月份天數不固定、閏年 2 月 29 天、年底跨年(12 月 31 日 → 翌年 1 月 1 日)。

閏年判斷標準算法


bool is_leap_year(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

月份天數查表法(含閏年動態調整)


int days_in_month(int year, int month) {
    static const int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    if (month == 2 && is_leap_year(year)) return 29;
    return days[month - 1];
}

完整 C 語言實現(健壯版)


#include <stdio.h>
#include <stdbool.h>

bool is_leap_year(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

int days_in_month(int year, int month) {
    static const int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    if (month == 2 && is_leap_year(year)) return 29;
    return days[month - 1];
}

void next_day(int year, int month, int day, int* ny, int* nm, int* nd) {
    int dim = days_in_month(year, month);
    if (day < dim) {
        *ny = year; *nm = month; *nd = day + 1;
    } else { // 月底
        if (month < 12) {
            *ny = year; *nm = month + 1; *nd = 1;
        } else { // 年底
            *ny = year + 1; *nm = 1; *nd = 1;
        }
    }
}

int main() {
    int year, month, day;
    char cont;
    do {
        printf("請輸入日期 (年 月 日):");
        if (scanf("%d %d %d", &year, &month, &day) != 3) {
            printf("輸入格式錯誤\n");
            while (getchar() != '\n'); // 清空緩衝區
            continue;
        }
        // 基本驗證
        if (year < 1 || year > 9999 || month < 1 || month > 12 || day < 1 || day > days_in_month(year, month)) {
            printf("日期無效\n");
            continue;
        }
        int ny, nm, nd;
        next_day(year, month, day, &ny, &nm, &nd);
        printf("下一天:%04d-%02d-%02d\n\n", ny, nm, nd);
        printf("繼續?(y/n) ");
        scanf(" %c", &cont); // 空格跳過換行
    } while (cont == 'y' || cont == 'Y');
    return 0;
}

關鍵設計點解析

1. 表驅動消除冗長 switch

原代碼 12 個 case,現用 static const int days[12] 陣列,閏年動態修正 2 月。代碼從 40+ 行縮減至 10 行,易維護、無重複、效能更好(陣列索引 O(1))。

2. 閏年判斷獨立函數化

單一職責原則,便於單元測試、復用、修正(如儒略曆/格里曆切換)。

3. 邊界條件分層處理

  • 非月底:day + 1
  • 月底非年底:month + 1, day = 1
  • 年底:year + 1, month = 1, day = 1

邏輯清晰互斥,無遺漏無重疊。

4. 輸入驗證與錯誤恢復

  • scanf 返回值檢查(防非數字輸入死循環)
  • 範圍驗證(年 1-9999、月 1-12、日 1-當月天數)
  • getchar() 清空錯誤緩衝區

5. 格式化輸出

%04d-%02d-%02d 統一輸出 YYYY-MM-DD 格式,便於日誌/解析。

進階擴展方向

  1. 日期結構體封裝:struct Date { int y,m,d; } + 運算子多載(C++)
  2. 任意天數加減:遞歸/迭代調用 next_day,或用儒略日數轉換 O(1) 計算
  3. 星期計算:蔡勒公式 / Zeller 同餘
  4. 時區/夏令時:結合 <time.h> struct tm / time_t
  5. 農曆轉換:查表法或天文算法

測試用例驗證

輸入輸出說明
2023-01-152023-01-16普通日期
2023-01-312023-02-01大月月底
2023-02-282023-03-01平年 2 月底
2024-02-292024-03-01閏年 2 月底
2023-12-312024-01-01跨年
2000-02-292000-03-01世紀閏年
1900-02-281900-03-01世紀非閏年

全部通過,算法正確健壯。

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