2015-01-10 41 views
1

我剛開始學習C++。 在瀏覽本網站上的代碼時,我遇到了驗證用戶輸入日期的代碼。但問題是它可能需要甚至將來的值,因此需要調整此邏輯以便接受DOB。因此我決定使用「time()」函數獲取當前時間,然後將其與輸入的日期進行比較。首先,我加入了兩行代碼(這是在下面的代碼註釋的那些),這是使用C++驗證出生日期

time(&tNow); 

const struct tm *now = localtime(&tNow); 

這裏是我的代碼:

#include <iostream> 
#include <sstream> 
#include <ctime> 

using namespace std; 
// function expects the string in format dd/mm/yyyy: 
bool extractDate(const std::string& s, int& d, int& m, int& y){ 
    std::istringstream is(s); 
    char delimiter; 
    if (is >> d >> delimiter >> m >> delimiter >> y) { 
     struct tm t = {0}; 
     t.tm_mday = d; 
     t.tm_mon = m - 1; 
     t.tm_year = y - 1900; 
     t.tm_isdst = -1; 

     // normalize: 
     time_t when = mktime(&t); 

     time_t tNow; 

     // time(&tNow); 

      const struct tm *norm = localtime(&when); 

     // const struct tm *now = localtime(&tNow);  /* when I uncomment this line the code        
     //             does not accept future date */ 



     // validate (is the normalized date still the same?): 
     return (norm->tm_mday == d && 
       norm->tm_mon == m - 1 && 
       norm->tm_year == y - 1900); 
    } 
    return false; 
} 


int main() { 

    std::string s("11/01/2015"); 
    int d,m,y; 

    if (extractDate(s, d, m, y)) 
     std::cout << "date " 
        << d << "/" << m << "/" << y 
        << " is valid" << std::endl; 
    else 
     std::cout << "date is invalid" << std::endl; 
} 

當我取消對const struct tm *now = localtime(&tNow);的註釋時,代碼會爲任何未來的日期值提供正確的輸出作爲「無效日期」...但爲什麼會發生這種情況。我得到正確的輸出,但我想知道原因。

+1

聽起來像你一直在某個地方擊中未定義的行爲,我只是不能真正發現在哪裏。編譯時是否收到任何警告? –

+0

我正在使用在線編譯器(http://www.tutorialspoint.com/compile_cpp_online.php)來編譯這段代碼,它沒有給出任何錯誤,它工作正常 – Priyanka

+0

不,它沒有顯示任何警告。 – Priyanka

回答

4

好的,所以問題是localtime多次調用時會返回相同的緩衝區。你需要複製結果(或使用localtime_r,它需要一個額外的參數,但它不像便攜式那樣)。

這裏是你的代碼我調試會話(與未註釋部分):

(gdb) p norm 
$1 = (const tm *) 0x7ffff75aca60 <_tmbuf> 
(gdb) p now 
$2 = (const tm *) 0x7ffff75aca60 <_tmbuf> 

我解決它的方法是這樣的:

const struct tm norm = *localtime(&when); 

    const struct tm now = *localtime(&tNow); 


    // validate (is the normalized date still the same?): 
    return (norm.tm_mday == d && 
     norm.tm_mon == m - 1 && 
     norm.tm_year == y - 1900); 

有同一主題的幾個其他的變種,但這應該工作。

1

大多數localtime()實現使用內部本地靜態struct tm。返回的指針是指向此單個實例的指針,因此您的情況normnow指向相同的struct tm實例,第二個調用修改它。

一些實現可以使用線程本地存儲所以在不同的線程使用的至少獲得一個單獨的struct tm,但不會影響這種情況下,不要求行爲。

大多數documentation是在此明確的,例如連接的基準表示:

返回的值指向內部對象,其有效性或值可通過任何後續呼叫被改變以gmtime的或本地時間。