欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解如何用C++寫(xiě)一個(gè)日期計(jì)算器

 更新時(shí)間:2024年04月21日 10:43:56   作者:東洛的克萊斯韋克  
寫(xiě)一個(gè)日期計(jì)算器是一個(gè)很有現(xiàn)實(shí)意義的,比如,我想弄一個(gè)倒計(jì)時(shí)或者你女朋友問(wèn)你和她認(rèn)識(shí)多少天了,這就需要讓兩個(gè)日期相減,又或者和別人約定幾年以后怎么怎么樣,這就得知道那一天的日期,接下來(lái)小編借給大家介紹一下如何用C++寫(xiě)一個(gè)日期計(jì)算器,感興趣的朋友可以動(dòng)手嘗試

前言

寫(xiě)一個(gè)日期計(jì)算器對(duì)學(xué)習(xí)的意義也很大。初學(xué)C++,接觸了類(lèi)和對(duì)象的概念,又認(rèn)識(shí)了默認(rèn)成員函數(shù),然后又學(xué)習(xí)了運(yùn)算符的重載。而日期計(jì)算器就很好的涵蓋了這些知識(shí)。能很好的幫助我們復(fù)習(xí)學(xué)過(guò)的知識(shí)。

代碼的布局

建兩個(gè) .cpp文件:Date.cpp      Test.cpp

建一個(gè)   .h文件  :Date.h

作用:Date.h聲明一個(gè)類(lèi) ,      Date.cpp類(lèi)的方法的具體實(shí)現(xiàn),      Test.cpp測(cè)試方法的邏輯

d41d4b0d75bf4f7db8b8b103b696539f.png

設(shè)計(jì)數(shù)據(jù)

年:_year     月:_month     日:_day

變量名前面加“  _ ”符號(hào),是為了和普通的數(shù)據(jù)或一些參數(shù)做區(qū)分。增加代碼可讀性。

方法聲明

	// 獲取某年某月的天數(shù)
	int GetMonthDay(int year, int month);
 
	// 全缺省的構(gòu)造函數(shù)
	Date(int year = 2024, int month = 4, int day = 18);
 
	// 拷貝構(gòu)造函數(shù)
	Date(const Date& d);
 
	// 賦值運(yùn)算符重載
	Date& operator=(const Date& d);
 
	// 析構(gòu)函數(shù)
	~Date();
 
	// 日期+=天數(shù)
	Date& operator+=(int day);  //其結(jié)果為日期
 
	// 日期+天數(shù)
	Date operator+(int day);
 
	// 日期-天數(shù)
	Date operator-(int day);
 
	// 日期-=天數(shù)
	Date& operator-=(int day);  
 
	// 前置++
	Date& operator++();  //天數(shù)加1
 
	// 后置++
	Date operator++(int);
 
	// 后置--
	Date operator--(int);  //天數(shù)減1
 
	// 前置--
	Date& operator--();     
 
	// >運(yùn)算符重載
	bool operator>(const Date& d);  //比較日期大小
 
	// ==運(yùn)算符重載
	bool operator==(const Date& d);  
 
	// >=運(yùn)算符重載
	bool operator >= (const Date& d);   
 
	// <運(yùn)算符重載
	bool operator < (const Date& d);   
 
	// <=運(yùn)算符重載
	bool operator <= (const Date& d);  
 
	// !=運(yùn)算符重載
	bool operator != (const Date& d);  
 
	// 日期-日期 返回天數(shù)    
	int operator-(const Date& d);  

聲明的方法要有其意義,比如日期和天數(shù)相乘就沒(méi)有意義,也沒(méi)必要聲明。

方法的實(shí)現(xiàn)

獲取某年某月的天數(shù)

int GetMonthDay(int year, int month);

閏年

一年有365天,但地球公轉(zhuǎn)的周期比一年多了大約5.82個(gè)小時(shí)。所以每過(guò)4年,二月的28天就要變成29天,即4年一潤(rùn)。但每四年都要潤(rùn)一次的話(huà),每過(guò)100年,我們計(jì)算的天數(shù)要比地球公轉(zhuǎn)的天數(shù)多了大概0.75天,所以二月的28天保持不變,即百年不潤(rùn)。100年不潤(rùn)是為了補(bǔ)足4年一潤(rùn)的精度,而400一潤(rùn)是為了補(bǔ)足100年不潤(rùn)的精度。只有這樣,日期才不會(huì)與四季脫離。

