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

基于C++實現(xiàn)日期計算器的詳細教程

 更新時間:2022年06月26日 10:30:54   作者:三分苦  
在現(xiàn)代社會中,計算器已經(jīng)進入了每一個家庭,人們在生活和學(xué)習(xí)中經(jīng)常需要使用到計算器,下面這篇文章主要給大家介紹了關(guān)于基于C++實現(xiàn)日期計算器的相關(guān)資料,需要的朋友可以參考下

一、前言

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

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

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

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

檢查日期的合法性

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

class Date
{
public:
    bool isLeapYear(int year) //判斷是否為閏年
    {
    	//四年一閏百年不閏或四百年一閏
    	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }
	static int GetMonthDay(int year, int month)
//加上static防止函數(shù)頻繁調(diào)用開辟幾十個字節(jié)大小的數(shù)組,最好加上
	{
		int monthDayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if (month == 2 && isLeapYear(year))
			return 29; //閏月29天
		else
			return monthDayArray[month];
	}
	Date(int year = 1, int month = 1, int day = 1)
	{
		if (year >= 1 && month <= 12 && month >= 1 && day <= GetMonthDay(year, month))
		{
            //確保日期合法
			_year = year;
			_month = month;
			_day = day;
		}
	}
private:
	int _year;
	int _month;
	int _day;
};

<  運算符重載

思路:

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

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

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

代碼如下:

// <運算符重載
bool Date::operator<(const Date& d) const //類外訪問成員函數(shù)需要設(shè)定類域
{
	if (_year < d._year ||
		_year == d._year && _month < d._month ||
		_year == d._year && _month == d._month && _day < d._day)
		return true;
	else
		return false;
}

== 運算符重載  

思路:

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

代碼如下:

// ==運算符重載
bool Date::operator==(const Date& d) const
{
	return _year == d._year &&
		_month == d._month &&
		_day == d._day;
}

<= 運算符重載

思路: --  復(fù)用

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

代碼如下:

// <=運算符重載
bool Date::operator<=(const Date& d) const
{
	return *this < d || *this == d;
}

>  運算符重載

思路: --  復(fù)用

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

代碼如下:

// >運算符重載
bool Date::operator>(const Date& d) const
{
	return !(*this <= d);
}

>= 運算符重載

思路: --  復(fù)用

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

代碼如下:

// >=運算符重載
bool Date::operator>=(const Date& d) const
{
	return !(*this < d);
}

!= 運算符重載

思路: --  復(fù)用

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

代碼如下:

//!=運算符重載
bool Date::operator!=(const Date& d) const
{
	return !(*this == d);
}

改進和優(yōu)化

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

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

Date.h 文件:

#pragma once
#include<iostream>
#include<assert.h>
using std::cout;
using std::cin;
using std::endl;
class Date
{
public:
	bool isLeapYear(int year)
	{
		//四年一潤百年不潤或四百年一潤
		return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
	}
	//獲取某月天數(shù)
	int GetMonthDay(int year, int month);
	//構(gòu)造函數(shù)
	Date(int year = 1, int month = 1, int day = 1);
	//打印
	void Print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	// <運算符重載
	bool operator<(const Date& d) const;
	// ==運算符重載
	bool operator==(const Date& d) const;
	// <=運算符重載
	bool operator<=(const Date& d) const
	{
		return *this < d || *this == d;
	}
	// >運算符重載
	bool operator>(const Date& d) const
	{
		return !(*this <= d);
		//return (d < *this);
	}
	// >=運算符重載
	bool operator>=(const Date& d) const
	{
		return !(*this < d);
	}
	// !=運算符重載
	bool operator!=(const Date& d) const
	{
		return !(*this == d);
	}
private:
	int _year;
	int _month;
	int _day;
};

Date.cpp 文件:

