time.h — Проверка даты рождения в переполнении стека

Я только начал изучать C ++.
Просматривая коды на этом сайте, я наткнулся на код, который проверяет дату, введенную пользователем. Но проблема в том, что он может принимать даже будущие значения, поэтому эту логику необходимо настроить для работы с DOB.
поэтому я решил взять текущее время, используя функцию «time ()», а затем сравнить его с введенной датой. Для начала я добавил две строки в коде (те, которые прокомментированы в приведенном ниже коде), которые

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

Решение

Итак, проблема в том, что 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);

Есть несколько других вариантов на ту же тему, но это должно работать.

4

Другие решения

Наиболее localtime() реализации используют внутреннюю локальную статическую struct tm, Возвращенный указатель является указателем на этот единственный экземпляр, так что в вашем случае norm а также now указывают на то же самое struct tm экземпляр, и второй вызов изменяет его.

Некоторые реализации могут использовать поток локального хранилища так что использование в разных потоках как минимум получает отдельную struct tm, но это не повлияет на этот случай, и не требуется поведение.

Наиболее документация Это ясно, например, ссылка на ссылку говорит:

Возвращаемое значение указывает на внутренний объект, действительность или значение которого можно изменить при любом последующем обращении к gmtime или localtime.

1

По вопросам рекламы [email protected]