最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解如何用C++寫一個日期計算器

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

前言

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

代碼的布局

建兩個 .cpp文件:Date.cpp      Test.cpp

建一個   .h文件  :Date.h

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

d41d4b0d75bf4f7db8b8b103b696539f.png

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

年:_year     月:_month     日:_day

變量名前面加“  _ ”符號,是為了和普通的數(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);
 
	// 賦值運算符重載
	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--();     
 
	// >運算符重載
	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);  
 
	// 日期-日期 返回天數(shù)    
	int operator-(const Date& d);  

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

方法的實現(xiàn)

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

int GetMonthDay(int year, int month);

閏年

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

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

翻譯成計算機語言就是

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

有了閏年的概念,那么獲取某年某月的天數(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];
		}
}

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

b24768dd22e64e578803dd9ab3418c4f.png

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

*全缺省的構(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ù)在定義的時候不需要給缺省值。

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

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

賦值運算符重載

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ù)

因為沒有涉及到資源管理可以不寫,編譯器會自動生成默認(rèn)的析構(gòu)函數(shù)。

日期+=天數(shù)

Date& operator+=(int day);

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

邏輯示意圖

78bd766509ef4189a4b6133f7bdda8db.png

代碼

Date& Date::operator+=(int day) 
{
	_day += day; //把天數(shù)加到日期的天數(shù)上
 
	while (_day > GetMonthDay(_year, _month)) //如果日期的天數(shù)大于該月最大天數(shù)就進位                                     
                                                           
	{
		_day -= GetMonthDay(_year, _month); //要想進位,得把該月的最大天數(shù)減掉
 
		++_month; //進位
 
		if (_month > 12) //如果月不合法就調(diào)整月
		{
			++_year;
			_month = 1;
        }
	}
 
	return *this;  //返回日期,因為出了作用域不會銷毀,可以引用返回
}

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

日期+天數(shù)

Date operator+(int day);

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

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

日期加天數(shù)不能改變?nèi)掌诘闹?,所以要?chuàng)建臨時對象。臨時對象出了作用域就銷毀了,所以不能傳引用返回。

日期-天數(shù)

Date operator-(int day);

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

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

代碼

Date Date::operator-(int day)
{
	Date d = (*this); //創(chuàng)建臨時對象,把日期類的數(shù)據(jù)拷貝給臨時對象
 
	d._day -= day;  //讓日期的天數(shù)直接和天數(shù)相減
 
	while (d._day <= 0)  //日期的天數(shù)小于零就調(diào)整
	{
		--d._month;  //該月已經(jīng)是負的,應(yīng)該往下個月借天數(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

因為臨時對象出了作用域要銷毀,所以不能傳引用返回。

日期-=天數(shù)

Date& operator-=(int day); 

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

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

前置++

Date& Date::operator++() 

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

Date& Date::operator++()  //前置++需要先++在使用,所以不需要創(chuàng)建臨時對象,返回值可以是引用
{
	++_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;  //返回該類
}

后置++

Date Date::operator++(int)

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

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

后置--

Date Date::operator--(int)

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

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

前置--

Date& Date::operator--()

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

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

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

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

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

f89fefbf9b1c42ac9c6d96c78edaaea0.png

>運算符重載

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; //不然就是小的
}

==運算符重載

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

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

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

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

這里不做重點,大家可以點擊“目錄”,再點擊”日期-日期“即可跳過 

>=運算符重載

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)

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

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

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

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

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

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

代碼錯誤和bug分享

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

725a3e15179741ec869d383b4773d765.png

48bb3f6de90f476ea01e6f7c0e3c5f0d.png

大家不要這樣寫呀。

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

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

21af940a9edc42bd9ed4e40a2eeeca6b.png

哈哈,其實正是因為邏輯太順了,忽略了一些情況如下圖

6a605206bdbe4dc292dcbf33deb0d0e6.png

大家在測方法的時候盡量要跨過幾個平年和閏年,這樣方法才有可信度。

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

