基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程_第1頁
基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程_第2頁
基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程_第3頁
基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程_第4頁
基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程_第5頁
已閱讀5頁,還剩11頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程目錄一、前言二、日期類的實(shí)現(xiàn)檢查日期的合法性運(yùn)算符重載==運(yùn)算符重載=運(yùn)算符重載運(yùn)算符重載=運(yùn)算符重載!=運(yùn)算符重載改進(jìn)和優(yōu)化日期+天數(shù)日期+=天數(shù)日期-=天數(shù)日期-天數(shù)前置++后置++前置--后置--日期-日期三、總結(jié)

一、前言

在我們的日常生活中,我們可能需要計(jì)算幾天后的日期,或計(jì)算日期差等,現(xiàn)如今計(jì)算日期的方式有很多,簡單粗暴的直接查看日歷,快捷點(diǎn)的直接使用日期計(jì)算器來求得,先給一個(gè)網(wǎng)絡(luò)上的日期計(jì)算器截圖:

現(xiàn)在,就讓我們用代碼來實(shí)現(xiàn)其工作原理吧。

注意:本篇日期類.h文件放聲明,.cpp文件放定義

二、日期類的實(shí)現(xiàn)

檢查日期的合法性

實(shí)現(xiàn)日期類首先就得檢查日期的合法性,這其中就包括大小月,閏年的2月有29天,一年只有12個(gè)月等等細(xì)節(jié)都要考慮到。

classDate

public:

boolisLeapYear(intyear)//判斷是否為閏年

//四年一閏百年不閏或四百年一閏

return(year%4==0year%100!=0)||(year%400==0);

staticintGetMonthDay(intyear,intmonth)

//加上static防止函數(shù)頻繁調(diào)用開辟幾十個(gè)字節(jié)大小的數(shù)組,最好加上

intmonthDayArray[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};

if(month==2isLeapYear(year))

return29;//閏月29天

else

returnmonthDayArray[month];

Date(intyear=1,intmonth=1,intday=1)

if(year=1month=12month=1day=GetMonthDay(year,month))

//確保日期合法

_year=year;

_month=month;

_day=day;

private:

int_year;

int_month;

int_day;

};

運(yùn)算符重載

思路:

運(yùn)算符重載在我上一篇博文已經(jīng)詳細(xì)講解過,主要是先把大于的情況全部統(tǒng)計(jì)出來,就比如我要比較實(shí)例化對象d1是否小于實(shí)例化對象d2,只需考慮如下三種滿足的情況:

d1的年小于d2的年d1與d2年相等,d1的月小于d2的月d1與d2年相等月相等,d1的天小于d2的天

這三種全是小于的情況,返回true,其余返回false

代碼如下:

//運(yùn)算符重載

boolDate::operator(constDated)const//類外訪問成員函數(shù)需要設(shè)定類域

if(_yeard._year||

_year==d._year_monthd._month||

_year==d._year_month==d._month_dayd._day)

returntrue;

else

returnfalse;

}

==運(yùn)算符重載

思路:

==運(yùn)算符重載其實(shí)非常簡單,只需要判斷d1和d2的年、月、天是否對應(yīng)相等即可:

代碼如下:

//==運(yùn)算符重載

boolDate::operator==(constDated)const

return_year==d._year

_month==d._month

_day==d._day;

}

=運(yùn)算符重載

思路:--復(fù)用

=的運(yùn)算符重載,這里要仔細(xì)想一想=成立的條件是啥。不就是要么要么=嗎?我們只需要復(fù)用先前寫的運(yùn)算符重載和=運(yùn)算符重載,無需自己費(fèi)老大勁推導(dǎo)其內(nèi)部原理。

代碼如下:

//=運(yùn)算符重載

boolDate::operator=(constDated)const

return*thisd||*this==d;

}

運(yùn)算符重載

思路:--復(fù)用

的反義就是=,所以我們只需要復(fù)用=運(yùn)算符重載,再對其取反即可解決此問題。

代碼如下:

//運(yùn)算符重載

boolDate::operator(constDated)const

return!(*this=d);

}

=運(yùn)算符重載

思路:--復(fù)用

=的反義就是,所以我們只需要復(fù)用運(yùn)算符重載,再對其取反即可。

代碼如下:

//=運(yùn)算符重載

boolDate::operator=(constDated)const

return!(*this

}

!=運(yùn)算符重載

思路:--復(fù)用

