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

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

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

前言

寫一個日期計算器對學(xué)習(xí)的意義也很大。初學(xué)C++,接觸了類和對象的概念,又認(rèn)識了默認(rèn)成員函數(shù),然后又學(xué)習(xí)了運(yùn)算符的重載。而日期計算器就很好的涵蓋了這些知識。能很好的幫助我們復(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);
 
	// 賦值運(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ù)相乘就沒有意義,也沒必要聲明。

方法的實現(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年不潤是為了補(bǔ)足4年一潤的精度,而400一潤是為了補(bǔ)足100年不潤的精度。只有這樣,日期才不會與四季脫離。

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

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

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];
		}
}

下圖是代碼控制的細(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ù)在定義的時候不需要給缺省值。

拷貝構(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ù)

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

日期+=天數(shù)

Date& operator+=(int day);

思路:可以把要加的天數(shù)直接加到日期的天數(shù)上,如果日期的天數(shù)沒有超過該月的最大天數(shù),直接返回日期。如果超過了,就寫個循環(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;  //返回日期,因為出了作用域不會銷毀,可以引用返回
}

*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ù)用+=的邏輯。現(xiàn)在反過來,先實現(xiàn)-的邏輯,在實現(xiàn)-=的邏輯的時候復(fù)用-的邏輯。

思路:把天數(shù)直接和日期中的天數(shù)相減。若不為負(fù)數(shù),直接返回。若為負(fù)數(shù),則需要寫個循環(huán)不斷向前借位,如果把月借成負(fù)數(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)是負(fù)的,應(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ù)雜的邏輯了,只需要控制年月日的進(jìn)位即可。代碼如下

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) //這里可以不用寫小于,因為一天一天的減是不可能跨過零來到負(fù)數(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)比較大小運(yùn)算符重載思路

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

要實現(xiàn)比較大小的運(yùn)算符有 >==>= < , <= , !=。只需要實現(xiàn)> 和  ==就可以復(fù)用并實現(xiàn)后四個運(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ù)用實現(xiàn)其他比較運(yùn)算符重載

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

>=運(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ù):第一個參數(shù)為隱含的this指針,第二個參數(shù)為 const  Date&,傳引用是為了提高傳值效率。

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

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

思路2:直接復(fù)用++運(yùn)算符,在設(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++寫一個日期計算器的詳細(xì)內(nèi)容,更多關(guān)于C++日期計算器的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語言掃雷詳細(xì)代碼分步實現(xiàn)流程

    C語言掃雷詳細(xì)代碼分步實現(xiàn)流程

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

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

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

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

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

    詳解C語言動態(tài)內(nèi)存的分配

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

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

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

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

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

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

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

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

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

    C語言編寫多功能日歷

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

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

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

最新評論