【C++小项目】实现一个日期计算器
目录
Ⅰ. 引入
Ⅱ. 列轮廓
Ⅲ. 功能的实现
构造函数
判断是否相等 == | !=
➡️==:
➡️!=:
判断大小 > | >= | < | <=
➡️>:
➡️<=:
➡️>=:
➡️<:
加减天数 + | += | - | -=
➡️+=:
➡️+:
➡️-:
➡️-=:
自增/自减 ++ | --
➡️前置++
➡️后置++
➡️前置--
➡️后置--
日期减日期
➡️Way1(推荐)
➡️Way2( 这个思路繁杂很多)
Ⅰ. 引入
本篇我们用C++来实现一个日期计算器。
想知道迄今为止你在地球上一共度过了多少天吗?距离寒假还有多少天呢?一百天后会是几月几号呢?
解开这些问题的答案,只需来写一个日期计算器~👻
日期计算器是C++入门以来的第一个小项目,亲自实践一遍,我们在C++上的经验值将⬆️⬆️⬆️
🚩我们将分三步:
Step1:在头文件中把日期类的大体轮廓列出来
Step2:把声明的功能一一实现
Step3:逐个测试。我们写一点,测一点。
这样,就可顺利把日期计算器写出个七七八八。
在遇到较复杂的算法时,我会提供思路。
至于某些锦上添花的功能,我们后续想到了,再添上去。
Ⅱ. 列轮廓
🤔我们先来定义一个日期类,同时看看要实现哪些功能:
#pragma once
#include<iostream>
using namespace std;
class Date {
public:Date(int year = 1900, int month = 1, int day = 1); //构造函数:用于初始化
void Print(); //打印日期,便于测试
//功能的具体实现bool operator==(const Date& d); //判断俩date是否相等bool operator!=(const Date& d);
bool operator>(const Date& d); //date间比较大小bool operator>=(const Date& d);bool operator<(const Date& d);bool operator<=(const Date& d);
Date operator+(int day); //加(减)天数,今夕是何年Date& operator+=(int day);Date operator-(int day);Date& operator-=(int day);
Date& operator++(); //date的自增/自减Date operatoe++(int);Date& operator--();Date operatoe--(int);
int operator-(const Date& d); //算两个date间差多少天
private:int _year;int _month;int _day;
};
Ⅲ. 功能的实现
构造函数
➡️我们实现一个全缺省的构造函数:
class Date{
public:Date(int year = 1900, int month = 1, int day = 1) { _year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
}
每次实例化出一个对象,都要调用构造函数,调用频率非常高。
所以,我们干脆就把这短短的几行定义在类里,做内联函数。
❓你可能会疑惑:为啥_year可以直接拿来用,不需要this->year嘛?
后者当然可以写,但没必要。因为我们在使用类的成员函数or成员变量时,this指针会默认加上的。
我们就不用一一手动加啦✌
➡️Print,写在Date.c里:
void Date::Print() {printf("%d-%d-%d\n", _year, _month, _day);
}
❓为啥要加Date::呢?
要知道,类定义了一个全新的作用域。类里类外,是有一层屏障的。
正因为类域的存在,我们不能直接从外部访问类的成员。
因此,把成员函数拿到类外定义时,要指明作用域,即加上Date::
❓我们不是学了cout嘛,为啥不直接cout输出,还得用printf?
这个问题我们先保留着,下一趴再讲。🤪
🔬🧪这俩函数先测试一波:
void Test1() {Date d1(2023, 8, 23);Date d2;d1.Print();d2.Print();
}
int main()
{Test1();return 0;
}
结果:
判断是否相等 == | !=
➡️==:
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指针。只有第二个形参可见。
“d1!=d2; ” 就相当于在调用函数 “d1.operator!=(d2); ”
此函数的this指针指向d1,形参的d即d2。
🔬🧪测试一下:
void Test2() {Date d1(2023, 8, 23);Date d2(2000, 1, 1);if (d1 != d2) {cout << "unequal"<<endl;}
}
int main()
{//Test1();Test2();return 0;
}
结果:
判断大小 > | >= | < | <=
日期的大小,听着蛮抽象。其实就是日期的先后:2023年1月1日比2000年1月1日要大(后)。
➡️>:
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 !(*this > d);
}
➡️>=:
bool Date::operator>=(const Date& d) {return *this > d || *this == d;
}
➡️<:
bool Date::operator<(const Date& d) {return !(*this >= d);
}
🔬🧪测试一下:
void Test3() {Date d1(2023, 8, 23);Date d2(2000, 1, 1);cout << (d1 > d2) << endl;cout << (d1 <= d2)<<endl;
}
int main()
{//Test1();//Test2();Test3();return 0;
}
结果:
加减天数 + | += | - | -=
➡️+=:
日期加天数要考虑进位的问题。我举个例子,先顺下思路:
2023-12-21往后推40天
61相比当月的31已经溢出了,
怎么判断是否溢出呢?
写个函数GetMonthDay(),取到每月的天数进行比对
GetMonthDay()实现如下:
int Date::GetMonthDay(int year, int month) {int days[13]={ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int ret = days[month];
//考虑闰年的2月是29天的情况//闰年,要么能被4整除&&不能被100~;要么能被400整除
if (month == 2&& (year % 4 == 0 && year % 100 == 0|| year % 400 == 0)) {ret += 1;}
return ret;
}
☑️operator+=实现如下:
Date& Date::operator+=(int day) {_day += day;int MaxDay = GetMonthDay(_year, _month);
while (_day > MaxDay) {_day -= MaxDay;_month++;
//防止month溢出if (_month == 13) {_month = 1;_year++;}
MaxDay = GetMonthDay(_year, _month);}
return *this;
}
➡️+:
有了+=,+就直接复用~👻
Date Date::operator+(int day) {Date ret = *this;ret += day;return ret;
}
🤔❓思考:为啥不能这样写?
Date Date::operator+(int day) {Date ret = *this+day;return ret;
}
因为:
➡️-:
加要考虑进位,减要考虑借位。
举例:2023-3-2 往前40天
思路:
🌀你可能有点晕:-38为什么要借2月的28?
可以把2023-3-2往前40天视为2023-3-0往前38天。
此时要借位,我们没法从3月借,因为它是空的。只能从2月借。
☑️实现:
Date& Date::operator-=(int day) {_day -= day;
while (_day <= 0) {_month--;
if (_month == 0) {_month = 12;_year--;}int BorrowDay = GetMonthDay(_year, _month);_day += BorrowDay;}
return *this;
}
➡️-=:
同样,复用🥰
Date Date::operator-(int day) {Date ret = *this;ret -= day;return ret;
}
🔬🧪测试一下:
void Test4() {Date d1(2023, 12, 21); //+ +=Date d2(d1);(d1 + 40).Print();(d2 += 700).Print();Date d3(d1); //- -=Date d4(2023, 3, 2);(d3 -= 400).Print();(d4 - 40).Print();
}
结果:
自增/自减 ++ | --
我们用参数占位来区分前置/后置++:
前置:operator++( )
后置:operator++( int )
❓前置++和后置++的区别是什么?
这俩都能实现自增,但返回值不同。
前置:++d; 先加加,再使用。返回的是加加后的值。
后置:d++;先使用,再加加。返回的是加加前的值。
假设d=0,d++:返回1,d=1
++d:返回0,同时实现自增,d=1
所以说,后置加加是不能引用返回的。而前置可以。
➡️前置++
Date& Date::operator++() {return *this += 1;
}
➡️后置++
Date Date::operator++(int) {Date ret = *this;*this += 1;return ret;
}
➡️前置--
Date& Date::operator--() {return *this -= 1;
}
➡️后置--
Date Date::operator--(int) {Date ret = *this;*this -= 1;return ret;
}
🔬🧪测试一下:
void Test5() {Date d1(2023, 1, 1); //++Date d2(d1);(++d1).Print();(d2++).Print();
Date d3(2023, 1, 1); //--Date d4(d3);(--d3).Print();(d4--).Print();
}
结果:
日期减日期
距离新年还有多少天呢?
Date(2024,1,1) - Date(2023,8,24) =❓天
➡️Way1(推荐)
我们刚刚不是写了好多功能嘛,复用起来~👻
实现:
int Date::operator-(const Date& d) {Date More = *this; //先把date标个大小Date Less = d;
if (Less > More) {More=d;Less=*this;}
int count = 0; //用计数法算差值while (Less<More) {Less++; //复用🥰👻count++;}
int flag = 1; //我们不知道是大-小or小-大if (More == d) { //为了区分结果的正负,引入flagflag = -1; }
return count*flag;
}
这种方法虽然思路简单,但是深度复用了代码,效率会下降。
➡️Way2( 这个思路繁杂很多)
(❗这个方法效率会⬆️,但是较复杂,可略过不看!)
Q: 2023-2-13到2024-1-15,要过多少天?、
思路:
Step1:把月、日转化成总天数;
Step2:年与年之间相减,天与天之间相减
Step3:全化成天
实现:
Step1 我们先写一个把月、日转换成天数的函数ConverttoDay( )
如下:
int Date::ConverttoDay(int year, int month, int day) {int MonthtoDay = 0;month -= 1;
while (month) {MonthtoDay += GetMonthDay(year, month);month--;}
int ret = MonthtoDay + day;return ret;
}
Step2 实现operator-函数
int Date::operator-(const Date& d) {//先判断日期的大小Date BigDate = *this;Date SmallDate = d;
if (BigDate < SmallDate) {Date tmp = SmallDate;SmallDate = BigDate;BigDate = tmp;}
//把月、日都转换成天int BigDay = ConverttoDay(BigDate._year, BigDate._month, BigDate. _day);int SmallDay = ConverttoDay(SmallDate._year, SmallDate._month, SmallDate._day);
int RetofDay = BigDay - SmallDay; //天之间相减,大天-小天int BigYear = BigDate._year;int SmallYear = SmallDate._year;
//年之间相减,大年-小年int CountDay = 0;
while (SmallYear < BigYear) {CountDay += 365;
if (SmallYear % 4 == 0 && SmallYear % 100 != 0 //考虑闰年|| SmallYear % 400 == 0) {CountDay += 1;}
SmallYear++;}
//把两者的天数合一int ret = RetofDay + CountDay;
int flag = 1;if (*this == BigDate) {flag = -1;}
return flag * ret;
}
🔬🧪测试一下:
void Test6() {Date d1(2023, 8, 24);Date d2(2024, 1, 1);
printf("%d\n", d2 - d1);
}
结果:
OK, 到这我们的日期计算器已经完成啦~🥰👻
相关文章:
【C++小项目】实现一个日期计算器
目录 Ⅰ. 引入 Ⅱ. 列轮廓 Ⅲ. 功能的实现 构造函数 Print 判断是否相等 | ! ➡️: ➡️!: 判断大小 > | > | < | < ➡️>: ➡️<: ➡️>: ➡️<: 加减天数 | | - | - ➡️:…...
Ext JS 之Microloader(微加载器)
“Microloader”是 Sencha 数据驱动的 JavaScript 和 CSS 动态加载器的名称。 清单 app.json 用于应用的设置,Sencha Cmd 在构建的时候会读取这个文件。 Sencha Cmd 转换“app.json”的内容并将生成的清单传递给 Microloader 以在运行时使用。 最后,Ext JS 本身也会查阅运…...
【科研】-- 如何将Endnote中参考文献格式插入到Word?
文章目录 如何将Endnote中参考文献格式插入到Word? 如何将Endnote中参考文献格式插入到Word? 1、首先确保Endnote和Word安装正确,正常可以从学校官网中下载到正版软件,下载后在word栏目中会出现EndNote的标签; 2、可…...
Python爬虫实战案例——第二例
某某美剧剧集下载(从搜索片名开始) 本篇文章主要是为大家提供某些电影网站的较常规的下载电影的分析思路与代码思路(通过爬虫下载电影),我们会从搜索某部影片的关键字开始直到成功下载某一部电影。 地址:aHR0cHM6Ly93d3cuOTltZWlqdXR0LmNvbS9pbmRleC5od…...
深入理解Spring的ImportBeanDefinitionRegistrar接口及其应用
0 导言 ImportBeanDefinitionRegistrar接口在动态注册Bean定义方面发挥着重要作用。本篇博客将深入探讨ImportBeanDefinitionRegistrar接口的作用、用法以及实际应用场景。 1 简介 ImportBeanDefinitionRegistrar接口是Spring Framework中的一个关键接口,位于org…...
【面试题】你理解中JS难理解的基本概念是什么?
前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 作用域与闭包 作用域 作用域是当前的执行上下文,值和表达式在其中“可见”或可被访问。如果一个变量或表达式不在当前的作用域中࿰…...
微服务中间件--MQ服务异步通信
MQ服务异步通信 MQ服务异步通信a.消息可靠性1) 生产者消息确认2) 消息持久化3) 消费者消息确认4) 消费者失败重试4.a) 本地重试4.b) 失败策略 b.死信交换机1) 初识死信交换机2) TTL3) 延迟队列a) 安装延迟队列插件b) SpringAMQP使用延迟队列插件 c.惰性队列1) 消息堆积问题2) 惰…...
爆火「视频版ControlNet」开源了!靠提示词精准换画风,全华人团队出品
“视频版ControlNet”来了! 让蓝衣战神秒变迪士尼公举: 视频处理前后,除了画风以外,其他都不更改。 女孩说话的口型都保持一致。 正在插剑的姜文,也能“下一秒”变猩球崛起了。 这就是由全华人团队打造的最新视频处理…...
常用的数据可视化工具有哪些?要操作简单的
随着数据量的剧增,对分析效率和数据信息传递都带来了不小的挑战,于是数据可视化工具应运而生,通过直观形象的图表来展现、传递数据信息,提高数据分析报表的易读性。那么,常用的操作简单数据可视化工具有哪些࿱…...
ssl卸载原理
SSL卸载,也称为SSL解密,是一种将SSL加密数据流卸成非加密的明文数据流的过程。SSL卸载通常在负载均衡器、代理服务器、WAF等设备中实现,可以提高传输效率和安全性。 SSL卸载的原理是将SSL数据流拦截下来,通过设备内置的证书进行解…...
【C语言】动态内存管理,详细!!!
文章目录 前言一、为什么存在动态内存分配二、动态内存开辟函数的介绍1.malloc2.calloc3.realloc4.free 三、动态内存开辟中的常见错误1.误对NULL进行解引用操作2.对于动态开辟的空间进行了越界访问3.对于非动态开辟的内存进行了free操作4.只free掉动态开辟内存的一部分5.多次f…...
2023年国赛 高教社杯数学建模思路 - 案例:退火算法
文章目录 1 退火算法原理1.1 物理背景1.2 背后的数学模型 2 退火算法实现2.1 算法流程2.2算法实现 建模资料 ## 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 退火算法原理 1.1 物理背景 在热力学上&a…...
jenkins 日志输出显示时间戳的方式
网上很多方式比较片面,最新版插件直接使用即可无需更多操作。 使用方式如下: 1.安装插件 Timestamper 2.更新全局设置 系统设置-找到 Timestamper 勾选 Enabled for all Pipeline builds 也可修改时间戳格式。 帮助信息中显示 When checked, timesta…...
geacon_pro配合catcs4.5上线Mac、Linux
我的个人博客: xzajyjs.cn 一些链接 Try师傅的catcs4.5项目: https://github.com/TryGOTry/CobaltStrike_Cat_4.5,最新版解压密码见:https://www.nctry.com/2708.html geacon_pro: https://github.com/testxxxzzz/geacon_pro BeaconTool.jar: https:/…...
vue 实现腾讯地图搜索选点功能(附加搜索联想功能)
注意:开发环境、正式环境需在腾讯地图配置ip地址白名单、域名白名单 封装map组件: <template><iframe width"100%" style"border: none;width: 100%;height: 100%;" :src"map_src"></iframe> </t…...
解密长短时记忆网络(LSTM):从理论到PyTorch实战演示
目录 1. LSTM的背景人工神经网络的进化循环神经网络(RNN)的局限性LSTM的提出背景 2. LSTM的基础理论2.1 LSTM的数学原理遗忘门(Forget Gate)输入门(Input Gate)记忆单元(Cell State)…...
17.1.2 【Linux】systemd使用的unit分类
systemd 有什么好处? 平行处理所有服务,加速开机流程: 旧的 init 启动脚本是“一项一项任务依序启动”的模式,因此不相依的服务也是得要一个一个的等待。但目前我们的硬件主机系统与操作系统几乎都支持多核心架构了,s…...
vue离线缓存资源文件
本文章主要是解决大文件,实时请求资源浪费网络资源的问题 从而有效的将解决用户体验的问题 话不多说上才艺 ⬇️⬇️⬇️⬇️⬇️⬇️⬇️ 找到项目中的 index.html 文件,并在 html 标签中加入 manifest"manifest.appcache" 安装 appcache-manifest 包 npm ins…...
2023华为杯研赛数学建模A题B题C题D题E题F题资料 华为杯
本次比赛我们将会全程更新华为杯研赛赛题思路模型及代码,大家查看文末名片获取 之前华为杯相关的资料和助攻可以查看 2022华为杯数学建模研赛选题建议和思路分析_方形件组批优化问题_UST数模社_的博客-CSDN博客 我们华为杯更新的流程如下: A题思路&a…...
星际争霸之小霸王之小蜜蜂(六)--让子弹飞
目录 前言 一、添加子弹设置 二、创建子弹 三、创建绘制和移动子弹函数 四、让子弹飞 五、效果 总结 前言 小蜜蜂的基本操作已经完成了,现在开始编写子弹的代码了。 一、添加子弹设置 在我的预想里,我们的小蜜蜂既然是一只猫,那么放出的子弹…...
opencv简单使用
cv2库安装, conda install opencv-python注意cv2使用时,路径不能有中文。(不然会一直’None’ _ update # 处理中文路径问题 def cv_imread(file_path): #使用之前需要导入numpy、cv2库,file_path为包含中文的路径return cv2.imd…...
SpringBoot 微人事 职称管理模块(十三)
职称管理前端页面设计 在职称管理页面添加输入框 export default {name: "JobLevelMarna",data(){return{Jl:{name:""}}}}效果图 添加一个下拉框 v-model的值为当前被选中的el-option的 value 属性值 <el-select v-model"Jl.titlelevel" …...
动态规划之0-1背包问题
动态规划之0-1背包问题 文章目录 动态规划之0-1背包问题一、先给出代码二、讲解第一步:初始化第二步:动态规划,填表第三步:回溯,找到选择方案总结 三、进阶(用一维数组解决问题) 一、先给出代码…...
为什么需要单元测试?
为什么需要单元测试? 从产品角度而言,常规的功能测试、系统测试都是站在产品局部或全局功能进行测试,能够很好地与用户的需要相结合,但是缺乏了对产品研发细节(特别是代码细节的理解)。 从测试人员角度而言…...
《合成孔径雷达成像算法与实现》Figure3.13——匹配滤波器的三种实现方式
clc clear close all% 参数设置 TBP 80; % 时间带宽积 T 10e-6; % 脉冲持续时间 N_ZD 60; % 零频点位于中点右侧的距离,P58% 参数计算 B TBP/T; …...
Android企业项目开发实训室建设方案
一 、系统概述 Android企业项目开发作为新一代信息技术的重点和促进信息消费的核心产业,已成为我国转变信息服务业的发展新热点:成为信息通信领域发展最快、市场潜力最大的业务领域。互联网尤其是移动互联网,以其巨大的信息交换能力和快速渗透…...
11_Redis经典五大类型源码及底层实现
Redis经典五大类型源码及底层实现 一、Redis数据类型的底层数据结构 SDS动态字符串双向链表压缩列表 zpilist哈希表 hashtable调表 skiplist整数集合 intset快速列表 quicklist紧凑列表 listpack 二、Redis源码地址 Github:https://github.com/redis/redis 三、…...
AWS WAF实战、优势对比和缺陷解决
文章目录 挑战和目标AWS WAF的优势AWS WAF的不足我是怎么做的?什么是比较好的AWS WAF设计? 笔者为了解决公司Web站点防御性问题,较为深入的研究AWS WAF的相关规则。面对上千万的冲突,笔者不得设计出一种能漂亮处理冲突数据WAF规则。 AWS WAF开发人员在…...
13,【设计模式】代理
代理 代理支持任意参数的简单代理实现 代理 代理的本质是函数指针 代理分为单播,多播,动态多播(ue4中提出的) 单播:在网络通信中,单播是一种一对一的通信方式 多播:在网络通信中,…...
基于IDEA使用maven创建hibernate项目
1、创建maven项目 2、导入hibernate需要的jar包 <!--hibernate核心依赖--><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.4.1.Final</version></dependency><!--…...
wordpress 文章 视频/搜索引擎优化的实验结果分析
一,启动jar包命令 1. java -jar Zhglpt.Boot-1.0-SNAPSHOT.jar 格式: java -jar 包名.jar 描述:java -jar 包名.jar 这个命令在linux,window 操作中,一般关闭window 窗口,或者关闭ssh 连接,都…...
swoole+wordpress/新闻内容摘抄
eval将值代入字符串之中。语法: void eval(string code_str);传回值: 无函式种类: 数据处理内容说明本函式可将字符串之中的变量值代入,通常用在处理数据库的数据上。参数 code_str 为欲处理的字符串。值得注意的是待处理的字符串要符合 PHP 的字符串格式࿰…...
52影院/优化seo厂家
执行数据比较的时候,pandas出现报错: ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). 错误意思是:所选的真值不明确,也就是给的值和作比较的值的类型不同。 应…...
专业的句容网站建设/石家庄百度搜索引擎优化
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能。但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索引的概念,需要了解大量…...
网站建设大/saas建站
构建Chrome扩展程序很容易,而且从很多方面来说都是如此。 该文档确实做得很好,并且包含大量示例。 此外,检查已安装的任何组件以查看其背后的魔力很容易。 另一个很大的优点是,它全都是Javascript,CSS和HTML࿰…...
ps如何做网站专题/推广手段
Windows 10 家庭组其实特别好用,但是使用过程中也可能会遇到一些问题。常见的现象有:在建立或加入家庭组时,显示“Windows 无法在此计算机上设立家庭组”;或者无法启动 Peer Name Resolution Protocol 和 Peer Networking Groupin…...