總結(jié)就是:四年一潤(rùn),百年不潤(rùn),四百年又一潤(rùn)。

翻譯成計(jì)算機(jī)語(yǔ)言就是

year % 4 == 0 && year % 100 != 0 || year % 400 == 0

有了閏年的概念,那么獲取某年某月的天數(shù)的代碼就可以實(shí)現(xiàn)了

// 獲取某年某月的天數(shù)
int Date::GetMonthDay(int year, int month)    
{
	assert(month > 0 && month < 13);
	
		static int a[13] = { -1,31, 28, 31, 30, 31, 30, 31, 31, 30, 31,30,31 };
		if (2 == month && year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
		{
			return a[month] + 1;
		}
		else
		{
			return a[month];
		}
}

下圖是代碼控制的細(xì)節(jié)

b24768dd22e64e578803dd9ab3418c4f.png

下面加*的函數(shù)不做重點(diǎn)

*全缺省的構(gòu)造函數(shù)

Date(int year = 2024, int month = 4, int day = 18);
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

注意:全缺省構(gòu)造函數(shù)在定義的時(shí)候不需要給缺省值。

拷貝構(gòu)造函數(shù)

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

賦值運(yùn)算符重載

Date& operator=(const Date& d);
Date& Date::operator=(const Date& d) 
{
	if (this != &d)  
	{
		_year = d._year; 
		_month = d._month; 
		_day = d._day;
 
		return *this;
	}
 
	return *this;
}

析構(gòu)函數(shù)

因?yàn)闆](méi)有涉及到資源管理可以不寫(xiě),編譯器會(huì)自動(dòng)生成默認(rèn)的析構(gòu)函數(shù)。

日期+=天數(shù)

Date& operator+=(int day);

思路:可以把要加的天數(shù)直接加到日期的天數(shù)上,如果日期的天數(shù)沒(méi)有超過(guò)該月的最大天數(shù),直接返回日期。如果超過(guò)了,就寫(xiě)個(gè)循環(huán)往前進(jìn)位,直到日期的天數(shù)小于該月的最大天數(shù),然后再返回日期。

邏輯示意圖

78bd766509ef4189a4b6133f7bdda8db.png

代碼

Date& Date::operator+=(int day) 
{
	_day += day; //把天數(shù)加到日期的天數(shù)上
 
	while (_day > GetMonthDay(_year, _month)) //如果日期的天數(shù)大于該月最大天數(shù)就進(jìn)位                                     
                                                           
	{
		_day -= GetMonthDay(_year, _month); //要想進(jìn)位,得把該月的最大天數(shù)減掉
 
		++_month; //進(jìn)位
 
		if (_month > 12) //如果月不合法就調(diào)整月
		{
			++_year;
			_month = 1;
        }
	}
 
	return *this;  //返回日期,因?yàn)槌隽俗饔糜虿粫?huì)銷(xiāo)毀,可以引用返回
}

*this是返回聲明在頭文件中的日期類(lèi),該類(lèi)出了該函數(shù)的作用域不會(huì)銷(xiāo)毀,所以傳引用返回,提高效率。

日期+天數(shù)

Date operator+(int day);

實(shí)現(xiàn)日期+天數(shù)的時(shí)候不用把類(lèi)似于日期+=天數(shù)的邏輯再寫(xiě)一遍,可以直接復(fù)用。

Date Date::operator+(int day)
{
	Date tmp = *this;  //在實(shí)例化對(duì)象的時(shí)候,調(diào)用拷貝構(gòu)造函數(shù),將日期類(lèi)的數(shù)據(jù)拷貝給臨時(shí)對(duì)象
	tmp += day;  //直接復(fù)用+=的邏輯
 
	return tmp;
}

日期加天數(shù)不能改變?nèi)掌诘闹担砸獎(jiǎng)?chuàng)建臨時(shí)對(duì)象。臨時(shí)對(duì)象出了作用域就銷(xiāo)毀了,所以不能傳引用返回。

日期-天數(shù)

Date operator-(int day);

