vsnprintf
, , _vsnprintf
, _vsnprintf_l
, , _vsnwprintf
_vsnwprintf_l
Zapis sformatowanych danych wyjściowych przy użyciu wskaźnika do listy argumentów. Dostępne są bezpieczniejsze wersje tych funkcji; zobacz , , _vsnprintf_s
, _vsnprintf_s_l
, _vsnwprintf_s
, _vsnwprintf_s_l
.vsnprintf_s
Składnia
int vsnprintf(
char *buffer,
size_t count,
const char *format,
va_list argptr
);
int _vsnprintf(
char *buffer,
size_t count,
const char *format,
va_list argptr
);
int _vsnprintf_l(
char *buffer,
size_t count,
const char *format,
_locale_t locale,
va_list argptr
);
int _vsnwprintf(
wchar_t *buffer,
size_t count,
const wchar_t *format,
va_list argptr
);
int _vsnwprintf_l(
wchar_t *buffer,
size_t count,
const wchar_t *format,
_locale_t locale,
va_list argptr
);
template <size_t size>
int vsnprintf(
char (&buffer)[size],
size_t count,
const char *format,
va_list argptr
); // C++ only
template <size_t size>
int _vsnprintf(
char (&buffer)[size],
size_t count,
const char *format,
va_list argptr
); // C++ only
template <size_t size>
int _vsnprintf_l(
char (&buffer)[size],
size_t count,
const char *format,
_locale_t locale,
va_list argptr
); // C++ only
template <size_t size>
int _vsnwprintf(
wchar_t (&buffer)[size],
size_t count,
const wchar_t *format,
va_list argptr
); // C++ only
template <size_t size>
int _vsnwprintf_l(
wchar_t (&buffer)[size],
size_t count,
const wchar_t *format,
_locale_t locale,
va_list argptr
); // C++ only
Parametry
buffer
Lokalizacja magazynu dla danych wyjściowych.
count
Maksymalna liczba znaków do zapisu. W przypadku funkcji, które przyjmują wchar_t
, jest to liczba znaków szerokich do zapisania.
format
Specyfikacja formatu.
argptr
Wskaźnik do listy argumentów.
locale
Ustawienia regionalne do użycia.
Aby uzyskać więcej informacji, zobacz Składnia specyfikacji formatu.
Wartość zwracana
Liczba zapisanych znaków, a nie w tym zakończenie NULL
lub wartość ujemna, jeśli wystąpi błąd wyjściowy.
Aby uzyskać szczegółowe informacje, zobacz Podsumowanie zachowania.
Uwagi
Każda z tych funkcji przyjmuje wskaźnik do listy argumentów, a następnie formatuje dane i zapisuje maksymalnie count
znaki do pamięci wskazywanej przez buffer
wartość . Funkcja vsnprintf
zawsze zapisuje terminator o wartości null, nawet jeśli obcina dane wyjściowe. Jeśli używasz _vsnprintf
wartości i _vsnwprintf
, bufor jest zakończony wartością null tylko wtedy, gdy na końcu znajduje się miejsce (czyli jeśli liczba znaków do zapisania jest mniejsza niż count
).
Począwszy od UCRT w programach Visual Studio 2015 i Windows 10, vsnprintf
nie jest już identyczny z _vsnprintf
. Funkcja vsnprintf
jest zgodna ze standardem C99; _vsnprintf
jest zachowana w celu zapewnienia zgodności z poprzednim kodem. Różnica polega na tym, że jeśli zabraknie buforu, vsnprintf
wartość null kończy koniec buforu i zwraca liczbę znaków, które byłyby wymagane, podczas gdy _vsnprintf
bufor nie kończy się wartością null i zwraca wartość -1. Ponadto zawiera jeszcze jeden znak w danych wyjściowych, _vsnprintf()
ponieważ nie powoduje zakończenia buforu o wartości null.
Ważne
Aby zapobiec pewnym rodzajom zagrożeń bezpieczeństwa, upewnij się, że format
nie jest to ciąg zdefiniowany przez użytkownika. Aby uzyskać więcej informacji, zobacz Unikanie przekroków buforu.
Począwszy od systemu Windows 10 w wersji 2004 (kompilacja 19041), printf
rodzina funkcji drukuje dokładnie możliwe liczby zmiennoprzecinkowe zgodnie z regułami IEEE 754 dotyczącymi zaokrąglania. W poprzednich wersjach systemu Windows dokładnie reprezentowane liczby zmiennoprzecinkowe kończące się na "5" zawsze zaokrągla się w górę. IEEE 754 stwierdza, że muszą zaokrąglić do najbliższej parzysta cyfra (znana również jako "Zaokrąglanie Bankiera"). Na przykład oba printf("%1.0f", 1.5)
printf("%1.0f", 2.5)
elementy i powinny być zaokrąglone do 2. Wcześniej 1,5 zaokrągliłoby się do 2 i 2,5 do 3. Ta zmiana dotyczy tylko dokładnie możliwych do reprezentowania liczb. Na przykład 2,35 (który, gdy jest reprezentowany w pamięci, jest bliżej 2,350000000000000008) nadal zaokrągla się do 2,4. Zaokrąglanie wykonywane przez te funkcje jest teraz również zgodne z trybem zaokrąglania zmiennoprzecinkowego ustawionym przez fesetround
. Wcześniej zaokrąglanie zawsze wybierało FE_TONEAREST
zachowanie. Ta zmiana dotyczy tylko programów utworzonych przy użyciu programu Visual Studio 2019 w wersji 16.2 lub nowszej. Aby użyć starszego zachowania zaokrąglania zmiennoprzecinkowego, połącz się z elementem "legacy_stdio_float_rounding.obj".
Uwaga
Aby upewnić się, że istnieje miejsce na zakończenie wartości null podczas wywoływania _vsnprintf
parametrów , _vsnprintf_l
_vsnwprintf
i _vsnwprintf_l
, upewnij się, że count
długość buforu jest ściśle mniejsza niż długość buforu i zainicjuj bufor do wartości null przed wywołaniem funkcji.
Ponieważ vsnprintf
zawsze zapisuje wartość null zakończenia, count
parametr może być równy rozmiarowi buforu.
Wersje tych funkcji z sufiksem _l
są identyczne, z tą różnicą, że używają parametru ustawień regionalnych przekazanych zamiast bieżących ustawień regionalnych wątku.
W języku C++te funkcje mają przeciążenia szablonu, które wywołują nowsze, bezpieczne odpowiedniki tych funkcji. Aby uzyskać więcej informacji, zobacz Bezpieczne przeciążenia szablonów.
Podsumowanie zachowania
W poniższej tabeli:
- Niech
sizeOfBuffer
będzie rozmiar .buffer
Jeśli funkcja przyjmujechar
bufor, rozmiar jest w bajtach. Jeśli funkcja przyjmujewchar_t
bufor, rozmiar określa liczbę 16-bitowych wyrazów. - Pozwól
len
na rozmiar sformatowanych danych. Jeśli funkcja przyjmujechar
bufor, rozmiar jest w bajtach. Jeśli funkcja przyjmujewchar_t
bufor, rozmiar określa liczbę 16-bitowych wyrazów. - Znaki odwołują się do
char
znaków funkcji, które przyjmująchar
bufor, oraz dowchar_t
znaków funkcji, które przyjmująwchar_t
bufor. - Aby uzyskać więcej informacji na temat nieprawidłowej procedury obsługi parametrów, zobacz Walidacja parametrów.
Stan | Zachowanie | Wartość zwracana | errno |
Wywołuje nieprawidłową procedurę obsługi parametrów |
---|---|---|---|---|
Powodzenie | Zapisuje znaki w buforze przy użyciu określonego ciągu formatu. | Liczba zapisanych znaków, bez zliczania znaku null zakończenia. | Nie dotyczy | Nie. |
Błąd kodowania podczas formatowania | Jeśli przetwarzanie specyfikatora s ciągów , S lub Z , przetwarzanie specyfikacji formatu zatrzymuje się. |
-1 | EILSEQ (42) |
Nie. |
Błąd kodowania podczas formatowania | Jeśli specyfikator c znaków przetwarzania lub C , jest pomijany nieprawidłowy znak. Liczba zapisanych znaków nie jest zwiększana dla pominiętego znaku ani żadnych zapisanych dla niego danych. Przetwarzanie specyfikacji formatu jest kontynuowane po pomijaniu specyfikatora z błędem kodowania. |
Liczba zapisanych znaków, a nie łącznie z kończeniem NULL . |
EILSEQ (42) |
Nie. |
buffer == NULL i count != 0 |
Jeśli wykonanie będzie kontynuowane po wykonaniu nieprawidłowego programu obsługi parametrów, ustawia errno i zwraca wartość ujemną. |
-1 | EINVAL (22) |
Tak |
count == 0 |
Żadne dane nie są zapisywane | Liczba znaków, które zostałyby zapisane, a nie łącznie z kończeniem NULL . Możesz użyć tego wyniku, aby przydzielić wystarczającą ilość miejsca buforu dla ciągu i zakończenia NULL , a następnie wywołać funkcję ponownie, aby wypełnić bufor. |
Nie dotyczy | Nie. |
count < 0 |
Niebezpieczne: wartość jest traktowana jako niepodpisane, prawdopodobnie tworząc dużą wartość, która powoduje zastąpienie pamięci, która następuje po buforze. | Liczba zapisanych znaków. | Nie dotyczy | Nie. |
count < sizeOfBuffer i len <= count |
Wszystkie dane są zapisywane i dołączane są kończenie NULL . |
Liczba zapisanych znaków, a nie łącznie z kończeniem NULL . |
Nie dotyczy | Nie. |
count < sizeOfBuffer i len > count |
count-1 Pierwsze znaki są zapisywane, a następnie terminator o wartości null. |
Liczba zapisanych znaków count była zgodna z liczbą znaków w danych wyjściowych, a nie w tym terminatorem o wartości null. |
Nie dotyczy | Nie. |
count >= sizeOfBuffer i len < sizeOfBuffer |
Wszystkie dane są zapisywane z kończeniem NULL . |
Liczba zapisanych znaków, a nie łącznie z kończeniem NULL . |
Nie dotyczy | Nie. |
count >= sizeOfBuffer i len >= sizeOfBuffer |
Niebezpieczne: zastępuje pamięć, która następuje po buforze. | Liczba zapisanych znaków, a nie łącznie z kończeniem NULL . |
Nie dotyczy | Nie. |
format == NULL |
Żadne dane nie są zapisywane. Jeśli wykonanie będzie kontynuowane po wykonaniu nieprawidłowego programu obsługi parametrów, ustawia errno i zwraca wartość ujemną. |
-1 | EINVAL (22) |
Tak |
Aby uzyskać informacje o tych i innych kodach błędów, zobacz _doserrno
, errno
, _sys_errlist
i _sys_nerr
.
Mapowania procedur tekstu ogólnego
TCHAR.H rutyna |
_UNICODE i _MBCS niezdefiniowane |
_MBCS zdefiniowany |
_UNICODE zdefiniowany |
---|---|---|---|
_vsntprintf |
_vsnprintf |
_vsnprintf |
_vsnwprintf |
_vsntprintf_l |
_vsnprintf_l |
_vsnprintf_l |
_vsnwprintf_l |
Wymagania
Procedura | Wymagany nagłówek (C) | Wymagany nagłówek (C++) |
---|---|---|
vsnprintf , , _vsnprintf _vsnprintf_l |
<stdio.h> |
<stdio.h> lub <cstdio> |
_vsnwprintf , _vsnwprintf_l |
<stdio.h> lub <wchar.h> |
<stdio.h> , <wchar.h> , lub <cstdio> <cwchar> |
Funkcje _vsnprintf
, _vsnprintf_l
_vsnwprintf
i _vsnwprintf_l
są specyficzne dla firmy Microsoft. Aby uzyskać więcej informacji o zgodności, zobacz Zgodność.
Przykład: używanie znaków szerokich z _vsnwprintf()
// crt_vsnwprintf.c
// compile by using: cl /W3 crt_vsnwprintf.c
// To turn off error C4996, define this symbol:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <wtypes.h>
#define BUFFCOUNT (10)
void FormatOutput(LPCWSTR formatstring, ...)
{
int nSize = 0;
wchar_t buff[BUFFCOUNT];
memset(buff, 0, sizeof(buff));
va_list args;
va_start(args, formatstring);
// Note: _vsnwprintf is deprecated; consider vsnwprintf_s instead
nSize = _vsnwprintf(buff, BUFFCOUNT - 1, formatstring, args); // C4996
wprintf(L"nSize: %d, buff: %ls\n", nSize, buff);
va_end(args);
}
int main() {
FormatOutput(L"%ls %ls", L"Hi", L"there");
FormatOutput(L"%ls %ls", L"Hi", L"there!");
FormatOutput(L"%ls %ls", L"Hi", L"there!!");
}
nSize: 8, buff: Hi there
nSize: 9, buff: Hi there!
nSize: -1, buff: Hi there!
Zachowanie zmienia się, jeśli zamiast tego używasz vsnprintf wraz z parametrami wąskich ciągów. Parametr count
może być całym rozmiarem buforu, a zwracana wartość to liczba znaków, które zostałyby zapisane, gdyby count
były wystarczająco duże:
Przykład: użyj z vsnprintf()
wąskimi ciągami
// crt_vsnprintf.c
// compile by using: cl /W4 crt_vsnprintf.c
#include <stdio.h>
#include <stdarg.h> // for va_list, va_start
#include <string.h> // for memset
#define BUFFCOUNT (10)
void FormatOutput(char* formatstring, ...)
{
int nSize = 0;
char buff[BUFFCOUNT];
memset(buff, 0, sizeof(buff));
va_list args;
va_start(args, formatstring);
nSize = vsnprintf(buff, sizeof(buff), formatstring, args);
printf("nSize: %d, buff: %s\n", nSize, buff);
va_end(args);
}
int main() {
FormatOutput("%s %s", "Hi", "there"); // 8 chars + null
FormatOutput("%s %s", "Hi", "there!"); // 9 chars + null
FormatOutput("%s %s", "Hi", "there!!"); // 10 chars + null
}
nSize: 8, buff: Hi there
nSize: 9, buff: Hi there!
nSize: 10, buff: Hi there!
Zobacz też
We/Wy strumienia
vprintf
, funkcje
Składnia specyfikacji formatu: printf
i wprintf
funkcje
fprintf
, , _fprintf_l
, , fwprintf
_fwprintf_l
printf
, , _printf_l
, , wprintf
_wprintf_l
sprintf
, , _sprintf_l
, swprintf
, , _swprintf_l
__swprintf_l
va_arg
, , va_copy
, , va_end
va_start