De gebruiker aan het woord
Arnout van Kempen over rommelen in een digitale wereld.
Programmeren in C wordt ineens behoorlijk vreemd, als je gegevens van de gebruiker nodig hebt. In veel programmeertalen zorgt de taal zelf op de achtergrond voor veel foutoplossend vermogen. In BASIC kan je bijvoorbeeld zeggen:
10 INPUT A$: PRINT A$
BASIC weet dat een variabele met $ aan het eind van de naam een string is. Hoe lang die is, hoef je niet te weten. Waar die in het geheugen staat? Doet er niet toe. Wanneer heb je het einde van de string bereikt? Het zal wel. Met bovenstaande programmaatje lees je een tekst-string in, en print die vervolgens weer. Er kan vrijwel niets mis gaan.
C is ongeveer het andere uiterste. In C kan echt alles mis gaan. De variabele 'string' bestaat niet. Je definieert een array van characters, en daarbij zal je moeten aangeven hoe lang je string maximaal is. Maar als je die string met printf() wil printen, trekt die functie zich van de lengte niets aan. De characters worden geprint tot een NULL wordt gevonden. Staat die niet in je array, dan gaat printf() vrolijk verder tot ergens in het geheugen alsnog een NULL wordt gevonden. Dat ziet er niet goed uit.
Het wordt nog lastiger als je een variabele wil lezen, dus de gebruiker mag invoer geven vanaf het toetsenbord (of beter: vanaf stdin, wat je via pipes en redirection kan verleggen in linux, maar dat is voor een andere keer). Een relatief makkelijke functie daarvoor is scanf(). Net als printf() gebruikt scanf() een string met codes om aan te geven wat precies aan input verwacht wordt. Bijvoorbeeld %d voor een integer, of %s voor een string.
Ik zei relatief makkelijk, want in feite kan hier bizar veel mis gaan. Om dat te illustreren heb ik een programmaatje op GitHub gezet dat vraagt om een voornaam, achternaam, geboortejaar, -maand en -dag. Vervolgens geeft het de naam en de geboortedatum terug. De ergste fouten heb ik al afgevangen. Zo kan je in scanf() aangeven hoeveel tekens je wil hebben. Bijvoorbeeld scanf("%19s",voornaam) neemt maximaal de eerste negentien tekens die de gebruiker invoert en plaatst die in array voornaam[], waarmee nog tenminste één teken overblijft voor de NULL.
Met scanf("%4d",&jaar) zorg je dat maximaal vier cijfers worden gebruikt voor het geboortejaar, en die worden geplaatst in het geheugen op de locatie van jaar. De & geeft de pointer naar jaar!
Als je netjes invoert:
Kees
Jansen
1970
10
4
Dan krijg je de correcte output:
Naam: Kees Jansen
Geboortedatum: 4/10/1970
Maar probeer eens zaken als een voornaam van pakweg vijftig tekens. Of een achternaam met een spatie, zoals De Vries. Al spelend met rare of foute input ga je zien dat C niets corrigeert dat je niet zelf opvangt.
De afgrenzingen in scanf() noemde ik al, maar eigenlijk heb je dus nog meer error-handling nodig. Dat is typisch aan C: wat jij niet regelt, regelt C ook niet voor je. Een voorbeeld van basale error-handling heb ik toegevoegd aan de input van de dag met
if(scanf(“%2d”, &dag)!=1
{
printf(“Error: onjuiste input ontvangen\n”);
exit(1);
}
Nog vrij beperkt, maar het is tenminste iets.
Voor wie graag met een schoon scherm begint, zit in de code trouwens nog een kleinigheidje. In de header-file stdlib.h zit de functie system(). Hiermee kan je een commando aanroepen uit het operating system van waaruit je programma draait. Aangezien ik in linux werk, vanuit de bash-shell wordt met system(“clear”) het scherm van de terminal leeg gemaakt. Een schoon startscherm dus. Ik weet het niet 100 procent zeker, maar ik neem aan dat je onder MS Windows system(“cls”) kan gebruiken voor hetzelfde effect. C kent overigens meer methodes, maar deze is duidelijk en simpel. Niet erg portable maar ik programmeer voor mijn eigen systeem, niet om op allerlei systemen te kunnen draaien.
Naast scanf() kent C nog een aantal functies om input te verwerken en daar kom ik nog op. Het wordt helemaal mooi als we zo ook bestanden kunnen gaan lezen. Maar dat komt nog wel.
Gerelateerd

BSN-nummers controleren?
Arnout van Kempen over rommelen in een digitale wereld.

Make it
Arnout van Kempen over rommelen in een digitale wereld.

Data-analyse!
Arnout van Kempen over rommelen in een digitale wereld.

Efficiënte headers
Arnout van Kempen over rommelen in een digitale wereld.

Gekkigheid, pure gekkigheid: linked lists
Arnout van Kempen over rommelen in een digitale wereld.