4 Invoer en uitvoer Strikt genomen maken invoer- en uitvoerfaciliteiten geen deel uit van de taal C, zoals dat in FORTRAN wel het geval is, waar de statements READ en WRITE als deel van de taal zijn gedefinieerd. Toch moeten echte programma's met de buitenwereld communiceren. In dit hoofdstuk bespreken we een deelverzameling van de bibliotheek voor standaard-I/0 (input/output), bestaande uit een verzameling functies die bedoeld zijn als standaardfaciliteit voor invoer en uitvoer. We zullen hier niet de hele I/O-bibliotheek behandelen. We beperken ons tot vier functies die met de terminal van de gebruiker communiceren. Dat is voldoende voor het schrijven van volledige werkende programma's. In hoofdstuk 14 zullen we op I/0 terugkomen en programma's bekijken die werken met data die in computerfiles staan.
4.1 Toegang tot de standaardbibliotheek Als een C-programma wordt uitgevoerd, worden door het besturingssysteem automatisch drie files geopend voor gebruik door dat programma. Die files zijn standaardinvoer, standaarduitvoer en standaardfout. Het is de bedoeling dat normale invoer door het programma uit de standaardinvoer wordt gelezen. In een interactieve omgeving zal de standaardinvoer normaal gekoppeld zijn aan de terminal (het toetsenbord) van de gebruiker. Normale uitvoer wordt naar de standaarduitvoer geschreven en dat zal normaal ook de terminal (het beeldscherm) van de gebruiker zijn. Tenslotte wordt er nog een uitvoerfile geopend. Het is de bedoeling dat eventuele foutmeldingen die het programma oplevert naar deze standaardfoutfile worden geschreven. In dit hoofdstuk houden we ons alleen bezig met programma's die met de standaardinvoer en uitvoer werken. In hoofdstuk 14, waar invoer en uitvoer via files wordt behandeld, bestuderen we de files standaardinvoer, standaarduitvoer en standaardfout nader. In elke bronprogrammafile die naar een functie uit de standaard-I/O-bibliotheek verwijst, moet aan het begin de regel #include <stdio.h> voorkomen. Strikt genomen is dit niet helemaal waar, want alleen bepaalde functies uit deze bibliotheek hebben informatie nodig die in de headerfile stdio.h staan. Maar als we deze regel altijd opnemen, hoeven we niet te onderzoeken of het nodig is of niet. Een nauwkeurige beschrijving van deze statement #include geven we in het volgende hoofdstuk. Hier is het voldoende te zeggen dat een file met de naam stdio.h bepaalde dingen definieert die de standaard-I/O-bibliotheek nodig heeft. Daar worden bijvoorbeeld de standaardinvoer, 1
standaarduitvoer en standaardfout gedefinieerd. Deze gegevens worden vanuit deze headerfile in het toepassingsprogramma opgenomen.
4.2 Geformatteerde uitvoer Geformatteerde regels uitvoer worden geproduceerd met de functie printf uit de standaardI/O-bibliotheek. We hebben de functie printf in hoofdstuk 2 al informeel gebruikt. De volledige en algemene beschrijving van printf luidt: printf(formaat, argument1, argument2, ... ); De functie printf formatteert de argumenten en drukt ze in de standaarduitvoer af. De argumenten zijn de expressies die de waarden produceren die moeten worden afgedrukt. De weergave van deze argumenten wordt geregeld door de formatteringsstringformaat. Deze string (zie paragraaf 3.4) bevat twee soorten informatie: gewone karakters, die gewoon in de uitvoer worden gekopieerd, en conversiespecificaties, die de argumenten van printf converteren en afdrukken. In het eenvoudigste geval heeft printf een formaatstring zonder conversie en geen argumenten. In dat geval wordt de string letterlijk naar de standaarduitvoer gekopieerd: printf("Een eenvoudige mededeling.\n"); Het resultaat van deze statement is dat de inhoud van de formaatstring in de standaarduitvoer terecht komt. Omdat de formaatstring een newline-symbool als laatste af te drukken karakter bevat, verschijnt latere uitvoer vanaf de linker kantlijn van de regel die na deze uitvoer komt. En deze uitvoer komt na eventuele eerdere uitvoer. Voor elk argument van printf moet een corresponderende conversiespecificatie in de formaatstring staan. Er moet precies het juiste aantal argumenten van de juiste typen zijn, die met de conversies overeenkomen; anders is het resultaat van het uitvoeren van printf onvoorspelbaar. Als een van de conversiespecificaties in de formaatstring onjuist is geformuleerd, is het effect ook onvoorspelbaar. Een conversiespecificatie in de formaatstring begint met het procentteken Daarna komt een reeks van nul of meer opties van de conversie. De specificatie eindigt met een conversieoperator, die als één karakter wordt genoteerd. De volledige definitie voor een conversiespecificatie is:
2
Alleen het procentteken en de uit één karakter bestaande conversie-operatie moeten aanwezig zijn. De andere velden zijn optioneel (opt). Verder hebben niet alle combinaties van velden betekenis. De precisiespecificatie regelt bijvoorbeeld het aantal decimale plaatsen dat in een decimaal getal wordt afgedrukt. Dit is een zinloos gegeven als er een integer waarde wordt geformatteerd en afgedrukt. We verkennen in deze paragraaf niet alle mogelijke combinaties. Het zijn er gewoon te veel. We geven hier een uitleg van een aantal voorbeelden van de beginselen van geformatteerde uitvoer. Een minimale conversiespecificatie bestaat uit het procentteken en een conversie-operatie. Deze laatste wordt genoteerd als een van de karakters uit volgende tabel. Het procentteken wordt gebruikt als representatie van het procentteken zelf, omdat dit in formaatstrings verder gereserveerd is voor conversiespecificaties. De uitvoer van printf("De korting bedraagt 10%%\n"); is De korting bedraagt 10% Tabel 4-1 bevat een beknopte beschrijving van elke operatie en is gemakkelijk om de werking even snel op te zoeken. Daarna volgen enkele voorbeelden. Conversieoperatie d, i u 0 x, X c s f e, E g, G p n
Toepassing conversie van int naar signed decimaal getal conversie van int naar unsigned decimaal getal conversie van unsigned naar unsigned octaaf getal conversie van int naar unsigned hexadecimaal getal conversie van int naar één karakter conversie naar string conversie naar signed decimaal floating-point getal (met komma) conversie naar signed decimaal floating-point getal (wetenschappelijke notatie) conversie naar signed decimaal floating-point getal conversie naar pointer aantal geschreven karakters
Tabel 4-1 Conversie-operaties bij gebruik van printf 3
Een argument expressie die bij evaluatie een integer waarde oplevert, wordt geformatteerd met de conversie-operator d. Als de declaraties en toekenningen int a=10, b=15; gelden, produceert de functieaanroep printf ("De som van %d en %d is %d. \n", a, b, a+b); de uitvoer De som van 10 en 15 is 25. De conversie-operatie %d zorgt ervoor dat de waarde van het corresponderende argument naar een signed decimaal getal wordt geconverteerd. Elk voorkomen van %d verbruikt één argument. Het argument moet van type int zijn. De geconverteerde waarde is een reeks decimale cijfers. De reeks is de kortste die nodig is om de waarde af te drukken. De waarde van variabele a (10) vereist bijvoorbeeld twee karakterposities in de uitvoerstroom. In een conversiespecificatie kan ook een minimale veldbreedte staan. In zijn eenvoudigste vorm bestaat deze uit een unsigned decimale integer constante. Als het argument minder karakters oplevert dan de opgegeven veldbreedte, worden de karakters rechts in het veld uitgelijnd en aan de linkerkant met spaties aangevuld. De functieaanroep printf ("De som van %d en %d is %4d \n", a, b, a+b); produceert als uitvoer De som van 10 en 15 is 25 (nota: drie blanco’s tussen is en 25!) waarbij de waarde van de expressie a + b wordt weergegeven in een veld met een breedte van vier karakterposities. Maar als de geconverteerde waarde van het argument meer karakters omvat dan de opgegeven veldbreedte, wordt het veld voldoende verbreed om plaats te maken voor de af te drukken waarde. De waarde wordt niet afgekapt, maar de geformatteerde uitvoer ziet er nu anders uit dan verwacht. Zo levert het voorbeeld printf ("De som van %d en %1d is %3d. \n”, a, b, a+b); als uitvoer De som van 10 en 15 is 25. 4
De conversiespecificatie die bij het argument b hoort, is %1d. Dit zegt dat de waarde moet worden afgedrukt in een veld met breedte 1, maar aangezien de geconverteerde waarde van het argument een veld met breedte 2 nodig heeft, heeft deze grotere breedte voorrang. Floating-point waarden worden met de conversiespecificatie %f weergegeven. De geconverteerde waarde is een reeks decimale cijfers met daarin een decimale punt, maar hoogstens zoveel als nodig is voor het representeren van de waarde. Als er geen precisie wordt gespecificeerd, wordt er uitgegaan van een precisie van zes decimale plaatsen. Als de declaraties en toekenningen float x, y; x = 1.234; y = 56.78; gelden, produceert printf ("%f afgetrokken van %f is %f \n" y, x, x-y); de uitvoer 56.780000 afgetrokken van 1.234000 is -55.546000 De minimale veldbreedte en de precisie kunnen worden opgegeven als twee unsigned integer constanten gescheiden door een punt. Deze elementen zijn beide optioneel. Als de precisie niet wordt opgegeven, wordt de punt weggelaten en wordt de standaardprecisie 6 aangehouden. Zo nodig kan de geconverteerde waarde worden afgerond. Het voorbeeld printf ("%5.2f afgetrokken van %4.2f is %7.2f \n", y, x, x-y); geeft als uitvoer 56.78 afgetrokken van 1.23 is -55.55 Tenslotte laten we zien hoe de formattering van een string wordt geregeld. De vereiste conversie-operatie is %s. Als er geen veldbreedte wordt opgegeven, worden de karakters van de string afgedrukt in het kleinste benodigde veld: printf ("[%s] \n", "Hallo allemaal"); levert [Hallo allemaal] 5
Een veldbreedte wordt gerepresenteerd als een unsigned decimale integer constante voorafgaand aan de conversie-operatie. De string wordt rechts uitgelijnd en aan de linkerkant met spaties aangevuld: printf ("[%20s] \n","Hallo allemaal"); levert [
Hallo allemaal]
In geen van de voorbeelden is tot nu toe een vlagkarakter gebruikt. Vlagkarakters wijzigen de betekenis van de hoofdconversie-operatie. In alle voorbeelden waarin de geconverteerde waarde minder karakters beslaat dan de expliciete veldbreedte, wordt de waarde rechts uitgelijnd in het veld en aan de linkerkant met spaties aangevuld. Door een koppelteken als vlagkarakter aan de conversiespecificatie te laten voorafgaan, kunnen we de waarde links laten uitlijnen en aan de rechterkant met spaties laten aanvullen: printf ("[%-20s] \n", "Hallo allemaal"); levert [Hallo allemaal
]
Samenvattend: Om een variabele van een bepaald type af te drukken, is een formaat nodig. In volgende tabel geven we voor de meest voorkomende types het overeenkomende (basis)formaat. De parameters x, ., en y kunnen weggelaten worden. Type int short int long int float double long double
formaat %xd %xhd %xld %x.yf %x.ylf %x.yLf
De x komt steeds overeen met een minimale veldbreedte. De y staat eventueel voor het aantal cijfers na de komma. %x.ye %x.yle %x.yLe
%x.yg %x.ylg %x.yLg
Merk op dat wat hier voor %d genoteerd is, ook geldt voor U, 0 en x. Dit zijn natuurlijk minder gebruikte getalvoorstellingen en types (voor U -unsigned). De lezer (programmeur) moet zich strikt aan deze voorschriften houden, anders worden bijvoorbeeld getallen compleet verkeerd afgedrukt (of ingelezen, zie volgende paragraaf)
6
4.3 Geformatteerde invoer De functie scanf is de tegenhanger van printf . De stroom invoerkarakters uit de standaardinvoer wordt ontleed aan de hand van een besturingsstring en de ingevoerde waarden worden aan programmavariabelen toegekend. De functieaanroep heeft de vorm scanf(formaat, argument1, argument2, ...); Elk argument is het adres van een geheugenlocatie die de bijbehorende invoerwaarde moet krijgen. Elk argument moet dus het adres van de ontvangende variabele zijn. Dit wordt in C genoteerd door middel van de adresoperator, weergegeven als het ampersand-teken (&) voor de naam van de variabele. Verdere details over deze operator worden in hoofdstuk 5 gegeven. Om twee datawaarden in te voeren en op te bergen in locaties waarnaar de identifiers maand en jaar verwijzen, gebruiken we: scanf ("…", &maand, &jaar); De string formaat is een 'plaatje' van de verwachte vorm van de invoer. De functie scanf ontleedt de stroom invoerkarakters aan de hand van de formaatstring. In de formaatstring worden conversiespecificaties gebruikt die lijken op die bij printf. Er moet precies het juiste aantal argumenten aanwezig zijn, die overeenkomen met de conversiespecificaties in de formaatstring, anders zijn de resultaten onvoorspelbaar. Als een conversiespecificatie niet correct is genoteerd, is het effect ook onvoorspelbaar. Behalve conversiespecificaties kan een formaatstring ook witruimtekarakters bevatten. Een witruimtekarakter in de formaatstring heeft als gevolg dat er een of meer witruimtekarakters uit de standaardinvoer worden gelezen en weggegooid. Het eerste karakter in de invoer dat geen witruimtekarakter is, wordt als volgende te lezen karakter beschouwd. Tenslotte kunnen er in een formaatstring andere dan witruimtekarakters en karakters voor een conversiespecificatie voorkomen. Deze andere karakters moeten precies met de resterende karakters in de invoerstroom overeenkomen. Als er geen overeenkomst is, eindigt scanf en blijft het onverwachte karakter in de invoer als volgend beschikbaar karakter staan. En conversiespecificatie begint met een procentteken (%). conversiespecificatie bij scanf is:
De vorm van een
7
De conversieoperaties die scanf kent, lijken op die van printf en worden in tabel 4-2 getoond. Conversieoperatie d, i u 0 x c s f e g p n
Toepassing conversie van signed decimaal getal naar int conversie van unsigned decimaal getal naar int conversie van unsigned octaaf getal naar unsigned conversie van unsigned hexadecimaal getal naar int conversie van één karakter conversie van string conversie van signed decimaal floating-point getal (met komma) conversie van signed decirnaal floating-point getal (wetenschappelijke notatie) conversie van signed decimaal floating-point getal invoer van pointer aantal gelezen karakters
Tabe1 4-2 Conversie-operaties bij gebruik van scanf Hoeveel karakters er uit de invoerstroom worden gelezen, hangt van de conversieoperatie af. In het algemeen verwerkt een conversieoperatie een reeks van een of meer karakters totdat (a) er een witruimtekarakter of een andere niet passend karakter wordt gelezen, of (b) het aantal gelezen karakters gelijk is aan de opgegeven maximale veldbreedte. Als de declaraties int dag, maand, jaar; char ch1, ch2; gegeven zijn, verwacht de aanroep van scanf scanf ("%d %d %d", &dag, &maand, &jaar); dat er drie integers worden opgegeven. De eerste integer waarde die gelezen wordt, wordt aan de variabele dag toegekend. Eventuele witruimtekarakters die vóór de cijfers van het getal komen, worden genegeerd. De tweede integer waarde wordt van de eerste gescheiden door een of meer witruimtekarakters en wordt aan de variabele maand toegekend. Hetzelfde gebeurt met de laatste variabele jaar. Als de invoer is: 31
12
1985 8
wordt de waarde 31 toegekend aan de variabele dag, 12 aan de variabele maand en 1985 aan de variabele jaar. De invoerwaarden worden door een reeks witruimtekarakters van elkaar gescheiden. Tussen de waarden 31 en 12 staan spaties en/of tabs, en tussen 12 en 1985 staan newline-karakters. De waarde 1985 wordt ook met een newline-karakter afgesloten. Het laatste karakter blijft in de invoerbuffer staan om door de volgende aanroep van scanf te worden verwerkt. In het voorbeeld scanf("%d/%d/%d", &dag, &maand, &jaar); wordt verwacht dat de integer waarden door een /-karakter worden gescheiden. voorbeeld van een geldige invoerstroom voor bovenstaande aanroep van scanf is:
Een
12/4/1985 In een conversiespecificatie kan ook een maximale veldbreedte voorkomen. Die wordt opgegeven als een unsigned decimale integer constante ongelijk aan nul. De conversie eindigt als het vereiste aantal karakters is gelezen of als de invoerwaarde eindigt met witruimte of een ongeldig karakter. Het vorige voorbeeld van een aanroep van scanf kan ook worden geschreven als scanf("%2d/%2d/%4d", &dag, &maand, &jaar); zodat er plaats is voor een dag en een maand van 2 cijfers en een jaar van 4 cijfers. Als er maximale veldbreedten worden gebruikt, hoeven er geen witruimtekarakters te worden gebruikt. De invoer 12051985 kan zo worden ontleed dat de waarde 12 aan de variabele dag wordt toegekend, de waarde 5 aan de variabele maanden de waarde 1985 aan de variabele jaar. Bij gebruik van de conversiespecificatie %c is voorzichtigheid geboden. Bij deze operatie worden eventuele witruimtekarakters aan het begin niet overgeslagen. De aanroep scanf("%d%c%d%c%d", &dag, &ch1, &maand, &ch2, &jaar); kent bij de invoer 5-9/1985 9
weer de waarde 5 aan de integer variabele dag toe, de waarde 9 aan de integer variabele maand en de waarde 1985 aan de integer variabele jaar. Aan de karaktervariabelen ch1 en ch2 worden respectievelijk het koppelteken (-) en de slash (/) toegekend.
4.4 De functies getchar en putchar In de vorige twee paragrafen hebben we gezien hoe we met routines voor geformatteerde I/O één karakter kunnen overbrengen. Als de declaratie char ch; gegeven is, kunnen we één karakter uit de standaardinvoer lezen en naar de standaarduitvoer schrijven met: scanf ("%c", &ch) ; printf ("%c", ch) ; Op deze manier gebeurt onnodig dubbel werk. Dat komt doordat scanf en printf beide hun formaatstring moeten verwerken. Voor invoer en uitvoer van één karakter zijn er ook de twee eenvoudigere mogelijkheden getchar en putchar. Strikt genomen moeten we dit geen functies noemen, want zoals we later in het boek zullen zien, zijn het helemaal geen bibliotheekfuncties. Wat ze precies wel zijn, zien we in hoofdstuk 14. Voorlopig kunnen we ze wel als functies beschouwen. De functie putchar heeft één argument en drukt het betreffende karakter af in de standaarduitvoer. Om de waarde van de karaktervariabele ch als uitvoer te produceren, gebruiken we putchar(ch); Om één newline-karakter als uitvoer te produceren, kunnen we gebruiken: putchar(‘\n’); De functie getchar() leest het volgende karakter uit de standaardinvoerstroom. Er worden aan getchar() geen argumenten opgegeven, maar de haakjes zijn wel verplicht. De waarde van het gelezen karakter wordt in de vorm van een int als functiewaarde afgeleverd. Deze waarde kan in een toekenning worden gebruikt: ch = getchar(); Als de variabele ch van type char is, worden bij de toekenning de juiste conversies uitgevoerd. 10
Het oorspronkelijke probleem van het invoeren en weer uitvoeren van één karakter kan nu zo worden opgelost: ch = getchar(); putchar(ch); Opmerking: Indien men wenst te verifiëren of het einde van een bestand gelezen is, kan men de waarde van de ingelezen character vergelijken met EOF. Aangezien EOF een int is, kan men best voor de variabele die de waarde van getchar() krijgt, eveneens een int gebruiken! De invoer/uitvoeroperaties scanf, printf, getchar en putchar kunnen vrijelijk gemengd worden gebruikt. De in te voeren datum 12-10/1985 kan bijvoorbeeld worden gelezen met de functies: scanf ("%d", &dag) ch1 = getchar () ; scanf("%d", &maand); ch2 = getchar () ; scanf ("%d", &jaar); waarna de karaktervariabelen ch1 en ch2 de scheidingstekens tussen de drie getallen bevatten. Als we geformatteerde invoer met scanf gebruiken, moeten we eraan denken dat het invoeren van bijvoorbeeld een getal doorgaat tot de eerste witruimte of een karakter dat geen deel uitmaakt van een getal. De gegeven invoer kan worden gelezen met: scanf ("%d%c%d%c%d", &dag, &ch1, &maand, &ch2, &jaar); De waarde voor de variabele dag wordt gelezen als de karakterreeks tot aan (niet tot en met) het koppelteken. Dat blijft in de invoerstroom staan voor de volgende toekenning. De volgende conversiespecificatie is %c, zodat er één karakter wordt ingevoerd en aan de variabele ch1 wordt toegekend. Dit ene karakter is het koppelteken. Als een gelezen getal door witruimte wordt afgesloten, blijft het witruimtekarakter als eerste karakter achter voor de volgende invoeroperatie. Laten we eens kijken naar een programma dat de gebruiker om een getal vraagt, de door een newline afgesloten waarde leest, de gebruiker vraagt of de waarde juist is en het als één karakter J of N (voor 'ja' respectievelijk 'nee') verwachte antwoord leest. Een eerste poging om dit te programmeren kan zijn:
11
printf ("Voer een getal in: “); scanf("%d”, &getal); printf("Correct?"); antwoord = getchar () ; Nadat het getal is gelezen, blijft het afsluitende newline-karakter in de invoerbuffer staan. Als de vraag “Correct?” wordt weergegeven, wacht het programma niet op invoer van de gebruiker, maar beschouwt het newline-karakter in de buffer als antwoord. Het programma loopt dan verder zonder dat er nog invoer van de gebruiker wordt gevraagd. Dit is natuurlijk niet de bedoeling. Een eenvoudige oplossing voor dit probleem is het newline-karakter weg te gooien voordat er een antwoord wordt gevraagd. Aangenomen dat het getal door een onmiddellijk volgend newline-karakter is afgesloten, kunnen we één extra karakter lezen. Dat kan in de eerste scanf zelf gebeuren, of met een aparte getchar(). Deze laatste oplossing ziet er zo uit: printf ("Voer een getal in: "); scanf ("%d", &getal); weggooien = getchar(); // verwijder newline uit invoer printf("Correct? "); antwoord = getchar();
4.5 Speciaaltjes. Men kan de uitvoer van printf ook naar een string (rij van characters) sturen. Een voorbeeld: char tekst[256]; sprintf(tekst, "formaat", argumenten); Het enige verschil met printf is dus dat de eerste (extra) parameter de naam van een string is. Hetzelfde kan men doen met sscanf: sscanf(tekst, "formaat", argumenten); Voor het gebruik van het formaat en de argumenten kan men teruggrijpen Zowel printf als sprintf geven ook een resultaat terug. Zo zou men bijvoorbeeld kunnen schrijven: int i; i=printf("voorbeeld %d",5+3);
12
i bevat nadien het aantal afgedrukte tekens. Indien dit aantal EOF is, is er een fout gebeurd, bijvoorbeeld: de schijf was vol, … . Voor scanf en sscanf kan men hetzelfde zeggen: int i; i=scanf("%d",&j); Hier bevat i het aantal ingelezen variabelen. Indien dit 0 is, is er iets fout. Indien niet kon gelezen worden is dit EOF.
4.6 Invoer vanuit het toetsenbord. Getchar() is een functie die een teken uit de inputbuffer neemt. In sommige gevallen, bijvoorbeeld een menuoptie is het handig een teken rechtstreeks van het toetsenbord te kunnen lezen, zonder de inputbuffer te moeten aanbieden met het <enter> teken. C kent twee functies om rechtstreeks het toetsenbord te lezen: • getch(); is een functie die een teken rechtstreeks van het toetsenbord leest. • getche(); doet hetzelfde en zet het teken eveneens op het scherm (e van echo). In gebruik (toekenning aan variabele, headerbestand, …) zijn getch en getche gelijk aan getchar. Putch bestaat ook, maar is hetzelfde als putchar. Volgens sommige C compilers is het af te raden putch te gebruiken (minder portabel) kbhit() is een functie die kijkt of een toets van het toetsenbord is ingedrukt. Indien een toets is ingedrukt, geeft de functie een waarde TRUE (waar) af. De header conio.h is vereist. Indien het de bedoeling is tekens van en naar een bestand te schrijven gebruikt men getc en putc: • int getc(FILE *stream); • int putc(int c, FILE *stream); Voor het gebruik van het FILE type, verwijzen we eerst naar het hoofdstuk over bestand invoer en uitvoer.
13
4.7 Samenvatting 1. Invoer/uitvoerfaciliteiten worden in C geleverd door een aantal functies in de standaardbibliotheek. 2. Bij gebruik van invoer/uitvoer constructies met de systeem-headerfile stdio.h in een programma worden opgenomen door middel van de besturingsregel #include <stdio.h>. 3. Geformatteerde uitvoer wordt gedaan door de bibliotheekfunctie printf. Geformatteerde invoer wordt gedaan door de bibliotheekfunctie scanf. Formatteren is het regelen van de lay-out van de afgedrukte uitvoer en de invoer van het programma. 4. Een formateringsstring bestaat uit een mengsel van witruimtekarakters, gewone karakters en conversiespecificaties. 5. Invoer en uitvoer van één karakter wordt gedaan met de bibliotheek-'functies' getchar en putchar.
14