实现数据成员仅为 '自 1970 年 1 月 1 日以来的天数' ,满足下面接口的类 Date,并进行测试。

class Date {

private:

    static Date default_date;   //缺省日期

     ....... 其他你认为必要的数据成员

public:

    class Bad_date {};  //可选,成员类,用于采用“异常”策略向调用者报告错误

    static void set_default(); //为缺省参数赋值

    static bool leap_year(int year);//判断闰年

    Date(int dd = 0, int mm = 0, int year = 0);  //带有默认参数的构造函数

    Date& add_year(int n);  //自增 n 年,返回对象自身

    Date& add_month(int n); //自增 n 月,返回对象自身

    Date& add_day(int n); //自增 n 日,返回对象自身

    int day()const;//返回日

    int year()const;//返回年份

    int month()const;//返回月份

    int week()const;//返回这一天是星期几

    ..... 其他你认为必要的接口操作声明 ......

};

解:

我们需要实现一个 Date 类,数据成员仅为 '自 1970 年 1 月 1 日以来的天数'。这个数据成员可以用一个整数表示,比如 days_since_1970_01_01。同时,我们应该在类内部定义一个缺省日期,以及一些成员函数,比如判断闰年、增加年月日等操作,以及获取年月日、星期几等操作。

下面是一个可能的实现:

#include <iostream>
#include <stdexcept>

class Date {
private:
    static const int days_per_week = 7;  //一周有7天
    static const int days_per_normal_year = 365;  //一年有365天
    static const int days_per_leap_year = 366;  //一个闰年有366天
    static const int days_since_1970_01_01 = 719528;  //1970年1月1日距离公元0年1月1日的天数

    static Date default_date;  //缺省日期

    int days_since_1970_01_01_;  //自1970年1月1日以来的天数

    int get_days_per_month(int year, int month) const;  //获取某个月的天数
    bool is_leap_year(int year) const;  //判断是否为闰年

public:
    class Bad_date {};  //可选,成员类,用于采用“异常”策略向调用者报告错误

    static void set_default();  //为缺省参数赋值

    static bool leap_year(int year);  //判断闰年

    Date(int dd = default_date.day(), int mm = default_date.month(), int yyyy = default_date.year());  //带有默认参数的构造函数

    Date& add_year(int n);  //自增 n 年,返回对象自身

    Date& add_month(int n);  //自增 n 月,返回对象自身

    Date& add_day(int n);  //自增 n 日,返回对象自身

    int day() const;  //返回日

    int year() const;  //返回年份

    int month() const;  //返回月份

    int week() const;  //返回这一天是星期几

    friend std::ostream& operator<<(std::ostream& os, const Date& date);  //输出日期

    friend bool operator==(const Date& lhs, const Date& rhs);  //判断是否相等
};

Date Date::default_date(1, 1, 1970);

void Date::set_default() {
    default_date = Date(1, 1, 1970);
}

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

int Date::get_days_per_month(int year, int month) const {
    switch (month) {
        case 2:
            return is_leap_year(year) ? 29 : 28;
        case 4:
        case 6:
        case 9:
        case 11:
            return 30;
        default:
            return 31;
    }
}

bool Date::is_leap_year(int year) const {
    return leap_year(year);
}

Date::Date(int dd, int mm, int yyyy) {
    if (yyyy < 1970 || mm < 1 || mm > 12 || dd < 1 || dd > get_days_per_month(yyyy, mm)) {
        throw Bad_date{};
    }
    int days_since_0000_01_01 = (yyyy - 1) * days_per_normal_year + (yyyy - 1) / 4 - (yyyy - 1) / 100 + (yyyy - 1) / 400;
    for (int i = 1; i < mm; ++i) {
        days_since_0000_01_01 += get_days_per_month(yyyy, i);
    }
    days_since_0000_01_01 += dd - 1;
    days_since_1970_01_01_ = days_since_0000_01_01 - days_since_1970_01_01;
}

Date& Date::add_year(int n) {
    int yyyy = year();
    if (n > 0) {
        while (n > 0) {
            days_since_1970_01_01_ += is_leap_year(yyyy) ? days_per_leap_year : days_per_normal_year;
            ++yyyy;
            --n;
        }
    } else if (n < 0) {
        while (n < 0) {
            days_since_1970_01_01_ -= is_leap_year(yyyy - 1) ? days_per_leap_year : days_per_normal_year;
            --yyyy;
            ++n;
        }
    }
    return *this;
}

