我想知道正确的方法是什么也转换为未知值的双倍 尺寸 到没有分配太多内存的字符串。有没有办法弄清楚双倍的数字?我不想分配太多或太少的内存。
你可以使用NULL
作为snprintf
的第一个参数来获得大小:
C99允许str为NULL并且返回值(一如既往)为在输出字符串足够大的情况下写入的字符数。
然后malloc
:
int main(void)
{
double num = 3.14;
size_t len;
char *str;
len = (size_t)snprintf(NULL, 0, "%f", num) + 1;
str = malloc(len);
snprintf(str, len, "%f", num);
puts(str);
free(str);
return 0;
}
这里有一个基本的例子,当你只想知道表示的长度时如何使用snprintf
:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main(void)
{
int size = snprintf(NULL, 0, "%.15lf", M_PI);
char *pi = malloc(size + 1);
sprintf(pi, "%.15lf", M_PI);
printf("PI: '%s'\n", pi);
free(pi);
return 0;
}
将double转换为字符串而不分配超出要求的内存的正确方法?
使用snprintf()
确定字符数需求。
double value = foo();
int size = snprintf(NULL, 0, some_format, value);
if (size < 0) Handle_encoding_error(); // This is very rare
else {
char *buffer = malloc(size + 1u);
if (buffer == NULL) Handle_OOM_error(); // This is also rare
else {
snprintf(buffer, 0, some_format, value);
puts(buffer);
free(buffer);
}
}
使用什么格式取决于编码目标。 "%f"
经常导致许多大数据的无信息数字和大约一半"0.00000"
的double
,因为许多数值小于0.0000005。
打印带有效数字的double
的好方法是采用指数表示法。使用指数表示法的好处不仅是double
被完全表达,它的最大字符串大小需要可以预先计算(大约28)并且不会过多。
通过使用指数表示法和DBL_DECIMAL_DIG - 1
的精度打印,代码不需要更多的数字来将字符串“往返”返回到与double
或strtod()
相同的sscanf()
。
"%a" // Hexadecimal signicand
"%.*e" // Decimal
int size = snprintf(NULL, 0, "%a", value);
// or
int size = snprintf(NULL, 0, "%.*e", DBL_DECIMAL_DIG-1, value);
// or directly with minimal extra space
// - d . dddddd e - expo \0
#define N (1 + 1 + 1 + (DBL_DECIMAL_DIG - 1) + 1 + 1 + 6 + 1)
char buf[N];
snprintf(buf, sizeof buf, "%.*e", DBL_DECIMAL_DIG-1, value);
见Printf width specifier to maintain precision of floating-point value