基于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语言实现动态顺序表的实现代码的相关资料,动态顺序表在内存中开辟一块空间,可以随我们数据数量的增多来扩容,需要的朋友可以参考下
    2017-08-08
  • C++加密解密php代码的方法

    C++加密解密php代码的方法

    这篇文章主要介绍了C++加密解密php代码的方法,实例分析了基于C++实现加密解密的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • C++ 结构体初始化与赋值详解

    C++ 结构体初始化与赋值详解

    本文主要介绍了C++ 结构体初始化与赋值详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • vs2019创建WebService服务的实现

    vs2019创建WebService服务的实现

    这篇文章主要介绍了vs2019创建WebService服务的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • VisualStudio 禁用移动文件到文件夹自动修改命名空间功能

    VisualStudio 禁用移动文件到文件夹自动修改命名空间功能

    这篇文章主要介绍了VisualStudio 禁用移动文件到文件夹自动修改命名空间功能,文章底部给大家介绍了解决安装VS2022时,出现未能安装包“Microsoft.VisualCpp.Redist.14,version=14.32.31332,chip”=x86,的问题及解决方法,需要的朋友可以参考下
    2022-09-09
  • C语言实现英文文本词频统计

    C语言实现英文文本词频统计

    这篇文章主要为大家详细介绍了C语言实现英文文本词频统计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • 关于单片机按键问题性能提升总结

    关于单片机按键问题性能提升总结

    今天小编就为大家分享一篇关于关于单片机按键问题性能提升总结,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • C++ float、double判断是否等于0问题

    C++ float、double判断是否等于0问题

    这篇文章主要介绍了C++ float、double判断是否等于0问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • C++使用ffmpeg实现rtsp取流的代码

    C++使用ffmpeg实现rtsp取流的代码

    这篇文章主要介绍了C++使用ffmpeg实现rtsp取流,文章介绍了ffmepg采用rtsp取流流程图,CMakeLists.txt编写方法,通过示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • C++ CopyFile,MoveFile用法案例详解

    C++ CopyFile,MoveFile用法案例详解

    这篇文章主要介绍了C++ CopyFile,MoveFile用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09

最新评论