Я только начал изучать 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);
код дает правильный вывод как «недопустимая дата» для любых будущих значений даты … но почему это происходит. Я получаю правильный вывод, но я хочу знать, почему.
Итак, проблема в том, что 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);
Есть несколько других вариантов на ту же тему, но это должно работать.
Наиболее localtime()
реализации используют внутреннюю локальную статическую struct tm
, Возвращенный указатель является указателем на этот единственный экземпляр, так что в вашем случае norm
а также now
указывают на то же самое struct tm
экземпляр, и второй вызов изменяет его.
Некоторые реализации могут использовать поток локального хранилища так что использование в разных потоках как минимум получает отдельную struct tm
, но это не повлияет на этот случай, и не требуется поведение.
Наиболее документация Это ясно, например, ссылка на ссылку говорит:
Возвращаемое значение указывает на внутренний объект, действительность или значение которого можно изменить при любом последующем обращении к gmtime или localtime.