C/printf: Różnice pomiędzy wersjami
< C
Usunięta treść Dodana treść
UWAGA! Zastąpienie treści hasła bardzo krótkim tekstem: „.” |
|||
Linia 1: | Linia 1: | ||
. |
|||
===Deklaracja=== |
|||
#include <[[C/Biblioteka standardowa/Indeks tematyczny#stdio.h|stdio.h]]> |
|||
int printf(const char *format, ...); |
|||
int fprintf(FILE *stream, const char *format, ...); |
|||
int sprintf(char *str, const char *format, ...); |
|||
int snprintf(char *str, size_t size, const char *format, ...) |
|||
#include <[[C/Biblioteka standardowa/Indeks tematyczny#stdarg.h|stdarg.h]]> |
|||
int vprintf(const char *format, va_list ap); |
|||
int vfprintf(FILE *stream, const char *format, va_list ap); |
|||
int vsprintf(char *str, const char *format, va_list ap); |
|||
int vsnprintf(char *str, size_t size, const char *format, va_list ap); |
|||
===Opis=== |
|||
Funkcje formatują tekst zgodnie z podanym formatem opisanym poniżej. Funkcje printf i vprintf wypisują tekst na standardowe wyjście (tj. do stdout); fprintf i vfprintf do strumienia podanego jako argument; a sprintf, vsprintf, snprintf i vsnprintf zapisują go w podanej jako argument tablicy znaków. |
|||
Funkcje vprintf, vfprintf, vsprintf i vsnprintf różnią się od odpowiadających im funkcjom printf, fprintf, sprintf i snprintf tym, że zamiast zmiennej liczby argumentów przyjmują argument typu va_list. |
|||
Funkcje snprintf i vsnprintf różnią się od sprintf i vsprintf tym, że nie zapisuje do tablicy nie więcej niż <tt>size</tt> znaków (wliczając kończący znak '\0'). Oznacza to, że można je używać bez obawy o wystąpienie przepełnienia bufora. |
|||
===Argumenty=== |
|||
; format: format, w jakim zostaną wypisane następne argumenty |
|||
; stream: strumień wejściowy, z którego mają być odczytane dane. |
|||
; str: tablica znaków, do której ma być zapisany sformatowany tekst |
|||
; size: rozmiar tablicy znaków |
|||
; ap: wskaźnik na pierwszy argument z listy zmiennej liczby argumentów |
|||
===Format=== |
|||
Format składa się ze zwykłych znaków (innych niż znak '%'), które są kopiowane bez zmian na wyjście oraz sekwencji sterujących, zaczynających się od symbolu procenta, po którym następuje: |
|||
* dowolna liczba flag, |
|||
* opcjonalne określenie minimalnej szerokości pola, |
|||
* opcjonalne określenie precyzji, |
|||
* opcjonalne określenie rozmiaru argumentu, |
|||
* określenie formatu. |
|||
Jeżeli po znaku procenta występuje od razu drugi procent to cała sekwencja traktowana jest jak zwykły znak procenta (tzn. jest on wypisywany na wyjście). |
|||
====Flagi==== |
|||
W sekwencji możliwe są następujące flagi: |
|||
* '''-''' (minus) oznacza, że pole ma być wyrównane do lewej, a nie do prawej. |
|||
* '''+''' (plus) oznacza, że dane liczbowe zawsze poprzedzone są znakiem (plusem dla liczb nieujemnych lub minusem dla ujemnych). |
|||
* spacja oznacza, że liczby nieujemne poprzedzone są dodatkową spacją; jeżeli flaga plus i spacja są użyte jednocześnie to spacja jest ignorowana. |
|||
* '''#''' (''hash'') powoduje, że wynik jest przedstawiony w ''alternatywnej postaci'': |
|||
** dla formatu '''o''' powoduje to zwiększenie precyzji, jeżeli jest to konieczne, aby na początku wyniku było zero; |
|||
** dla formatów '''x''' i '''X''' niezerowa liczba poprzedzona jest ciągiem '''0x''' lub '''0X'''; |
|||
** dla formatów '''a''', '''A''', '''e''', '''E''', '''f''', '''F''', '''g''' i '''G''' wynik zawsze zawiera kropkę nawet jeżeli nie ma za nią żadnych cyfr; |
|||
** dla formatów '''g''' i '''G''' końcowe zera nie są usuwane. |
|||
* '''0''' (zero) dla formatów '''d''', '''i''', '''o''', '''u''', '''x''', '''X''', '''a''', '''A''', '''e''', '''E''', '''f''', '''F''', '''g''' i '''G''' do wyrównania pola wykorzystywane są zera zamiast spacji za wyjątkiem wypisywania wartości nieskończoność i NaN. Jeżeli obie flagi 0 i - są obecne to flaga zero jest ignorowana. Dla formatów '''d''', '''i''', '''o''', '''u''', '''x''' i '''X''' jeżeli określona jest precyzja flaga ta jest ignorowana. |
|||
====Szerokość pola i precyzja==== |
|||
Minimalna szerokość pola oznacza ile najmniej znaków ma zająć dane pole. Jeżeli wartość po formatowaniu zajmuje mniej miejsca jest ona wyrównywana spacjami z lewej strony (chyba, że podano flagi, które modyfikują to zachowanie). Domyślna wartość tego pola to 0. |
|||
Precyzja dla formatów: |
|||
* '''d''', '''i''', '''o''', '''u''', '''x''' i '''X''' określa minimalną liczbę cyfr, które mają być wyświetlone i ma domyślną wartość 1; |
|||
* '''a''', '''A''', '''e''', '''E''', '''f''' i '''F''' - liczbę cyfr, które mają być wyświetlone po kropce i ma domyślną wartość 6; |
|||
* '''g''' i '''G''' określa liczbę cyfr znaczących i ma domyślną wartość 1; |
|||
* dla formatu '''s''' - maksymalną liczbę znaków, które mają być wypisane. |
|||
Szerokość pola może być albo dodatnią liczbą zaczynającą się od cyfry różnej od zera albo gwiazdką. Podobnie precyzja z tą różnicą, że jest jeszcze poprzedzona kropką. Gwiazdka oznacza, że brany jest kolejny z argumentów, który musi być typu int. Wartość ujemna przy określeniu szerokości jest traktowana tak jakby podano flagę '''-''' (minus). |
|||
====Rozmiar argumentu==== |
|||
Dla formatów '''d''' i '''i''' można użyć jednego ze modyfikator rozmiaru: |
|||
* '''hh''' - oznacza, że format odnosi się do argumentu typu signed char, |
|||
* '''h''' - oznacza, że format odnosi się do argumentu typu short, |
|||
* '''l''' (el) - oznacza, że format odnosi się do argumentu typu long, |
|||
* '''ll''' (el el) - oznacza, że format odnosi się do argumentu typu long long, |
|||
* '''j''' - oznacza, że format odnosi się do argumentu typu intmax_t, |
|||
* '''z''' - oznacza, że że format odnosi się do argumentu typu będącego odpowiednikiem typu size_t ze znakiem, |
|||
* '''t''' - oznacza, że że format odnosi się do argumentu typu ptrdiff_t. |
|||
Dla formatów '''o''', '''u''', '''x''' i '''X''' można użyć takich samych modyfikatorów rozmiaru jak dla formatu '''d''' i oznaczają one, że format odnosi się do argumentu odpowiedniego typu bez znaku. |
|||
Dla formatu '''n''' można użyć takich samych modyfikatorów rozmiaru jak dla formatu '''d''' i oznaczają one, że format odnosi się do argumentu będącego wskaźnikiem na dany typ. |
|||
Dla formatów '''a''', '''A''', '''e''', '''E''', '''f''', '''F''', '''g''' i '''G''' można użyć modyfikatorów rozmiaru '''L''', który oznacza, że format odnosi się do argumentu typu long double. |
|||
Dodatkowo, modyfikator '''l''' (el) dla formatu '''c''' oznacza, że odnosi się on do argumentu typu wint_t, a dla formatu '''s''', że odnosi się on do argumenty typu wskaźnik na wchar_t. |
|||
====Format==== |
|||
Funkcje z rodziny printf obsługują następujące formaty: |
|||
* '''d''', '''i''' - argument typu int jest przedstawiany jako liczba całkowita ze znakiem w postaci '''[-]ddd'''. |
|||
* '''o''', '''u''', '''x''', '''X''' - argument typu unsigned int jest przedstawiany jako nieujemna liczba całkowita zapisana w systemie oktalnym ('''o'''), dziesiętnym ('''u''') lub heksadecymalnym ('''x''' i '''X'''). |
|||
* '''f''', '''F''' - argument typu double jest przedstawiany w postaci '''[-]ddd.ddd'''. |
|||
* '''e''', '''E''' - argument typu double jest reprezentowany w postaci '''[i]d.ddde+dd''', gdzie liczba przed kropką dziesiętną jest różna od zera, jeżeli liczba jest różna od zera, a '''+''' oznacza znak wykładnika. Format '''E''' używa wielkiej litery E zamiast małej. |
|||
* '''g''', '''G''' - argument typu double jest reprezentowany w formacie takim jak '''f''' lub '''e''' (odpowiednio '''F''' lub '''E''') zależnie od liczby znaczących cyfr w liczbie oraz określonej precyzji. |
|||
* '''a''', '''A''' - argument typu double przedstawiany jest w formacie '''[-]0xh.hhhp+d''' czyli analogicznie jak dla '''e''' i '''E''', tyle że liczba zapisana jest w systemie heksadecymalnym. |
|||
* '''c''' - argument typu int jest konwertowany do unsigned char i wynikowy znak jest wypisywany. Jeżeli podano modyfikator rozmiaru '''l''' argument typu wint_t konwertowany jest do wielobajtowej sekwencji i wypisywany. |
|||
* '''s''' - argument powinien być typu wskaźnik na char (lub wchar_t). Wszystkie znaki z podanej tablicy, kończące się na null, są wypisywane. |
|||
* '''p''' - argument powinien być typu wskaźnik na void. Jest on konwertowany na serię drukowalnych znaków w sposób zależny od implementacji. |
|||
* '''n''' - argument powinien być wskaźnikiem na liczbę całkowitą ze znakiem, do którego zwracana jest liczba zapisanych znaków. |
|||
W przypadku formatów '''f''', '''F''', '''e''', '''E''', '''g''', '''G''', '''a''' i '''A''' wartość nieskończoność jest przedstawiana w formacie '''[-]inf''' lub '''[-]infinity''' zależnie od implementacji. Wartość NaN jest przedstawiana w postaci '''[-]nan''' lub '''[i]nan(''sekwencja'')''', gdzie '''sekwencja''' jest zależna od implementacji. W przypadku formatów określonych wielką literą również wynikowy ciąg znaków jest wypisywany wielką literą. |
|||
............................................................................................................................................ :P ............................................................................................................................................ :P |
|||
............................................................................................................................................ :P |
|||
............................................................................................................................................ :P |
|||
............................................................................................................................................ :P |
|||
............................................................................................................................................ :P |
|||
............................................................................................................................................ :P |
|||
............................................................................................................................................ :P |
|||
............................................................................................................................................ :P |
|||
............................................................................................................................................ :P |
|||
===Przykład użycia=== |
|||
<source lang="c"> |
|||
#include <stdio.h> |
|||
int main() |
|||
{ |
|||
int i = 4; |
|||
float f = 3.1415; |
|||
const char *s = "Monty Python"; |
|||
printf("i = %d\nf = %.1f\nWskaznik s wskazuje na napis: %s\n", i, f, s); |
|||
return 0; |
|||
} |
|||
</source> |
|||
i = 4 |
|||
f = 3.1 |
|||
Wskaznik s wskazuje na napis: Monty Python |
|||
<!------- |
|||
--------- co ten kod ma ukazywać? |
|||
--------- |
|||
Funkcja formatująca ciąg znaków i alokująca odpowiednią ilość pamięci: |
|||
<source lang="c"> |
|||
#include <stdarg.h> |
|||
#include <stdlib.h> |
|||
char *sprintfalloc(const char *format, ...) |
|||
{ |
|||
int ret; |
|||
size_t size = 100; |
|||
char *str = malloc(size); |
|||
if (!str) |
|||
return 0; |
|||
for(;;) |
|||
{ |
|||
va_list ap; |
|||
char *tmp; |
|||
va_start(ap, format); |
|||
ret = vsnprintf(str, size, format, ap); |
|||
va_end(ap); |
|||
if (ret<size) |
|||
break; |
|||
tmp = realloc(str, (size_t)ret + 1); |
|||
if (!tmp) |
|||
{ |
|||
ret = -1; |
|||
break; |
|||
} else |
|||
{ |
|||
str = tmp; |
|||
size = (size_t)ret + 1; |
|||
} |
|||
} |
|||
if (ret<0) |
|||
{ |
|||
free(str); |
|||
str = 0; |
|||
}else if (size-1>ret) |
|||
{ |
|||
char *tmp = realloc(str, (size_t)ret + 1); |
|||
if (tmp) |
|||
str = tmp; |
|||
} |
|||
return str; |
|||
} |
|||
</source> |
|||
-------> |
|||
===Uwagi=== |
|||
Funkcje snprintf i vsnprintf nie były zdefiniowane w standardzie C89. Zostały one dodane dopiero w standardzie C99. |
|||
Biblioteka glibc do wersji 2.0.6 włącznie posiadała implementacje funkcji snprintf oraz vsnprintf, które były niezgodne ze standardem, gdyż zwracały -1 w przypadku, gdy wynikowy tekst nie mieścił się w podanej tablicy znaków. |
|||
{{TODO|Porównać ze standardem C89 i oznaczyć funkcjonalności wprowadzone dopiero w C99.}} |
|||
===Zobacz też=== |
|||
:[[C/scanf|scanf]] |
|||
:[[C/Podstawowe procedury wejścia i wyjścia|Podstawowe procedury wejścia i wyjścia]] |
|||
:[[C/Napisy#Znaki_specjalne|Znaki specjalne]] |
Wersja z 13:50, 18 wrz 2013
.