C/printf: Różnice pomiędzy wersjami
m →pierwszy: konwersja |
|||
Linia 182: | Linia 182: | ||
</source> |
</source> |
||
-------> |
-------> |
||
====Konwersja ==== |
|||
<source lang=c> |
|||
/* |
|||
gcc s.c -Wall |
|||
http://stackoverflow.com/questions/7228438/convert-double-float-to-string |
|||
*/ |
|||
#include <stdio.h> |
|||
int main() { |
|||
size_t size = sizeof(double); |
|||
double d = 234.567; |
|||
char s[size]; // 16 |
|||
snprintf(s, size, "%f", d); // convert double to string |
|||
printf(" d = %f = %s \n", d,s); // check |
|||
return 0; |
|||
} |
|||
</source> |
|||
====Liczby całkowite==== |
====Liczby całkowite==== |
||
Wersja z 11:52, 17 sty 2016
Deklaracja
#include <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 <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ż size 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ń wyjściowy, do którego mają być zapisane 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ą.
Wartość zwracana
Jeżeli funkcje zakończą się sukcesem zwracają liczbę znaków w tekście (wypisanym na standardowe wyjście, do podanego strumienia lub tablicy znaków) nie wliczając kończącego '\0'. W przeciwnym wypadku zwracana jest liczba ujemna.
Wyjątkami są funkcje snprintf i vsnprintf, które zwracają liczbę znaków, które zostałyby zapisane do tablicy znaków, gdyby była wystarczająco duża.
Przykład użycia
pierwszy
#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;
}
i = 4 f = 3.1 Wskaznik s wskazuje na napis: Monty Python
Konwersja
/*
gcc s.c -Wall
http://stackoverflow.com/questions/7228438/convert-double-float-to-string
*/
#include <stdio.h>
int main() {
size_t size = sizeof(double);
double d = 234.567;
char s[size]; // 16
snprintf(s, size, "%f", d); // convert double to string
printf(" d = %f = %s \n", d,s); // check
return 0;
}
Liczby całkowite
/*
gcc l.c -lm -Wall
./a.out
http://stackoverflow.com/questions/29592898/do-long-long-and-long-have-same-range-in-c-in-64-bit-machine
*/
#include <stdio.h>
#include <math.h> // M_PI; needs -lm also
#include <limits.h> // INT_MAX, http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
int main(){
double lMax;
lMax = log2(INT_MAX);
printf("INT_MAX \t= %25d ; lMax = log2(INT_MAX) \t= %.0f \n",INT_MAX, lMax);
lMax = log2(UINT_MAX);
printf("UINT_MAX \t= %25u ; lMax = log2(UINT_MAX) \t= %.0f \n", UINT_MAX, lMax);
lMax = log2(LONG_MAX);
printf("LONG_MAX \t= %25ld ; lMax = log2(LONG_MAX) \t= %.0f \n",LONG_MAX, lMax);
lMax = log2(ULONG_MAX);
printf("ULONG_MAX \t= %25lu ; lMax = log2(ULONG_MAX) \t= %.0f \n",ULONG_MAX, lMax);
lMax = log2(LLONG_MAX);
printf("LLONG_MAX \t= %25lld ; lMax = log2(LLONG_MAX) \t= %.0f \n",LLONG_MAX, lMax);
lMax = log2(ULLONG_MAX);
printf("ULLONG_MAX \t= %25llu ; lMax = log2(ULLONG_MAX) \t= %.0f \n",ULLONG_MAX, lMax);
return 0;
}
Wynik :
INT_MAX = 2147483647 ; lMax = log2(INT_MAX) = 31 UINT_MAX = 4294967295 ; lMax = log2(UINT_MAX) = 32 LONG_MAX = 9223372036854775807 ; lMax = log2(LONG_MAX) = 63 ULONG_MAX = 18446744073709551615 ; lMax = log2(ULONG_MAX) = 64 LLONG_MAX = 9223372036854775807 ; lMax = log2(LLONG_MAX) = 63 ULLONG_MAX = 18446744073709551615 ; lMax = log2(ULLONG_MAX) = 64
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.
W przygotowaniu: Porównać ze standardem C89 i oznaczyć funkcjonalności wprowadzone dopiero w C99. |