4

这是一个关于无效输入的问题,而不是无效格式。例如给出以下代码:

tm bar;

foo >> get_time(&bar, "%Y-%m-%d");

cout >> bar.tm_year >> bar.tm_mon >> bar.tm_mday >> endl;

如果我定义这很好:stringstream foo("2001-02-28 non-leap year");并且如果我的格式无效,则有一个明显的错误,例如:stringstream foo("bad format 2001-02-28 non-leap year");

但我不知道如何检测我的输入是否无效,例如:

stringstream foo("2001-02-30 non-leap year");

在这种情况下bar,可以解读为好像没有任何问题。有什么我可以听的东西会提醒我输入无效吗?

4

2 回答 2

3

由于mktime试图解释超出范围的值(即 2001-02-30 将被解释为 2001-03-01),您可以执行 anmktime后跟 a localtime,如果您得到不同的值,则意味着原始值无效。

于 2015-03-27T22:54:32.167 回答
1

正如Matteo Italia的回答所提到的,除了编写自己的公历验证器之外,您唯一可靠的双重检查是mktime. tm获得的 sget_time无法验证,因为可能会也可能不会填写字段。考虑以下 2 个无效示例:

这样做:istringstream("2001-02-30") >> get_time(&bar, "%Y-%m-%d");结果在彻底运行时发生变化mktime

bar.tm_mday: 30
bar.tm_mon : 1
bar.tm_year: 100

执行此操作时:istringstream("2001-13-30") >> get_time(&bar, "%Y-%m-%d");导致运行时不会改变的结果mktime

bar.tm_mday: 13
bar.tm_mon : 0
bar.tm_year: 100

为了更改所有无效日期,mktime我们需要在不使用的情况下读取日期get_time

int year;
int month;
int day;
istringstream foo("2000-13-30");

foo >> year >> ws;
foo.ignore();
foo >> month >> ws;
foo.ignore();
foo >> day;

tm bar = { 0, 0, 0, day, month - 1, year - 1900 };

此时,任何错误都bar可以被纠正,mktime因此我们的实际验证步骤将是检查非time_t(-1)返回并将修改bar 的值与原始值进行比较: if(time_t(-1) != mktime(&bar) && bar.tm_mday == day && bar.tm_mon == month - 1 && bar.tm_year == year - 1900)如果此条件为真,则输入bar有效。

总之,可以在tm不编写 Gregorian 验证器的情况下验证 a,但无法验证tm已被 读入的a get_time

于 2015-04-02T12:55:27.197 回答