#include"Date.h"
//獲取某月天數(shù)
int Date::GetMonthDay(int year, int month)
{
	assert(year >= 0 && month > 0 && month < 13);
	static int monthDayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (month == 2 && isLeapYear(year))
		return 29;
	else
		return monthDayArray[month];
}
//構(gòu)造函數(shù)
Date::Date(int year, int month, int day)
{
	if (year >= 1 && month <= 12 && month >= 1 && day <= GetMonthDay(year, month))
	{
		_year = year;
		_month = month;
		_day = day;
	}
	else
		cout << "日期非法" << endl;
}
// <運算符重載
bool Date::operator<(const Date& d) const //類外訪問成員函數(shù)需要設(shè)定類域
{
	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) const
{
	return _year == d._year &&
		_month == d._month &&
		_day == d._day;
}

日期 + 天數(shù)

思路:

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

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

當月進位到13時,年進位+1,月置為1

法一:

Date Date::operator+(int day) const
{
	Date ret(*this); //拷貝構(gòu)造,拿d1去初始化ret
	ret._day += day;
	while (ret._day > GetMonthDay(ret._year, ret._month))
	{
		ret._day -= GetMonthDay(ret._year, ret._month);
		ret._month++;
		if (ret._month == 13)
		{
			ret._year++;
			ret._month = 1;
		}
	}
	return ret;
}

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

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

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

Date Date::operator+(int day) const
{
	//法二:復(fù)用日期 += 天數(shù)
	Date ret(*this);
	ret += day;
	return ret;
}

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

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

日期 += 天數(shù)

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

法一:

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

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

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

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

Date& Date::operator+=(int day) //傳引用返回
{
	//如果day小于0,要單獨處理
	if (day < 0)
	{
		return *this -= -day;
	}
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		_month++;
		if (_month == 13)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;
}

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

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

Date& Date::operator+=(int day)
{
	//法二:復(fù)用
	* this = *this + day; //讓d1+過天數(shù)后再返回給自己從而實現(xiàn)+=
	return *this;
}

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

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

日期 -= 天數(shù)

思路:

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

  • 當減的天數(shù)為負數(shù),則為+=,直接調(diào)用
  • 若減后的day<0,月-1
  • 若月 = 0,則年-1,月置為12

代碼如下:

