在C中将double转换为char *的缓冲区大小

时间:2015-03-19 10:15:38

标签: c string double

为了将C中的double(或floatintlong)转换为char*,我们可以使用

i)sprintf()

ii)itoa()ftoa()

等功能

但是所有这些函数都希望将缓冲区作为参数。 在每种情况下缓冲区的大小应该是什么,以便可以转换最大整数或最大精度float / double?

4 个答案:

答案 0 :(得分:3)

snprintf可用于确定大小,使用0参数作为大小:

double x = 42;
const char fmt[] = "%f";
int size = snprintf(0, 0, fmt, x);
if(size < 0) { /* handle error */ }
char buf[size+1];
sprintf(buf, fmt, x);

C标准要求snprintf使用0大小的参数。但请注意,一些较旧的实现不符合(例如,根据man page,如果输出被截断而不是已经写入的字符数,则直到版本2.0.6的Glibc返回-1 )。

上面的错误检查可能没用,唯一可能发生的错误是编码错误。

您不应该更改snprintfsprintf来电之间的区域设置,区域设置可能会影响大小。如果干预区域设置更改是一个问题,sprintf可以再次被snprintf调用替换,但是您可能希望通过malloc分配内存,然后realloc必要。 [谢谢,Chux!]

在Glibc下,还有asprintf分配缓冲区本身。不要忘记之后将其释放。 [感谢Abligh!]

答案 1 :(得分:1)

使缓冲区足够大。双人有大约15个位置加上指数和标志。缓冲区char buffer[25]应该这样做。

答案 2 :(得分:1)

要将double转换为字符串并使用sprintf(),缓冲区大小需要取决于格式说明符。

请注意,下面的缓冲区在编译时是固定的,而不是VLA。

//       -   digits               .   000000 \0
char buf[1 + 1 + DBL_MAX_10_EXP + 1 + 6 + 1];
sprintf(buf, "%f", x);

//       -   digit.digits          e   -  xxxx \0
char buf[1 + 2 + DBL_DECIMAL_DIG + 1 + 1 + 4 + 1];
sprintf(buf, "%.*e", DBL_DECIMAL_DIG, x);

// Others: %0.100f %a %*.*E etc.

但是printf()函数会考虑他们的locale,因此可以显示其他字符。使用snprintf()建议超大缓冲到预期大小的2倍,然后在晚上睡得好。

//       -   digit.digits          e   -  xxxx \0
char buf[(1 + 2 + DBL_DECIMAL_DIG + 1 + 1 + 4 + 1)*2];
int len = snprintf(buf, "%.*e", DBL_DECIMAL_DIG, x);
if (len < 0 || len >= sizeof buf) {
  Handle_Insanity();
}

参考:Printf width specifier to maintain precision of floating-point value

答案 3 :(得分:0)

不幸的是,没有办法用%f说明符限制长度,因为length参数是最小值,而不是最大值。如此大的值需要与指数一样多的字符,而不是小数。

例如,"%f.10", 1.e20f会产生100000002004087730000.0000000000

在这方面,sprintf非常不安全(应该被禁止),更喜欢snprintf