在 C++ 中验证出生日期
Validating Date of birth in C++
我刚开始学习C++。
在浏览此站点上的代码时,我遇到了一个验证 user.But 输入的日期的代码,问题是它甚至可以采用未来的值,因此需要调整此逻辑才能接受 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);
时,代码会为任何未来的日期值提供正确的输出 "invalid date"...但是为什么 happening.I 得到正确的输出但我想知道为什么了。
好的,所以问题是localtime
returns 多次调用同一个缓冲区。您需要复制结果(或使用 localtime_r
需要一个额外的参数,但它不是那么便携)。
这是我对你的代码的调试会话(有未注释的部分):
(gdb) p norm
= (const tm *) 0x7ffff75aca60 <_tmbuf>
(gdb) p now
= (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
,但这不会影响这种情况,也不会要求的行为。
大多数 documentation 对此很清楚,例如参考链接说:
The returned value points to an internal object whose validity or value may be altered by any subsequent call to gmtime or localtime.
我刚开始学习C++。 在浏览此站点上的代码时,我遇到了一个验证 user.But 输入的日期的代码,问题是它甚至可以采用未来的值,因此需要调整此逻辑才能接受 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);
时,代码会为任何未来的日期值提供正确的输出 "invalid date"...但是为什么 happening.I 得到正确的输出但我想知道为什么了。
好的,所以问题是localtime
returns 多次调用同一个缓冲区。您需要复制结果(或使用 localtime_r
需要一个额外的参数,但它不是那么便携)。
这是我对你的代码的调试会话(有未注释的部分):
(gdb) p norm
= (const tm *) 0x7ffff75aca60 <_tmbuf>
(gdb) p now
= (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
,但这不会影响这种情况,也不会要求的行为。
大多数 documentation 对此很清楚,例如参考链接说:
The returned value points to an internal object whose validity or value may be altered by any subsequent call to gmtime or localtime.