基于C++实现一个日期计算器

 更新时间:2022年10月10日 08:27:04   作者:蒋灵瑜的笔记本  
这篇文章主要为大家详细介绍了如何利用C++实现一个简单的日期计算器,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下

一、日期计算器的功能

实现日期类的==、!=、+=、+、-=、-、>=、>、<=、<、前置++和--、后置++和--。

二、获取每个月的天数

int GetMonthDay(int year, int month)
{
    //静态数组,每次调用不用频繁在栈区创建数组
    static int monthArr[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
    //判断是否闰年
    int day = monthArr[month - 1];
    if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
    {
        day = 29;
    }
    return day;
}

1、因为GetMonthDay这个函数需要在日期类中被频繁调用,所以将 monthArr存放至静态区,减少数组频繁开辟、销毁空间的开销。

三、Date类中的默认成员函数

1、构造函数

Date(int year = 1, int month = 1, int day = 1)
{
    if (year >= 1 && month >= 1 && day >= 1 && day <= GetMonthDay(year, month))
    {
        _year = year;
        _month = month;
        _day = day;
        //cout << "构造成功" << endl;
    }
    else
    {
        cout << "日期不合法" << endl;
    }
}

日期类的构造函数需要对日期的的合法性进行判断。

2、析构函数

~Date()//可不写
{
    ;
}

日期类因为没有申请资源(动态开辟空间、文件的打开等),所以无需写析构函数,系统默认生成的就可以。

3、拷贝构造

Date(const Date& d)//可不写
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
    //cout << "拷贝构造成功" << endl;
}

系统默认生成的拷贝构造函数会对内置类型完成浅拷贝,所以内置类型也可以不用写,用系统默认生成的就可以。

4、赋值运算符重载

Date& operator=(Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
    //cout << "赋值成功" << endl;
    return *this;
}

也可不写,使用系统默认生成的即可。

拷贝构造和赋值运算符重载的区别在于拷贝构造用于对象构造时使用,而赋值运算符重载用于已存在对象赋值时使用。

四、运算符重载

1、+=、+、-=、-

Date& operator+=(int day)
{
    if (day < 0)
        *this -= -day;
    else
    {
        _day += day;
        while (_day > GetMonthDay(_year, _month))
        {
            _day -= GetMonthDay(_year, _month);
            ++_month;
            if (_month > 12)
            {
                _month = 1;
                ++_year;
            }
        }
    }
    return *this;
}
Date operator+(int day)
{
    Date tmp(*this);
    return tmp += day;
}
Date& operator-=(int day)
{
    if (day < 0)
        *this += -day;
    else
    {
        _day -= day;
        while (_day <= 0)
        {
            --_month;
            if (_month <= 0)
            {
                _month = 12;
                --_year;
            }
            _day += GetMonthDay(_year, _month);
        }
    }
    return *this;
}
Date operator-(int day)
{
    Date tmp(*this);
    return tmp -= day;
}
//日期减日期
int operator-(const Date& d)
{
    Date tmpThis = *this, tmpDay = d;
    int count = 0;//用于计数
    if (*this >= d)
    {
        while (tmpDay != tmpThis)
        {
            ++tmpDay;
            ++count;
        }
    }
    else
    {
        while (tmpDay != tmpThis)
        {
            ++tmpThis;
            --count;
        }
    }
    return count;
}

1、注意这几个运算符要防止外部传入的day是负数。例如+=传入的参数如果是负数,则去调用-=函数。

2、注意传值返回和传引用返回,当return对象出了作用域还存在时,可以用传引用返回,减少一次拷贝构造。

3、实现完+=、-=后,+、-运算符可复用逻辑。

2、==、!=、>、>=、<、<=

bool operator==(const Date& d)
    {
        if (_year == d._year && _month == d._month && _day == d._day)
        {
            return true;
        }
        return false;
    }
    bool operator>(const Date& d)
    {
        if (_year > d._year)
            return true;
        if (_year == d._year && _month > d._month)
            return true;
        if (_year == d._year && _month == d._month && _day > d._day)
            return true;
        return false;
    }
    bool operator>=(const Date& d)
    {
        return *this > d || *this == d;
    }
    bool operator!=(const Date& d)
    {
        return !(*this == d);
    }
    bool operator<(const Date& d)
    {
        return !(*this >= d);
    }
    bool operator<=(const Date& d)
    {
        return !(*this > d);
    }

