文章目录
日期类
我们要有一个习惯就是写代码或者是写项目的时候我们要写一点编一点,要养成良好的习惯,万万不可以写完了再编,然后出了一堆错误自己都不想看,我们先自己编个最小项目或者系统框架在加其他功能
Date.h
Date.h
就是一些头文件,声明啥的
#pragma once #include <iostream> using std::cout; using std::cin; using std::endl; class Date { public: Date(int year = 0, int month = 1, int day = 1); void Print(); //像析构,拷贝构造,赋值重载可以不需要写,因为默认生成的就够用了, //像Stack才需要自己写这三个 //日期加 减天数 Date operator+(const int& day); Date operator-(const int& day); private: int _year; int _month; int _day; };
Date.cpp
Date.cpp
这里面就是写日期类的函数了
#include "Date.h" Date::Date(int year, int month, int day) { _year = year; _month = month; _day = day; } void Date::Print() { cout << _year << "年" << _month << "月" << _day << "日" << endl; } Date Date::operator+(const int& day) { return *this; } Date Date::operator-(const int& day) { return *this; }
test.cpp
test.cpp
#include "Date.h" int main() { Date d(2022,1,1); d.Print(); return 0; }
测试情况
功能添加
当我们能基本丐版跑出来了那我们接下来的路还是要走的,我们要考虑到数据是否合理啊什么的
所以我们需要检查日期的合法性
上面的确是排除了百分之99的滤掉了,但是闰年2月是特殊考虑的反而没有代码实现
我们可不可以优化一下,比如我就输错了一个日期你就直接程序死了是不是有点太霸道了,你应该抛出异常,或隔一下啥的
inline int GetMonthDay(int year, int month) { //数组存放平年每个月的天数 刚好对应的下标是月 里面的元素是天 static int dayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; //该月天数 int day = dayArray[month]; //闰年是4年一润百年不润或者四百年一润 if (month == 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { //闰年的2月是29天 day = 29; } return day; } Date::Date(int year, int month, int day) { //检查日期的合法性 if (year > 0 && month > 0 && month <13 && day > 0 && day <= GetMonthDay(year,month)) { _year = year; _month = month; _day = day; } else { cout << endl; cout << "非法日期" << endl; cout << year << "年" << month << "月" << day << "日" << endl; } } void Date::Print() { cout << _year << "年" << _month << "月" << _day << "日" << endl; }
日期加天数后那个日期
Date& Date::operator+=(const int& day) { //我们先不管,我们先直接把天加上去 _day += day; //然后再判断合不合法 while (_day > GetMonthDay(_year,_month)) { //先把当月的天数减掉 _day -= GetMonthDay(_year, _month); //然后月++ _month++; //假如月也过了就年++ if (_month > 12) { _year++; _month = 1; } } return *this; }
日期加天数
仅仅就是加没有赋值过去,要和上面那个分清了,所以我需要一个中间临时变量(这个我们叫临时对象)来存储运算后的数据
//日期加天数 不赋回去 Date Date::operator+(const int& day) { //首先创建一个临时对象 先把之前的拷贝复制给他 Date ret(*this); //复用+= ret += day; return ret; }
日期++,++日期
日期加加和加加日期都是++,但是operator运算符重载怎么区分呢,
前置++
前置++返回运算以后的值
//++d 日期前置++ 被转换成d.operator++(&d) Date& Date::operator++() { //返回运算后的值 *this += 1; return *this; }
后置++
后置++返回运算前的值
//d++ 日期后置++ 被转换成d.operator++(&d,0) //这里的int仅仅是占位,不需要给实参,起到函数重载的作用 Date& Date::operator++(int) { //后置++返回运算前的值 //所以需要一个临时对象先存起来 Date tmp(*this); *this += 1; return tmp; }
日期减天数后那个日期
//日期减天数同时赋回去 Date& Date::operator-=(const int& day) { //啥也不多说,先把天减掉 _day -= day; //不合法就等他合法 while (_day <= 0) { //先把月减了 _month--; //先判断月是不是零,是的话就操作年了 if (_month <= 0) { _year--; _month = 12; } //然后让他加上正确的月的天数 _day += GetMonthDay(_year,_month); } return *this; }
日期减天数
复用上面那个函数就行
//日期减天数 不赋回去 Date Date::operator-(const int& day) { Date ret(*this); //-=的复用 ret -= day; return ret; }
日期–,--日期
日期减减和减减日期都是–,但是operator运算符重载怎么区分呢,
前置–
前置–返回运算以后的值
//前置减减 Date& Date::operator--() { *this -= 1; return *this; }
后置–
后置–返回运算前的值
//后置减减 Date& Date::operator--(int) { Date tmp(*this); *this -= 1; return tmp; }
修一修bug
若是-=里面的日期是负数的话
我们有时候是需要考虑日期里面是有负数的
所以需要我们改一下代码,需要+=的代码,直接挪用
复用即可
//日期减天数同时赋回去 Date& Date::operator-=(const int& day) { //每月天数超过他本身了也是违法的 //复用+=即可 if (day < 0) { *this += -day; } else { //啥也不多说,先把天减掉 _day -= day; //不合法就等他合法 while (_day <= 0) { //先把月减了 _month--; //先判断月是不是零,是的话就操作年了 if (_month <= 0) { _year--; _month = 12; } //然后让他加上正确的月的天数 _day += GetMonthDay(_year, _month); } } return *this; }
若是+=里面的日期是负数的话
同样的+=里面有负数也是一样的处理
所以我们也把-=的代码拎过来
同理复用即可
//日期加天数同时赋回去 Date& Date::operator+=(const int& day) { //负数复用-=的 if (day < 0) { *this -= -day; } else { //我们先不管,我们先直接把天加上去 _day += day; //然后再判断合不合法 while (_day > GetMonthDay(_year, _month)) { //先把当月的天数减掉 _day -= GetMonthDay(_year, _month); //然后月++ _month++; //假如月也过了就年++ if (_month > 12) { _year++; _month = 1; } } } return *this; }
比较运算符
大于 >
d1 > d2
//比较 //大于 d1 > d2转换成d1.operator>(&d1,d2) bool Date::operator>(const Date& d) { if (_year > d._year) { return true; } else if (_year == d._year) { if (_month > d._month) { return true; } else if(_month == d._month) { if (_day > d._day) return true; } } //不是上面情况就false return false; }
等于 ==
d1 == d2
//等于 bool Date::operator==(const Date& d) { return _year == d._year && _month == d._month && _day == d._day; }
大于等于 >=
d1 >= d2
//大于等于 bool Date::operator>=(const Date& d) { return *this > d || *this == d; }
小于<
d1 < d2
//小于 bool Date::operator<(const Date& d) { return !(*this >= d); }
小于等于 <=
d1 <= d2
//小于等于 bool Date::operator<=(const Date& d) { return !(*this > d); }
不等于 !=
d1 != d2
//不等于 bool Date::operator!=(const Date& d) { return !(*this == d); }
生活实际
我们思考一个问题就是日期减日期有没有意义
日期减日期是不是就是相差多少天,那你这个怎么操作呢
//日期减日期 //通过计数的方式来 要是年减年 月减月就是无法找到实际多少天了 int Date::operator-(const Date& d) { //首先假设前面的大 Date max = *this; //所以后面的就小 Date min = d; //符号标记 int flag = 1; //如果错了就交换 if (max < min) { max = d; min = *this; flag = -1; } //当min与max相同时就是停止计数的时候 int count = 0; while (min != max) { min++; count++; } //出来就把计数返回出去顺带着标记 return count * flag; }
代码
Date.h
Date.h
#pragma once #include <iostream> #include <assert.h> using std::cout; using std::cin; using std::endl; class Date { public: Date(int year = 0, int month = 1, int day = 1); void Print(); //像析构,拷贝构造,赋值重载可以不需要写,因为默认生成的就够用了, //像Stack才需要自己写这三个 //日期加 减天数 然后同时赋值赋过去 Date& operator+=(const int& day); Date& operator-=(const int& day); //日期加 减天数 不需要赋值 Date operator+(const int& day); Date operator-(const int& day); //日期前置后置加加 Date& operator++(); Date& operator++(int); //日期前置后置减减 Date& operator--(); Date& operator--(int); //比较 bool operator>(const Date& d); bool operator<(const Date& d); bool operator>=(const Date& d); bool operator<=(const Date& d); bool operator==(const Date& d); bool operator!=(const Date& d); //日期减日期 int operator-(const Date& d); private: int _year; int _month; int _day; };
Date.cpp
Date.cpp
#include "Date.h" inline int GetMonthDay(int year, int month) { //数组存放平年每个月的天数 刚好对应的下标是月 里面的元素是天 static int dayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; //该月天数 int day = dayArray[month]; //闰年是4年一润百年不润或者四百年一润 if (month == 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { //闰年的2月是29天 day = 29; } return day; } //构造函数 Date::Date(int year, int month, int day) { //检查日期的合法性 if (year > 0 && month > 0 && month <13 && day > 0 && day <= GetMonthDay(year,month)) { _year = year; _month = month; _day = day; } else { cout << endl; cout << "非法日期" << endl; cout << year << "年" << month << "月" << day << "日" << endl; } } //日期打印 void Date::Print() { cout << _year << "年" << _month << "月" << _day << "日" << endl; } //日期加天数同时赋回去 Date& Date::operator+=(const int& day) { //负数复用-=的 if (day < 0) { *this -= -day; } else { //我们先不管,我们先直接把天加上去 _day += day; //然后再判断合不合法 while (_day > GetMonthDay(_year, _month)) { //先把当月的天数减掉 _day -= GetMonthDay(_year, _month); //然后月++ _month++; //假如月也过了就年++ if (_month > 12) { _year++; _month = 1; } } } return *this; } //日期加天数 不赋回去 Date Date::operator+(const int& day) { //首先创建一个临时对象 先把之前的拷贝复制给他 Date ret(*this); //复用+= ret += day; return ret; } //++d 日期前置++ 被转换成d.operator++(&d) Date& Date::operator++() { //返回运算后的值 *this += 1; return *this; } //d++ 日期后置++ 被转换成d.operator++(&d,0) //这里的int仅仅是占位,不需要给实参,起到函数重载的作用 Date& Date::operator++(int) { //后置++返回运算前的值 //所以需要一个临时对象先存起来 Date tmp(*this); *this += 1; return tmp; } //日期减天数同时赋回去 Date& Date::operator-=(const int& day) { //每月天数超过他本身了也是违法的 //复用+=即可 if (day < 0) { *this += -day; } else { //啥也不多说,先把天减掉 _day -= day; //不合法就等他合法 while (_day <= 0) { //先把月减了 _month--; //先判断月是不是零,是的话就操作年了 if (_month <= 0) { _year--; _month = 12; } //然后让他加上正确的月的天数 _day += GetMonthDay(_year, _month); } } return *this; } //日期减天数 不赋回去 Date Date::operator-(const int& day) { Date ret(*this); //-=的复用 ret -= day; return ret; } //前置减减 Date& Date::operator--() { *this -= 1; return *this; } //后置减减 Date& Date::operator--(int) { Date tmp(*this); *this -= 1; return tmp; } //比较 //大于 d1 > d2转换成d1.operator>(&d1,d2) bool Date::operator>(const Date& d) { if (_year > d._year) { return true; } else if (_year == d._year) { if (_month > d._month) { return true; } else if(_month == d._month) { if (_day > d._day) return true; } } //不是上面情况就false return false; } //等于 bool Date::operator==(const Date& d) { return _year == d._year && _month == d._month && _day == d._day; } //大于等于 bool Date::operator>=(const Date& d) { return *this > d || *this == d; } //小于 bool Date::operator<(const Date& d) { return !(*this >= d); } //小于等于 bool Date::operator<=(const Date& d) { return !(*this > d); } //不等于 bool Date::operator!=(const Date& d) { return !(*this == d); } //日期减日期 //通过计数的方式来 要是年减年 月减月就是无法找到实际多少天了 int Date::operator-(const Date& d) { //首先假设前面的大 Date max = *this; //所以后面的就小 Date min = d; //符号标记 int flag = 1; //如果错了就交换 if (max < min) { max = d; min = *this; flag = -1; } //当min与max相同时就是停止计数的时候 int count = 0; while (min != max) { min++; count++; } //出来就把计数返回出去顺带着标记 return count * flag; }
test.cpp
test.cpp
#include "Date.h" void test1() { //前置++和后置++都完成++,不同的地方在于是返回值不同 Date d(2022, 1, 1); d ++; //后置++返回++以前的值 d.Print(); ++d; //前置++返回++以后的值 d.Print(); } void test2() { //前置--和后置--都完成--,不同的地方在于是返回值不同 Date d(2022, 1, 1); d--; //后置--返回--以前的值 d.Print(); --d; //前置--返回--以后的值 d.Print(); } void test3() { Date d1(2022, 1, 2); Date d2(2022, 1, 2); cout << (d1 != d2) << endl; d2 -= 1; cout << (d1 != d2) << endl; } void test4() { Date d1(2024, 1, 2); Date d2(2022, 5, 7); cout << d1 - d2 << endl; cout << d2 - d1 << endl; } int main() { test1(); test2(); test3(); test4(); Date d(2022,1,1); d += -40; d.Print(); Date d2(2022, 1, 1); d2 += 4000; d2.Print(); Date d3(2022, 1, 1); d3 = d3 + 3000; d3.Print(); Date d4(2022, 1, 1); d4 -= -3000; d4.Print(); Date d5(2022, 1, 1); d5 = d5-2000; d5.Print(); return 0; }