Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中将双精度转换为字符*的缓冲区大小_C_String_Double - Fatal编程技术网

在C中将双精度转换为字符*的缓冲区大小

在C中将双精度转换为字符*的缓冲区大小,c,string,double,C,String,Double,为了将C中的double(或float,int,long)转换为char*,我们可以使用 i) sprintf() ii)类似于itoa(),ftoa() 但所有这些函数都期望缓冲区作为参数。 在每种情况下,缓冲区的大小应该是多少,以便可以转换最大整数或最大精度浮点/双精度 使缓冲区足够大。一个double有大约15个位置加上指数和符号。缓冲区字符缓冲区[25]应该可以。不幸的是,无法使用%f说明符限制长度,因为长度参数是最小值,而不是最大值。因此,大的值采用与其指数相同的字符数,而不计算小数

为了将C中的
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()的问题。