1、注意右操组数一定要加上&,减少一次传参时的拷贝构造;再加上const,防止被引用的对象被改变。

2、写完==和>函数,其他运算符都可以复用逻辑。

3、前置++和--、后置++和--

Date& operator++()
    {
        ++_day;
        if (_day > GetMonthDay(_year, _month))
        {
            _day = 1;
            ++_month;
            if (_month > 12)
            {
                _month = 1;
                ++_year;
            }
        }
        return *this;
    }
    Date operator++(int)
    {
        Date tmp(*this);
        ++* this;
        return tmp;
    }
    Date& operator--()
    {
        --_day;
        if (_day <= 0)
        {
            --_month;
            if (_month == 0)
            {
                _month = 12;
                --_year;
            }
            _day += GetMonthDay(_year, _month);
        }
        return *this;
    }
    Date operator--(int)
    {
        Date tmp(*this);
        --* this;
        return tmp;
    }

1、因为++和--是单操作数的运算符,在重载时,无法区分是前置的重载还是后置的重载,所以C++规定:前置重载与普通运算符重载一致,后置重载需要在参数列表中加入一个无用的参数。这个参数必须是int类型(用别的类型编译器报错)。

2、前置++--可以使用传引用返回,但后置++--因为返回值暂时不改变,所以只能传值返回。这也是使用前置++--性能优于后置++--的原因。

五、日期类代码

class Date
{
public:
    void Print()
    {
        cout << _year << " " << _month << " " << _day << endl;
    }
    int GetMonthDay(int year, int month)
    {
        //静态数组,每次调用不用频繁在栈区创建数组
        static int monthArr[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
        //判断是否闰年
        int day = monthArr[month - 1];
        if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
        {
            day = 29;
        }
        return day;
    }
    //构造函数
    Date(int year = 1, int month = 1, int day = 1)
    {
        if (year >= 1 && month >= 1 && day >= 1 && day <= GetMonthDay(year, month))
        {
            _year = year;
            _month = month;
            _day = day;
            //cout << "构造成功" << endl;
        }
        else
        {
            cout << "日期不合法" << endl;
        }
    }
    //析构函数
    ~Date()
    {
        cout << "析构成功" << endl;;
    }
    //拷贝构造
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
        cout << "拷贝构造成功" << endl;
    }
    ////赋值运算符重载
    Date& operator=(Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
        cout << "赋值成功" << endl;
        return *this;
    }
    //运算符重载
    Date& operator+=(int day)
    {
        if (day < 0)
            *this -= -day;
        else
        {
            _day += day;
            while (_day > GetMonthDay(_year, _month))
            {
                _day -= GetMonthDay(_year, _month);
                ++_month;
                if (_month > 12)
                {
                    _month = 1;
                    ++_year;
                }
            }
        }
        return *this;
    }
    Date operator+(int day)
    {
        Date tmp(*this);
        return tmp += day;
    }
    Date& operator-=(int day)
    {
        if (day < 0)
            *this += -day;
        else
        {
            _day -= day;
            while (_day <= 0)
            {
                --_month;
                if (_month <= 0)
                {
                    _month = 12;
                    --_year;
                }
                _day += GetMonthDay(_year, _month);
            }
        }
        return *this;
    }
    Date operator-(int day)
    {
        Date tmp(*this);
        return tmp -= day;
    }
    int operator-(const Date& d)
    {
        Date tmpThis = *this, tmpDay = d;
        int count = 0;//用于计数
        if (*this >= d)
        {
            while (tmpDay != tmpThis)
            {
                ++tmpDay;
                ++count;
            }
        }
        else
        {
            while (tmpDay != tmpThis)
            {
                ++tmpThis;
                --count;
            }
        }
        return count;
    }
    bool operator==(const Date& d)
    {
        if (_year == d._year && _month == d._month && _day == d._day)
        {
            return true;
        }
        return false;
    }
    bool operator>(const Date& d)
    {
        if (_year > d._year)
            return true;
        if (_year == d._year && _month > d._month)
            return true;
        if (_year == d._year && _month == d._month && _day > d._day)
            return true;
        return false;
    }
    bool operator>=(const Date& d)
    {
        return *this > d || *this == d;
    }
    bool operator!=(const Date& d)
    {
        return !(*this == d);
    }
    bool operator<(const Date& d)
    {
        return !(*this >= d);
    }
    bool operator<=(const Date& d)
    {
        return !(*this > d);
    }
    Date& operator++()
    {
        ++_day;
        if (_day > GetMonthDay(_year, _month))
        {
            _day = 1;
            ++_month;
            if (_month > 12)
            {
                _month = 1;
                ++_year;
            }
        }
        return *this;
    }
    Date operator++(int)
    {
        Date tmp(*this);
        ++* this;
        return tmp;
    }
    Date& operator--()
    {
        --_day;
        if (_day <= 0)
        {
            --_month;
            if (_month == 0)
            {
                _month = 12;
                --_year;
            }
            _day += GetMonthDay(_year, _month);
        }
        return *this;
    }
    Date operator--(int)
    {
        Date tmp(*this);
        --* this;
        return tmp;
    }
private:
    int _year;
    int _month;
    int _day;
};

