Pergunta

O problema é alocar estaticamente um tampão suficientemente grande para caber uma dupla impresso, formatado com% g a máxima precisão. Esta parece ser uma tarefa bastante simples, bu estou tendo problemas. O melhor que eu vim com (assumindo que o número a ser impresso é x) é

char buf[1 + DBL_DIG + DBL_DIG + 1 + 1 + 1 + DBL_DIG + 1];
int len = sprintf(buf, "%.*g", DBL_DIG, x);

A macro DBL_DIG é de float.h, e aparentemente é suposto para indicar a precisão máxima para o tipo de casal. Precisamos de:

  • 1 byte para um sinal negativo
  • bytes suficientes para capturar os dígitos significativos
  • , no máximo, um char 'separador' (vírgula, etc.) por algarismos
  • 1 byte para um ponto decimal
  • 1 byte por 'e'
  • 1 byte para o sinal no expoente
  • alguns bytes para o expoente
  • 1 byte para o nulo de arrasto escrito por sprintf.

Eu estou usando o número de dígitos significativos como um limite superior para o número de dígitos no expoente. Fiz todos os erros? Existe uma solução melhor? Devo apenas alocar 64, 128 ou 256 bytes e esperança para o melhor?

Foi útil?

Solução 4

Em vez de usar sprintf, você poderia usar asprintf . Isso aloca um buffer do tamanho correto para caber sua string.

Outras dicas

Você não pode pré-calcular o tamanho em tempo de compilação. O formatador% g leva a localidade em conta (para o separador de 1000, etc.) Consulte http://linux.die.net/man/3/sprintf para uma descrição sobre como calcular o tamanho segurança.

Use snprintf() para descobrir quantos caracteres que você precisa:

#include <float.h> /* DBL_DIG */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
  double x = rand() / (double)RAND_MAX;
  char find_len[1];
  int need_len;
  char *buf;

  need_len = snprintf(find_len, 1, "%.*g", DBL_DIG, x);
  buf = malloc(need_len + 1);
  if (buf) {
    int used = sprintf(buf, "%.*g", DBL_DIG, x);
    printf("need: %d; buf:[%s]; used:%d\n", need_len, buf, used);
    free(buf);
  }
  return 0;
}

Você precisa de um compilador C99 para snprintf().
snprintf() foi definida pela norma C99. implementação A C89 não é obrigado a ter snprintf() definido, e se ele tem como uma extensão, não é necessária a "trabalhar" como descrito pelo C99 padrão.

Duas coisas:% g não mostra todos os dígitos representáveis,% G mostra um resultado arredondado agradável-para-humanos. Você pode especificar a precisão usando% f ou% e se você gostaria de um resultado diferente.

Nunca uso sprintf () ao invés de usar snprintf (). No seu caso: int len = snprintf(buf, dimensionof(buf), "%.*f", DBL_DIG, x);

Eu deveria rodada até 64, 128, ou 256 e esperar o melhor?

Sim, basta fazer isso -.-

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top