在實(shí)現(xiàn)日期+=天數(shù)和日期+天數(shù)的時(shí)候,先實(shí)現(xiàn)了+=的邏輯,在實(shí)現(xiàn)+的邏輯的時(shí)候復(fù)用+=的邏輯。現(xiàn)在反過(guò)來(lái),先實(shí)現(xiàn)-的邏輯,在實(shí)現(xiàn)-=的邏輯的時(shí)候復(fù)用-的邏輯。

思路:把天數(shù)直接和日期中的天數(shù)相減。若不為負(fù)數(shù),直接返回。若為負(fù)數(shù),則需要寫(xiě)個(gè)循環(huán)不斷向前借位,如果把月借成負(fù)數(shù)就向年借,然后調(diào)整月,再調(diào)整日,直到日大于零為止。因?yàn)槿掌?天數(shù)不改變?nèi)掌?,所以要?jiǎng)?chuàng)建臨時(shí)的對(duì)象。

代碼

Date Date::operator-(int day)
{
	Date d = (*this); //創(chuàng)建臨時(shí)對(duì)象,把日期類(lèi)的數(shù)據(jù)拷貝給臨時(shí)對(duì)象
 
	d._day -= day;  //讓日期的天數(shù)直接和天數(shù)相減
 
	while (d._day <= 0)  //日期的天數(shù)小于零就調(diào)整
	{
		--d._month;  //該月已經(jīng)是負(fù)的,應(yīng)該往下個(gè)月借天數(shù)
 
		if (d._month <= 0)  //月不合法就調(diào)整月
		{
			--d._year;
			d._month = 12;
		}
 
		d._day += GetMonthDay(d._year, d._month); //把該月的所有天數(shù)都借給日期的天數(shù)
	}
 
	return d; 
 
}

邏輯示意圖

34f95c1cf11f4be78a9fb98f646f85e0.png

因?yàn)榕R時(shí)對(duì)象出了作用域要銷(xiāo)毀,所以不能傳引用返回。

日期-=天數(shù)

Date& operator-=(int day); 

直接復(fù)用-的邏輯,代碼如下

Date& Date::operator-=(int day)
{
	return *this = *this - day;
}

前置++

Date& Date::operator++() 

實(shí)現(xiàn)前置++就不需要復(fù)雜的邏輯了,只需要控制年月日的進(jìn)位即可。代碼如下

Date& Date::operator++()  //前置++需要先++在使用,所以不需要?jiǎng)?chuàng)建臨時(shí)對(duì)象,返回值可以是引用
{
	++_day;   //天數(shù)加一
	
	if (_day > GetMonthDay(_year, _month))  //如果天數(shù)不符合該月最大天數(shù),則需要調(diào)整
	{
		++_month;  //讓月加一
		if (_month > 12)  //月不合法就調(diào)整月
		{
			++_year;
			_month = 1;
			
		}
		_day = 1;  讓天數(shù)置一
 
	}
 
	return *this;  //返回該類(lèi)
}

后置++

Date Date::operator++(int)

可直接復(fù)用前置++,后置++需要先使用再++,所以需要?jiǎng)?chuàng)建臨時(shí)對(duì)象,代碼如下

Date Date::operator++(int)
{
	Date d = *this;
	
	++(*this);
 
	return d;
}

后置--

Date Date::operator--(int)

與++的實(shí)現(xiàn)不同,--的話(huà)先實(shí)現(xiàn)后置再實(shí)現(xiàn)前置。代碼如下

Date Date::operator--(int)
{
	Date d = *this;  // 創(chuàng)建臨時(shí)對(duì)象,保存日期類(lèi)中的值
 
	--_day;  //日期類(lèi)中的天數(shù)減一
	if (_day <= 0) //這里可以不用寫(xiě)小于,因?yàn)橐惶煲惶斓臏p是不可能跨過(guò)零來(lái)到負(fù)數(shù)的
	{
		--_month;  //如果天數(shù)等于零了,就需要借上個(gè)月的天數(shù),月要減一
		if (_month <= 0) //月不合法就調(diào)整月
		{
			--_year;
			_month = 12;
		}
 
		_day = GetMonthDay(_year, _month);  //把天數(shù)置成該月最大天數(shù)
 
	}
 
	return d;  //返回保存好的數(shù)據(jù),這樣就實(shí)現(xiàn)了后置--的效果
}

前置--

Date& Date::operator--()

直接復(fù)用后置--,代碼如下

Date& Date::operator--()
{
	 (*this)--;
 
	 return *this;
}

實(shí)現(xiàn)比較大小運(yùn)算符重載思路

小編先理一下思路,方便大家理解。

要實(shí)現(xiàn)比較大小的運(yùn)算符有 >==>= < , <= , !=。只需要實(shí)現(xiàn)> 和  ==就可以復(fù)用并實(shí)現(xiàn)后四個(gè)運(yùn)算符。如下圖

f89fefbf9b1c42ac9c6d96c78edaaea0.png

>運(yùn)算符重載

bool Date::operator>(const Date& d)

代碼如下

bool Date::operator>(const Date& d)
{
	if (_year > d._year)  //年大就大
	{
		return true;
	}
	if (_year == d._year)//年相等比月
	{
		if (_month > d._month) //月大就大
		{
			return true;
		}
		if (_month == d._month) //月相等比天
		{
			if (_day > d._day) //天大就大
			{
				return true;
			}
		}
	}
 
	return false; //不然就是小的
}

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

bool Date::operator==(const Date& d)

年月日都相等才相等,代碼如下

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

*>  = 運(yùn)算符復(fù)用實(shí)現(xiàn)其他比較運(yùn)算符重載

這里不做重點(diǎn),大家可以點(diǎn)擊“目錄”,再點(diǎn)擊”日期-日期“即可跳過(guò) 

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

bool Date::operator >= (const Date& d)
{
	return (*this) > d || (*this) == d;  
}

<運(yùn)算符重載

bool Date::operator < (const Date & d)
{
	return !((*this) >= d);
}

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

bool Date::operator <= (const Date& d)
{
	return !((*this) > d);
}

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

bool Date::operator != (const Date& d)
{
	return !((*this) == d);
}

日期-日期

int Date::operator-(const Date& d)

參數(shù):第一個(gè)參數(shù)為隱含的this指針,第二個(gè)參數(shù)為 const  Date&,傳引用是為了提高傳值效率。

返回值:日期-日期代表的是兩個(gè)日期之間相差的天數(shù),返回值類(lèi)型為 int。

思路1:可以先算出兩個(gè)日期相差多少年,把每一年的總天數(shù)加在一起,但要判斷該年是否為閏年。

思路2:直接復(fù)用++運(yùn)算符,在設(shè)一個(gè)變量,每加一天,變量就加一。

下面用思路2實(shí)現(xiàn),代碼如下

int Date::operator-(const Date& d)
{
	int counst = 0;  //定義一個(gè)變量,保存天數(shù)
 
	if ((*this) == d)  //如果兩個(gè)日期相等,直接返回零
	{
		return 0;
	}
	else if ((*this) > d) 
	{
		Date tmp = d; //如果this的的日期大,就給d創(chuàng)建臨時(shí)變量tmp,然tmp小日期去追this大日期
 
		while ((*this) != tmp)
		{
			++tmp;
			counst++;
		}
 
		return counst; 
	}
	else
	{
		Date tmp = (*this); //同上
		
			while (tmp != d)    
			{
				++tmp;
				counst++;
			}
 
			return counst;  
	}
 
	
}

代碼錯(cuò)誤和bug分享

小編在實(shí)現(xiàn)方法的時(shí)候把域作用限定符寫(xiě)在了返回值的前面,如下

725a3e15179741ec869d383b4773d765.png

48bb3f6de90f476ea01e6f7c0e3c5f0d.png

大家不要這樣寫(xiě)呀。

在寫(xiě)前置++的時(shí)候?qū)懥艘粋€(gè)不易察覺(jué)的bug,寫(xiě)完測(cè)了幾組數(shù)據(jù)沒(méi)問(wèn)題,但其他方法調(diào)用的時(shí)候卻出問(wèn)題了,調(diào)了好久才發(fā)現(xiàn),如下代碼,大家能看出來(lái)哪里出錯(cuò)了嗎

// 前置++
Date& Date::operator++()  // bug分享   
{
	++_day;   
	
	if (_day > GetMonthDay(_year, _month))
	{
		++_month;
		if (_month > 12)
		{
			++_year;
			_month = 1;
			_day = 1;
		}
		
 
	}
 
	return *this;
}

21af940a9edc42bd9ed4e40a2eeeca6b.png

