赞
踩
根据我们对C++特性的学习,我们现在可以尝试下一些新玩法,来强化我们对C++的理解。
在现代的软件开发中,日期作为一个常见的基础需求,广泛用于各类系统的日程管理,数据分析,交易记录等场景。但是C++库中的时间日期功能比较有限,无法满足复杂的开发需求。为此我们需要开发一款简单高效的“日期类”C++项目。
以上就是该项目的基本需求,请务必确保程序的健壮性与可维护性。
该部分我们给出以下框架:
class Date{ public: // 获取某年某月的天数 int GetMonthDay(int year, int month); //展示日期 void show(); // 全缺省的构造函数 Date(int year = 1900, int month = 1, int day = 1); // 拷贝构造函数 // d2(d1) Date(const Date& d); // 析构函数 ~Date(); //--------------------------------------------------------------- // 赋值运算符重载 // d2 = d3 -> d2.operator=(&d2, d3) Date& operator=(const Date& d); // 日期+=天数 Date& operator+=(int day); // 日期+天数 Date operator+(int day); // 日期-天数 Date operator-(int day); // 日期-=天数 Date& operator-=(int day); // 前置++ Date& operator++(); // 后置++ Date operator++(int); // 后置-- Date operator--(int); // 前置-- Date& operator--(); //------------------------------------------------------------- // >运算符重载 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); // 日期-日期 返回天数 int operator-(const Date& d); //----------------------------------------------- // 转换为字符串“ YYYY-MM-DD ” string toString() const; //通过字符串构建对象 static Date fromString(const string& dateStr); private: int _year; int _month; int _day; };
这里给出较为全面的框架:
成员变量:私有成员变量 _year、_month 和 _day 分别表示年份、月份和日期。
构造函数:
全缺省构造函数,默认日期为1900年1月1日。
拷贝构造函数,复制给定日期对象的所有信息。
赋值运算符重载 (operator=):用于拷贝另一个Date对象的日期信息到当前对象。
算术运算符重载:
+= 和 -= 运算符用于日期增加或减少指定天数。
+和 - 运算符分别用于返回增加或减少指定天数后的日期对象,以及两个日期之间的天数差。
自增/自减运算符重载:
前缀和后缀形式的 ++ 与 – 运算符,用于向前或向后移动一天。
关系运算符重载:
<、>、>=、<= 和 == 分别用于比较两个日期的大小关系。
!= 判断两个日期是否不相等。
方法:
show() 用于输出日期。
GetMonthDay() 根据年份和月份获取该月的天数,考虑了闰年的特殊情况。
析构函数:
简单地将日期成员变量设为0,但在实际应用中这通常不是必要的,因为类的生命周期结束后,系统会自动释放其占用的内存资源。
下面我们逐一实现功能:
首先我们需要提供一个全缺省的构造函数,方便对象的实例化。
这里我们提供默认的(1900 -1- 1)作为缺省值
Date::Date(int year , int month , int day ) {
_year = year;
_month = month;
_day = day;
}
然后我们还需要一个拷贝构造函数,让我们更加灵活的创建对象
Date::Date(const Date& d) {
_year = d._year;
_month = d._month;
_day = d._day;
}
析构函数简单一写即可,因为我们没有开辟空间,不需要考虑复杂问题。
这里我们需要实现:
= + - += -= 前置++ 后置++ 前置-- 后置–
加和减原理类似,讲解中只以加为例,详细代码请看结尾全部代码。
注意返回值类型,这里传回引用,效率更好。
Date& Date::operator=(const Date& d) {
_year = d._year;
_month = d._month;
_day = d._day;
//灵活使用this指针
return *this;
}
这里我们先实现+= 之后再实现+,这样可以避免多次创建变量,效率更高。
首先对于+= 我们需要准确知道该月的月份,保证日期的有效性。
int Date::GetMonthDay(int year, int month) {
int day[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 day[month];
}
完成+=重载
Date& Date::operator+=(int day) {
_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) {
Date temp(*this);
temp += day;
return temp;
}
前置后置这里使用了不同参数来做区分。不得感叹祖师爷的巧妙。
//前置++
Date& Date::operator++() {
//直接返回+=后答案即可
return *this += 1;
}
//后置++ 不能传引用
Date Date::operator++(int) {
//创建一个临时变量来储存 ++前的值
Date temp(*this);
*this += 1;
//返回++前的值
return temp;
}
这里十分巧妙,我们只需要实现== > 即可通过巧妙使用完成全部操作符重载:
bool Date::operator==(const Date& d) { return d._year == _year && d._month == _month && d._day == _day; } bool Date::operator>(const Date& d) { if (_year < d._year) return false; else if (_month < d._month) return false; else if (_day < d._day) return false; else return true; } 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); }
这里使用朴素算法,逐渐++到较大日期即可即可
//注意正负 int Date::operator-(const Date& d) { //默认前值大 int flag = 1; Date max = *this; Date min = d; if (max < min) { flag = -1; max = d; min = *this; } int day = 0; while (min != max){ min++; day++; } return flag * day; }
使用库函数轻松实现:
string Date::toString() const {
char buffer[11]; // 预留足够的空间存储 "YYYY-MM-DD"
snprintf(buffer, sizeof(buffer), "%04d-%02d-%02d", _year, _month, _day);
return string(buffer);
}
这一步比较复杂:
首先在声明中加入static 保证可以随时调用。
然后需要保证日期的合法性
最后返回类对象
static Date fromString(const string& dateStr); Date Date::fromString(const std::string& dateStr) { int year = 0, month = 0, day= 0; sscanf(dateStr.c_str(), "%d-%d-%d", &year, &month, &day); // 使用sscanf解析字符串 Date d(year,month,day); // 在这里应该添加必要的日期合法性检查 if (month < 1 || month > 12) { throw std::invalid_argument("月份错误\n"); } int maxDays = d.GetMonthDay(year, month); if (day < 1 || day > maxDays) { throw std::invalid_argument("给定月份和年份的日期值无效\n"); } return Date(year, month, day); }
#pragma once #include<iostream> using namespace std; class Date{ public: // 获取某年某月的天数 int GetMonthDay(int year, int month); //展示日期 void show(); // 全缺省的构造函数 Date(int year = 1900, int month = 1, int day = 1); // 拷贝构造函数 // d2(d1) Date(const Date& d); // 析构函数 ~Date(); // 赋值运算符重载 // d2 = d3 -> d2.operator=(&d2, d3) Date& operator=(const Date& d); // 日期+=天数 Date& operator+=(int day); // 日期+天数 Date operator+(int day); // 日期-天数 Date operator-(int day); // 日期-=天数 Date& operator-=(int day); // 前置++ Date& operator++(); // 后置++ Date operator++(int); // 后置-- Date operator--(int); // 前置-- Date& operator--(); // >运算符重载 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); // 日期-日期 返回天数 int operator-(const Date& d); // 转换为字符串“ YYYY-MM-DD ” string toString() const; static Date fromString(const string& dateStr); private: int _year; int _month; int _day; };
#include"Date.h" void Date::show() { printf("%4d 年 %2d 月 %2d 日\n",_year,_month,_day); } int Date::GetMonthDay(int year, int month) { int day[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 day[month]; } Date::Date(int year , int month , int day ) { _year = year; _month = month; _day = day; } Date::Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } Date::~Date() { _year = 0; _month = 0; _day = 0; } Date& Date::operator+=(int day) { _day += day; while (_day > GetMonthDay(_year, _month)) { _day -= GetMonthDay(_year, _month); _month++; if (_month > 12) { _year++; _month = 1; } } return *this; } Date& Date::operator=(const Date& d) { _year = d._year; _month = d._month; _day = d._day; return *this; } Date Date::operator+(int day) { Date temp(*this); temp += day; return temp; } Date& Date::operator-=(int day) { _day -= day; while (_day < 0) { _month--; if (_month < 1) { _year--; _month = 12; } _day += GetMonthDay(_year,_month); } return *this; } Date Date::operator-(int day) { Date temp(day); temp -= day; return temp; } Date& Date::operator++() { return *this += 1; } Date Date::operator++(int) { Date temp(*this); *this += 1; return temp; } Date& Date::operator--() { return *this -= 1; } Date Date::operator--(int) { Date temp(*this); *this -= 1; return temp; } bool Date::operator==(const Date& d) { return d._year == _year && d._month == _month && d._day == _day; } bool Date::operator>(const Date& d) { if (_year < d._year) return false; else if (_month < d._month) return false; else if (_day < d._day) return false; else return true; } 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); } int Date::operator-(const Date& d) { Date max = *this; Date min = d; int flag = 1; if (max < min) { flag = -1; max = d; min = *this; } int day = 0; while (min != max) { min++; day++; } return flag * day; } string Date::toString() const { char buffer[11]; // 预留足够的空间存储 "YYYY-MM-DD" snprintf(buffer, sizeof(buffer), "%04d-%02d-%02d", _year, _month, _day); return string(buffer); } Date Date::fromString(const std::string& dateStr) { int year = 0, month = 0, day= 0; sscanf(dateStr.c_str(), "%d-%d-%d", &year, &month, &day); // 使用sscanf解析字符串 Date d(year,month,day); // 在这里应该添加必要的日期合法性检查 if (month < 1 || month > 12) { throw std::invalid_argument("月份错误\n"); } int maxDays = d.GetMonthDay(year, month); if (day < 1 || day > maxDays) { throw std::invalid_argument("给定月份和年份的日期值无效\n"); } return Date(year, month, day); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。