Could keep trying larger buffers until code succeeds (or decides this is too much). The below uses a VLA (not C++), to sneakily avoid "attempt to allocate extra memory dynamically" - wink wink.
Simply allocating a large buffer, say char buf[J_STRFTIME_MAX]
, should be sufficient for practical coding. @Michaël Roy and avoid the iterative approach.
#include <stdio.h>
#include <time.h>
#define J_STRFTIME_MAX 100
size_t j_strftime(char * s, size_t maxsize, const char * fmt, const struct tm * t) {
size_t sz = strftime(s, maxsize, fmt, t);
if (sz) {
return sz;
}
size_t new_size = maxsize ? maxsize : 1;
do {
new_size *= 2;
char new_s[new_size];
sz = strftime(new_s, sizeof new_s, fmt, t);
if (sz) {
s[0] = 0;
// strncat(s, new_s, maxsize);
strncat(s, new_s, maxsize - 1);
return strlen(new_s);
}
} while (sz < J_STRFTIME_MAX/2);
return 0;
}
int main() {
time_t now;
time(&now);
struct tm tm = *gmtime(&now);
for (size_t i = 1; i < 30; i += 3) {
char s[i];
size_t sz = j_strftime(s, sizeof s, "%c", &tm);
printf("%2zu %2zu <%s>\n", i, sz, s);
}
}
Output
1 24 <T>
4 24 <Thu >
7 24 <Thu Jul>
10 24 <Thu Jul 6>
13 24 <Thu Jul 6 14>
16 24 <Thu Jul 6 14:45>
19 24 <Thu Jul 6 14:45:00>
22 24 <Thu Jul 6 14:45:00 20>
25 24 <Thu Jul 6 14:45:00 2017>
28 24 <Thu Jul 6 14:45:00 2017>
Non-iterative
size_t j_strftime2(char * s, size_t maxsize, const char * fmt, const struct tm * t) {
size_t sz = strftime(s, maxsize, fmt, t);
if (sz == 0) {
char new_s[J_STRFTIME_MAX];
sz = strftime(new_s, sizeof new_s, fmt, t);
if (sz == 0) {
return 0; // Too too big
}
s[0] = 0;
// strncat(s, new_s, maxsize);
strncat(s, new_s, maxsize - 1);
}
return sz;
}
[Edit] Code corrected.
stdarg.h
andvsnprintf
can be helpful to achieve that. – Volscian