哈哈,其實(shí)正是因?yàn)檫壿嬏樍耍雎粤艘恍┣闆r如下圖

6a605206bdbe4dc292dcbf33deb0d0e6.png

大家在測(cè)方法的時(shí)候盡量要跨過(guò)幾個(gè)平年和閏年,這樣方法才有可信度。

以上就是詳解如何用C++寫(xiě)一個(gè)日期計(jì)算器的詳細(xì)內(nèi)容,更多關(guān)于C++日期計(jì)算器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語(yǔ)言?huà)呃自敿?xì)代碼分步實(shí)現(xiàn)流程

    C語(yǔ)言?huà)呃自敿?xì)代碼分步實(shí)現(xiàn)流程

    掃雷是電腦上很經(jīng)典的游戲,特意去網(wǎng)上玩了一會(huì),幾次調(diào)試之后,發(fā)現(xiàn)這個(gè)比三子棋要復(fù)雜一些,尤其是空白展開(kāi)算法上和堵截玩家有的一拼,與實(shí)際游戲差別較大,不能使用光標(biāo),下面來(lái)詳解每一步分析
    2022-02-02
  • 基于matlab實(shí)現(xiàn)DCT數(shù)字水印嵌入與提取

    基于matlab實(shí)現(xiàn)DCT數(shù)字水印嵌入與提取

    數(shù)字水印技術(shù)是將一些標(biāo)識(shí)信息直接嵌入數(shù)字載體當(dāng)中,?或間接表示在信號(hào)載體中,?且不影響原載體的使用價(jià)值。本文主要為大家介紹了基于matlab如何實(shí)現(xiàn)數(shù)字水印的嵌入與提取,感興趣的可以學(xué)習(xí)一下
    2022-01-01
  • c++中為什么可以通過(guò)指針或引用實(shí)現(xiàn)多態(tài)詳解

    c++中為什么可以通過(guò)指針或引用實(shí)現(xiàn)多態(tài)詳解

    這篇文章主要給大家介紹了關(guān)于c++中為何可以通過(guò)指針或引用實(shí)現(xiàn)多態(tài),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 詳解C語(yǔ)言動(dòng)態(tài)內(nèi)存的分配

    詳解C語(yǔ)言動(dòng)態(tài)內(nèi)存的分配

    這篇文章主要為大家介紹了C語(yǔ)言動(dòng)態(tài)內(nèi)存的分配,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-12-12
  • C++ 仿函數(shù)使用講解

    C++ 仿函數(shù)使用講解

    這篇文章主要介紹了C++ 仿函數(shù)使用講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • C語(yǔ)言的strcpy函數(shù)你了解嗎

    C語(yǔ)言的strcpy函數(shù)你了解嗎

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的strcpy函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • Qt音視頻功能實(shí)現(xiàn)方法詳解

    Qt音視頻功能實(shí)現(xiàn)方法詳解

    音視頻應(yīng)用往往需要大量的計(jì)算資源,尤其是在處理高分辨率、高碼率的音視頻數(shù)據(jù)時(shí),這篇文章主要給大家介紹了關(guān)于Qt音視頻功能實(shí)現(xiàn)方法的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • C語(yǔ)言模擬實(shí)現(xiàn)字符串庫(kù)函數(shù)的示例講解

    C語(yǔ)言模擬實(shí)現(xiàn)字符串庫(kù)函數(shù)的示例講解

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言模擬實(shí)現(xiàn)字符串庫(kù)函數(shù)的具體方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01
  • C語(yǔ)言編寫(xiě)多功能日歷

    C語(yǔ)言編寫(xiě)多功能日歷

    之前看到本站給大家分享了一則C語(yǔ)言實(shí)現(xiàn)的簡(jiǎn)單日歷,就手癢了,也想自己寫(xiě)一個(gè),既然有簡(jiǎn)單了,那咱寫(xiě)個(gè)稍微復(fù)雜點(diǎn)的,多功能的吧。呵呵,玩笑玩笑
    2015-03-03
  • C++實(shí)現(xiàn)LeetCode(105.由先序和中序遍歷建立二叉樹(shù))

    C++實(shí)現(xiàn)LeetCode(105.由先序和中序遍歷建立二叉樹(shù))

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(105.由先序和中序遍歷建立二叉樹(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07

最新評(píng)論