当前位置: 首页 > 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;帮助你们了解未来的职业选择。…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...