#klooienmetcomputers

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.

Gebruik GitHub om te klooien met de computer!

Wie mee wil doen met #klooienmetcomputers, maar niet alle teksten van Arnout wil overtypen, of de eigen code wil delen met andere lezers, kan dat doen via GitHub:

1. Maak een account op www.github.com

2. Zoek naar Abmvk/kmc

Het account Abmvk volgen kan ook.

Arnout plaatst daar alle stukjes code voor #klooienmetcomputers, met als naam eerst een volgnummer van het stukje waar de code bij hoort en dan een term uit de titel. Zaken die bijvoorbeeld in een config-bestand thuishoren plaatst hij als .txt bestand, wat overtypen kan besparen. Ook plaatst hij stukjes code waar hij zelf mee rommelt en die niet in een stukje op accountant.nl terechtkomen. Die stukjes zijn te herkennen omdat er geen volgnummer voor staat.

Lezers zijn vrij te gebruiken wat ze willen en om zelf zaken toe te voegen of aan te passen, vragen te stellen of commentaar te leveren. Samen kom je een eind. Om dit goed te laten werken: maak een clone van Arnout’s repo, haal met pull nieuwe bestanden binnen en voeg met push zelf toe. Wie er niet uitkomt: laat het Arnout weten.

Arnout van Kempen di CCO CISA is Senior manager Risk & Compliance bij Baker Tilly. Hij schrijft op persoonlijke titel. Hij is lid van de Commissie Financiële verslaggeving & Accountancy van de AFM en lid van de signaleringsraad van de NBA. Daarnaast is hij diaken van het bisdom 's-Hertogenbosch.

Gerelateerd

reacties

Reageren op een artikel kan tot drie maanden na plaatsing. Reageren op dit artikel is daarom niet meer mogelijk.

Aanmelden nieuwsbrief

Ontvang elke werkdag (maandag t/m vrijdag) de laatste nieuwsberichten, opinies en artikelen in uw mailbox.

Bent u NBA-lid? Dan kunt u zich ook aanmelden via uw ledenprofiel op MijnNBA.nl.