2013-11-24 51 views
0

我有這個程序的小問題。我正在嘗試創建一個C++程序來計算一個人的生活天數。它接受三個稱爲月,日和年的參數。這是該計劃背後的整個邏輯:天計算器不總是產生準確的結果

  1. 首先計算今天的日期和保存到三個變量稱爲天,月,年,並尋找當年差

  2. 假設一年差爲10,計算9年的天數乘以365.

  3. 假設輸入月份爲5,則計算4個月內的天數並添加相應天數,並將結果值添加到總天數中。

  4. 計算從輸入年份到當前年份的閏年數並將該值添加到總天數中。

  5. 最終的輸出是由函數返回的,但是在某些日期我得到了輕微的錯誤。輸出並不總是準確的。任何幫助將不勝感激。下面 是整個代碼:

    #include <iostream> 
    #include <ctime> 
    #include <cmath> 
    #include <vector> 
    using namespace std; 
    
    bool IsLeap(int); 
    int LeapCount(int); 
    int current_year; 
    int calculator(int month, int day, int year); 
    
    int main() 
    { 
        cout << calculator(9,24,1994); 
    } 
    
    int calculator(int month, int day, int year) 
    { 
        int final_result; 
        int day_difference; 
        int total_days = 0; 
        const int days_inayear = 365; 
        vector <int> m_days = {31,28,31,30,31,30,31,31,30,31,30,31}; 
    
        time_t theTime = time(NULL); 
        struct tm *aTime = localtime(&theTime); 
    
        int current_day = aTime->tm_mday; 
        int current_month = aTime->tm_mon + 1; 
        current_year = aTime->tm_year + 1900; 
    
        if(year > current_year){ 
         return 0; 
        } 
        else if (year == current_year && month > current_month){ 
         return 0; 
        } 
        else if(year == current_year && month == current_month && day > current_day){ 
         return 0; 
        } 
        else if(year == current_year &&month == current_month && day <= current_day){ 
          return abs(current_day - day); 
        }else 
        { 
         int year_difference = current_year - year; 
         int day_difference = abs(current_day - day); 
         for(int a = month+1; a < m_days.size(); a++){ 
          total_days+= m_days[a]; 
         } 
        int leap_years = LeapCount(year); 
    
        total_days+=(year_difference)*days_inayear; 
        if(year_difference <= 1 && month < 2){ 
         leap_years -= 2; 
        } 
    
        final_result = total_days+leap_years+day_difference; 
        if(IsLeap(year) && month > 2){ 
         final_result = final_result; 
        } 
        return final_result; 
    } 
    } 
    bool IsLeap(int year) 
    { 
        if(year%4 == 0 && year%100!=0){ 
         return true; 
        } 
        else if(year%4==0 && year%100==0 && year%400==0){ 
         return true; 
        } 
        else{ 
         return false; 
        } 
    } 
    int LeapCount(int year) 
    { 
        int difference = current_year - year; 
        int count = 0; 
        for(int x = 0; x<=difference; x++){ 
         if(IsLeap(year+x)){ 
          count++; 
         } 
        } 
        return count; 
    } 
    
+1

如果您提供了一些結果正確和不正確的情況,這將有助於追蹤問題。如果您能夠找到計算器出現故障的情況的模式,則應該很容易找出不正確的邏輯部分。不看代碼,你是否跟蹤你只需要添加閏日,如果這一天在該範圍內? (僅僅知道它發生的那一年是不夠的,而不管它是在出生日期和當前日期之後 –

回答

0

計算的日期是不是一個特別簡單明瞭的任務,它更容易簡單地使用驗證算法,而不是嘗試調試一個破碎的一個。

從Howard Hinnant(欣南特)的論文chrono-Compatible Low-Level Date Algorithms,這裏有一個計算1970-01-01以來的天數的算法:

#include <limits> 
#include <iostream> 

// Returns number of days since civil 1970-01-01. Negative values indicate 
// days prior to 1970-01-01. 
// Preconditions: y-m-d represents a date in the civil (Gregorian) calendar 
//     m is in [1, 12] 
//     d is in [1, last_day_of_month(y, m)] 
//     y is "approximately" in 
//     [numeric_limits<Int>::min()/366, numeric_limits<Int>::max()/366] 
//     Exact range of validity is: 
//     [civil_from_days(numeric_limits<Int>::min()), 
//     civil_from_days(numeric_limits<Int>::max()-719468)] 
template <class Int> 
constexpr 
Int 
days_from_civil(Int y, unsigned m, unsigned d) noexcept 
{ 
    static_assert(std::numeric_limits<unsigned>::digits >= 18, 
      "This algorithm has not been ported to a 16 bit unsigned integer"); 
    static_assert(std::numeric_limits<Int>::digits >= 20, 
      "This algorithm has not been ported to a 16 bit signed integer"); 
    y -= m <= 2; 
    const Int era = (y >= 0 ? y : y-399)/400; 
    const unsigned yoe = static_cast<unsigned>(y - era * 400);  // [0, 399] 
    const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1; // [0, 365] 
    const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + doy;   // [0, 146096] 
    return era * 146097 + static_cast<Int>(doe) - 719468; 
} 

此實現恰巧使用C++ 14層的功能,但它轉換到C++ 11或甚至C++ 98應該不難。

這是一個非常聰明的算法。霍華德的文章解釋了細節。

要計算天數兩個日期之間的數使用該算法來計算天數從時代的兩個不同的日期,然後減去這些值,讓他們

int main() { 
    int serial_birth_date = days_from_civil(1994, 9, 24); 
    int serial_current_date = days_from_civil(2013, 11, 24); 
    std::cout << "Days lived: " << serial_current_date - serial_birth_date << '\n'; 
} 

之間的天數

如果你真的想調試你自己的算法,你可以使用霍華德公佈的算法作爲基準。將程序各個組件的結果與使用這些算法計算的結果進行比較,以將問題縮小到單個組件。比較大量測試用例的結果,也許你會在錯誤中看到一個模式。