Как безопасно форматировать числа с плавающей запятой / double с помощью функции sprintf () в C? - PullRequest
4 голосов
/ 04 ноября 2010

Я портирую одну из моих библиотек C ++ на несколько шаткий компилятор - он не поддерживает строковые потоки или функции C99, такие как snprintf(). Мне нужно отформатировать значения int, float и т. Д. Как char*, и единственными доступными опциями являются: 1) использование sprintf() 2) процедуры форматирования с ручным управлением.

Учитывая это, как мне определить (во время компиляции или во время выполнения), сколько байтов требуется для форматированного значения с плавающей точкой? Моя библиотека может использоваться для нечеткого тестирования, поэтому она должна обрабатывать даже необычные или экстремальные значения.

В качестве альтернативы, есть ли небольшая (предпочтительно 100-200 строк) портативная реализация snprintf(), которую я мог бы просто связать со своей библиотекой?

В идеале я хотел бы получить либо обычный snprintf() код, либо что-то вроде этого:

static const size_t FLOAT_BUFFER_SIZE = /* calculate max buffer somehow */;

char *fmt_double(double x)
{
    char *buf = new char[FLOAT_BUFFER_SIZE + 1];
    sprintf(buf, "%f", x);
    return buf;
}

Похожие вопросы:

Ответы [ 2 ]

3 голосов
/ 04 ноября 2010

Поддерживает ли компилятор любой из ecvt, fcvt или gcvt? Они немного причудливы и сложны в использовании, но у них есть свой собственный буфер (ecvt, fcvt), и / или вам может повезти и вы обнаружите, что системные заголовки имеют, как в VC ++, определение максимального числа из gcvt будет производить. И вы можете взять его оттуда.

Если это не удастся, я бы посчитал следующее вполне приемлемым в соответствии с приведенным кодом. 500 символов довольно консервативны для двойника; допустимые значения примерно от 10 ^ -308 до 10 ^ 308, поэтому даже если реализация определена как раздражающая при распечатке всех цифр, переполнения быть не должно.

char *fmt_double(double d) {
    static char buf[500];
    sprintf(buf,"%f",d);
    assert(buf[sizeof buf-1]==0);//if this fails, increase buffer size!
    return strdup(buf);
}

Это не дает никаких удивительных гарантий, но должно быть довольно безопасно (тм). Я думаю, что это так же хорошо, как это происходит с таким подходом, к сожалению. Но если у вас есть привычка регулярно запускать отладочные сборки, вы должны по крайней мере получать раннее предупреждение о любых проблемах ...

1 голос
/ 04 ноября 2010

Я думаю GNU Libiberty - это то, что вы хотите. Вы можете просто включить реализацию snprintf.

vasprintf.c - 152 LOC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...