我想知道正确的方法是将未知值的两倍 size 转换为字符串而不分配太多内存。有没有办法弄清楚双倍的数字?我不想分配太多或太少的内存。
答案 0 :(得分:5)
您可以使用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;
}
答案 1 :(得分:4)
这里有一个如何使用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;
}
答案 2 :(得分:0)
将double转换为字符串而不分配超出所需内存的正确方法?
使用> dt2
id date with.90d
1: A 2017-01-01 FALSE
2: A 2017-02-01 TRUE
3: A 2017-05-01 FALSE
4: B 2017-01-01 FALSE
5: B 2017-05-01 FALSE
6: B 2017-10-01 FALSE
7: C 2017-01-01 FALSE
8: C 2017-02-01 TRUE
9: C 2017-02-15 TRUE
确定字符数需求。
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
的指数表示法和精度进行打印,代码不需要更多数字来进行&#34;往返&#34;字符串返回double
strtod()
或sscanf()
。{/ p>
"%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