printf - Google

printf

Z Wikipedii

Skocz do: nawigacji, szukaj

W językach programowania printf jest rodziną funkcji służących do tworzenia i zapisywania tekstu na podstawie szablonu i zestawu argumentów, które są w ten szablon wstawiane.

Funkcje grupy printf zostały stworzone na potrzeby języka C. Obecnie są dostępne również dla wielu innych języków programowania.

Spis treści

[edytuj] Rodzina funkcji printf w C

Wikibooks
Zobacz podręcznik na Wikibooks: Programowanie:C - printf

W C występuje wiele funkcji grupy printf. Różnią się one jedynie sposobem przekazywania argumentów, znaczeniem kodu zwrotnego (który w zwykłym printfie zwykle jest pomijany) i tym, co robi się z wygenerowanym tekstem.

Funkcje, które pojawiły się we wczesnych Uniksach:

  • int printf (const char *format, ...); - wygenerowany tekst pisany jest na standardowe wyjÅ›cie.
  • int fprintf (FILE *stream, const char *format, ...); - wygenerowany tekst pisany jest do strumienia stream
  • int sprintf(char *str, const char *format, ...); - wygenerowany tekst jest zapisywany do bufora str. Funkcji tej nie należy stosować ze wzglÄ™du na niebezpieczeÅ„stwo wystÄ…pienia przepeÅ‚nienia bufora.

W BSD 2.11 pojawiły się wersje dla argumentów przekazywanych przez stdarg:

  • 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);

W BSD 4.4 pojawiÅ‚a siÄ™ funkcja :

  • int snprintf(char *str, size_t size, const char *format, ...); - to samo co sprintf, tylko że zapisuje co najwyżej size znaków (wliczajÄ…c w to koÅ„cowe \0), dziÄ™ki czemu jest o wiele bezpieczniejsza.
  • oraz jej dpowiednik dla stdarg: int vsnprintf(char *str, size_t size, const char *format, va_list ap);

W FreeBSD i GNU libc są obecne też (niestandardowe)

  • int asprintf(char **strp, const char *fmt, ...);
  • int vasprintf(char **strp, const char *fmt, va_list ap);

które same alokują pamięć pod tekst. Jest to najbezpieczniejsza funkcja printf pisząca do pamięci, jednak nie jest standardowa i może być trochę wolniejsza.

W GNU libc dodatkowo są też obecne:

  • int dprintf(int fd, const char *format, ...);
  • int vdprintf(int fd, const char *format, va_list ap);

piszÄ…ce do deskryptora zamiast do strumienia.

Istnieją też odpowiedniki dla szerokich znaków:

  • int wprintf(const wchar_t *format, ...);
  • int fwprintf(FILE *stream, const wchar_t *format, ...);
  • int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);
  • int vwprintf(const wchar_t *format, va_list args);
  • int vfwprintf(FILE *stream, const wchar_t *format, va_list args);
  • int vswprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, va_list args);

[edytuj] Printf w innych językach

W wielu innych językach występują funkcje printf i sprintf (która wbrew nazwie prawie wszędzie sama alokuje pamięć).

