C/printf: Różnice pomiędzy wersjami

Z Wikibooks, biblioteki wolnych podręczników.
< C
Usunięta treść Dodana treść
Mina86 (dyskusja | edycje)
W zasadzie wszystko od nowa - sprawdzane z draftem C99
Mina86 (dyskusja | edycje)
Linia 22: Linia 22:


===Argumenty===
===Argumenty===
:<tt>format</tt> - format, w jakim zostaną wypisane następne argumenty
*<tt>format</tt> - format, w jakim zostaną wypisane następne argumenty
:<tt>stream</tt> - strumień wyjściowy, do którego mają być zapisane dane
*<tt>stream</tt> - strumień wyjściowy, do którego mają być zapisane dane
:<tt>str</tt> - tablica znaków, do której ma być zapisany sformatowany tekst
*<tt>str</tt> - tablica znaków, do której ma być zapisany sformatowany tekst
:<tt>size</tt> - rozmiar tablicy znaków
*<tt>size</tt> - rozmiar tablicy znaków
*<tt>ap</tt> - wskaźnik na pierwszy argument z listy zmiennej liczby argumentów


===Format===
===Format===

Wersja z 14:58, 21 sty 2007

Deklaracja

W pliku nagłówkowym 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, ...)

W pliku nagłówkowym 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 może nastąpić:

  • dowolna liczba flag,
  • opcjonalne określenie minimalnej szerokości pola,
  • opcjonalne określenie precyzji,
  • opcjonalne określenie rozmiaru argumentu,
  • określenie formatu.

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ą spacje 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, aż do i z wyłączeniem znaku null są wypisywane.
  • p - argument powinien być typu wskaźnik na void. Jest to 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 zapisana 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

#include <stdio.h>
int main() {
  int i = 4;
  float f = 3.1415;
  char *s = "Monty Python";
  printf("i = %i\nf = %.1f\nWskaźnik s wskazuje na napis: %s\n", i, f, s);
  return 0;
}

Wyświetli:

i = 4
f = 3.1
Wskaźnik s wskazuje na napis: Monty Python

Funkcja formatująca ciąg znaków i alokująca odpowiednią ilość pamięci:

#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;
}

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.

Zobacz też

scanf
Podstawowe procedury wejścia i wyjścia