Сегодня и snprintf
, и vsnprintf
должны быть доступны везде, за исключением Windows с MSVC12 и старше. Самый простой способ для вас - предоставить snprintf
/ vsnprintf
в Windows, где он недоступен.
Windows предоставляет функцию _vsnprintf_s
, которая уже похожа на vsnprintf
, но имеет следующие важные различия в отношении того, что происходит, когда буфер слишком мал:
- Содержимое буфера зависит от дополнительного аргумента
count
, которого нет в vsnprintf
. Чтобы получить поведение vsnprintf
, вы можете передать _TRUNCATE
здесь.
-1
возвращается вместо требуемого количества символов. Это можно исправить с помощью функции _vscprintf
, которую нужно вызывать только в случае сбоя предыдущего вызова _vsnprintf_s
.
Кроме того, эти функции не поддерживают спецификаторы формата, добавленные в C99, такие как %zd
. Это не может быть легко решено, вам придется избегать их использования.
Код ниже:
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
{
int r = -1;
if (size != 0)
{
va_list args_copy;
va_copy(args_copy, args);
r = _vsnprintf_s(buf, size, _TRUNCATE, fmt, args_copy);
va_end(args_copy);
}
if (r == -1)
{
r = _vscprintf(fmt, args);
}
return r;
}
int snprintf(char *buf, size_t size, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int r = vsnprintf(buf, size, fmt, args);
va_end(args);
return r;
}
Примечание: Windows также предоставляет _vsnprintf
, который выглядит лучше подходящим для этой реализации, но не завершает полученную строку. Если вы хотите использовать его, вы должны быть осторожны.