strptime() 在 C 中产生垃圾时间

strptime() produces junk times in C

我尝试使用 strptime() 来解析 ISO 8601 格式的日期(由“%F”或“%Y-%m-%d”指定),但是当我从结果结构 tm 中读取时,我得到时间、分钟和秒的荒谬值。 这是一个示例代码和结果:

char *s_date = (char *)malloc(sizeof(char) * 255);
scanf("%s", s_date);

struct tm bd_date;
strptime(s_date, "%Y-%m-%d", &bd_date)

printf("%d-%d-%d %d:%d:%d\n", (bd_date.tm_year + 1900), (bd_date.tm_mon + 1), bd_date.tm_mday, bd_date.tm_hour, bd_date.tm_min, bd_date.tm_sec);

输入“1990-05-01”的结果输出是: 1990-5-1 2007659173:32766:1076394855,显示 tm_hour、tm_min 和 tm_sec 的非法值。 我究竟做错了什么?有什么我想念的吗?我虽然 strptime() 会自动将格式中未使用的字段设置为 0,但似乎并非如此。

您可能需要在自己调用 strptime 之前将所有字段设置为零。注意 struct tm bd_date; 是在栈上分配的,所以此时 bd_date 充满了垃圾(随机值),而不是充满了零。

strptime 函数将只设置格式字符串中指定的字段。来自 man page:

In principle, this function does not initialize tm but only stores the values specified. This means that tm should be initialized before the call. Details differ a bit between different UNIX systems. The glibc implementation does not touch those fields which are not explicitly specified, except that it recomputes the tm_wday and tm_yday field if any of the year, month, or day elements changed.

因此在您的情况下,由于仅指定了年、月和日,因此仅设置了那些相应的字段(以及星期几和一年中的某一天)。

Apple 的 strptime 手册页明确指出:

If the <i>format</i> string does not contain enough conversion specifications to completely specify the resulting <i>struct tm, the unspecified members of <i>timeptr are left untouched. For example, if format is “%H:%M:%S”, only <i>tm_hour, <i>tm_sec and <i>tm_min will be modified.

Linux man pages 没有那么明确,但与此一致:

In principle, this function does not initialize <i>tm but stores only the values specified. This means that <i>tm should be initialized before the call.

POSIX 标准,苹果的 macOS 和 Linux 都试图符合,在我手头的 2008 版本中既没有上述也没有类似的文字。根本不关心其他结构体成员是否被修改或结构体是否被初始化

因此,至少在某些实现中,strptime 不会修改格式字符串中没有相应描述符的成员。例如,如果没有 hour 的描述符,例如 %H,它不会修改结构的 hour 成员。如果你想设置这些成员,你可以在调用 strptime.

之前设置它们