Date& Date::add_month(int n) {
    int yyyy = year();
    int mm = month();
    if (n > 0) {
        while (n > 0) {
            int days_in_month = get_days_per_month(yyyy, mm);
            days_since_1970_01_01_ += days_in_month;
            ++mm;
            if (mm > 12) {
                mm = 1;
                ++yyyy;
            }
            --n;
        }
    } else if (n < 0) {
        while (n < 0) {
            --mm;
            if (mm < 1) {
                mm = 12;
                --yyyy;
            }
            int days_in_month = get_days_per_month(yyyy, mm);
            days_since_1970_01_01_ -= days_in_month;
            ++n;
        }
    }
    return *this;
}

Date& Date::add_day(int n) {
    days_since_1970_01_01_ += n;
    return *this;
}

int Date::day() const {
    int days_since_0000_01_01 = days_since_1970_01_01_ + days_since_1970_01_01;
    int yyyy = 1;
    while (days_since_0000_01_01 >= (is_leap_year(yyyy) ? days_per_leap_year : days_per_normal_year)) {
        days_since_0000_01_01 -= is_leap_year(yyyy) ? days_per_leap_year : days_per_normal_year;
        ++yyyy;
    }
    int mm = 1;
    while (days_since_0000_01_01 >= get_days_per_month(yyyy, mm)) {
        days_since_0000_01_01 -= get_days_per_month(yyyy, mm);
        ++mm;
    }
    return days_since_0000_01_01 + 1;
}

int Date::year() const {
    int days_since_0000_01_01 = days_since_1970_01_01_ + days_since_1970_01_01;
    int yyyy = 1;
    while (days_since_0000_01_01 >= (is_leap_year(yyyy) ? days_per_leap_year : days_per_normal_year)) {
        days_since_0000_01_01 -= is_leap_year(yyyy) ? days_per_leap_year : days_per_normal_year;
        ++yyyy;
    }
    return yyyy;
}

int Date::month() const {
    int days_since_0000_01_01 = days_since_1970_01_01_ + days_since_1970_01_01;
    int yyyy = 1;
    while (days_since_0000_01_01 >= (is_leap_year(yyyy) ? days_per_leap_year : days_per_normal_year)) {
        days_since_0000_01_01 -= is_leap_year(yyyy) ? days_per_leap_year : days_per_normal_year;
        ++yyyy;
    }
    int mm = 1;
    while (days_since_0000_01_01 >= get_days_per_month(yyyy, mm)) {
        days_since_0000_01_01 -= get_days_per_month(yyyy, mm);
        ++mm;
    }
    return mm;
}

int Date::week() const {
    return (days_since_1970_01_01_ + 4) % days_per_week + 1;
}

std::ostream& operator<<(std::ostream& os, const Date& date) {
    os << date.year() << '-' << date.month() << '-' << date.day();
    return os;
}

bool operator==(const Date& lhs, const Date& rhs) {
    return lhs.days_since_1970_01_01_ == rhs.days_since_1970_01_01_;
}

测试代码:

#include <iostream>

int main() {
    Date d1;  //使用缺省日期
    std::cout << d1 << std::endl;  //1970-1-1
    Date d2(31, 12, 2021);  //指定日期
    std::cout << d2 << std::endl;  //2021-12-31
    Date d3(29, 2, 2020);  //闰年的2月29日
    std::cout << d3 << std::endl;  //2020-2-29
    try {
        Date d4(29, 2, 2021);  //非闰年的2月29日,应该抛出异常
    } catch (const Date::Bad_date&) {
        std::cout << 'Bad date' << std::endl;
    }
    d2.add_year(1).add_month(-1).add_day(2);  //2022-11-2
    std::cout << d2 << std::endl;
    Date d5 = d2.add_year(1);  //2023-11-2
    std::cout << d2 << std::endl;
    std::cout << d5 << std::endl;
    std::cout << (d2 == d5) << std::endl;  //0
    Date d6 = d2;  //拷贝构造函数
    std::cout << (d2 == d6) << std::endl;  //1
    return 0;
}
C++ Date 类实现:仅使用自 1970 年 1 月 1 日以来的天数作为数据成员

原文地址: https://www.cveoy.top/t/topic/nKn5 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录