检测网站是否做了301,wordpress 循环菜单,制作相册,湖南网站建设制作公司目录
一、前言 二、日期类计算器 三、日期计算器的实现
#x1f34e;日期计算器各个接口的实现
#x1f350;日期计算器的需求 #x1f349;打印当前日期#xff08;并检查日期是否合理#xff09; #x1f4a6;检查日期是否合理 #x1f4a6;日期类构造函数#x…目录
一、前言 二、日期类计算器 三、日期计算器的实现
日期计算器各个接口的实现
日期计算器的需求 打印当前日期并检查日期是否合理 检查日期是否合理 日期类构造函数用于日期的初始化 ⭐效果展示 日期之间的大小比较 运算符重载 运算符重载 运算符重载 运算符重载 运算符重载 ! 运算符重载 ⭐效果展示
日期的加减天数计算 日期 天数 日期 天数 日期 - 天数
日期 - 天数 日期 前置 日期 后置 日期 前置-- 日期 后置-- ⭐效果展示 日期与日期之间的减法运算 日期 - 日期 ⭐效果展示 四、日期计算器的完整代码
Date.h
Date.cpp
Test.cpp 代码运行的界面 五、共勉 一、前言 在之前的博客学习中我们已经详细的讲解了C中的引用、缺省函数、this指针、构造函数、析构函数、拷贝构造函数、运算符重载等非常重要的知识但是对于这些知识如何如何的使用还没有进行讲解所以本次博客将以日期计算器为例将以上知识融合起来讲解帮助大家更好的理解。 二、日期类计算器 在我们的日常生活中我们可能需要计算几天后的日期或计算日期差等现如今计算日期的方式有很多简单粗暴的直接查看日历快捷点的直接使用日期计算器来求得先给一个网络上的日期计算器截图 现在就让我们用代码来实现其工作原理吧。 三、日期计算器的实现
日期计算器各个接口的实现 这里先建立三个文件 1️⃣ Date.h文件用于类中---函数声明 2️⃣ Date.cpp文件用于类中---函数的定义 3️⃣ Test.cpp文件用于测试函数 建立三个文件的目的 将日期计算器作为一个项目来进行书写方便我们的学习与观察。 日期计算器的需求 这里我们需要考虑我们实现的这个日期计算器需要实现怎样的需求呢 需要打印当前的日期请检查日期是否合理实现日期之间的大小比较实现日期的加减天数计算实现日期与日期之间的减法运算 打印当前日期并检查日期是否合理 实现日期类首先就得检查日期的合法性这其中就包括大小月闰年的2月有29天一年只有12个月等等细节都要考虑到。 检查日期是否合理 //判断是否为闰年
bool Date::isLeaveYear(int year)
{// 四年一润百年不润 或者 四百年一润return (year % 4 0 year % 100 ! 0) || (year % 400 0);
}// 获取每个月的天数
int Date::GetMonthDay(int year, int month)
{int monthday[13] { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month 2 isLeaveYear(year)){return 29;}else{return monthday[month];}
} 日期类构造函数用于日期的初始化 //判断是否为闰年
bool Date::isLeaveYear(int year)
{// 四年一润百年不润 或者 四百年一润return (year % 4 0 year % 100 ! 0) || (year % 400 0);
}// 获取每个月的天数
int Date::GetMonthDay(int year, int month)
{int monthday[13] { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month 2 isLeaveYear(year)){return 29;}else{return monthday[month];}
} ⭐效果展示 1️⃣错误的日期演示 ------ -1 / -1 / -1 年/月/日 // 测试初始化
void Test()
{Date d1(-1,-1,-1);d1.Printf();
}
int main()
{Test();return 0;
} 1️⃣正确的日期演示 -------- 2023 / 10 / 28 年/月/日 // 测试初始化
void Test()
{cout 请输入今日的日期 endl;Date d1(2023,10,28);d1.Printf();
}
int main()
{Test();return 0;
} 日期之间的大小比较 运算符重载 思路 运算符重载在我上一篇博文已经详细讲解过主要是先把大于的情况全部统计出来就比如我要比较实例化对象d1是否小于实例化对象d2只需考虑如下三种满足的情况 d1的年小于d2的年d1与d2年相等d1的月小于d2的月d1与d2年相等月相等d1的天小于d2的天 这三种全是小于的情况返回true其余返回false 代码如下 // 运算符重载
bool Date::operator(const Date d)
{if (_year d._year ||_year d._year _month d._month ||_year d._year _month d._month _day d._day){return true;}else{return false;}
} 运算符重载 思路 运算符重载其实非常简单只需要判断d1和d2的年、月、天是否对应相等即可 代码如下 // 运算符重载
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);
} ⭐效果展示 此时我们拿 运算符 举例子 // 测试运算符
void Test1()
{Date d1(2023,10,28);cout d1的日期为;d1.Printf();cout d2的日期为;Date d2(2023, 10, 27);d2.Printf();cout endl;if (d2 d1){cout d1的日期 d2的日期 endl;}else{cout d2的日期 d1的日期 endl;}
}int main()
{Test1();return 0;
} 日期的加减天数计算 日期 天数 思路 对于日期 天数我们得到的还是一个日期。特别需要注意进位的问题天满了往月进月满了往年进主要考虑如下几个特殊点 加过的天数超过该月的最大天数需要进位当月进位到13时年进位1月置为1 法一 Date Date::operator(int day)
{Date ret(*this); //拷贝构造拿d1去初始化retret._day day;while (ret._day GetMonthDay(ret._year, ret._month)){ret._day - GetMonthDay(ret._year, ret._month);ret._month;if (ret._month 13){ret._year;ret._month 1;}}return ret;
} 出了作用域对象ret不在它是一个局部对象我们这里不能用引用用了的话返回的就是ret的别名但是ret又已经销毁了访问野指针了所以出了作用域如果对象不在了就不能用引用返回要用传值返回 法二复用日期天数 此法是建立在日期天数的基础上完成的这里各位可以先看下文日期天数然后我们进行复用 Date Date::operator(int day)
{//法二复用日期 天数Date ret(*this);ret day;return ret;
} 法一和法二熟优 答案法二更好也就是用去复用具体原因在下文会解释。 日期 天数 这里实现 其实有两种方案 法一 前面我实现的日期天数仔细观察我的代码函数的第一行我就调用了一个拷贝构造 Date ret(*this); //拷贝构造拿d1去初始化ret 这里调用拷贝构造是为了不在*this本身上做变动只在ret上进行操作其理由是日期天数得到的是另一个日期而不用拷贝构造直接在*this上做改动只会导致原有的日期也变化而这个变化正是我日期 天数的需求 仔细想想天数就是在原有的日期上再加一定的天数直接对*this做手脚即可因此只需对日期天数的代码进行小改动即可 Date Date::operator(int day) //传引用返回
{//如果day小于0要单独处理if (day 0){return *this - -day;}_day day;while (_day GetMonthDay(_year, _month)){_day - GetMonthDay(_year, _month);_month;if (_month 13){_year;_month 1;}}return *this;
} 注意这里是传引用返回原因就在于我返回的*this是全局的出了作用域还在 法二复用日期 天数 Date Date::operator(int day)
{//法二复用* this *this day; //让d1过天数后再返回给自己从而实现return *this;
} 法一和法二熟优 答案法一。其实讨论这个问题就是在讨论用去复用好还是用复用好答案是用去复用好因为有两次拷贝而没有拷贝所以实现并且用去复用效率更高 日期 - 天数 思路 日期-天数得到的还是一个日期且是在原日期的基础上做改动。合法的日期减去天数后的day只要0就没问题若小于0就要借位了。要注意当减去的天数0时单独讨论。具体步骤如下 当减的天数为负数则为直接调用若减后的day0月-1若月 0则年-1月置为12 代码如下 // 日期- 天数 d1 d1 - 100
Date Date::operator-(int day)
{if (day 0){return *this (-day);}_day - day;while (_day 0){_month--;if (_month 0){_month 12;_year--;}_day GetMonthDay(_year, _month);}return *this;
} 日期 - 天数 有了先前日期和的基础这里实现日期 - 天数直接复用日期 - 天数即可 // 日期-天数 d1 - 100
Date Date::operator-(int day)
{// 调用拷贝构造Date temp(*this);// 复用 -temp - day;return temp;
} 日期 前置 思路 C里有前置和后置这就导致一个巨大的问题该如何区分它们具体实现过程不难直接复用即可难的是如何区分前置和后置。因此C规定无参的为前置有参的为后置。 代码如下 // 前置 无参的为前置有参的为后置
Date Date::operator()
{// 直接复用 *this 1;return *this;
} 日期 后置 思路 有参的即为后置后置拿到的返回值应该是自己本身未加过的因此要先把自己保存起来再*this随后返回自己。 代码如下 // 后置无参的为前置有参的为后置
// int i 这里的形参可以写可以不写
Date Date::operator(int i)
{Date temp(*this);*this 1;return temp;
}日期 前置-- 思路 前置--和前置没啥区别只不过内部复用的是- 代码如下 // 前置--
Date Date::operator--()
{*this - 1;return *this;
} 日期 后置-- 思路 后置--和后置类似只不过内部复用的是-不再赘述 代码如下 //后置--
Date Date::operator--(int i)
{Date temp(*this);*this - 1;return temp;
} ⭐效果展示 举例将日期 100 天 2023 / 10 / 28 100 // d1100 测试
void Test3()
{Date d1(2023, 10, 28);cout d1的日期为;d1.Printf();cout endl;d1 100;cout d1的日期100为;d1.Printf();
}int main()
{Test3();return 0;
} 日期与日期之间的减法运算 日期 - 日期 思路 日期 - 日期得到的是天数首先我们得判断两个日期的大小用min和max代替小的和大的随后算出min和max之间的差距若min!max则min就随即定义变量n也自增最后返回n注意符号 代码如下 // 日期 - 日期
int Date::operator-(const Date d)
{// 方便后续计算正负int flag 1;Date max *this;Date min d;// 确保max是大的 min是小的if (*this d){min *this;max d;flag -1; //计算正负}int n 0;// 计算min和max之间的绝对值差距while (min ! max){min;n;}return n * flag;
} ⭐效果展示 举例计算 2023 / 10 /28 ------------- 2023 / 11 / 11 的天数差距 // 日期 - 日期
void Test4()
{Date d1(2023, 11, 11);cout d1的日期为;d1.Printf();cout d2的日期为;Date d2(2023, 10, 28);d2.Printf();cout endl;cout d1与d2之间的天数差距为;int ret d1 - d2;cout ret endl;}int main()
{Test4();return 0;
} 四、日期计算器的完整代码
Date.h #pragma once
#include iostream
#include stdio.h
#include assert.h
#include stdbool.h
using std::cout;
using std::cin;
using std::endl;class Date
{
public:// 构造函数用于初始化 -- 声明 // 在声明中缺省函数需要 写清楚 在定义中缺省函数就不要写了 防止编译器分不清Date(int year 1, int month 1, int day 1);//判断是否为闰年bool isLeaveYear(int year);// 获取每个月的天数int GetMonthDay(int year, int month);// 打印void Printf();// 运算符重载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);// 日期 天数: d1 d1 100Date operator (int day);// 日期 天数 d1100 d1不变Date operator(int day);// 日期- 天数 d1 d1 - 100Date operator-(int day);// 日期-天数 d1 - 100Date operator-(int day);// 前置 无参的为前置有参的为后置Date operator();// 后置无参的为前置有参的为后置Date operator(int i);// 前置--Date operator--();//后置--Date operator--(int i);// 日期 - 日期int operator-(const Date d);
private:int _year;int _month;int _day;
};Date.cpp #define _CRT_SECURE_NO_WARNINGS 1
#include Date.h// 构造函数用于初始化
Date::Date(int year, int month, int day)
{_year year;_month month;_day day;if (_year 1 || _month 1 || _month12 || _day1 || _dayGetMonthDay(_year, _month)){assert(false);}
}//判断是否为闰年
bool Date::isLeaveYear(int year)
{// 四年一润百年不润 或者 四百年一润return (year % 4 0 year % 100 ! 0) || (year % 400 0);
}// 获取每个月的天数
int Date::GetMonthDay(int year, int month)
{int monthday[13] { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month 2 isLeaveYear(year)){return 29;}else{return monthday[month];}
}void Date::Printf()
{cout _year / _month / _day endl;
}// 运算符重载
bool Date::operator(const Date d)
{if (_year d._year ||_year d._year _month d._month ||_year d._year _month d._month _day d._day){return true;}else{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);
}// 日期 天数: d1 d1 100
Date Date::operator(int day)
{// 防止传入的天数为 负数-100if (day 0){return *this - (-day);}_day day;while (_day GetMonthDay(_year, _month)){_day - GetMonthDay(_year, _month);_month;if (_month 13){_year;_month 1;}}return *this;
}// 日期 天数 d1100 d1不变
Date Date::operator(int day)
{// 调用拷贝构造Date temp(*this);temp day;return temp;
}// 日期- 天数 d1 d1 - 100
Date Date::operator-(int day)
{if (day 0){return *this (-day);}_day - day;while (_day 0){_month--;if (_month 0){_month 12;_year--;}_day GetMonthDay(_year, _month);}return *this;
}// 日期-天数 d1 - 100
Date Date::operator-(int day)
{// 调用拷贝构造Date temp(*this);// 复用 -temp - day;return temp;
}// 前置 无参的为前置有参的为后置
Date Date::operator()
{// 直接复用 *this 1;return *this;
}// 后置无参的为前置有参的为后置
// int i 这里的形参可以写可以不写
Date Date::operator(int i)
{Date temp(*this);*this 1;return temp;
}// 前置--
Date Date::operator--()
{*this - 1;return *this;
}//后置--
Date Date::operator--(int i)
{Date temp(*this);*this - 1;return temp;
}// 日期 - 日期
int Date::operator-(const Date d)
{// 方便后续计算正负int flag 1;Date max *this;Date min d;// 确保max是大的 min是小的if (*this d){min *this;max d;flag -1; //计算正负}int n 0;// 计算min和max之间的绝对值差距while (min ! max){min;n;}return n * flag;
} Test.cpp #define _CRT_SECURE_NO_WARNINGS 1
#include Date.h// 测试初始化
void Test()
{cout 请输入今日的日期 endl;Date d1(2023,10,28);d1.Printf();
}// 测试运算符
void Test1()
{Date d1(2023,10,28);cout d1的日期为;d1.Printf();cout d2的日期为;Date d2(2023, 10, 27);d2.Printf();cout endl;if (d2 d1){cout d1的日期 d2的日期 endl;}else{cout d2的日期 d1的日期 endl;}
}// d1 100 测试
void Test2()
{Date d1(2023,10,27);cout d1的日期为;d1.Printf();Date d2;d2 d1 100;cout d1的日期100为;d2.Printf();
}// d1100 测试
void Test3()
{Date d1(2023, 10, 28);cout d1的日期为;d1.Printf();cout endl;d1 100;cout d1的日期100为;d1.Printf();
}// 日期 - 日期
void Test4()
{Date d1(2023, 11, 11);cout d1的日期为;d1.Printf();cout d2的日期为;Date d2(2023, 10, 28);d2.Printf();cout endl;cout d1与d2之间的天数差距为;int ret d1 - d2;cout ret endl;}void Test5()
{cout *********** 欢迎来到 日期计算器 *********** endlendl;cout 输入今日的日期: ;int y, m, d;cin y m d;cout endl;Date d1(y, m, d);//d1.Printf();cout 输入需要对比的日期: ;int y1, m1, dd;cin y1 m1 dd;cout endl;Date d2(y1, m1, dd);//d2.Printf();cout 两个日期之间的天数差距为;int ret d - dd;cout ret endl;
}int main()
{Test5();return 0;
} 代码运行的界面 五、共勉 以下就是我对C日期计算器的理解如果有不懂和发现问题的小伙伴请在评论区说出来哦同时我还会继续更新对C 类和对象的理解请持续关注我哦