Domanda

Il problema è quello di allocare staticamente un buffer sufficientemente grande da contenere un doppio stampata, formattato con% g alla massima precisione. Questo mi sembra un compito abbastanza semplice, bu sto avendo difficoltà. Il migliore che ho messo a punto (supponendo che il numero da stampare è x) è

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

La macro DBL_DIG è da float.h, e apparentemente si suppone per indicare la massima precisione per il tipo double. Abbiamo bisogno di:

  • 1 byte per un segno negativo
  • abbastanza byte per catturare le cifre significative
  • al massimo un char 'separator' (virgola, etc.) per digit
  • 1 byte per un punto decimale
  • 1 byte per 'e'
  • 1 byte per il segno sulla esponente
  • alcuni byte per l'esponente
  • 1 byte per la finale NULL scritto da sprintf.

Sto utilizzando il numero di cifre significative come un limite superiore al numero di cifre dell'esponente. Ho ho fatto errori? C'è una soluzione migliore? Devo solo allocare 64, 128, o 256 byte e sperare per il meglio?

È stato utile?

Soluzione 4

Invece di usare sprintf, è possibile utilizzare asprintf . Questo alloca un buffer della dimensione corretta per misura il vostro stringa.

Altri suggerimenti

Non è possibile pre-calcolare la dimensione in fase di compilazione. Il% g formattatore prende il locale in considerazione (per il 1000 separatore etc.) Vedere http://linux.die.net/man/3/sprintf per un descrizione su come calcolare le dimensioni in modo sicuro.

Usa snprintf() per scoprire quanti caratteri è necessario:

#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;
}

Hai bisogno di un compilatore C99 per snprintf().
snprintf() è stato definito dallo standard C99. Un'implementazione C89 non è necessario avere snprintf() definita, e se ha come estensione, non è richiesto di "lavoro" come descritto dal C99 standard.

Due cose:% g non mostra tutte le cifre rappresentabili,% g mostra una bella-per-gli esseri umani risultato arrotondato. È possibile specificare la precisione utilizzando% fo% e se si desidera un risultato diverso.

Non usare sprintf () piuttosto che utilizzare snprintf (). Nel tuo caso: int len = snprintf(buf, dimensionof(buf), "%.*f", DBL_DIG, x);

  

Devo solo arrotondare fino a 64, 128, o   256 e sperare per il meglio?

Sì, basta farlo -.-

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top