为了将C中的double
(或float
,int
,long
)转换为char*
,我们可以使用
i)sprintf()
ii)itoa()
,ftoa()
但是所有这些函数都希望将缓冲区作为参数。 在每种情况下缓冲区的大小应该是什么,以便可以转换最大整数或最大精度float / double?
答案 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 )。
上面的错误检查可能没用,唯一可能发生的错误是编码错误。
您不应该更改snprintf
和sprintf
来电之间的区域设置,区域设置可能会影响大小。如果干预区域设置更改是一个问题,sprintf
可以再次被snprintf
调用替换,但是您可能希望通过malloc
分配内存,然后realloc
必要。 [谢谢,Chux!]
答案 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
。