使用%g的sprintf的最小缓冲区大小是多少?

时间:2009-11-03 00:34:09

标签: c double printf

问题是静态分配一个足够大的缓冲区以适应打印的双精度格式,格式为%g,最大精度。这似乎是一个足够简单的任务,我遇到了麻烦。我想出的最好的(假设要打印的数字是x)是

char buf[1 + DBL_DIG + DBL_DIG + 1 + 1 + 1 + DBL_DIG + 1];
int len = sprintf(buf, "%.*g", DBL_DIG, x);

DBL_DIG宏来自float.h,显然它应该表示double类型的最大精度。我们需要:

  • 1个字符表示负号
  • 足够的字节来捕获有效数字
  • 每个数字最多一个“分隔符”字符(逗号等)
  • 小数点1个字节
  • 'e'
  • 的1个字节
  • 指数上的符号为1个字节
  • 指数的一些字节
  • 由sprintf写的尾随空值的1个字节。

我使用有效位数作为指数中位数的上限。我有任何错误吗?有更好的解决方案吗?我应该只分配64,128或256个字节并希望最好吗?

5 个答案:

答案 0 :(得分:5)

使用snprintf()找出您需要的字符数:

#include <float.h> /* DBL_DIG */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
  double x = rand() / (double)RAND_MAX;
  char find_len[1];
  int need_len;
  char *buf;

  need_len = snprintf(find_len, 1, "%.*g", DBL_DIG, x);
  buf = malloc(need_len + 1);
  if (buf) {
    int used = sprintf(buf, "%.*g", DBL_DIG, x);
    printf("need: %d; buf:[%s]; used:%d\n", need_len, buf, used);
    free(buf);
  }
  return 0;
}

您需要snprintf()的C99编译器。
snprintf()由C99标准定义。 C89实现不需要定义snprintf(),如果它具有扩展名,则不需要按照C99标准的说明“工作”。

答案 1 :(得分:5)

您无法在编译时预先计算大小。 %g格式化程序考虑了区域设置(对于1000的分隔符等) 有关如何安全地计算大小的说明,请参阅http://linux.die.net/man/3/sprintf

答案 2 :(得分:1)

两件事:%g没有显示所有可表示的数字,%g显示了一个非常适合人类的圆形结果。如果您想要不同的结果,可以使用%f或%e指定精度。

永远不要使用sprintf()而不是使用snprintf()。在你的情况下: int len = snprintf(buf, dimensionof(buf), "%.*f", DBL_DIG, x);

答案 3 :(得分:1)

您可以使用asprintf而不是sprintf。这将分配一个正确大小的缓冲区以适合您的字符串。

答案 4 :(得分:-2)

  

我应该直接到64,128还是   256并希望最好?

是的,就这样做 - .-