Provided by:
manpages-nl_20051127-4_all
NAAM
printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf,
vsnprintf - geformateerde uitvoer conversie
SAMENVATTING
#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);
BESCHRIJVING
De functies in de printf familie produceren uitvoer volgens een format
zoals onder beschreven. De functies printf en vprintf schrijven uitvoer
naar stdout, de standaard uitvoer stroom; fprintf en vfprintf schrijven
uitvoer naar de gegeven uitvoer stroom; sprintf, snprintf, vsprintf en
vsnprintf schrijven naar de karakter string str.
De functies vprintf, vfprintf, vsprintf, vsnprintf zijn vergelijkbaar
met respectievelijk de functies printf, fprintf, sprintf, snprintf; het
verschil is dat ze worden aangeroepen met een va_list inplaats van een
variabel aantal argumenten. Deze functies roepen de va_end macro niet
aan. Daarom is de waarde van ap ongedefinieerd na de aanroep. De
toepassing zou naderhand zelf va_end(ap) moeten aanroepen.
Deze acht functies schrijven de uitvoer onder controle van een format
string, die specificeerd hoe opeenvolgende argumenten worden omgezet
voor uitvoer. Deze argumenten kunnen ook via de mogelijkheden van
stdarg(3) om argumenten van variable lengte te geven, meegegeven zijn.
Teruggeef Waarde
Deze functies geven het aantal afgedrukte karakters terug (de afslui‐
tende ‘\0’, gebruikt om de uitvoer van strings te beëindigen, wordt
niet meegeteld). snprintf En vsnprintf schrijven niet meer dan size
bytes (inclusief de afsluitende ‘\0’), en geven -1 terug als de uitvoer
werd afgekapt door deze limiet. (Zo was het tot glibc 2.0.6. Sinds
glibc 2.1 volgen deze functies de C99 standaard en geven ze het aantal
karakters (exclusief de afsluitende ‘\0’) dat geschreven zou zijn naar
de uiteindelijke string als genoeg ruimte voorhanden was geweest.)
Vorm van de formatstring
De formatstring is een karakterstring, beginnend en eindigend in zijn
initiële "shift state", als die er is. De vormstring bestaat uit nul
of meer aanwijzingen: normale karakters (niet %), die onveranderd naar
de uitvoer stroom worden gekopiërd; en conversie specificaties, die elk
zorgen dat nul of meer opeenvolgende argumenten gepakt worden. Elke
conversie specificatie wordt begonnen met het karakter %, en eindigt
met een conversie specificatie. Daar tussenin mogen (in deze volgorde)
nul of meer vlaggen aanwezig zijn, een optionele minimum veldbreedte,
een optionele precisie en een optionele lengte aanpasser.
De argumenten moeten correct overeenkomen (na type promotie) met de
conversie specificatie. Standaard worden de argumenten in de gegeven
volgorde gebruikt, waarbij elke ‘*’ en elke conversie specificatie
vraagt om het volgende argument (en het is een fout als een onvoldoende
aantal argumenten zijn gegeven). Men kan ook expliciet opgeven welk
argument genomen zal worden, op elke plaats waar een argument vereist
is, door ‘%m$’ te schrijven inplaats van ‘%’ en ‘*m$’ inplaats van ‘*’,
waar het decimale hele getal m de positie in de argumenten lijst van
het gewenst argument bepaald, genummerd vanaf 1. Dus,
printf("%*d", width, num);
en
printf("%2$*1$d", width, num);
zijn gelijk. De tweede stijl laat herhaaldelijke referenties naar het‐
zelfde argument toe. De C99 standaard specificeert de ‘$’ stijl niet;
die komt van de Single Unix Specification. Als de ‘$’ stijl wordt
gebruikt, dan moet die gebruikt worden voor alle conversies die een
argument meekrijgen en alle breedte en precisie argumenten. De stijl
mag echter gemengd worden met ‘%%’ vormen die geen argument gebruiken.
Er mogen geen gaten zitten in de nummering van de argumenten die met
‘$’ gespecificeerd worden; bijvoorbeeld, als argumenten 1 en 3 gespeci‐
ficeerd zijn, dan moet ook argument 2 ergens in de formatstring
gespecificeerd zijn.
Voor sommige numerieke conversies wordt een breuk-karakter (‘decimale
komma’) of duizendtallen-scheidingskarakter gebruikt. Het feitelijk
gebruikte karakter hangt af van het LC_NUMERIC deel van de
‘localiteit’. De POSIX localiteit gebruikt ‘.’ als breuk-karakter, en
heeft geen duizendtallen-scheidingskarakter. Dus:
printf("%’.2f", 1234567.89);
resulteert in ‘1234567.89’ in de POSIX localiteit, in ‘1234567,89’ in
de nl_NL localiteit, en in ‘1.234.567,89’ in de da_DK localiteit.
De vlag karakters
Het karakter % wordt gevolgd door nul of meer van de volgende vlaggen:
# De waarde moet omgezet worden naar een ‘‘alternatieve vorm’’.
Voor o conversies betekent dat dat het eerste karakter van de
uitvoerstring nul wordt (door een 0 ervoor te zetten als het
niet al nul was). Voor x en X conversies, heeft een niet-nul
resultaat de string ‘0x’ (‘0X’ voor X conversies) ervoor gezet.
Voor a, A, e, E, f, g, en G omzettingen zal het resultaat altijd
een decimale punt hebben, zelfs als er geen cijfers op volgen
(gewoonlijk verschijnt een decimale punt alleen in de resultaten
van deze conversies als er een cijfer op volgt). Voor g en G
conversies worden nakomende nullen niet verwijderd van het
resultaat, wat anders wel het geval zou zijn. Voor andere
omzettingen is het resultaat onbepaald.
0 De waarde moet met nullen aangevuld worden. Voor d, i, o, u, x,
X, a, A, e, E, f, F, g, en G omzettingen wordt de geconverteerde
waarde links met nullen aangevuld, in plaats van met witruimte.
Als de 0 en - vlaggen allebei gezet zijn, dan wordt de 0 vlag
genegeerd. Als een precisie gegeven is met een numerieke
omzetting (d, i, o, u, x, en X), dan wordt de 0 vlag genegeerd.
Voor andere conversies is het gedrag onbepaald.
- De geconverteerde waarde wordt links uitgelijnd op de veldgrens.
(Normaal wordt rechts uitgelijnd.) De geconverteerde waarde
wordt aan de rechterkant aangevuld met witruimte, in plaats van
links met witruimte of nullen (dit geldt niet voor n conver‐
sies). Een - heeft voorrang op een 0 als beide gegeven zijn.
(een spatie) Een spatie gaat vooraf aan een positief getal (of
lege string) dat gegeven wordt na een conversie met teken.
+ Een teken (+ of -) wordt altijd geplaatst voor een getal dat
door een conversie met teken gegeven wordt. Normaal gesproken
wordt een teken alleen gebruikt voor negatieve getallen. Een +
heeft voorrang op een spatie als beiden gebruikt worden.
De vijf vlagkarakters boven zijn gedefinieerd in de C standaard. De
SUSv2 standaard geeft nog één extra vlagkarakter.
Voor decimale conversie (i, d, u, f, F, g, G) moet de uitvoer
gegroepeerd worden met duizendtallen scheidingstekens, als de
localiteit die opgeeft. Merk op dat veel versies van gcc deze
optie niet kunnen lezen, en een waarschuwing zullen geven.
SUSv2 geeft %’F niet.
glibc 2.2 geeft nog een vlagkarakter.
I Voor decimale integer conversie (i, d, u) gebruikt de uitvoer de
alternatieve uitvoer cijfers van de localiteit, als die er is
(bijvoorbeeld arabische cijfers). Echter, er zijn geen
localiteit definities met zulke outdigits meegegeven.
De veldbreedte
Een optionele decimale cijfer string (met het eerste cijfer niet-nul)
dat een minimale veldbreedte opgeeft. Als de geconverteerde waarde
minder karakters dan de veldbreedte heeft, dan wordt die links aange‐
vuld met spaties (of rechts, als de links-uitlijnen vlag gegeven is).
In plaats van een decimale cijfer string kan men ook ‘*’ of ‘*m$’
schrijven (voor een decimale integer m) op aan te geven dat de veld‐
breedte gegeven is in het volgende argument, of in het m-de argument,
respectievelijk, dat van type int moet zijn. Een negatieve veldbreedte
wordt gelezen als een ‘-’ vlag, gevolgd door een positieve veldbreedte.
In geen geval leidt een niet-bestaande of kleine veldbreedte tot afkap‐
pen van een veld; als het resultaat van een conversie breder is dan de
veldbreedte, dan wordt het veld breder gemaakt om het resultaat te kun‐
nen bevatten.
De precisie
Een optionele precisie, in de vorm van een punt (‘.’) gevolgd door een
optionele decimale cijferstring. In plaats van een decimale cijfer‐
string kan men ‘*’ of ‘*m$’ schrijven (waarbij m een decimale integer
is) om aan te geven dat de precisie gegeven is in respectievelijk het
volgende argument of het m-de argument, wat van type int moet zijn.
Als de precisie gegeven is als slechts ‘.’, of als de precisie negatief
is, dan wordt dit gelezen als precisie nul. Dit geeft het minimum aan‐
tal cijfers dat voor d, i, o, u, x, en X conversies moet voorkomen, het
aantal cijfers dat na het radix karakter moet voorkomen voor a, A, e,
E, f, en F conversies, het maximum aantal significante cijfers voor g
en G conversies, of het maximum aantal karakters dat afgedrukt moet
worden van een string voor s en S conversies.
De lengteaanpasser
Met ‘integer conversie’ wordt hier d, i, o, u, x, of X conversie
bedoeld.
hh Een volgende integer conversie correspondeert met een signed
char of unsigned char argument, of een volgende n conversie cor‐
respondeert met een pointer naar een signed char argument.
h Een volgende integer conversie correspondeert met een short int
of unsigned short int argument, of een volgende n conversie cor‐
respondeert met een pointer naar een short int argument.
l (el) Een volgende integer conversie correspondeert met een long
int of unsigned long int argument, of een volgende n conversie
correspondeert met een pointer naar een long int argument, of
een volgende c conversie correspondeert met een wint_t argument,
of een volgende s conversie correspondeert met een pointer naar
een wchar_t argument.
ll (el-el). Een volgende integer conversie correspondeert met een
long long int of unsigned long long int argument, of een
volgende n conversie correspondeert met een pointer naar een
long long int argument.
L Een volgende a, A, e, E, f, F, g, of G conversie correspondeert
met een long double argument. (%LF wordt toegestaan door C99,
maar niet door SUSv2.)
q (‘quad’. Alleen bij BSD 4.4 en Linux libc5 . Niet gebruiken.)
Dit is een synoniem voor ll.
j Een volgende integer conversie correspondeert met een intmax_t
of uintmax_t argument.
z Een volgende integer conversie correspondeert met een size_t of
ssize_t argument. (Linux libc5 heeft Z met deze betekenis. Niet
gebruiken.)
t Een volgende integer conversie correspondeert met een ptrdiff_t
argument.
SUSv2 kent alleen de lengte aanpassers h (in hd, hi, ho, hx, hX, hn) en
l (in ld, li, lo, lx, lX, ln, lc, ls) en L (in Le, LE, Lf, Lg, LG).
De conversie specificator
Een karakter dat aangeeft welk type van conversie moet worden
toegepast. De conversie specificatoren en hun betekenis zijn:
d,i Het int argument wordt geconverteerd naar decimale notatie met
teken. De precisie, als die er is, geeft het minimum aantal
cijfers dat moet voorkomen; als de geconverteerde waarde minder
cijfers nodig heeft, dan wordt het links met nullen aangevuld.
De standaard precisie is 1. Als 0 wordt afgedrukt met een
expliciete precisie 0, dan is de uitvoer leeg.
o,u,x,X
Het unsigned int argument wordt geconverteerd naar octaal zonder
teken. (u), of hexadecimaal zonder teken (x en X) notatie. De
letters abcdef worden gebruikt voor x conversies; de letters
ABCDEF worden gebruikt voor X conversies. De precisie, als die
er is, geeft het minimum aantal cijfers dat voor moet komen; als
de geconverteerde waarde minder cijfers nodig heeft, dan wordt
het links met nullen aangevuld. De standaard precisie is 1.
Als 0 wordt afgedrukt met een expliciete precisie 0, dan is de
uitvoer leeg.
e,E Het double argument wordt afgerond en geconverteert in de stijl
[-]d.ddde±dd waar er één cijfer voor het decimale-punt karakter
is, en het aantal cijfers erna gelijk is aan de precisie; als de
precisie ontbreekt, dan wordt die als 6 genomen; als de precisie
nul is, dan verschijnt er geen decimale-punt karakter. Een E
conversie gebruikt de letter E (in plaats van e) om de exponent
aan te geven. De exponent bevat altijd ten minste twee cijfers;
als de waarde nul is, dan is de exponent 00.
f,F Het double argument wordt afgerond en geconverteerd naar deci‐
male notatie in de stijl [-]ddd.ddd, waar het aantal cijfers na
het decimale-punt karakter gelijk is aan de precisie specifi‐
catie. Als de precisie ontbreekt, dan wordt die als 6 genomen;
als de precisie expliciet nul is, dan verschijnt er geen deci‐
male-punt karakter. Als er een decimale punt verschijnt, dan
komt er tenminste één cijfer vóór.
(SUSv2 kent geen F en zegt dat karakterstring representaties
voor oneindig en NaN beschikbaar zouden kunnen komen. De C99
standaard specificeert ‘[-]inf’ of ‘[-]infinity’ voor oneindig,
en een string, beginnend met ‘nan’ voor NaN, in het geval van f
conversie, en ‘[-]INF’ of ‘[-]INFINITY’ of ‘NAN*’ in het geval
van F conversie.)
g,G Het double argument wordt geconverteerd in stijl f of e (of F of
E voor G conversies). De precisie specificeert het aantal sig‐
nificante cijfers. Als de precisie ontbreekt, dat worden 6
cijfers gegeven; als de precisie nul is, dan wordt het behandeld
als 1. Stijl e wordt gebruikt als de exponent van de conversie
minder dan -4 is of groter dan of gelijk aan de precisie.
Nullen aan het eind worden verwijderd van het fractionele deel
van het resultaat; een decimale punt verschijnt alleen als die
gevolgd wordt door ten minste één cijfer.
a,A (C99; niet in SUSv2) Voor a conversie, wordt het double argument
geconverteerd naar hexadecimale notatie (gebruikmakend van de
letters abcdef) in de stijl [-]0xh.hhhhp±d; voor A conversie
wordt de prefix 0X, de letters ABCDEF, en de exponent scheider P
gebruikt. Er is één hexadecimaal cijfer voor de decimale punt,
en het aantal cijfers erna is gelijk aan de precisie. De stan‐
daard precisie is genoeg voor een exacte representatie van de
waarde als een exacte binaire representatie bestaat; anderzijds
is die groot genoeg om waarden van type double te kunnen onder‐
scheiden. Het cijfer voor de decimale punt is onbepaald voor
niet-genormaliseerde getallen, en niet-nul maar verder onbepaald
voor genormaliseerde getallen.
c Als er geen l aanpasser is, dan wordt het int argument geconver‐
teerd naar een unsigned char; het resulterende karakter wordt
dan geschreven. Als er een l aanpasser is, dan wordt het wint_t
(breed karakter) argument geconverteerd naar een multibyte rij
door een aanroep van de wcrtomb functie, met een conversie sta‐
tus in de initiële status; de resulterende byte wordt dan
geschreven.
s Als er geen l aanpasser is: Het const char * argument wordt
aangenomen een pointer naar een rij van karaktertype (pointer
naar een string) te zijn. Karakters van de rij worden
geschreven tot aan (en zonder) een afsluitend NUL karakter; als
een precisie gegeven is, dan worden er niet meer dan het
aangegeven getal geschreven. Als een precisie gegeven is, dan
hoeft er geen null karakter te zijn; als de precisie niet
gegeven is, of groter is dan de maat van de rij, dan moet de rij
een afsluitend NUL karakter bevatten.
Als er een l aanpasser is: Van het const wchar_t * wordt
aangenomen dat het een pointer naar een rij van brede karakters
is. Brede karakters van de rij worden geconverteerd naar multi‐
byte karakters (ieder door een aanroep van de wcrtomb functie,
met een conversie status beginnend in de initiële status vóór
het eerste brede karakter), tot aan en met een afsluitend null
breed karakter. De resulterende multibyte karakters worden
geschreven tot aan (en zonder) de afsluitende null byte. Als
een precisie gegeven is, dan worden niet meer bytes dan het
aangegeven getal geschreven; echter, er worden geen gedeel‐
telijke multibyte karakters geschreven. Merk op dat de precisie
het aantal geschreven bytes bepaald, niet het aantal brede
karakters of screen positions. De rij moet een afsluitend null
breed karakter bevatten, tenzij een precisie gegeven is, en de
rij zo klein is dat het aantal geschreven bytes er voorbij gaat
voordat het einde van de rij bereikt is.
C (Niet in C99, wel in SUSv2.) Synoniem voor lc. Niet gebruiken.
ls . Niet gebruiken.
p Het void * pointer argument is afgedrukt in hexadecimaal (net
als bij %#x of %#lx).
n Het aantal karakters tot nog toe geschreven wordt opgeslagen in
de integer aangegeven door het int * (of variant) pointer argu‐
ment. Er wordt geen argument geconverteerd.
% Een ‘%’ wordt geschreven. Er wordt geen argument geconverteerd.
De volledige conversie specificatie is ‘%%’.
VOORBEELDEN
Om pi af te drukken in vijf decimalen:
#include <math.h>
#include <stdio.h>
fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
Om een datum en tijd in de vorm ‘Sunday, July 3, 10:02’, waar weekday
en maand pointers naar strings zijn:
#include <stdio.h>
fprintf(stdout, "%s, %s %d, %.2d:%.2d\n",
weekday, month, day, hour, min);
In veel landen wordt de dag-maand-jaar volgorde gebruikt. Daarom moet
een geinternationaliseerde versie de argumenten af kunnen drukken in
een volgorde die gespecificeerd wordt door het format:
#include <stdio.h>
fprintf(stdout, format,
weekday, month, day, hour, min);
waar format afhangt van localiteit, en de argumenten zou kunnen per‐
muteren. Met de waarde
"%1$s, %3$d. %2$s, %4$d:%5$.2d\n"
zou men ‘Sonntag, 3. Juli, 10:02’ kunnen krijgen.
Om een voldoende grote string te alloceren en ernaar af te drukken
(correcte code voor zowel glibc 2.0 als glibc 2.1):
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
char *
make_message(const char *fmt, ...) {
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p;
va_list ap;
if ((p = malloc (size)) == NULL)
return NULL;
while (1) {
/* Try to print in the allocated space. */
va_start(ap, fmt);
n = vsnprintf (p, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
return p;
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n+1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((p = realloc (p, size)) == NULL)
return NULL;
}
}
printf(1), wcrtomb(3), wprintf(3), scanf(3), locale(5)
De fprintf, printf, sprintf, vprintf, vfprintf, en vsprintf functies
voldoen aan de ANSI X3.159-1989 (‘‘ANSI C’’) en ISO/IEC 9899:1999
(‘‘ISO C99’’) standaarden. De snprintf en vsnprintf functies voldoen
aan ISO/IEC 9899:1999.
Wat betreft de teruggeef waarde van snprintf spreken SUSv9 en C99
elkaar tegen: als snprintf aangeroepen wordt met size=0 dan schrijft
SUSv2 een ongespecificeerde teruggeef waarde kleiner dan 1 voor, ter‐
wijl C99 in dit geval toestaat dat str NULL is; C99 schrijft als
teruggeef waarde voor (net als altijd) het aantal karakters dat
geschreven zou zijn als de uitvoer string groot genoeg zou zijn
geweest.
Linux libc4 kent de vijf standaard C vlaggen. Het kent de lengte aan‐
passers h,l,L en de conversies cdeEfFgGinopsuxX, waar F een synoniem
voor f is. Verder worden D,O,U als synoniemen voor ld,lo,lu geac‐
cepteerd. (Dit is een kwalijke zaak, en veroorzaakte later ernstige
bugs, toen %D niet meer ondersteund werd.) Geen localiteit-afhankelijk
radix karakter, geen duizendtallen scheider, geen NaN of oneindig, geen
%m$ en *m$.
Linux libc5 kent de vijf standaard C vlaggen, en de ’ vlag, localiteit,
%m$ en *m$. Het kent de lengte aanpassers h,l,L,Z,q, maar accepteert L
en q zowel voor long doubles als voor long integers (dit is een bug).
De conversie karakters FDOU worden niet langer herkent, maar een nieuw
conversie karakter m, dat strerror(errno) geeft, is toegevoegd.
glibc 2.0 voegt conversie karakters C en S toe.
glibc 2.1 voegt lengte aanpassers hh,j,t,z en conversie karakters a,A
toe.
glibc 2.2 voegt het conversie karakter F met C99 semantiek, en het vlag
karakter I toe.
GESCHIEDENIS
Unix V7 definieert de drie routines printf, fprintf, sprintf, en heeft
de vlag -, de breedte of precisie *, de lengte aanpasser l, de conver‐
sies doxfegcsu, en D,O,U,X als synoniemen voor ld,lo,lu,lx. Dit geld
ook nog voor BSD 2.9.1, maar BSD 2.10 heeft de vlaggen #, + en
<spatie>; D,O,U,X worden niet meer genoemd. BSD 2.11 heeft vprintf,
vfprintf, vsprintf, en waarschuwt D,O,U,X niet meer te gebruiken. BSD
4.3 Reno heeft de vlag 0, de lengte aanpassers h en L, en de conversies
n, p, E, G, X (met huidige betekenis) en verklaart D,O,U als verouderd.
BSD 4.4 indtroduceert de functies snprintf en vsnprintf, en de lengte
aanpasser q. FreeBSD heeft ook de functies asprintf en vasprintf, die
een buffer die groot genoeg is voor sprintf alloceren.
BUGS
Omdat sprintf en vsprintf uitgaan van een willekeurig lange string,
moeten aanroepers oppassen dat ze niet over de aanwezige ruimte heen‐
gaan (overflow); het is vaak onmogelijk dit te verzekeren. Merk op dat
de lengte van de geproduceerde strings locale-afhankelijk en moelijk te
voorspellen is. Gebruik, in plaats hiervan, snprintf en vsnprintf (of
asprintf en vasprintf).
Linux libc4.[45] heeft geen snprintf, maar levert een libbsd die een
snprintf equivalent aan sprintf bevat, i.e., één die het size argument
negeert. Daarom leidt het gebruik van snprintf met vroege libc4 tot
ernstige beveiligingsproblemen.
Code zoals printf(foo); doet vaak een bug vermoeden, omdat foo een %
karakter zou kunnen bevatten. Als foo van niet betrouwbare gebruik‐
ersinvoer komt, dan zou het een %n kunnen bevatten, wat de printf naar
het geheugen doet schrijven en hiermee een beveiligingslek creëert.
Sommige floating point conversies onder vroege libc4 veroorzaakten
lekken in het geheugen.