Почему vsnwprintf отсутствует - PullRequest
0 голосов
/ 02 июля 2018

Я использую vsnprintf для строки ANSI, и она работает хорошо, возвращает -1 только в случае ошибки и возвращает счетчик размера needen, если он не помещается в буфер. Мне нужна та же функция для широких строк, vsnwprintf просто не существует. Я также пытался _vsnwprintf, но он действует по-другому, он возвращает -1, даже если буфер слишком мал, хотя мне нужно знать, сколько расширить буфер, но только когда это необходимо, я не хочу делать фиктивные вызовы просто чтобы определить размер needen и только потом расширять буфер.

Если посмотреть на vsnprintf код:

int const _Result = __stdio_common_vsprintf(
    _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR,
    _Buffer, _BufferCount, _Format, NULL, _ArgList);
return _Result < 0 ? -1 : _Result;

В то время как _vsnwprintf приблизительно имеет:

int const _Result = __stdio_common_vswprintf(
    _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION,
    _Buffer, _BufferCount, _Format, NULL, _ArgList);
return _Result < 0 ? -1 : _Result;

Похоже, разница только во флагах, я пытался вызвать __stdio_common_vswprintf вручную с флагом _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, и он работает именно так, как мне нужно, но также вызывает случайные сбои / зависания при выходе из приложения. Поэтому мне нужна функция vsnwprintf, может кто-то знает, как это сделать?

P.S. Я использую Microsoft Visual Studio 2017 на Windows 7.

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Вы можете использовать _vsnwprintf(). Согласно документации для _vsnwprintf() (обратите внимание на нижнее подчеркивание):

...

int _vsnwprintf(
   wchar_t *buffer,
   size_t count,
   const wchar_t *format,
   va_list argptr
);

...

Значение, возвращаемое всеми этими функциями, не включает завершается нулем, написано ли одно или нет. Когда count равен нулю, возвращаемое значение - это количество символов, которые будут выполнять функции написать, не включая завершающий ноль. Вы можете использовать этот результат для выделить достаточно места в буфере для строки и ее окончания null, а затем снова вызовите функцию, чтобы заполнить буфер.

0 голосов
/ 02 июля 2018

Широкая версия символа vsnprintf называется vswprintf (примечание: нет n). Согласно документации , она совместима с ISO C, поэтому вы можете проверить поведение в стандарте C или здесь .

Правильно, что возвращается -1, когда вывод превысит размер буфера. Нет возможности обрезать вывод; Вы должны сделать "фиктивный вызов", чтобы проверить размер буфера.

Вы всегда можете заключить вызов vswprintf в другую функцию, имеющую желаемое поведение (выполните фиктивный вызов, а затем либо обрежьте его до нужного размера, либо верните буфер malloc'd). Остерегайтесь усечения в середине символа UTF-16.


Обратите внимание, что MSVC vsnprintf изменил свое поведение в какой-то момент (может быть, в 2015 году?), Чтобы соответствовать ISO C; исходное поведение MSVC можно получить, вызвав _vsnprintf.

...