Drop hier links of afbeeldingen om ze aan de editor toe te voegen.

Wanneer je leert programmeren, gebeurt het wel meer dan eens dat er een fout in je programma zit. Sommige fouten zijn eenvoudiger te vinden dan andere. We hebben het hier over de fouten die ervoor zorgen dat je programma niet doet wat jij als programmeur ervan verwacht.

Normaal geef je een programma pas aan de gebruiker wanneer het volgens jou foutloos werkt. Toch glipt er soms nog een fout door. Zo’n overgebleven fout in een programma noemen we een bug.

Het woord bug komt uit het Engels en betekent letterlijk beestje. De term raakte in zwang bij de eerste computers: er kroop wel eens een echt insect tussen de onderdelen, waardoor de machine niet meer werkte. Het opsporen en wegwerken van fouten heet sindsdien debuggen.

We onderscheiden drie soorten fouten. Elke soort herken je op een andere manier, en hieronder bekijken we ze één voor één.

Schrijffouten of syntaxisfouten

De eerste soort fouten kan je al hebben tegengekomen. Het zijn fouten die je maakt tegen de syntaxregels van de taal C#. Zoals elke taal heeft een programmeertaal regels: er is een grammatica en een woordenschat. Het vergeten van haakjes, accolades of een puntkomma op het einde van een zin zijn allemaal mogelijke fouten van deze soort.

In de code hieronder werden met opzet enkele schrijffouten gemaakt:

int getal1 = 5;
Console.WriteLin(getal1 / 0

Er zitten meerdere fouten in deze twee regels: WriteLin bestaat niet (het moet WriteLine zijn), het sluithaakje ) ontbreekt en ook de afsluitende puntkomma ; is vergeten.

Hoe herken je ze? Een syntaxisfout verhindert dat je programma start: de code wordt eerst gecontroleerd en pas uitgevoerd als ze grammaticaal klopt. Krijg je je programma niet aan de praat en wijst de foutmelding naar een bepaalde regel, dan gaat het bijna altijd om een schrijffout. Begin steeds bij de eerste fout in de melding: vaak verdwijnen meerdere fouten zodra je die ene oplost. Sla dus niet meteen in paniek wanneer er verschillende fouten tegelijk verschijnen.

Waarschuwingen zijn geen fouten

Naast echte fouten geeft de compiler soms ook waarschuwingen (warnings). Een waarschuwing wijst op iets dat misschien niet de bedoeling is, maar die je programma niet tegenhoudt: het start en loopt gewoon verder. Een typisch voorbeeld is een variabele die je wel declareert maar nergens gebruikt.

int ongebruikt = 5;          // waarschuwing: gedeclareerd maar nooit gebruikt
Console.WriteLine("Hallo");

Een fout (error) moet je oplossen voor je programma kan draaien; een waarschuwing mag je in principe negeren, maar het is een goede gewoonte om ze toch weg te werken, want vaak wijzen ze op een vergetelheid.

Uitvoeringsfouten of run-time fouten

Tijdens het uitvoeren van een programma kan je nog andere soorten fouten tegenkomen. De code is dan grammaticaal in orde en het programma start netjes op, maar onderweg loopt er iets mis. Wanneer je probeert te delen door nul, of wanneer een variabele het resultaat niet kan opslaan, ontstaat zo’n run-time fout.

Het programma wordt dan tijdens de uitvoering onderbroken en geeft een melding met de oorzaak en de plaats van de fout. Twee veelvoorkomende fouten:

System.FormatException — de invoer heeft de verkeerde vorm

Deze fout is vaak het gevolg van een omzetting van gegevens. Je vraagt via Console.ReadLine een getal in te vullen, maar de gebruiker vult niets in of typt letters. In je programma probeer je die tekst dan met Convert.ToInt32 om te vormen tot een getal, en dat lukt uiteraard niet.

int leeftijd = Convert.ToInt32(Console.ReadLine());

Typt de gebruiker hier vijf in plaats van 5, dan kan C# daar geen getal van maken en gooit het een System.FormatException.

System.DivideByZeroException — delen door nul

Wiskundig is delen door nul niet toegelaten. Het is dus ook logisch dat dit niet kan in een programma. Bij een gehele deling door nul onderbreekt C# het programma met een System.DivideByZeroException.

int teller = 10, noemer = 0;
int resultaat = teller / noemer;

Er bestaan nog veel meer mogelijke uitvoeringsfouten, zoals een OverflowException wanneer een getal te groot wordt voor zijn type. Het is onbegonnen werk om ze hier allemaal op te sommen. Komt er een fout voor, dan vind je meestal op het internet voldoende informatie om de oorzaak ervan te achterhalen.

Hoe herken je ze? Een run-time fout duikt pas op tijdens het uitvoeren, en meestal alleen bij bepaalde invoer (lege invoer, letters in plaats van cijfers, een noemer die nul wordt). De melding noemt het type uitzondering (FormatException, DivideByZeroException, …) en wijst naar de regel waar het misging. Verderop leer je hoe je zulke fouten netjes kan opvangen zodat je programma niet crasht.

Logische fouten

Dit soort fouten is het moeilijkst op te sporen. Na het schrijven van je code kan je programma gewoon worden uitgevoerd, zonder enige foutmelding, maar het resultaat is niet wat je ervan verwacht. Je hebt dan waarschijnlijk een denkfout gemaakt, of je hebt de werking van de programmeertaal nog niet helemaal door.

Een klassiek voorbeeld is de omzetting van graden Celsius naar graden Fahrenheit. In de code ziet het er voor ons goed uit, maar C# doet het niet zoals wij verwachten:

double celsius, fahrenheit;
celsius = Convert.ToDouble(Console.ReadLine());

fahrenheit = (9 / 5) * celsius + 32;

Console.WriteLine("Omgezet in graden Fahrenheit is dat " + fahrenheit);

De formule lijkt te kloppen, en toch krijg je een verkeerd antwoord. De oorzaak is 9 / 5: omdat 9 en 5 allebei gehele getallen zijn, voert C# een gehele deling uit. Het resultaat is 1 in plaats van 1.8, en daardoor klopt de hele omzetting niet. De computer heeft exact gedaan wat er stond, alleen niet wat wij bedoelden.

Hoe herken je ze? Een logische fout geeft geen foutmelding: het programma loopt netjes tot het einde. Je merkt ze enkel doordat de uitvoer niet klopt. Daarom is het belangrijk om je programma te testen met invoer waarvan je het juiste antwoord op voorhand kent. Klopt de uitvoer niet, lees dan je code zorgvuldig regel voor regel na en redeneer wat de computer op elke lijn precies doet.

Samengevat:

  • Schrijffouten / syntaxisfouten — tegen de regels van de taal; het programma start niet.
  • Uitvoeringsfouten / run-time fouten — het programma start, maar valt onderweg stil met een uitzondering (bv. FormatException, DivideByZeroException).
  • Logische fouten — het programma loopt zonder melding, maar het resultaat klopt niet.