跨平台支持sprintf的格式’-Flag

Single UNIX Specification Version 2将sprintf的格式' -flag行为指定为:

十进制转换结果的整数部分( %i%d%u%f%g%G )将使用数千个分组字符进行格式化[ 1 ]

我在c或c ++规范中找不到格式' -flag。 g ++甚至警告 :

ISO C ++ 11不支持' printf标志

即使在Visual C中警告,也不会识别该标志; printf("%'d", foo)输出 :

倒是

我希望能够编写符合C标准的代码,该代码使用格式' -flag的行为。 因此答案我正在寻找以下之一:

  1. C-Standard格式' -flag的规范
  2. 跨平台兼容外推gcc的格式' -flag
  3. certificate跨平台外推是不可能的

标准C不直接提供格式化function,但它确实能够在特定于语言环境的基础上检索格式应该是什么的规范。 因此,您需要检索区域设置的正确格式规范,然后将其用于格式化数据(但即使这样,它也有点不重要)。 例如,这是一个用于格式化long数据的版本:

 #include  #include  #include  #include  static int next_group(char const **grouping) { if ((*grouping)[1] == CHAR_MAX) return 0; if ((*grouping)[1] != '\0') ++*grouping; return **grouping; } size_t commafmt(char *buf, /* Buffer for formatted string */ int bufsize, /* Size of buffer */ long N) /* Number to convert */ { int i; int len = 1; int posn = 1; int sign = 1; char *ptr = buf + bufsize - 1; struct lconv *fmt_info = localeconv(); char const *tsep = fmt_info->thousands_sep; char const *group = fmt_info->grouping; // char const *neg = fmt_info->negative_sign; size_t sep_len = strlen(tsep); size_t group_len = strlen(group); // size_t neg_len = strlen(neg); int places = (int)*group; if (bufsize < 2) { ABORT: *buf = '\0'; return 0; } *ptr-- = '\0'; --bufsize; if (N < 0L) { sign = -1; N = -N; } for ( ; len <= bufsize; ++len, ++posn) { *ptr-- = (char)((N % 10L) + '0'); if (0L == (N /= 10L)) break; if (places && (0 == (posn % places))) { places = next_group(&group); for (int i=sep_len; i>0; i--) { *ptr-- = tsep[i-1]; if (++len >= bufsize) goto ABORT; } } if (len >= bufsize) goto ABORT; } if (sign < 0) { if (len >= bufsize) goto ABORT; *ptr-- = '-'; ++len; } memmove(buf, ++ptr, len + 1); return (size_t)len; } #ifdef TEST #include  #define elements(x) (sizeof(x)/sizeof(x[0])) void show(long i) { char buffer[32]; commafmt(buffer, sizeof(buffer), i); printf("%s\n", buffer); commafmt(buffer, sizeof(buffer), -i); printf("%s\n", buffer); } int main() { long inputs[] = {1, 12, 123, 1234, 12345, 123456, 1234567, 12345678 }; for (int i=0; i 

这确实有一个错误(但我认为这个错误很小)。 在二进制补码硬件上,它不会正确转换最负数,因为它试图将负数转换为等效正数, N = -N; 在二进制补码中,最大负数没有相应的正数,除非您将其提升为更大的类型。 解决这个问题的一种方法是通过提升相应的无符号类型的数字(但这有点不重要)。

对其他整数类型实现相同的操作是相当简单的。 对于浮点类型来说,工作要多一些。 正确转换浮点类型(即使没有格式化)也足够了,对于它们来说,我至少考虑使用类似sprintf东西进行转换,然后将格式插入到生成的字符串中。