有了前面的基礎(chǔ),寫個(gè)!=也很簡單,對==取反即可

代碼如下:

//!=運(yùn)算符重載

boolDate::operator!=(constDated)const

return!(*this==d);

}

改進(jìn)和優(yōu)化

上述我們寫的運(yùn)算符重載都是建立在聲明定義分離的,這里我們可以對其進(jìn)行優(yōu)化,如下:

先前我們學(xué)過內(nèi)聯(lián),可以幫助我們對于短小函數(shù)減少函數(shù)調(diào)用而引發(fā)的效率損失問題,因此我們可以把上述幾個(gè)運(yùn)算符重載函數(shù)放成內(nèi)聯(lián),此外,有一種簡單粗暴的方法:直接在類里定義,因?yàn)轭惱锏暮瘮?shù)默認(rèn)內(nèi)聯(lián),還省的我們自己寫inline,而且我們也不用在類外加上類域了,當(dāng)然,有些長的函數(shù)還是聲明和定義分離比較好。

Date.h文件:

#pragmaonce

#includeiostream

#includeassert.h

usingstd::cout;

usingstd::cin;

usingstd::endl;

classDate

public:

boolisLeapYear(intyear)

//四年一潤百年不潤或四百年一潤

return(year%4==0year%100!=0)||(year%400==0);

//獲取某月天數(shù)

intGetMonthDay(intyear,intmonth);

//構(gòu)造函數(shù)

Date(intyear=1,intmonth=1,intday=1);

//打印

voidPrint()const

cout_year"-"_month"-"_dayendl;

//運(yùn)算符重載

booloperator(constDated)const;

//==運(yùn)算符重載

booloperator==(constDated)const;

//=運(yùn)算符重載

booloperator=(constDated)const

return*thisd||*this==d;

//運(yùn)算符重載

booloperator(constDated)const

return!(*this=d);

//return(d*this);

//=運(yùn)算符重載

booloperator=(constDated)const

return!(*this

//!=運(yùn)算符重載

booloperator!=(constDated)const

return!(*this==d);

private:

int_year;

int_month;

int_day;

};

Date.cpp文件:

#include"Date.h"

//獲取某月天數(shù)

intDate::GetMonthDay(intyear,intmonth)

assert(year=0month0month13);

staticintmonthDayArray[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};

if(month==2isLeapYear(year))

return29;

else

returnmonthDayArray[month];

//構(gòu)造函數(shù)

Date::Date(intyear,intmonth,intday)

if(year=1month=12month=1day=GetMonthDay(year,month))

_year=year;

_month=month;

_day=day;

else

cout"日期非法"endl;

//運(yùn)算符重載

boolDate::operator(constDated)const//類外訪問成員函數(shù)需要設(shè)定類域

if(_yeard._year||

_year==d._year_monthd._month||

_year==d._year_month==d._month_dayd._day)

returntrue;

else

returnfalse;

//==運(yùn)算符重載

boolDate::operator==(constDated)const

return_year==d._year

_month==d._month

_day==d._day;

}

日期+天數(shù)

思路:

對于日期+天數(shù),我們得到的還是一個(gè)日期。特別需要注意進(jìn)位的問題(天滿了往月進(jìn),月滿了往年進(jìn)),主要考慮如下幾個(gè)特殊點(diǎn):

加過的天數(shù)超過該月的最大天數(shù),需要進(jìn)位

當(dāng)月進(jìn)位到13時(shí),年進(jìn)位+1,月置為1

法一:

DateDate::operator+(intday)const

Dateret(*this);//拷貝構(gòu)造,拿d1去初始化ret

ret._day+=day;

while(ret._dayGetMonthDay(ret._year,ret._month))

ret._day-=GetMonthDay(ret._year,ret._month);

ret._month++;

if(ret._month==13)

ret._year++;

ret._month=1;

returnret;

}

出了作用域,對象ret不在,它是一個(gè)局部對象,我們這里不能用引用,用了的話,返回的就是ret的別名,但是ret又已經(jīng)銷毀了,訪問野指針了,所以出了作用域,如果對象不在了,就不能用引用返回,要用傳值返回

法二:復(fù)用日期+=天數(shù)

此法是建立在日期+=天數(shù)的基礎(chǔ)上完成的,這里各位可以先看下文日期+=天數(shù),然后我們進(jìn)行復(fù)用:

DateDate::operator+(intday)const

//法二:復(fù)用日期+=天數(shù)

Dateret(*this);

ret+=day;

returnret;

}