因为函数的声明和定义全部放在类中,会被编译器当成内联函数处理。所以可以根据自身需要,将部分调用不频繁、稍长的函数的声明写在类中,而定义写在类外。

到此这篇关于基于C++实现一个日期计算器的文章就介绍到这了,更多相关C++日期计算器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++初阶教程之类和对象

    C++初阶教程之类和对象

    C++是面向对象编程的,这也是C++与C语言的最大区别,而类和对象就是C++面向对象的基础,下面这篇文章主要给大家介绍了关于C++初阶教程之类和对象的相关资料,需要的朋友可以参考下
    2022-02-02
  • C++ 学习之旅二 说一说C++头文件

    C++ 学习之旅二 说一说C++头文件

    作为一个二手的.net程序员,你看到了C++头文件一定就犯迷糊了,这到底是个啥玩意。再我纠结了24个小时, google20次,度娘10下,看过10来骗文章以后,我可能稍微开窍了。我对C++头文件总结,与.net比较如下
    2012-11-11
  • Qt向ini文件写入中文出现乱码问题的解决方法详解

    Qt向ini文件写入中文出现乱码问题的解决方法详解

    这篇文章主要为大家详细介绍了当Qt向ini文件写入中文出现乱码问题时的解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • 浅析string类字符串和C风格字符串之间的区别

    浅析string类字符串和C风格字符串之间的区别

    string类是标准库的类,并不是内置类型,标准库就像是我们自己定义的类差不多的,string类型对象没有标配'\0'结尾的
    2013-09-09
  • C++中mutable与volatile的深入理解

    C++中mutable与volatile的深入理解

    这篇文章主要给的阿加介绍了关于C++中mutable与volatile的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • 通俗易懂的C语言快速排序和归并排序的时间复杂度分析

    通俗易懂的C语言快速排序和归并排序的时间复杂度分析

    这篇文章主要为大家通俗易懂的讲解了C语言快速排序和归并排序的时间复杂度分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • C++ vector 遍历的几种方法

    C++ vector 遍历的几种方法

    本文主要介绍了C++ vector 遍历的几种方法,对vector 遍历有一定的总结,具有一定的参考价值,感兴趣的可以了解一下
    2021-07-07
  • C++入门基础之命名空间、输入输出和缺省参数

    C++入门基础之命名空间、输入输出和缺省参数

    C++入门基础篇的内容为C++的基本特性,只有在掌握C++的基本特性后,是进入后面类和对象学习的基础,下面这篇文章主要给大家介绍了关于C++入门基础之命名空间、输入输出和缺省参数的相关资料,需要的朋友可以参考下
    2023-01-01
  • C/C++函数参数传递机制详解及实例

    C/C++函数参数传递机制详解及实例

    这篇文章主要介绍了C/C++函数参数传递机制详解及实例的相关资料,需要的朋友可以参考下
    2017-02-02
  • C++浅析构造函数的特性

    C++浅析构造函数的特性

    构造函数主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用;析构函数主要作用在于对象销毁前系统自动调用,执行一 些清理工作
    2022-07-07

最新评论