当前位置: 首页 > news >正文

C++日期类详解 第二级支线任务

日期类的整体

class Date
{
public:// 构造函数Date(int year = 0, int month = 1, int day = 1);// 打印函数void Print() const;// 日期+=天数Date& operator+=(int day);// 日期+天数Date operator+(int day) const;// 日期-=天数Date& operator-=(int day);// 日期-天数Date operator-(int day) const;// 前置++Date& operator++();// 后置++Date operator++(int);// 前置--Date& operator--();// 后置--Date operator--(int);// 日期的大小关系比较bool operator>(const Date& d) const;bool operator>=(const Date& d) const;bool operator<(const Date& d) const;bool operator<=(const Date& d) const;bool operator==(const Date& d) const;bool operator!=(const Date& d) const;// 日期-日期int operator-(const Date& d) const;// 析构,拷贝构造,赋值重载可以不写,使用默认生成的即可private:int _year;int _month;int _day;
};

上述代码表示了这次要实现的类,包括了多种运算符的重载,以及构造函数,相似的操作符,我们只实现一个。

日期类的析构和拷贝赋值函数不用写用默认的,因为日期类用的都是内置类型,没有动态开辟的空间,所以不用考虑深拷贝的问题

构造函数

// 获取某年某月的天数
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];if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){//闰年2月的天数day = 29;}return day;
}
// 构造函数
Date::Date(int year, int month, int day)
{// 检查日期的合法性if (year >= 0&& month >= 1 && month <= 12&& day >= 1 && day <= getmonthday(year, month)){_year = year;_month = month;_day = day;}else{// 严格来说抛异常更好cout << "非法日期" << endl;cout << year << "年" << month << "月" << day << "日" << endl;exit(1);}
}

上述代码解析:

一.getmonthday:这个函数用来判断是哪一年的哪一个月有几天

细节:

1.用static或者全局变量开辟dayArray[13],好处在于:节省每次调用函数时重复制造dayArray[13]。

2.inline内联函数,因为在Date对象进行++ -- 还有构造函数等多个函数都要用到getmonthday,所以用内联在调用的地方直接展开,省去了调用函数时找地址的时间消耗。

二.构造函数:构造函数很简单,但对于日期而言,每个月没有32天,没有13月,所以在构造函数要对传入的参数进行审批。错了以后直接exit退出。


operator+=和operator-=

为什么二者要一起讲,因为可以二者可以复用。

+=