法一和法二熟優(yōu)?

答案:法二更好,也就是用+去復(fù)用+=,具體原因在下文會(huì)解釋。

日期+=天數(shù)

這里實(shí)現(xiàn)+=其實(shí)有兩種方案

法一:

前面我實(shí)現(xiàn)的日期+天數(shù),仔細(xì)觀察我的代碼,函數(shù)的第一行,我就調(diào)用了一個(gè)拷貝構(gòu)造:

Dateret(*this);//拷貝構(gòu)造,拿d1去初始化ret

這里調(diào)用拷貝構(gòu)造,是為了不在*this本身上做變動(dòng),只在ret上進(jìn)行操作,其理由是日期+天數(shù)得到的是另一個(gè)日期,而不用拷貝構(gòu)造直接在*this上做改動(dòng)只會(huì)導(dǎo)致原有的日期也變化,而這個(gè)變化正是我日期+=天數(shù)的需求

仔細(xì)想想:+=天數(shù)就是在原有的日期上再加一定的天數(shù),直接對*this做手腳即可,因此只需對日期+天數(shù)的代碼進(jìn)行小改動(dòng)即可:

DateDate::operator+=(intday)//傳引用返回

//如果day小于0,要單獨(dú)處理

if(day0)

return*this-=-day;

_day+=day;

while(_dayGetMonthDay(_year,_month))

_day-=GetMonthDay(_year,_month);

_month++;

if(_month==13)

_year++;

_month=1;

return*this;

}

注意這里是傳引用返回,原因就在于我返回的*this是全局的,出了作用域還在

法二:復(fù)用日期+天數(shù)

DateDate::operator+=(intday)

//法二:復(fù)用

*this=*this+day;//讓d1+過天數(shù)后再返回給自己從而實(shí)現(xiàn)+=

return*this;

}

法一和法二熟優(yōu)?

答案:法一。其實(shí)討論這個(gè)問題就是在討論用+去復(fù)用+=號還是用+=復(fù)用+號,答案是用+去復(fù)用+=好,因?yàn)?有兩次拷貝,而+=沒有拷貝,所以實(shí)現(xiàn)+=,并且用+去復(fù)用+=效率更高

日期-=天數(shù)

思路:

日期-=天數(shù)得到的還是一個(gè)日期,且是在原日期的基礎(chǔ)上做改動(dòng)。合法的日期減去天數(shù)后的day只要0就沒問題,若小于0就要借位了。要注意當(dāng)減去的天數(shù)0時(shí)單獨(dú)討論。具體步驟如下:

當(dāng)減的天數(shù)為負(fù)數(shù),則為+=,直接調(diào)用若減后的day0,月-1若月=0,則年-1,月置為12

代碼如下:

//日期-=天數(shù)d1-=100

DateDate::operator-=(intday)

//如果減去的天數(shù)是負(fù)數(shù),要單獨(dú)處理,直接調(diào)用+=運(yùn)算符重載

if(day0)

return*this+=-day;

_day-=day;

while(_day=0)

--_month;

if(_month==0)

_month=12;

--_year;

_day+=GetMonthDay(_year,_month);

return*this;

}

日期-天數(shù)

有了先前日期+和+=的基礎(chǔ),這里實(shí)現(xiàn)日期-天數(shù)直接復(fù)用日期-=天數(shù)即可:

//日期-天數(shù)

DateDate::operator-(intday)const

Dateret(*this);

ret-=day;

returnret;

}

前置++

思路:

C++里有前置++和后置++,這就導(dǎo)致一個(gè)巨大的問題,該如何區(qū)分它們,具體實(shí)現(xiàn)過程不難(直接復(fù)用+=即可),難的是如何區(qū)分前置和后置。因此C++規(guī)定,無參的為前置,有參的為后置。

代碼如下:

//前置++

DateDate::operator++()//無參的為前置

*this+=1;//直接復(fù)用+=

return*this;

}

后置++

思路:

有參的即為后置,后置++拿到的返回值應(yīng)該是自己本身未加過的,因此要先把自己保存起來,再++*this,隨后返回自己。

代碼如下:

//后置++

DateDate::operator++(inti)//有參數(shù)的為后置

Datetmp(*this);

*this+=1;//復(fù)用+=

returntmp;

}

前置--

思路:

前置--和前置++沒啥區(qū)別,只不過內(nèi)部復(fù)用的是-=

代碼如下:

//前置--

DateDate::operator--()//無

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論