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

C++ 日期加一天算法錯誤:閏年判斷邏輯修正

     編輯:程式設計綜合問答

問題現象

代碼中 29/2/2001 加一天變成 30/2/2001(非法日期),而 28/2/2001 正確變為 1/3/2001。
根因在閏年判斷條件:

if (year/4==0)  // 錯誤:整除而非取模

閏年規則回顧

  1. 能被 4 整除但不能被 100 整除 → 閏年
  2. 能被 400 整除 → 閏年
  3. 其他 → 平年

2001 年:2001 % 4 = 1 → 平年,2月只有 28 天。

修正代碼

1. 修正閏年判斷函數

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

2. 重構 add_date() 邏輯

void Date::add_date() {
    // 每月天數表(平年)
    static const int daysInMonth[12] = {
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    
    int maxDay = daysInMonth[month - 1];
    // 2月閏年調整
    if (month == 2 && isLeapYear(year)) {
        maxDay = 29;
    }
    
    if (day < maxDay) {
        day++;
    } else {
        day = 1;
        if (month < 12) {
            month++;
        } else {
            month = 1;
            year++;
        }
    }
}

3. 完整類定義(現代 C++ 風格)

#include <iostream>
#include <stdexcept>

class Date {
public:
    Date(int y = 1970, int m = 1, int d = 1) : year(y), month(m), day(d) {
        if (!isValid()) throw std::invalid_argument("Invalid date");
    }
    
    void addDay() { /* 上述邏輯 */ }
    void show() const { 
        std::cout << day << '/' << month << '/' << year << '\n'; 
    }
    
private:
    int year, month, day;
    
    static bool isLeapYear(int y) {
        return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
    }
    
    bool isValid() const {
        if (month < 1 || month > 12) return false;
        static const int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
        int maxDay = days[month-1];
        if (month == 2 && isLeapYear(year)) maxDay = 29;
        return day >= 1 && day <= maxDay;
    }
};

測試驗證

int main() {
    Date d1(2001, 2, 28); d1.addDay(); d1.show(); // 1/3/2001
    Date d2(2000, 2, 28); d2.addDay(); d2.show(); // 29/2/2000 (閏年)
    Date d3(2000, 2, 29); d3.addDay(); d3.show(); // 1/3/2000
    Date d4(2023, 12, 31); d4.addDay(); d4.show(); // 1/1/2024
    return 0;
}

避坑總結

錯誤寫法正確寫法說明
year/4==0year%4==0整除 vs 取模
硬編碼每月天數判斷查表法 + 閏年調整減少重複代碼,易維護
無輸入驗證構造函數驗證合法性防止非法日期對象創建

日期計算看似簡單,邊界條件極多(閏年、月末、年末、閏秒等),生產環境建議使用成熟庫(C++20 <chrono>、Howard Hinnant's date、Boost.Date_Time),避免重複造輪子引入 Bug。

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