使用sscanf将字符串转换为时间

4

我正在尝试将时间字符串转换为C语言Windows平台上的时间格式。由于我的字符串中只有小时、分钟和秒,所以我尝试使用sscanf解析字符串到时间格式,然后使用mktime进行转换。但不知何故它没有转换成时间格式。为了检查,我尝试将转换后的时间再次打印成字符串。代码如下:

struct tm tm;
char time_buffer[100];
int hh, mm;
float ms;
time_t time_value;
char *timestamp = {"16:11:56.484"};
sscanf(timestamp, "%d:%d:%f", &hh, &mm,&ms);
tm.tm_hour =hh;
tm.tm_min = mm;
tm.tm_sec = ms*1000;
tm.tm_isdst = -1;
time_value = malloc(100*sizeof(char));
time_value = mktime(&tm);
if (time_value==-1)
    printf ("unable to make time");
strftime(time_buffer, sizeof(time_buffer), "%c", &tm);
printf(time_buffer);

你使用 malloc 进行堆内存分配的目的是什么?那只会让你出现内存泄漏。 - Some programmer dude
我在代码中有一个时间戳值的数组,所以我分配了内存。这里我没有展示数组,以保持代码简单。 - learningpal
如果您有一个 time_t 值的数组,应该按 sizeof(time_t) 的倍数分配内存,而不是 sizeof(char) - Some programmer dude
1
顺便提一下,sizeof(char) 是多余的,它已经被标准保证是 1 - user4520
2个回答

4
  1. 你没有初始化你的struct tm,只设置了tm_hourtm_mintm_sectm_isdst。所有其他字段都未初始化,因此具有未知/未定义的值。
  2. 如果你使用memset(&tm, 0, sizeof(tm))来初始化struct tm,你仍然可能会收到错误,因为结构体中保存的字段不允许所有值都为0(例如tm_mday)。请参考文档
  3. 你放入tm_sec 的值很可能是无效的。实际上,你想要的是ms/1000,而不是ms*1000

它只在time.h中定义。您声明变量,因此必须初始化它。如果您仍在学习:将每个声明的变量初始化为定义的值是一个好习惯。 - eckes
@ eckes:非常感谢您的评论。我将其初始化为: tm.tm_hour = 16; tm.tm_min = 11; tm.tm_sec = 56.484*1000; 但仍然显示“无法生成时间”。 - learningpal
@learningpal:请仔细阅读:*您必须初始化tm提供的 每个字段,而不仅仅是像tm_hour这样填充实际值的字段... - eckes
我在我的代码中使用了这三个变量,hour(小时),minute(分钟)和seconds(秒),并对它们进行了初始化。你所说的每个字段是指天数和月份的名称吗?还是你能举个例子来解释一下你实际上是什么意思?至于'tm_sec',我需要(ms*1000),因为我需要以毫秒为单位获取时间。 - learningpal
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/83121/discussion-between-learningpal-and-eckes。 - learningpal
@ eckes:非常感谢您的时间和建议.. :) - learningpal

4

在调用mktime()之前,代码需要初始化tm_struct()的7个字段以上,包括year, month,day, hour min, sec, isdst和其他可能需要的字段。

有两个例外:.tm_yday, .tm_wday在调用mktime()之前不需要赋值。

年份、月份和日期应该设置为合理的数值:让我们使用2000年1月1日。或者代码可以使用time_t()获取今天的日期。

代码使用ms提示该值以毫秒为单位,但事实上这个值仍然以秒为单位。

使用本地time_t变量而不是分配一个变量。不需要使用malloc()

struct tm tm = {0};
tm.tm_year = 2000 - 1900;  // Years from 1900
tm.tm_mon = 1 - 1; // Months from January
tm.tm_mday = 1;
char time_buffer[100];
int hh, mm;
float ss;
time_t time_value;
char *timestamp = "16:11:56.484";

if (sscanf(timestamp, "%d:%d:%f", &hh, &mm,&ss) != 3) Handle_BadData();
tm.tm_hour = hh;
tm.tm_min = mm;
tm.tm_sec = roundf(ss);  // or simply = ss;
tm.tm_isdst = 0;  // Keep in standard time
// time_value = malloc(100*sizeof(char));
time_value = mktime(&tm);
if (time_value == -1) {
    printf ("unable to make time");
}
else {
  strftime(time_buffer, sizeof(time_buffer), "%c", &tm);
  printf(time_buffer);
}

// Sat Jan  1 16:11:56 2000

1
代码无法可移植地使用time_t保存毫秒级时间值,因为time_tmktime()的类型结果。C语言未指定如何编码time_t值,除了它是一个数字。大多数(不是全部)将time_t作为从1970年1月1日开始以秒为单位的整数计数 - 参见Unix时间。代码可以使用自己的结构,可能包括一个用于time_t和另一个用于秒的分数的字段。许多操作系统已经使用了 typedef struct timeval { long tv_sec; long tv_usec; } timeval;或类似的内容 - 所以不需要重复造轮子。 - chux - Reinstate Monica
1
@learningpal 获取毫秒值很容易 float ms = modff(ss, NULL) * 1000.0f; 现在代码已经有了毫秒值,你想用它做什么? - chux - Reinstate Monica
也许代码缺少前置 #include <time.h> - chux - Reinstate Monica
你可能正在使用老式编译器。在赋值之前,将所有变量声明放在前面:struct tm tm; char time_buffer[100]; ...char *timestamp = "16:11:56.484"; tm.tm_year = 2000 - 1900;... tm.tm_mday = 1; - chux - Reinstate Monica
1
@chux:是的,你说得对。现在它可以工作了。非常感谢。 :) 我已经在上周开始处理它了,但没有遇到这些初始化错误。 - learningpal
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接