//日期 -=天數(shù)  d1-=100
Date& Date::operator-=(int day)
{
	//如果減去的天數(shù)是負數(shù),要單獨處理,直接調(diào)用+=運算符重載
	if (day < 0)
	{
		return *this += -day;
	}
	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			_month = 12;
			--_year;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

日期 - 天數(shù)

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

//日期 - 天數(shù)
Date Date::operator-(int day) const
{
	Date ret(*this);
	ret -= day;
	return ret;
}

前置 ++

思路:

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

代碼如下:

//前置++
Date& Date::operator++() //無參的為前置
{
	*this += 1; //直接復(fù)用+=
	return *this;
}

后置 ++

思路:

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

代碼如下:

//后置++
Date Date::operator++(int i) //有參數(shù)的為后置
{
	Date tmp(*this);
	*this += 1; //復(fù)用+=
	return tmp;
}

前置 --

思路:

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

代碼如下:

//前置--
Date& Date::operator--() //無參的為前置
{
	*this -= 1; //直接復(fù)用-=
	return *this;
}

后置 --

思路:

后置--和后置++類似,只不過內(nèi)部復(fù)用的是-=,不再贅述

代碼如下:

//后置--
Date Date::operator--(int i) //有參數(shù)的為后置
{
	Date tmp(*this);
	*this -= 1;
	return tmp;
}

日期 - 日期

思路:

日期 - 日期得到的是天數(shù),首先我們得判斷兩個日期的大小,用min和max代替小的和大的,隨后,算出min和max之間的差距,若min!=max,則min就++,隨即定義變量n也自增++,最后返回n(注意符號)

代碼如下:

//日期 - 日期
int Date::operator-(const Date& d) const
{
	int flag = 1; //方便后續(xù)計算正負
	Date max = *this;
	Date min = d;
	if (*this < d)
	{
		min = *this;
		max = d;
		flag = -1; //計算正負
	} //確保max是大的,min是小的
	int n = 0;
	while (min != max)
	{
		min++;
		n++;
	}//算出min和max之間絕對值差距
	return n * flag; //如果d1大,結(jié)果為正,d2大結(jié)果為負
}

三、總結(jié)

本篇日期類把先前學(xué)到的引用,傳值/傳引用返回、拷貝構(gòu)造、復(fù)用等等知識點柔和到了一起,非常值得大家操手練習(xí)練習(xí),創(chuàng)作不易,還望三連。

日期類的源碼鏈接:gitee鏈接:日期計算器完善版

到此這篇關(guān)于基于C++實現(xiàn)日期計算器的文章就介紹到這了,更多相關(guān)C++日期計算器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言項目爬樓梯的兩種實現(xiàn)方法參考

    C語言項目爬樓梯的兩種實現(xiàn)方法參考

    今天小編就為大家分享一篇關(guān)于C語言項目爬樓梯的兩種實現(xiàn)方法參考,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Linux下C語言實現(xiàn)貪吃蛇小游戲

    Linux下C語言實現(xiàn)貪吃蛇小游戲

    這篇文章主要為大家詳細介紹了Linux下C語言實現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • Visual?Studio2022的完全卸載及安裝到D盤的操作方法

    Visual?Studio2022的完全卸載及安裝到D盤的操作方法

    這篇文章主要介紹了Visual?Studio2022的完全卸載以及完全安裝到D盤,因為VS如果隨便寫在會有很多很多的亂七八糟的東西掉出來,所以我們選擇制式一點的卸載方式,需要的朋友可以參考下
    2022-09-09
  • 線程池的原理與實現(xiàn)詳解

    線程池的原理與實現(xiàn)詳解

    下面利用C語言來實現(xiàn)一個簡單的線程池,為了使得這個線程池庫使用起來更加方便,特在C實現(xiàn)中加入了一些OO的思想,與Objective-C不同,它僅僅是使用了struct來模擬了c++中的類,其實這種方式在linux內(nèi)核中大量可見
    2013-09-09
  • C++初始化函數(shù)列表詳細解析

    C++初始化函數(shù)列表詳細解析

    C++可以定義引用類型的成員變量,引用類型的成員變量必須在構(gòu)造函數(shù)的初始化列表中進行初始化
    2013-09-09
  • C語言實現(xiàn)簡易文本編譯器

    C語言實現(xiàn)簡易文本編譯器

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡易文本編譯器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Qt+Opencv實現(xiàn)梯度矯正功能

    Qt+Opencv實現(xiàn)梯度矯正功能

    這篇文章主要為大家詳細介紹了Qt如何結(jié)合Opencv實現(xiàn)梯度矯正功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-04-04
  • Visual?Studio?Code?配置C、C++?文件debug調(diào)試環(huán)境的詳細過程

    Visual?Studio?Code?配置C、C++?文件debug調(diào)試環(huán)境的詳細過程

    這篇文章主要介紹了Visual?Studio?Code?配置C、C++?文件debug調(diào)試環(huán)境,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • C++中malloc與free、new與delete的詳解與應(yīng)用

    C++中malloc與free、new與delete的詳解與應(yīng)用

    今天小編就為大家分享一篇關(guān)于C++中malloc與free、new與delete的詳解與應(yīng)用,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • 你必須知道的C語言預(yù)處理的問題詳解

    你必須知道的C語言預(yù)處理的問題詳解

    本篇文章介紹了,你必須知道的C語言預(yù)處理的問題。需要的朋友參考下
    2013-05-05

最新評論

东丰县| 平利县| 文水县| 北川| 闸北区| 罗甸县| 台东县| 东港市| 辽阳市| 晋州市| 镇原县| 贵德县| 图片| 广河县| 岐山县| 黄冈市| 汶上县| 漳州市| 弥渡县| 江孜县| 稻城县| 西华县| 唐海县| 江川县| 上蔡县| 邢台市| 荆门市| 金平| 荔浦县| 鄂尔多斯市| 麟游县| 颍上县| 育儿| 新野县| 通辽市| 陕西省| 突泉县| 通山县| 龙陵县| 潼关县| 句容市|