普象工业设计网站,佛山新网站建设代理商,当下最热的网页制作工具,最简单的做网站的软件目录 Ⅰ. 引入
Ⅱ. 列轮廓
Ⅲ. 功能的实现
构造函数
Print
判断是否相等 | !
➡️:
➡️!:
判断大小 | | |
➡️#xff1a;
➡️#xff1a;
➡️#xff1a;
➡️#xff1a;
加减天数 | | - | -
➡️#xff1a;…目录 Ⅰ. 引入
Ⅱ. 列轮廓
Ⅲ. 功能的实现
构造函数
Print
判断是否相等 | !
➡️:
➡️!:
判断大小 | | |
➡️
➡️
➡️
➡️
加减天数 | | - | -
➡️
➡️ ➡️-
➡️-
自增/自减 | --
➡️前置
➡️后置
➡️前置--
➡️后置--
日期减日期
➡️Way1推荐
➡️Way2 这个思路繁杂很多 Ⅰ. 引入
本篇我们用C来实现一个日期计算器。
想知道迄今为止你在地球上一共度过了多少天吗距离寒假还有多少天呢一百天后会是几月几号呢
解开这些问题的答案只需来写一个日期计算器~
日期计算器是C入门以来的第一个小项目亲自实践一遍我们在C上的经验值将⬆️⬆️⬆️ 我们将分三步 Step1在头文件中把日期类的大体轮廓列出来 Step2把声明的功能一一实现 Step3逐个测试。我们写一点测一点。 这样就可顺利把日期计算器写出个七七八八。
在遇到较复杂的算法时我会提供思路。
至于某些锦上添花的功能我们后续想到了再添上去。 Ⅱ. 列轮廓
我们先来定义一个日期类同时看看要实现哪些功能
#pragma once
#includeiostream
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
➡️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 unequalendl;}
}
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 *thisday;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;先使用再加加。返回的是加加前的值。 假设d0d返回1d1 d返回0同时实现自增d1 所以说后置加加是不能引用返回的。而前置可以。 ➡️前置
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) {Mored;Less*this;}
int count 0; //用计数法算差值while (LessMore) {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, 到这我们的日期计算器已经完成啦~