将double转换为字符串而不分配超出所需内存的正确方法?

时间:2018-01-04 16:51:59

标签: c string double

我想知道正确的方法是将未知值的两倍 size 转换为字符串而不分配太多内存。有没有办法弄清楚双倍的数字?我不想分配太多或太少的内存。

3 个答案:

答案 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