在C中将双精度转换为字符*的缓冲区大小
为了将C中的在C中将双精度转换为字符*的缓冲区大小,c,string,double,C,String,Double,为了将C中的double(或float,int,long)转换为char*,我们可以使用 i) sprintf() ii)类似于itoa(),ftoa() 但所有这些函数都期望缓冲区作为参数。 在每种情况下,缓冲区的大小应该是多少,以便可以转换最大整数或最大精度浮点/双精度 使缓冲区足够大。一个double有大约15个位置加上指数和符号。缓冲区字符缓冲区[25]应该可以。不幸的是,无法使用%f说明符限制长度,因为长度参数是最小值,而不是最大值。因此,大的值采用与其指数相同的字符数,而不计算小数
double
(或float
,int
,long
)转换为char*
,我们可以使用
i) sprintf()
ii)类似于itoa()
,ftoa()
但所有这些函数都期望缓冲区作为参数。
在每种情况下,缓冲区的大小应该是多少,以便可以转换最大整数或最大精度浮点/双精度 使缓冲区足够大。一个double有大约15个位置加上指数和符号。缓冲区
字符缓冲区[25]
应该可以。不幸的是,无法使用%f
说明符限制长度,因为长度参数是最小值,而不是最大值。因此,大的值采用与其指数相同的字符数,而不计算小数
例如,%f.10”,1.e20f
产生100000002004087730000.0000000000
在这方面,
sprintf
是非常不安全的(应该禁止),首选snprintf
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);
double x=42;
常量字符fmt[]=%f;
int size=snprintf(0,0,fmt,x);
如果(大小<0){/*句柄错误*/}
字符buf[大小+1];
sprintf(buf,fmt,x);
C标准要求使用带有0大小参数的snprintf
。但是,请注意,一些较旧的实现并不符合要求(例如,如果输出被截断,而不是根据报告中可能写入的字符数,则Glibc直到2.0.6版返回-1)
上面的错误检查可能是无用的,唯一可能发生的错误是编码错误
您不应该在snprintf
和sprintf
调用之间更改区域设置,区域设置可能会影响大小。如果需要进行干预性的区域设置更改,则可以再次调用snprintf
来替换sprintf
,但是您可能希望通过malloc
,然后在必要时通过realloc
分配内存。[谢谢,!]
在Glibc下,还有一个分配缓冲区本身的方法。以后别忘了把它放出来。[多亏了!]要使用
sprintf()
将double
转换为字符串,缓冲区大小需要取决于格式说明符
请注意,下面的缓冲区在编译时是固定的,而不是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.
< > >代码> Prtff()/Case>函数考虑它们的代码>区域> <代码>,这样可以显示附加字符。建议使用snprintf()
// - 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();
}
//-digit.digits e-xxxx\0
字符buf[(1+2+DBL_DECIMAL_DIG+1+1+4+1)*2];
int len=snprintf(buf,'%e',DBL\u DECIMAL\u DIG,x);
如果(len<0 | | len>=sizeof buf){
处理精神错乱;
}
参考:看看这是否有帮助。但是不知道浮动。没有标准的ftoa
函数。那么“足够大”到底是什么呢?这取决于架构等。此外,它永远不会是最小可能值(如果有关系的话)。只要架构使用IEEE浮点,字符串中双精度表示的最大长度应该是相当恒定的。只需将pi*-1.0*1e-15打印为字符串并计数字符,添加一个用于安全,另一个用于\0
这样草率地进行大小计算是非常糟糕的建议<例如,code>%f
默认情况下在
后面打印6位数字,这使得char[25]
对于某些IEEE双精度值来说太小了。@mafso遗憾的是,这是真的。所以,在一般情况下,我的回答是没有帮助的。如果你得到一个很好的公式,类似于<代码> SIEZOF(int)*CARYBIT /3 + 2 <代码> int <代码>,我会认为这是一个非常有用的答案。但我不知道有什么合理的方法来获取上限,特别是因为我不知道小数点的长度是否在所有地区都有上限(可能是MB_LEN_MAX
?)<来自
的code>DECIMAL\u DIG(以及来自那里的其他宏)可能会有帮助。非常迂腐的一点:C11不需要这样做,因为VLA是可选的。关于区域设置的更改(或者如果x可能是易失性的
),建议第二次调用snprintf()
。@MattMcNabb:Yes,我在这里使用它们是因为这是我发现VLA(不是指向VLA的指针)有用的少数情况之一:你没有一个好的长度上限,但你知道它不会“很大”。这是基本的C语言知识,没有它们怎么做,与这个问题没有太大关系,所以我没有提到它。@chux:然后做什么?在构建的调试中,您可以中止
。无论哪种方式,我认为最好记录函数在执行过程中不接受区域设置更改。或者,malloc
和realloc
在一个循环中运行,直到一切正常。但是是的,可能值得一提的是,我稍后会编辑,我目前没有时间。在glibc
下,您可以使用asprintf
分配正确大小的缓冲区。注意:在C
区域设置中,%f
长度限制为DBL\u MAX\u 10\u EXP+9
(+1表示'\0'
)。同意有关sprintf()的问题。