Question

Le problème consiste à répartir de manière statique un tampon suffisamment grand pour contenir une double imprimé, mis en forme avec g% à un maximum de précision. Cela semble être une tâche assez simple, bu, je vais avoir du mal. Le meilleur que je suis venu avec (en supposant que le nombre à imprimer est 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 est de float.h, et apparemment il est censé indiquer la précision maximale pour le type double. Nous avons besoin:

  • 1 octet pour un signe négatif
  • assez d'octets pour saisir les chiffres significatifs
  • au plus un char 'séparateur' (virgule, etc.) par chiffre
  • 1 octet pour un point décimal
  • 1 octet pour 'e'
  • 1 octet pour le signe de l'exposant
  • quelques octets pour l'exposant
  • 1 octet pour le null de fuite écrit par sprintf.

J'utilise le nombre de chiffres significatifs comme une limite supérieure du nombre de chiffres dans l'exposant. Ai-je fait une erreur? Y at-il une meilleure solution? Devrais-je allouer 64, 128 ou 256 octets et espérer le meilleur?

Était-ce utile?

La solution 4

Au lieu d'utiliser sprintf, vous pouvez utiliser asprintf . Cela alloue un buffer de la taille correcte pour l'adapter à votre chaîne.

Autres conseils

Vous ne pouvez pas pré-calculer la taille au moment de la compilation. Le formatter% g prend les paramètres régionaux en compte (pour le séparateur de 1000, etc. de) Voir http://linux.die.net/man/3/sprintf pour la description sur la façon de calculer la taille en toute sécurité.

Utilisez snprintf() pour savoir combien de caractères dont vous avez besoin:

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

Vous avez besoin d'un compilateur C99 pour snprintf().
snprintf() a été défini par la norme C99. Une mise en œuvre de C89 n'est pas nécessaire d'avoir snprintf() défini, et si elle a comme une extension, il n'est pas nécessaire de « travailler » tel que décrit par la norme C99.

Deux choses:% g ne montre pas tous les chiffres représentables,% g montre un beau-pour-homme arrondi résultat. Vous pouvez spécifier la précision en utilisant% f ou% e si vous voulez un résultat différent.

Ne jamais utiliser sprintf () plutôt que d'utiliser snprintf (). Dans ton cas: int len = snprintf(buf, dimensionof(buf), "%.*f", DBL_DIG, x);

  

Dois-je arrondir juste à 64, 128 ou   256 et espérer pour le mieux?

Oui, il suffit de faire que -.-

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top