2013-10-01 266 views
1

我需要計算給定日期的日期編號。全年有366天。然而每個月都有不同的值,我必須分配這些值。有沒有更快的方法來做到這一點,而不是我正在做的事情?從日期計算年份

#include<iostream> 
using namespace std; 
int main() 
{ 
    int day, month, year, dayNumber; 

    cout<< "Please enter the month, by numerical value:"; 
    cin>> month; 
    cout<<"Please enter the day, by numerical value:"; 
    cin>> day; 
    cout<<"Please enter the year, by numerical value:"; 
    cin>> year; 
    if (month == 1) 
    { 
     dayNumber= day; 
     cout<< "Month;" << '\t'<< month << '\n' 
      << "Day:"<<'\t'<< day<< '\n' 
      << "Year:"<<'\t'<< year<<'\n' 
      << "Day Number:"<< '\t'<< dayNumber<< endl; 
    } 
    else if(month==2) 
    { 
     dayNumber= day+31; 
    } 
} 
+0

請妥善縮進代碼。 – RedX

回答

1

在很多方面,最好避免手動滾動。

使用boost:

#include <boost/date_time/gregorian/gregorian.hpp> 

//... 
try { 
    boost::gregorian::date d(year, month, day); 
    dayNumber = d.day_of_year(); 
} 
catch (std::out_of_range& e) { 
    // Alternatively catch bad_year etc exceptions. 
    std::cout << "Bad date: " << e.what() << std::endl; 
} 

正如詹姆斯甘孜建議你也可以使用mktime避免升壓(未經測試)的依賴性:

tm timeinfo = {}; 
    timeinfo.tm_year = year - 1900; 
    timeinfo.tm_mon = month - 1; 
    timeinfo.tm_mday = day; 
    mktime(&timeinfo); 
    dayNumber = timeinfo.tm_yday; 
+0

你不需要提升; 'mktime'是標準庫的一部分(並且假設公曆)。 –

+0

@JamesKanze that's useful - added to the answer – Pete

+0

Re'timeinfo':你不需要'struct'關鍵字;這只是一個C'ism。你應該在聲明時初始化它:'tm timeinfo = {};',並跳過'memset'。 –

1

您可以創建一個包含在每月的天數向量:

std::vector<int> days_in_month; 
days_in_month.push_back(31); //Jan 
days_in_month.push_back(29); //Feb 
... // so on for each month 

然後,計算,你可以這樣做:

int day = <day_entered_by_user>; 
int month = <month_entered_by_user>; 

int num_of_days = 0; 
// Sum the number of days for all months preceding the current month 
for(int i = 0; i < (month - 1); ++i) 
    num_of_days += days_in_month[i]; 

// Finally just add the day entered for the current month 
num_of_days += day; 
+0

這是一個非常酷的方式。我們甚至沒有開始談論媒介,所以我永遠不會想到這樣做。 –

+0

爲什麼簡單,當你可以變得複雜。如果你真的想要的話,我可以看到'std :: array',但是這是C風格數組最好的地方。 –

+1

@JamesKanze除非有很強的理由這樣做,否則我不會將C語言引入C++。 std :: array可能是去這裏的理想方式。 – Nikhil

3

首先,你需要知道的如果年份是閏年:

bool isLeap(year) { 
    return (((year % 4) == 0) && (((year % 100) != 0) || ((year % 400) == 0)) 
} 

然後,你可以創建,對於給定年份和數組或一天逐月數:

unsigned int daysPerMonth[] = {31, (isLeap(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 

我只給你的代碼塊,但它們可以幫助你。

循環訪問該數組以獲取真實日期編號。以1989年4月4日爲例,不是閏年。這是天數31 + 28 + 31(1月至3月),然後+4。

+1

我想你忘了讓你的'daysPerMonth'成爲一個數組... – RedX

+0

@RedX謝謝:) –

+0

這意味着每次重新創建(並初始化)數組(加一個循環)。使用兩個數組,一個用於閏年,另一個用於非閏年。並將累積值放入數組中。 –

0

非常短的代碼看起來像follwoing:

{ 
    int nonleap[12]={0,31, 31+28, 31+28+31, 31+28+31+30 .....}; 
    int leap[12]={0,31, 31+29, 31+29+31, 31+29+31+30 .....}; 

    if(yearIsLeap(year)) 
     return leap[month]+day; 
    else 
     return nonleap[month]+day; 
} 
1

您可以每月的天數存入數組:

int days_per_month[] = {31, 29, 31, ...}; 

std::array<int, 12> days_per_month{{31, 29, 31,...}}; 

然後,你需要循環該數組以計算已經過去的天數之和:

int sum = 0; 
for (int i = 1; i < month; ++i) 
{ 
    sum += days_per_month[i - 1]; // note the index shift! 
} 
dayNumber += sum; 

另一種方法是直接存儲和的數組中:

std::array<int, 12> passed_days{{0, 31, 60,...}}; 

然後你擺脫循環:

dayNumber += passed_days[month - 1]; 

閏年,只需檢查的一年如果月份至少爲3.

+0

不考慮閏年。 – Pete

+0

而且是不必要的低效;這裏絕對不需要循環。 –

+0

@JamesKanze那麼你爲什麼認爲我包含一個無循環替代?正是這個原因。雖然我更喜歡循環。它表達了實際發生的事情。就我個人而言,我會被持有天數的數組弄糊塗,因爲這些數字對於任何人來說都是不尋常的數字。 – stefan

3

只需使用mktime

tm date = {}; 
date.tm_year = year - 1900; 
date.tm_mon = month - 1; 
date.tm_mday = day; 
mktime(&date); 
dayNumber = date.tm_yday; 

否則,你需要一個二維表:

int daysToMonth[2][12] = 
{ 
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, 
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }, 
}; 

和功能:

bool isLeapYear(int year) 
{ 
    return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); 
} 

年的一天則是:

daysToMonth[isLeapYear(year) ? 1 : 0][month] + day; 
+0

不需要'? 1:0「時,C++保證布爾值」true「和」false「在數字上下文中爲」1「和」0「。 –

+0

@MarkRansom當然。但是像這樣的隱式轉換隻會使代碼無法讀取,應該避免。 –