Каков минимальный размер буфера для sprintf с %g?

StackOverflow https://stackoverflow.com/questions/1664571

  •  12-09-2019
  •  | 
  •  

Вопрос

Проблема заключается в статическом выделении буфера, достаточно большого, чтобы вместить напечатанный двойной файл, отформатированный с %g с максимальной точностью.Это кажется достаточно простой задачей, но у меня возникли проблемы.Лучшее, что я придумал (при условии, что число, которое будет напечатано, равно x), это

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

Макрос DBL_DIG взят из float.h, и, по-видимому, предполагается, что он указывает максимальную точность для типа double .Нам нужно:

  • 1 байт для отрицательного знака
  • достаточно байт, чтобы записать значащие цифры
  • не более одного символа-разделителя (запятой и т.д.) На цифру
  • 1 байт для десятичной точки
  • 1 байт для 'e'
  • 1 байт для знака экспоненты
  • несколько байт для показателя степени
  • 1 байт для конечного значения null, записанного sprintf.

Я использую количество значащих цифр в качестве верхней границы количества цифр в экспоненте.Допустил ли я какие-либо ошибки?Есть ли лучшее решение?Должен ли я просто выделить 64, 128 или 256 байт и надеяться на лучшее?

Это было полезно?

Решение 4

Вместо использования sprintf, вы могли бы использовать asprintf.Это выделяет буфер правильного размера, соответствующий вашей строке.

Другие советы

Вы не можете предварительно рассчитать размер во время компиляции.Форматировщик %g учитывает языковой стандарт (для разделителя 1000 и т.д.) Смотрите http://linux.die.net/man/3/sprintf для получения описания того, как безопасно рассчитать размер.

Использовать snprintf() чтобы узнать, сколько символов вам нужно:

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

Вам нужен компилятор C99 для snprintf().
snprintf() был определен стандартом C99.Реализация C89 не требует наличия snprintf() определен, и если он имеет расширение, он не обязан «работать», как описано в стандарте C99.

Две вещи:%g не отображает все представимые цифры, %g показывает округленный результат, удобный для людей.Вы можете указать точность, используя %f или %e, если хотите другой результат.

Никогда не используйте sprintf() вместо snprintf().В твоем случае:int len = snprintf(buf, dimensionof(buf), "%.*f", DBL_DIG, x);

Должен ли я просто округлить до 64, 128 или 256 и надеяться на лучшее?

Да, просто сделай это ...-

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top