欢迎来到CILMY23的博客
本篇主题为: 用C++实现一个日期计算器
个人主页:CILMY23-CSDN博客
系列专栏:Python | C++ | C语言 | 数据结构与算法 | 贪心算法 | Linux
感谢观看,支持的可以给个一键三连,点赞关注+收藏。
写在前头:
知识所需:构造函数,运算符重载,类和对象,类的声明和定义分离,内联函数,拷贝构造
额外知识: 友元声明
文件: Date.h Date.cpp test.cpp
注意:日期类的拷贝构造和析构都是不需要写的
目录
一、功能逻辑图
二、Date.cpp代码实现
2.1 日期比较
2.2 日期加天数
2.3 日期减天数
2.4 日期前置++和后置++
2.5 日期前置--和后置--
2.6 日期与日期相差的天数
2.7 日期显示
2.8 流输出
2.9 流提取
2.10 日期类输入的检查和日期的初始化
三、Date.h中的声明
一、功能逻辑图
日期计算器的功能如下,我们要考虑日期的增加和减少,自增和自减,以及两个日期类的比较,以及当前日期类的日期显示和用户的输入输出。
二、Date.cpp代码实现
2.1 日期比较
日期比较主要实现以下六种比较,因为日期的比较是自定义类型,所以我们需要用到运算符重载来进行比较,先通过实现等于和小于,其余的功能复用就可以了。
代码如下:
//日期比较 //小于 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 _day < d._day; } } } return false; } //小于等于 bool Date::operator<=(const Date& d) { return (*this < d) || (*this == d); } //大于 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 _year == d._year && _month == d._month && _day == d._day; } //不等于 bool Date::operator!=(const Date& d) { return !(*this == d); }
2.2 日期加天数
日期增加天数我们所用到的运算符是 + 和 +=,日期增加有两种方式,一种是+复用+=,一种是+=复用+,我们实现的是+复用+=,另外一种会创建新对象造成效率降低。
Date& Date::operator+=(int day) { _day += day; while (_day > GetMonthDay(_year, _month)) { _day -= GetMonthDay(_year, _month); _month++; if (_month == 13) { _month = 1; _year += 1; } } return *this; } Date Date::operator+(int day) { Date tmp = *this;//拷贝构造 tmp += day; return tmp; }
2.3 日期减天数
日期减去天数也同理日期增加天数,先实现 -= 然后再去实现 -
Date& Date::operator-=(int days) { _day -= days; while (_day <= 0) { _month--; if (_month == 0) { _year--; _month = 12; } _day += GetMonthDay(_year, _month); } return *this; } Date Date::operator-(int days) { Date tmp = *this; tmp -= days; return tmp; }
2.4 日期前置++和后置++
日期前置++和后置++ 主要区别在于,C++中用一个形参类型区分前置和后置。在编译器传参的时候会传一个整型,然后表示这是一个后置++。
//日期自增 //前置++ Date& Date::operator++() { *this += 1; return *this; } //后置++ Date Date::operator++(int) { Date tmp = *this; *this += 1; return tmp; }
2.5 日期前置--和后置--
日期的前置--和后置--也同理日期的前置++和后置++。
//日期自减少 //前置-- Date& Date::operator--() { *this -= 1; return *this; } //后置-- Date Date::operator--(int) { Date tmp = *this; *this -= 1; return tmp; }
2.6 日期与日期相差的天数
日期与日期的相减,是运算符 - 的重载函数。 主要思路是,通过把最小的日期自增到最大的日期,计算次数就是它们之间相差的天数。
//日期与日期的相减 int Date::operator-(const Date& d) { int flag = -1; int n = 0; Date min = d; Date max = *this; if (*this < d) { flag = 1; min = *this; max = d; } while (min != max) { ++min; ++n; } return flag * n; }
2.7 日期显示
当前日期显示则较为容易,主要是让用户知道自己输入的两个日期是什么样的。
void Date::Print() { cout << "当前日期:" << _year << "/" << _month << "/" << _day << endl; }
2.8 流输出
流输出主要是方便我们对日期类的输出,用上流运算符方便打印。
ostream& operator<<(ostream& out, const Date& d) { out << d._year << "年" << d._month << "月" << d._day << "天" << endl; return out; }
2.9 流提取
流提取也同理流输出。但是注意在对日期的输入前,需要我们对日期进行检查。
istream& operator>>(istream& in, Date& d) { while (1) { cout << "请输入对应的年月日" << endl; in >> d._year >> d._month >> d._day; if (!d.CheckInvalid()) { cout << "日期输入错误,请重新输入" << endl; } else { break; } } return in; }
2.10 日期类输入的检查和日期的初始化
日期类的检查:
//日期检查 bool Date::CheckInvalid() { if (_year <= 0 || _month < 1 || _month >12 || _day < 1 || _day > GetMonthDay(_year, _month)) { return false; } else return true; }
日期类的初始化:
//日期初始化 Date::Date(int year, int month, int day) { _year = year; _month = month; _day = day; if (!CheckInvalid()) { cout << "构造日期非法" << endl; } }
三、Date.h中的声明
代码如下:
#pragma once #define _CRT_SECURE_NO_WARNINGS 1 //日期计算器的声明 #include#include using namespace std; class Date { public: //日期初始化 //全缺省构造函数 //声明给缺省值,定义不给缺省值 Date(int year = 1, int month = 1, int day = 1); //日期比较 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); //日期增加天数 Date& operator+=(int day); Date operator+(int day); //inline 不写:本质就是内联,不声明和定义分离 int GetMonthDay(int year, int month) { assert(month > 0 && month < 13); static int MonthDay[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) { return 29; } return MonthDay[month]; } //日期减少 Date& operator-=(int day); Date operator-(int day); //日期自增 //前置++ Date& operator++(); //后置++ Date operator++(int); //日期自减 //前置-- Date& operator--(); //后置++ Date operator--(int); //日期与日期的相减 int operator-(const Date& d); //用户输出 friend ostream& operator<<(ostream& out, const Date& d); //用户输入 friend istream& operator>>(istream& in, Date& d); //日期检查 bool CheckInvalid(); //日期打印 void Print(); private: int _year; int _month; int _day; }; //用户输出 ostream& operator<<(ostream& out,const Date& d); //用户输入 istream& operator>>(istream& in, Date& d);
后文:
日期计算器的大致功能如上,主要还是对运算符重载的应用和之前类和对象的知识掌握。有很多地方也不够完善,当然还有很多地方需要改进,在实际应用中还需要调用以上的接口,那日期计算器的界面我也写了一点,大家可以尽情发挥。
//日期界面 //显示日期计算器界面 void CalculatorInterface() { int n = 1; cout << "欢迎使用日期计算器!" << endl; cout << "请选择您想要执行的操作:" << endl; cout << "1. 计算两个日期之间的天数差" << endl; cout << "2. 计算某个日期之后或之前的日期" << endl; cout << "0. 退出" << endl; cout << "请输入选项数字: "; cin >> n; if (n == 0) { exit(1); } else if(n == 1) { //.... } else { cout << "无效的选项,请重新输入。" << endl; } }
为了简便,也可以使用转移表,或者使用switch case 来进行选择对应的功能……
感谢各位同伴的支持,本期日期计算器篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。