Как правильно заменить sprintf_s на sprintf в C ++ 03? - PullRequest
0 голосов
/ 17 января 2019

sprintf_s - это реализация Microsoft функции sprintf, в которой они исправили ошибку, добавив аргумент для получения граничного значения, когда функция ограничена для записи.

Эквивалент был введен в C++11: snprintf. Но здесь мы говорим о синтаксисе C++03.

Подпись:

count_char_written sprintf(char* string_out, const char* output_template, VARIADIC_ARGS);
// and
count_char_written sprintf_s(char* string_out, size_t buffer_max_size, const char* output_template, VARIADIC_ARGS);

Functionnaly, sprintf_s более продвинут, чем sprintf, потому что он предотвращает переполнение. Но sprintf_s только для Microsoft!

Что делать, если вы хотите перенести обратно код C++03, написанный с sprintf_s, в POSIX-совместимый синтаксис?

1 Ответ

0 голосов
/ 17 января 2019

Сегодня и 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, который выглядит лучше подходящим для этой реализации, но не завершает полученную строку. Если вы хотите использовать его, вы должны быть осторожны.

...