相關(guān)文章

  • C語言判斷語句和if語句形式及多層if使用示例

    C語言判斷語句和if語句形式及多層if使用示例

    這篇文章主要為大家介紹了C語言判斷語句和if語句形式及多層if使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • C++中異常的深度解析

    C++中異常的深度解析

    異常處理機制允許程序中獨立開發(fā)部分能夠在運行時就出現(xiàn)的問題進行通信并做出相應(yīng)的處理,這篇文章主要介紹了C++中異常的深度解析,需要的朋友可以參考下
    2025-03-03
  • C++設(shè)計模式之命令模式

    C++設(shè)計模式之命令模式

    這篇文章主要介紹了C++設(shè)計模式之命令模式,本文講解了什么是命令模式、命令模式的使用場合等內(nèi)容,并給出了一個代碼實例,需要的朋友可以參考下
    2014-10-10
  • C語言中&的多重用途解析

    C語言中&的多重用途解析

    本文主要介紹了C語言中&的多重用途解析,解釋了它作為一元取地址運算符和類型聲明中指針類型的兩種主要用法,具有一定的參考價值,感性的可以了解一下
    2026-03-03
  • C 語言基礎(chǔ)----詳解C中的運算符

    C 語言基礎(chǔ)----詳解C中的運算符

    這篇文章主要介紹了C語言中的運算符,文中講解非常詳細,適合初學(xué)小白進行學(xué)習(xí),想入門C語言的朋友不妨了解下
    2020-06-06
  • C++?常量成員函數(shù)學(xué)習(xí)筆記

    C++?常量成員函數(shù)學(xué)習(xí)筆記

    這篇文章主要為大家介紹了C++?常量成員函數(shù)學(xué)習(xí)筆記,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • C++字符串提取和分割的多種方法

    C++字符串提取和分割的多種方法

    在C++編程中,字符串處理是一個常見的任務(wù),尤其是在需要從字符串中提取特定數(shù)據(jù)時,本文將詳細探討如何使用C++標(biāo)準(zhǔn)庫中的工具來提取和分割字符串,并分析不同方法的適用場景和優(yōu)缺點,我們將通過多個示例代碼逐步講解,幫助讀者掌握字符串處理的技巧,需要的朋友可以參考下
    2025-03-03
  • C語言棧順序結(jié)構(gòu)實現(xiàn)代碼

    C語言棧順序結(jié)構(gòu)實現(xiàn)代碼

    一個能夠自動擴容的順序結(jié)構(gòu)的棧 ArrStack 實例 (GCC編譯),有需要的朋友可以參考一下
    2013-10-10
  • C++?超詳細講解stack與queue的使用

    C++?超詳細講解stack與queue的使用

    C++?Stack(堆棧)?是一個容器類的改編,為程序員提供了堆棧的全部功能,也就是說實現(xiàn)了一個先進后出(FILO)的數(shù)據(jù)結(jié)構(gòu),許多程序都使用了?queue?容器。queue?容器可以用來表示超市的結(jié)賬隊列或服務(wù)器上等待執(zhí)行的數(shù)據(jù)庫事務(wù)隊列
    2022-03-03
  • 利用C++如何實現(xiàn)一個阻塞隊列詳解

    利用C++如何實現(xiàn)一個阻塞隊列詳解

    這篇文章主要給大家介紹了關(guān)于利用C++如何實現(xiàn)一個阻塞隊列的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10

最新評論

石景山区| 友谊县| 万荣县| 营山县| 沙雅县| 郧西县| 荣昌县| 故城县| 拜泉县| 衡阳县| 板桥市| 蛟河市| 明溪县| 林芝县| 安仁县| 洱源县| 台东县| 屏南县| 布尔津县| 长乐市| 始兴县| 祥云县| 株洲县| 锡林郭勒盟| 山丹县| 嘉峪关市| 桑植县| 乡城县| 汤原县| 文登市| 桦川县| 丹凤县| 固原市| 古丈县| 晋江市| 桃园县| 揭西县| 南和县| 攀枝花市| 永修县| 甘德县|