Przykłady:

  • C - dla porównania
    • printf ("%d+%d=%d\n",2,2,2+2);
  • Perl
    • printf ("%d+%d=%d\n",2,2,2+2)
    • $s=sprintf ("%d+%d=%d\n",2,2,2+2); print $s
  • PowÅ‚oka
    • printf "%d+%d=%d\n" 2 2 $[2+2]
  • Ruby
    • printf ("%d+%d=%d\n",2,2,2+2)
    • s=sprintf ("%d+%d=%d\n",2,2,2+2); print s
  • Python posiada operator %, z lewej strony którego jest format a z prawej lista argumentów
    • print "%d+%d=%d\n"%(2,2,2+2)
    • s = "%d+%d=%d\n"%(2,2,2+2); print s
  • Pike posiada funkcje write o funkcjonalnoÅ›ci analogicznej do printf. Funkcja alokujÄ…ca zmiennÄ… tekstowÄ… jest jednak nazwana sprintf:
    • write ("%d+%d=%d\n", 2,2,2+2);
    • s = sprintf ("%d+%d=%d\n", 2,2,2+2); write (s);
  • Ocaml
    • open Printf;; printf "%d+%d=%d\n" 2 2 (2+2);;
    • open Printf;; let a = sprintf "%d+%d=%d\n" 2 2 (2+2);; printf "%s" a;;
  • Object Pascal (Delphi) posiada funkcjÄ™ Format, która dziaÅ‚a podobnie do sprintf.
    • writeln(format('%d+%d=%d'+#13,[2,2,2+2]));

[edytuj] Printf w Uniksie

Systemy uniksowe mają zaimplementowaną funkcję printf jako narzędzie konsolowe.

[edytuj] Przykład

$ printf "%d+%d=%d\n"  "2" "2" "2+2"

[edytuj] Składnia szablonów

Szablon to zwykły tekst zawierający pola do uzupełniania. Pole zaczyna się od znaku %, potem mogą wystąpić modyfikatory, a na koniec pojedynczy znak typu pola. Znak % pisze się %%.

Należy zauważyć że znaki specjalne postaci \X nie mają nic wspólnego z printfem i są obsługiwane przez kompilator C w czasie kompilacji lub interpreter w przypadku niektórych innych języków.

Zestaw dozwolonych pól jest różny zależnie od języka i standardu. Krótki przegląd częściej stosowanych pól:

  • %d - liczba caÅ‚kowita ze znakiem w formacie dziesiÄ™tnym
  • %i - synonim dla %d
  • %x - liczba caÅ‚kowita bez znaku w formacie szesnastkowym, z użyciem maÅ‚ych liter
  • %X - liczba caÅ‚kowita bez znaku w formacie szesnastkowym, z użyciem wielkich liter
  • %o - liczba caÅ‚kowita bez znaku w formacie oktalnym
  • %u - liczba caÅ‚kowita bez znaku w formacie dziesiÄ™tnym
  • %e - liczba zmiennoprzecinkowa w zapisie naukowym (1.2345e+3)
  • %E - liczba zmiennoprzecinkowa w zapisie naukowym (1.2345E+3)
  • %f - liczba zmiennoprzecinkowa typu double (float jest automatycznie konwertowany) w zapisie dziesiÄ™tnym (123.45)
  • %c - liczba caÅ‚kowita jest konwertowana na bajt o danej wartoÅ›ci
  • %s - Å‚aÅ„cuch tekstowy
  • %p - wskaźnik
  • %n - do argumentu zapisywana jest liczba dotychczas zapisanych znaków. Istnienie tego pola prowadzi do dużego niebezpieczeÅ„stwa (umożliwia przeprowadzenie niektórych wariantów ataku typu format string) a nie jest zbyt przydatne w praktyce.

Niektóre pola z modyfikatorami:

  • %ld - liczba caÅ‚kowita typu long ze znakiem w formacie dziesiÄ™tnym
  • %lld - liczba caÅ‚kowita typu long long ze znakiem w formacie dziesiÄ™tnym - w wiÄ™kszoÅ›ci popularnych kompilatorów (np. gcc)
  • %llu - liczba caÅ‚kowita typu long long bez znaku w formacie dziesiÄ™tnym - jw.
  • %I64d - liczba caÅ‚kowita typu long long ze znakiem w formacie dziesiÄ™tnym - używane w niektórych kompilatorach (np. Dev-cpp)
  • %zd - liczba caÅ‚kowita typu size_t ze znakiem w formacie dziesiÄ™tnym
  • %hd - liczba caÅ‚kowita typu short ze znakiem w formacie dziesiÄ™tnym
  • % d - liczba caÅ‚kowita ze znakiem w formacie dziesiÄ™tnym, w przypadku liczby dodatniej przed liczbÄ… dać spacjÄ™
  • %+d - liczba caÅ‚kowita typu short ze znakiem w formacie dziesiÄ™tnym, zawsze drukować znak
  • %04d - liczba caÅ‚kowita, uzupeÅ‚niana zerami do czterech miejsc.
  • %[^\n]s - w rodzinie sprintf wczytanie caÅ‚ej linii bez znaków koÅ„czÄ…cych liniÄ™ (CR, LF).

[edytuj] Kwestie bezpieczeństwa

Z użyciem funkcji z rodziny printf wiążą się dwie podstawowe grupy zagrożeń bezpieczeństwa:

  • Format string attack - w sytuacji, gdy użytkownik ma możliwość wpÅ‚ywu na użyty Å‚aÅ„cuch formatujÄ…cy, czÄ™sto możliwe jest nadpisanie pamiÄ™ci i przejÄ™cie kontroli nad procesem z wykorzystaniem funkcjonalnoÅ›ci %n. NajczÄ™stszÄ… przyczynÄ… takiej podatnoÅ›ci jest skorzystanie przez programistÄ™ z konstrukcji printf(zmienna); zamiast printf("%s",zmienna);.
  • PrzepeÅ‚nienie bufora - funkcja *sprintf (a także nieprawidÅ‚owo użyta *snprintf) może przepeÅ‚nić bufor przeznaczony przez programistÄ™ na zachowanie wyniku tej operacji, tym samym prowadzÄ…c do nadpisania struktur sterujÄ…cych w pamiÄ™ci procesu i przejÄ™cie nad nim kontroli przez osobÄ™ trzeciÄ….

Dodatkowo, pewne scenariusze ataków mogą pojawiać się, gdy dochodzi do niezgodności między budową szablonu a faktycznymi parametrami przekazanymi funkcji *printf - na przykład gdy parametrów jest mniej niż pól w szablonie, albo wartości liczbowe przekazywane są w miejsce wskaźników. Błędy tego typu zwykle prowadzą jednak do nieprawidłowego działania programu i zostają wykryte przez programistę szybciej, niż dwie wymienione wyżej klasy.

[edytuj] Argumenty za i przeciw funkcjom grupy printf oraz funkcjom na nich wzorowanych

Większość nowych języków udostępnia funkcje typu printf, choć zwykle dostępne są też inne mechanizmy, np. w Perlu można wpisywać bezpośrednio w łańcuch tekstowy nazwy zmiennych - np. $x=2;$y=2;$z=2+2; print "$x+$y=$z", a w Ruby nawet całe wyrażenia - print "#{2}+#{2}=#{2+2}\n".

W platformie .NET istnieje podobna funkcja String.Format("{0}+{1}={2}\n", 2, 2, 2 + 2), która dodatkowo umożliwia łatwą zmianę kolejności użycia argumentów.

Niektóre języki, np. Ada, celowo nie posiadają funkcji tego typu. Są one tu praktycznie niemożliwe do implementacji ze względu na zbyt silną kontrolę systemu typów.

Argumenty za:

  • sÄ… bardzo wygodne
  • caÅ‚y szablon jest w jednym miejscu
  • umożliwiajÄ… Å‚atwe dodawanie informacji nt. formatu

Przeciw:

  • trudno je rozszerzyć o nowe typy
  • kompilator nie zawsze może sprawdzić ich poprawnoÅ›ci
  • mogÄ… wystÄ…pić problemy z bezpieczeÅ„stwem
  • konieczna znajomość typu każdego wyrażenia

Co czwarty człowiek cierpi na zaburzenia psychiczne
Co czwarty mieszkaniec Ziemi może cierpieć na zaburzenia psychiczne. Takie alarmujące statystyki przedstawiła w najnowszym raporcie Światowa Organizacja Zdrowia.
Po "melaminowej" aferze zwiększą się kontrole
W związku ze skandalem z melaminą w chińskim sproszkowanym mleku Chiny zaostrzyły kontrolę procesu produkcji wyrobów mleczarskich i zagroziły umieszczeniem nieuczciwych producentów na czarnej liście - podały tamtejsze media.
Szklarnie są odpowiedzialne za ochłodzenie klimatu?
Białe dachy szklarni w hiszpańskiej prowincji Almeria odbijają tyle światła słonecznego, że w okolicy obniżyła się temperatura. - informuje "New Scientist".
Lider równa się narcyz
Kiedy grupa potrzebuje lidera, najłatwiej znajdzie go wśród osób narcystycznych - przekonują psycholodzy ze Stanów Zjednoczonych w piśmie "Personality and Social Psychology Bulletin".
"Melaminowe" słodycze dotarły do Francji
Cukierki White Rabbit i ciasteczka Koala, wyprodukowane w Chinach na bazie mleka w proszku skażonego melaminą, znaleziono we Francji - poinformowało francuskie ministerstwo rolnictwa.
Linki: Strona g³ówna