// 日期+=天数
Date& Date::operator+=(int day)
{if (day<0){// 复用operator-=*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-=(int day)
{if (day < 0){// 复用operator+=*this += -day;}else{_day -= day;// 日期不合法,通过不断调整,直到最后日期合法为止while (_day <= 0){_month--;if (_month == 0){_year--;_month = 12;}_day += GetMonthDay(_year, _month);}}return *this;
}

 对于上述代码:和+= 相同,-=只考虑下限不考虑上限。所以负数时复用+=。

 记住:减法考虑下限,加法考虑上限,负数考虑复用

operator+

// 日期+天数
Date Date::operator+(int day) const
{Date tmp(*this);// 拷贝构造tmp,用于返回// 复用operator+=tmp += day;return tmp;
}

对于上述代码:

1.我们复用了+= 。

2.为什么要用拷贝构造:参考int 时的加法;如果只是单纯的+1那对i并不影响,而如果是将i + 1赋值给i 那才会对 i 造成影响。所以拷贝构造出一份新的对象,返回这个新对象。而不是在原对象上更改

int i = 0;
i+1;
i = i + 1;

operator- 和 + 同理。 

前置++和后置++

和内置类型一样,前置++返回的是修改后的内容,后置++修改值,但是返回的是没++的内容。

前置++

// 前置++
Date& Date::operator++()
{// 复用operator+=*this += 1;return *this;
}

可以看到我们之间返回了*this,并且直接更改的*this。 

后置++

// 后置++
Date Date::operator++(int)
{Date tmp(*this);// 拷贝构造tmp,用于返回// 复用operator+=*this += 1;return tmp;
}

后置++因为我们要返回的值是修改前的,所以我们拷贝构造后返回tmp,但不能引用!!!局部变量后续会销毁,但是传值传出去的是复制体,所以要用传值返回

前置--和后置--同理。

比较运算符

operator==

这里以==为例,其他的符号只是逻辑不同但是代码是类似的。

但值得一提的有:>= 可以复用 operator> 和 operator==. <= 同理。

bool Date::operator==(const Date& d) const
{return _year == d._year&&_month == d._month&&_day == d._day;
}

把该判断的都判断了就对了。

日期-日期

日期类的计算难点就在于,日期的进位,但是对于日期相减是有一个取巧的方法滴。

日期-日期,算天数,我们可以找到较大的日期,然后用较小的日期一直+1,直到 == 较大的日期。中间在用一个变量一直计算+了多少个1.就可以实现了。

// 日期-日期
int Date::operator-(const Date& d) const
{Date max = *this;// 假设第一个日期较大Date min = d;// 假设第二个日期较小int flag = 1;// 此时结果应该为正值if (*this < d){// 假设错误,更正max = d;min = *this;flag = -1;// 此时结果应该为负值}int n = 0;// 记录所加的总天数while (min != max){min++;// 较小的日期++n++;// 总天数++}return n*flag;
}

相关文章:

C++日期类详解 第二级支线任务

日期类的整体 class Date { public:// 构造函数Date(int year 0, int month 1, int day 1);// 打印函数void Print() const;// 日期天数Date& operator(int day);// 日期天数Date operator(int day) const;// 日期-天数Date& operator-(int day);// 日期-天数Date …...

java--通用启动/停止shell脚本

脚本 #!/bin/bash# 定义超时时间&#xff08;秒&#xff09; timeout10# 检查命令参数 case "$1" instart|stop|restart|help)action"$1"jar_file"$2";;*)echo "Usage: $0 {start|stop|restart|help} [jar_file]"exit 1;; esac# 定义…...

Flutter-底部选择弹窗(showModalBottomSheet)

前言 现在有个需求&#xff0c;需要用底部弹窗来添加定时的重复。在这里使用原生的showModalBottomSheet来实现 showModalBottomSheet的Props 名称 描述 isScrollControlled全屏还是半屏isDismissible外部是否可以点击&#xff0c;false不可以点击&#xff0c;true可以点击&a…...

Linux——k8s认识

计算资源隔离 - 更方便进行高并发架构的维护和升级 - 架构管理的灵活性更高&#xff0c;不再以单个节点的物理资源作为基础 技术&#xff1a; - 硬件辅助虚拟化 - 容器技术 在企业部署方案中&#xff0c;很少以单节点实现虚拟化和容器技术&#xff0c;一般以集群状态来运…...

EC Shop安装指南 [ Apache PHP Mysql ]

这个是软件测试课上老师布置的一个作业&#xff0c;期间老师也出现了不少错误&#xff0c;所以还是有必要记录一下吧&#xff0c;凑一篇文章 主要是老师的文档以及自己的一些尝试记录&#xff0c;试错记录&#xff0c;解决方案等 主要介绍了Apache的安装&#xff0c;MySQL的安…...

无线感知会议系列【3】【基于WiFi和4G/5G的非接触无线感知:挑战、理论和应用-1】

前言&#xff1a; 2020年北京智源大会 张大庆老师的一个报告 参考链接&#xff1a; 基于WiFi和4G/5G的非接触无线感知&#xff1a;挑战、理论和应用_哔哩哔哩_bilibili 目录&#xff1a; 无线感知简介 无线感知的核心 研究方向 Frsenel 模型 基于Fresnel 感知的应用举例…...

Virtuoso服务在centos中自动停止的原因分析及解决方案

目录 前言1. 问题背景2. 原因分析2.1 终端关闭导致信号12.2 nohup命令的局限性 3. 解决方案3.1 使用 screen 命令保持会话3.2 使用 tmux 作为替代方案3.3 使用系统服务&#xff08;systemd&#xff09; 4. 其他注意事项4.1 网络配置4.2 日志监控 结语 前言 在使用Virtuoso作为…...

泽众P-One性能测试平台火焰图帮助定位产品性能问题

在软件开发过程中&#xff0c;性能问题往往是最头疼的问题之一。随着软件系统的日益复杂&#xff0c;快速准确地定位并解决性能问题变得尤为重要。泽众P-One作为一站式性能测试平台&#xff0c;通过引入火焰图性能分析可视化工具&#xff0c;极大地提升了性能问题的定位效率和解…...

数据结构修炼——顺序表和链表的区别与联系

目录 一、线性表二、顺序表2.1 概念及结构2.2 接口实现2.3 一些思考以及顺序表的缺点 三、链表3.1 概念及结构3.2 链表的分类3.3 链表的实现3.3.1 无头单向非循环链表3.3.2 带头双向循环链表 四、顺序表和链表的区别 一、线性表 线性表&#xff08;linear list&#xff09;是n…...

AD9854 为什么输出波形幅度受限??

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…...

在grafana上配置显示全部node资源信息概览

在grafana上配置显示全部node资源信息概览&#xff0c;便于巡检 1&#xff0c;注册grafana官网账号&#xff1a;Grafana dashboards | Grafana Labs&#xfeff; 2、寻找可以展示所有node资源概览信息的dashboard&#xff0c;并下载支持prometheus数据源的dashboard&#xff…...

MySQL —— 索引

索引的概念 MySQL的索引是⼀种数据结构&#xff0c;它可以帮助数据库高效地查询、更新数据表中的数据。索引通过 ⼀定的规则排列数据表中的记录&#xff0c;使得对表的查询可以通过对索引的搜索来加快速度。 MySQL索引类似于书籍的目录&#xff0c;通过指向数据行的位置&…...

(已解决)vscode如何选择python解释器

文章目录 前言解决方案 前言 有的时候可能有不同版本的编译器&#xff0c;以适用不同年份的项目。所以&#xff0c;怎么在vscode中换python解释器呢&#xff1f; 解决方案 对着要运行的python文件进行右键&#xff0c;比如我是要运行main文件&#xff0c;点击那个命令选项版…...

sql刷题常用函数

ROW_NUMBER() ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) 是一个窗口函数&#xff0c;用于生成每个分组内的唯一行号。这个函数非常适合在分组数据中进行排序&#xff0c;并为每一行分配一个序号。下面是对你的具体示例的详细解释&#xff1a; ROW_NUMBER() OVER (…...

Golang | Leetcode Golang题解之第417题太平洋大西洋水流问题

题目&#xff1a; 题解&#xff1a; type pair struct{ x, y int } var dirs []pair{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}func pacificAtlantic(heights [][]int) (ans [][]int) {m, n : len(heights), len(heights[0])pacific : make([][]bool, m)atlantic : make([][]bool, …...

Acwing Hash表

哈希表的作用&#xff1a;把一个比较大的空间&#xff0c;通过一个函数映射到一个比较小的空间 一般做哈希运算时&#xff0c;取一个质数作为模&#xff0c;会使得冲突的概率降低。 哈希表的冲突解决方法&#xff1a; 拉链法开放寻址法 下面详细介绍这两种方法的原理及其实现…...

大健康裂变分销小程序开发

大健康裂变分销小程序的开发是一个涉及技术、市场策略、用户体验和合规性等多个方面的综合项目。这类小程序旨在通过分销机制促进大健康产品的销售和品牌推广&#xff0c;同时利用社交网络的裂变效应扩大市场影响力。以下是大健康裂变分销小程序开发的主要步骤和考虑因素&#…...

js取出一个对象中指定的字段(封装公共方法)

需求&#xff1a;在一个对象里面挑选出所需要的一个或多个字段 例子&#xff1a;在{ a: 1, b: 2, c: 3, d: 4 }里面挑选出b和d字段 封装公共方法 const pick (obj, keys) > {return Object.keys(obj).filter(key > keys.includes(key)).reduce((result, key) > {if …...

【黑马点评】已解决java.lang.NullPointerException异常

Redis学习Day3——黑马点评项目工程开发-CSDN博客 问题发现及描述 在黑马点评项目中&#xff0c;进行到使用Redis提供的Stream消息队列优化异步秒杀问题时&#xff0c;我在进行jmeter测试时遇到了重大的错误 发现无论怎么测试&#xff0c;一定会进入到catch中&#xff0c;又由…...

计算机专业的就业方向

计算机专业的就业方向 亲爱的新生们&#xff0c;欢迎你们踏上计算机科学的旅程&#xff01;作为一名计算机专业的学生&#xff0c;你们即将进入一个充满无限可能的领域。今天&#xff0c;我将为大家介绍计算机专业的一些主要就业方向&#xff0c;帮助你们了解未来的职业选择。…...

隧道裂缝剥落病害AI识别系统

我国现有公路隧道超2.5万座&#xff0c;总里程超2.8万公里&#xff0c;其中运营超过15年的老旧隧道占比达35%。据交通运输部2025年统计&#xff0c;年均因隧道结构病害导致的交通中断超1200次&#xff0c;直接经济损失超45亿元。传统检测模式暴露四大核心痛点&#xff1a;检测周…...

AMLP:基于大语言模型的自动化机器学习势函数构建平台

1. 项目概述&#xff1a;当AI遇见原子模拟&#xff0c;AMLP如何重塑机器学习势函数构建在计算材料科学和化学物理领域&#xff0c;分子动力学模拟是我们窥探微观世界动态行为的“显微镜”。无论是研究新材料的相变过程&#xff0c;还是探索生物大分子的折叠机制&#xff0c;其核…...

从Gamma函数到泊松分布:一个概率论中的含参量积分实用案例解析

Gamma函数与泊松分布&#xff1a;概率论中的数学之美 在数据科学和机器学习的实践中&#xff0c;概率分布构成了建模的基石。当我们深入探究这些分布背后的数学原理时&#xff0c;Gamma函数以其优雅的性质和广泛的应用脱颖而出。它不仅连接了离散与连续概率世界&#xff0c;更在…...

Claude本地化部署终极方案(企业级容器化全栈手册):支持Anthropic API兼容、流式响应、模型热切换与RBAC权限隔离

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;Claude本地化部署的架构全景与企业级价值定位 Claude本地化部署并非简单地将模型权重下载后运行&#xff0c;而是一套融合推理引擎优化、安全沙箱隔离、API网关治理与可观测性集成的端到端架构体系。其核心目…...

[智能体-81]:工程化智能体 = 模型做脑力拆解 + 框架做流程落地。前者是决策者,后者是管理者,tools/function call是内部员工;mcp server是外部资源;

一、全角色人设 & 对应技术组件角色定位对应技术模块核心职责决策者&#xff08;脑力大脑&#xff09;大模型 LLM理解目标、任务拆解、逻辑判断、分支决策、内容生成&#xff0c;负责 “想方案、定步骤”管理者&#xff08;流程总管&#xff09;智能体编排框架&#xff08;…...

flameshow性能优化技巧:如何快速定位Go程序中的CPU热点

flameshow性能优化技巧&#xff1a;如何快速定位Go程序中的CPU热点 【免费下载链接】flameshow A terminal Flamegraph viewer. 项目地址: https://gitcode.com/gh_mirrors/fl/flameshow &#x1f525; 想要快速定位Go程序中的性能瓶颈吗&#xff1f;flameshow是一个强大…...

收藏干货|2026 版企业 AI 落地实操指南,程序员小白入门避坑必备

如今人工智能早已脱离概念炒作阶段&#xff0c;全面扎根企业实际业务场景&#xff0c;成为技术从业者与企业管理者无法回避的发展课题。各行各业都加速布局AI赛道&#xff0c;行业心态也从初期观望试探&#xff0c;彻底转变为实打实的落地攻坚。 不少企业高层主动牵头统筹AI规划…...

基于Cynthion逆向USB协议,为DP100电源开发Linux控制软件

1. 项目概述&#xff1a;用Cynthion嗅探USB&#xff0c;为DP100电源打造Linux软件作为一名长期在Linux环境下折腾硬件和嵌入式开发的爱好者&#xff0c;我经常遇到一个头疼的问题&#xff1a;很多不错的桌面小设备&#xff0c;比如电源、示波器、逻辑分析仪&#xff0c;它们的官…...

XXPermissions:Android权限管理框架的架构设计与最佳实践

XXPermissions&#xff1a;Android权限管理框架的架构设计与最佳实践 【免费下载链接】XXPermissions Android Permissions Framework, Adapt to Android 16 项目地址: https://gitcode.com/GitHub_Trending/xx/XXPermissions 在Android应用开发中&#xff0c;权限管理一…...

UE5项目打包后RenderTarget导出图片全黑?手把手教你解决伽马校正与资产打包问题

UE5打包后RenderTarget导出图片全黑的终极解决方案当你花了整整三天时间调试RenderTarget导出功能&#xff0c;终于在编辑器里看到完美的截图效果&#xff0c;却在打包成可执行文件后发现所有导出的图片都变成了一片漆黑——这种从云端跌入谷底的感觉&#xff0c;每个UE开发者都…...