strftime的合理snprintf样的替代品?
问题描述:
是否有可用于strftime的合理snprintf样的替代品?
- 任何标准(C,C++,POSIX,Linux的...)替代
strftime
计算串缓冲器的所需尺寸对于给定的格式和时间, - 截断输出(而不是像
strftime
那样未定义数组内容),如果缓冲区大小小于完整输出所需的大小。
例如,snprintf
类似于接受strftime
格式字符串的日期/时间格式的语义。
在C++ 11及更高版本中,像std::put_time
这样的函数不是一个选项,因为这些函数可能会试图动态分配额外的内存并可能会抛出异常。
答
在代码成功之前可以继续尝试更大的缓冲区(或者认为这太多了)。下面使用一个VLA(不是C++),来偷偷地避免“试图动态分配额外的内存” - 眨眼。
简单地分配一个大缓冲区,比如char buf[J_STRFTIME_MAX]
,对于实际编码来说应该是足够的。 @Michaël Roy并避免迭代方法。
#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);
}
}
输出
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>
非迭代
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;
}
[编辑]码纠正。
假设有人会在接下来的7983年更新您的代码,然后计算您需要的格式化时间在您的手指上的字节数。似乎没有必要自动执行此操作。避免长周和月名,因为它们依赖于语言环境。 – Art
不,没有,但你可以相对容易地写出你自己的。 ['stdarg.h'](http://www.cplusplus.com/reference/cstdarg/)和['vsnprintf'](http://www.cplusplus.com/reference/cstdio/vsnprintf/)可以有助于实现这一点。 – Akira
@Akira根据当前的语言环境等等,对于星期几和月份名称来说可能并不那么容易。stdarg和vsnprintf将不需要替换,因为strftime具有固定数量的参数。 – Ctx