在 C 中将 time_t 转换为给定格式的字符串

Converting a time_t to a string in a given format in C

因此,作为作业的一部分,我们已经完成了这个骨架函数:

char *time2str(time_t time) {
    static char *str_fmt = "%02d/%02d/%4d %02d:%02d";
    char *time_s = ""; // appropriate string allocation here

    return time_s;
}

但是我对 C 还很陌生,并且在努力了解我做错了什么(以及指针是如何工作的)......我一直在尝试使用 localtime 来获得struct 我可以使用它访问我需要添加到给定格式的字符串的特定值。像这样:

char *time2str(time_t time) {
    static char *str_fmt = "%02d/%02d/%4d %02d:%02d";

    struct tm *info;
    info = localtime(&time);

    char *time_s = (str_fmt, info->tm_mday, info->tm_mon...etc...);

    return time_s;
}

然而,无论我尝试做什么,我都只是在编译时收到警告和错误(删除 str_fmt 并将格式放在 time_s 开头的引号中,使用 info.tm_mday 等而不是 info->tm_mday)。然而,似乎没有任何效果,我在网上找不到任何可以帮助我按照我们被问到的方式解决问题的东西。

有人可以帮忙吗?可能值得一提的是,我们正在使用 MINIX 系统调用在 MINIX 3.2.1 上执行此操作。

根据您给我们的信息,我假设函数应该是:

char *time2str(time_t time) {
    static char *str_fmt = "%02d/%02d/%4d %02d:%02d";

    // Convert to struct tm
    // localtime returns a pointer, so shallow copy to info
    struct tm info = *localtime(&time);

    // Allocate memory for ##/##/#### ##:##
    char *time_s = malloc(17);  // Space for 16 chars and eos
    if (NULL == time_s) {// Handle error.....}
    sprintf(time_s, str_fmt, info.tm_mon + 1, info.tm_mday, 1900 + info.tm_year,
           info.tm_hour, info.tm_min);

    return time_s;
}

在 C 中管理字符串是一项棘手的任务。当存在意外情况时,多年成功的代码可能会失败。

考虑格式 "%02d/%02d/%4d %02d:%02d"。这通常需要一个大小为 16 + 1 的数组(对于空字符)。这与 Y2K bugs 的编码类型相同,因为在 9999 年后需要更多 space。考虑一个允许 time_t 表示遥远未来时间的系统,并尝试根据其最大值形成一个 date/time 字符串 --> 缓冲区溢出。

相反,允许 struct tm 中的所有潜在值并提供大量的临时缓冲区。然后分配。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// Max length needed for a `int` as decimal text 
#define INT_STR_LEN (sizeof(int)*CHAR_BIT/3 + 2)

#define TIME2STR_FMT "%02d/%02d/%04d %02d:%02d"
// Worst case size - and them some
#define TIME2STR_SZ (sizeof TIME2STR_FMT + 5*INT_STR_LEN)

char *time2str(time_t time) {

  struct tm *info = localtime(&time);
  if (info == NULL) return NULL;

  char buf[TIME2STR_SZ];
  int n = snprintf(buf, sizeof buf, TIME2STR_FMT, info->tm_mon + 1, info->tm_mday,
      info->tm_year + 1900, info->tm_hour, info->tm_min);
  if (n < 0 || n >= sizeof buf) return NULL;

  // Allocate and copy
  size_t sz = strlen(buf) + 1;
  char *time_s = malloc(sz);
  if (time_s) {
    memcpy(time_s, buf, sz);
  }

  return time_s;
}

int main(void) {
  time_t t;
  puts(time2str(time(&t)));
  return 0;
}