简体   繁体   中英

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

So as part of an assignment we've been given this skeleton function to complete:

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

    return time_s;
}

However I'm very new to C and struggling to get my head around what I'm doing wrong (and also how pointers work)... I've been trying to use localtime to get a struct with which I can access the specific values I need to add to the string in the given format. Something like this:

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;
}

However I'm just getting warnings and errors at compile no matter what I try and do (remove str_fmt and just put the format in quotations at the beginning of time_s , using info.tm_mday etc rather than info->tm_mday ). However nothing seems to have any effect and I can't find anything online that helps me solve the problem in the way we have been asked.

Can anyone help? It's probably worth mentioning that we are doing this on MINIX 3.2.1 using MINIX system calls.

Using what you've given us, I assume the function should be:

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;
}

Managing strings is a tricky task in C. Code with years of success can fail when an unexpected situation exist.

Consider the format "%02d/%02d/%4d %02d:%02d" . This would usually expect an array of size 16 + 1 (for the null character). This is the same type of coding that made for Y2K bugs as this one needs more space after the year 9999. Consider a system that allowed time_t to represent time into the far future and and tried forming a date/time string based in its max value --> buffer overflow.

Instead, allow for all potential values in struct tm and provide a generous temporary buffer. Then allocate.

#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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM