Nu we de elementaire zaken van C# en Visual Studio kennen is het tijd om onze programma's wat interessanter te maken. De ontwikkelde programma's tot nog toe waren steevast lineair van opbouw, ze werden lijn per lijn uitgevoerd zonder de mogelijkheid om de flow van het programma aan te passen. Het programma doorliep de lijnen braaf na elkaar en wanneer deze aan het einde kwam sloot het programma zich af.
Onze programma's waren met andere woorden niet meer dan een eenvoudige oplijstingen van opdrachten. Je kan het vergelijken met een lijst die je vertelt over hoe je een brood moet kopen:
Neem geld uit spaarpot
Wandel naar de bakker om de hoek
Vraag om een brood
Krijg het brood
Betaal het geld aan de bakker
Keer huiswaarts
Smullen maar
Alhoewel dit algoritme redelijk duidelijk en goed zal werken, zal de realiteit echter zelden zo rechtlijnig zijn. Een beter algoritme (dat foutgevoeliger is én interactiever voor de eindgebruiker) zal afhankelijk van de omstandigheden (bakker gesloten, geen geld meer, etc.) mogelijke andere stappen ondernemen. Het programma zal beslissingen nemen op basis van aanwezige informatie.
In een typisch project, bijvoorbeeld een bestelsysteem, kunnen we beslissingen gebruiken voor tal van zaken:
als we de voorraad van producten gaan bijhouden en we willen reageren wanneer de voorraad op is
als we op bepaalde dagen van de week kortingen op bepaalde producten willen geven in plaats van de gebruiker deze zelf te laten kiezen
als we spaarpunten willen introduceren en de gebruiker deze kan inwisselen
Om beslissingen te kunnen nemen in C# moeten we kunnen nagaan of een bepaalde uitspraak waar of niet waar is. Anders gezegd: we moeten stukjes code kunnen schrijven waarvan we achteraf kunnen zeggen of ze "waar" of "niet waar" zijn. Zo'n stukjes code noemen we booleaanse expressies. De meest typische booleaanse expressies schrijf je met de relationele operatoren. Deze stellen vergelijkingen tussen stukjes data voor. Gelukkig ken je deze al uit het lager onderwijs en moet je alleen de notatie hieronder leren:
>
groter dan
<
kleiner dan
==
gelijk aan
!=
niet gelijk aan
<=
kleiner dan of gelijk aan
>=
groter dan of gelijk aan
"Gelijk aan" noteren we met twee symbolen, omdat één symbool gebruikt wordt voor een toekenning.
Deze operatoren leveren je altijd één van twee mogelijkheden als uitkomst: true
of false
. Je kan dit ook uittesten: Console.WriteLine(4 < 7);
of Console.WriteLine(4 < 2);
toont je het verwachte resultaat.
Er bestaan nog simpelere booleaanse expressies dan die met de relationele operatoren: true
en false
zelf zijn hun eigen resultaat en zijn dus technisch gesproken ook booleaanse expressies. Je mag dus bv. ook true
schrijven in plaats van 4 > 2
.
In dit deel zullen we bekijken hoe we ons programma dynamischer kunnen maken met behulp van het if
-statement, al dan niet uitgebreid met else
en else if
.
De if
is een van de elementairste constructies in een programmeertaal. Vrijwel elke programmeertaal bezit deze constructie. We zullen de werking ervan eerst wat algemener bekijken, zodat je het concept goed begrijpt. Daarna zullen we inzoomen op de syntax in C#.
Het basisidee is als volgt: een if
-constructie bevat code die enkel uitvoert als een booleaanse expressie true
oplevert. Met andere woorden: als een voorwaarde naar keuze waar is. We noemen dergelijke code conditionele code, want een conditie is een voorwaarde.
We zullen dit tonen met een Flowgorithm programma. Dit is een beperkte, maar heel visuele programmeertaal. In een Flowgorithm programma start je bij Main
en volg je steeds de pijlen.
De gele box stelt een declaratie voor. Ook in Flowgorithm moet je variabelen declareren. Het blauw parallellogram: de gebruiker geeft iets in (de waarde van wachtwoord
). De rode ruit bevat een booleaanse expressie. Dan is er een vertakking, met daarop de waarden True
en False
. We volgen de pijl met daarop de uitkomst van de booleaanse expressie. Als we dus het juiste wachtwoord intypen, krijgen we de geheime info, anders gebeurt er niets.
Het if
-statement stemt overeen met alles tussen de rode ruit en het rode bolletje. Dus als aan een bepaalde voorwaarde voldaan is, voeren we afgebakende code uit.
Uit dit programma kan je dan ook volgende C#-code afleiden:
In de gegenereerde code stemt de rode ruit dus overeen met de haakjes meteen na if
en stemt de tak True
overeen met de accolades.
Er zijn enkele veelgemaakte fouten waar je op moet letten:
De types in je booleanse expressie moeten steeds vergelijkbaar zijn. Volgende code is dus fout: if( "4" > 3)
daar we hier een string
met een int
vergelijken.
Als je geen accolades schrijft, verandert de werking van if
. Het gevolg zal zijn dat enkel het eerste statement na de if
zal uitgevoerd worden indien true
. Gebruiken we de if
van daarnet maar zonder accolades dan zal het tweede statement altijd uitgevoerd worden ongeacht de if
:
Het eerdere voorbeeld toont dat we soms actie willen ondernemen als aan een voorwaarde voldaan is, maar heel vaak willen we een andere actie ondernemen als aan diezelfde voorwaarde niet voldaan is. In dat geval maken we gebruik van de if ... else ...
.
We gaan terug naar onze login. Een fout wachtwoord ingeven heeft bepaalde gevolgen. Dit kan bijvoorbeeld een alarm doen afgaan, omdat indringers soms foute wachtwoorden ingeven tot ze toevallig het juiste vinden. We stellen dit hier voor door een actie toe te voegen als het wachtwoord niet klopt.
De overeenkomstige C# code:
In bovenstaande code stemt de rode ruit dus nog steeds overeen met de haakjes meteen na if
, stemt de tak True
overeen met de accolades vlak na de ronde haakjes en stemt else { ... }
overeen met de tak False
. Anders gezegd: als aan een bepaalde voorwaarde voldaan is, voeren we het eerste blok afgebakende code uit, anders voeren we het tweede blok afgebakende code uit.
Als we iets altijd willen doen, hoort dat niet in een vertakking. Dan zetten we het in de flowchart na het rode bolletje. In ons programma zetten we het dan na de volledige if ... else ...
:
De gegenereerde code is dan:
Het is perfect mogelijk om bepaalde controles enkel te doen als eerdere controles wel of niet gelukt zijn. Dit kan er zo uitzien:
In de gegenereerde code leidt dit tot geneste conditionele code: een if
binnenin een grotere if
of else
. In digt geval gaat het om een if
in een else
. Je mag zo diep nesten als je maar wil. Er is geen technische limiet, maar je code zal wel onleesbaar worden als je overdrijft.
Nesten van conditionele code levert soms code op die moeilijk te ontrafelen is. Het gebeurt vaak dat we een else
nodig hebben met meteen daarin terug een if
, om zo verschillende gevallen af te handelen.
We kunnen een programma maken dat dit demonstreert: Er is niet aan de hoofdvoorwaarde voldaan, maar er is wel aan een andere voorwaarde voldaan:
De gegenereerde code voor dit frament is technisch juist:
Maar Flowgorithm is geen menselijke programmeur. Een menselijke programmeur zou volgende voorstelling gebruiken, die hetzelfde doet, maar makkelijker leesbaar is:
De logische EN, OF en NIET-operatoren die je misschien kent uit de lessen technologie of elektronica kan je ook gebruiken in C#:
&&
en-operator
||
of-operator
!
niet-operator
Je kan de &&
-operator tussen twee booleaanse expressies zetten om een nieuwe, grote expressie te schrijven die afhangt van de kleinere expressies aan beide kanten. Idem voor de ||
-operator. Je kan de niet-operator voor een booleaanse expressie zetten om het resultaat hiervan om te draaien. Bijvoorbeeld:
Hieronder krijg je nog eens het overzicht van de werking van de AND en OR operatoren:
niet waar
niet waar
niet waar
waar
niet waar
waar
niet waar
niet waar
waar
waar
waar
waar
Wat zal de uitkomst zijn van volgende expressies? (tip: het zal steeds true
of false
zijn, niets anders)
3>2
4!=4
4<5 && 4<3
"a"=="a" || 4>=3
(3==3 && 2<1) || 5!=4
!(4<=3)
true || false
!true && false
Je bent niet beperkt tot het gebruik van expressies met één relationele operator in de voorwaarde van een if. Je mag om het even welk type booleaanse expressie gebruiken. Anders gezegd: als het gedeelte tussen haakjes uiteindelijk maar true of false oplevert, is het goed. We kunnen dus ook gebruik maken van de logische operatoren &&, ||, ! in onze voorwaarden.
Goed gebruik van booleaanse expressies kan onze programma's drastisch vereenvoudigen. We tonen dit met een voorbeeld.
Volgend programma bepaalt of je korting krijgt op het openbaar vervoer. Volg zelf de flowchart om de logica te snappen:
Maar we kunnen dit eenvoudiger zo schrijven:
Deze code zegt dat je korting krijgt als je jonger bent dan 18 of als je ouder bent dan 65. Ze doet hetzelfde als de eerste versie, maar het diagram is eenvoudiger en de gegenereerde code is dat ook. Ook via de andere operatoren &&
en !
kan je gelijkaardige vereenvoudigingen verkrijgen.
De locatie waar je een variabele aanmaakt bepaalt de scope, oftewel de gegarandeerde levensduur, van de naam van de variabele. Ruwweg: als je binnen hetzelfde stel accolades werkt waarin een variabele is gedeclareerd, dan is die naam in scope en kan je hem gebruiken. Indien je de variabele dus buiten die accolades nodig hebt, dan heb je een probleem: de variabele is enkel bereikbaar binnen de accolades vanaf het punt in de code waarin het werd aangemaakt.
Zeker wanneer je begint met if
, loops, methoden, etc. zal de scope belangrijk zijn: deze code-constructies gebruiken steeds accolades om codeblocks aan te tonen. Een variabele die je dus binnen een if-blok aanmaakt zal enkel binnen dit blok bestaan, niet erbuiten.
Wil je dus getal ook nog buiten de if
gebruiken zal je je code moeten herschrijven zodat getal
voor de if
wordt aangemaakt:
Zolang je in de scope van een variabele bent kan je geen nieuwe variabele met dezelfde naam aanmaken:
Volgende code is dus niet toegestaan:
Je krijgt de error: A local variable named 'getal' cannot be declared in this scope because it would give a different meaning to 'getal', which is already used in a 'parent or current' scope to denote something else
Enkel de tweede variabele een andere naam geven is toegestaan in het voorgaande geval.
Dit is wel geldig, daar de scope van de eerste variabele afgesloten wordt door de accolades:
Een switch statement is een element om een veelvoorkomende constructie van if/if else...else eenvoudiger te schrijven. Vaak komt het voor dat we bijvoorbeeld aan de gebruiker vragen om een keuze te maken (bijvoorbeeld een getal van 1 tot 10, waarbij ieder getal een ander menu-item uitvoert van het programma), zoals:
Met een switch
kan dit eenvoudiger wat we zo meteen zullen tonen. Eerst bekijken we hoe switch
juist werkt. De syntax van een switch
is specialer dan de andere programma flow-elementen (if
, while
, enz.), namelijk als volgt:
value
is de variabele die wordt gebruikt als booleaanse test in de switch (option
in ons voorbeeld hier boven). Iedere case begint met het case
keyword gevolgd door de waarde die value
moet hebben om in deze case te springen. Na het dubbelpunt volgt vervolgens de code die moet uitgevoerd worden in deze case
. De case
zelf mag eender welke code bevatten (methoden, nieuwe program flow elementen, enz.), maar moet zeker afgesloten worden met het break
keyword.
Tijdens de uitvoer zal het programma value
vergelijken met iedere case constant van boven naar onder. Wanneer een gelijkheid wordt gevonden dan wordt die case uitgevoerd. Indien geen case wordt gevonden die gelijk is aan value
dan zal de code binnen de default
-case uitgevoerd worden (de else
achteraan indien alle vorige if else
-tests negatief waren).
Het menu van zonet kunnen we nu herschrijven naar een switch
:
De case waarden moeten constanten zijn en mogen dus geen variabelen zijn. Constanten zijn de welgekende literals (1
, "1"
, 1.0
, 1.d
, '1'
, enz.). Uiteraard moeten de case waarden van hetzelfde datatype zijn als die van de testwaarde.
Soms wil je dat dezelfde code uitgevoerd wordt bij 2 of meer cases. Je kan ook zogenaamde fallthrough cases beschrijven wat er als volgt uit ziet:
In dit geval zullen zowel de waarden 2
en 3
resulteren in de zin "Laden of opslaan gekozen" op het scherm.
Al deze oefeningen maak je in een klasse Beslissingen
flowchart omzetten naar conditionele code
Eenvoudige conditie
Uitbreiding: samengestelde booleaanse expressie
Functionele analyse
Basis: Maak een programma dat aan de gebruiker vraagt hoeveel paar schoenen hij/zij wenst te kopen. Ieder paar schoenen kost normaal 50 euro. Indien de gebruiker meer dan 2 paar koopt, is er 10% korting. Toon aan de gebruiker de totale prijs.
Uitbreiding: Breid in een tweede stap je programma uit zodat de korting enkel geldt als de gebruiker een klantenkaart heeft.
Technische analyse
Maak een methode met de naam ShoeSeller
. Maak gebruik van een if.
Zet volgende flowchart om in code. Een Real
in Flowgorithm stemt overeen met een double
in C#.
Basis:
Uitbreiding:
Basis:
Uitbreiding:
flowchart omzetten naar conditionele code
tweevoudige conditie
gebruik modulo
Maak een programma dat aan de gebruiker een geheel getal vraagt. Het programma geeft terug of het ingegeven getal even of oneven is.
Maak een methode met de naam EvenOrOdd
.
Een getal is even als de rest van de deling door 2 nul is. Hiervoor kan je de modulo operator gebruiken. Het teken voor de modulo is het %
-teken.
Voorbeelden:
7%2 geeft 1 => 7 is oneven
8%2 geeft 0 => 8 is even
Zet volgende flowchart om in code:
flowchart omzetten naar conditionele code
meervoudige conditie
Maak een programma dat aan de gebruiker een geheel getal vraagt. Het programma geeft terug of het ingegeven getal positief, negatief of 0 is.
Maak een methode met de naam PositiveNegativeZero
.
Maak gebruik van een if
– else if
- else
.
Zet volgende flowchart om in code:
Voorbeeldinteractie(s)
meervoudige conditie
gebruik van else if
Maak een programma om de BMI van de gebruiker te berekenen. (Meer info over BMI) De BMI wordt berekend aan de hand van de lengte en het gewicht van de persoon.
De formule is: BMI = gewicht / lengte².
Je toont niet enkel de BMI maar ook een beoordeling over de BMI:
- BMI lager dan 18,5 => ondergewicht
- BMI vanaf 18,5 maar lager dan 25 => normaal gewicht
- BMI vanaf 25 maar lager dan 30 => overgewicht
- BMI vanaf 30 maar lager dan 40 => zwaarlijvig
- BMI 40 of hoger dan 40 => ernstige obesitas
Maak een methode met de naam BMICalculator
.
Maak gebruik van een if
– else if
– else if
…
meervoudige conditie
samengestelde booleaanse expressie
gebruik van else if
Maak een programma om van 3 ingegeven getallen, het grootste te bepalen.
Maak een methode met de naam LargestNumberOfThree
.
Maak gebruik van een if
– else if
- else
Voorbeeldinteractie
conditie
samengestelde booleaanse expressie
Maak een programma waarmee je aan de gebruiker het resultaat van 3 examens opvraagt. De opgevraagde resultaten zijn de behaalde punten op 100. Om te slagen moet de student een gemiddelde van meer dan 50% hebben én maximaal 1 onvoldoende.
Maak een methode met de naam Exams
.
Maak gebruik van een if
– else
.
Voorbeeldinteractie
- conditionele berekeningen
De Wet van Ohm houdt in dat een elektrische stroom (voorgesteld als I) gelijk is aan een spanningsverschil (U) gedeeld door een weerstand (R), dus I = U / R.
Vraag aan de gebruiker wat hij wenst te berekenen: Spanning, Weerstand of Stroomsterkte. Vraag vervolgens de twee andere waarden. Als dus de gebruiker "Spanning" kiest, vraag je aan de gebruiker de waarden van de stroomsterkte en de weerstand. Bereken m.b.v. de Wet van Ohm de gewenste waarde en toon aan de gebruiker.
Maak een nieuwe methode genaamd OhmsLaw
.
Denk eraan dat de gegeven formule wiskundig gedefinieerd is. Houd rekening met het feit dat deze drie maten uitgedrukt kunnen worden in kommagetallen.
De gebruiker voert een jaartal in en jouw programma toont of het wel of geen schrikkeljaar is.
Maak een methode LeapYear
.
Je hebt een schrikkeljaar als het jaartal deelbaar is door 4, behalve als het ook deelbaar is door 100, tenzij het wél deelbaar is door 400. Bijvoorbeeld:
1997: geen schrikkeljaar
1996: wél schrikkeljaar
1900: geen schrikkeljaar
2000: wél schrikkeljaar
Je moet je zakgeld berekenen. Het zakgeld is standaard 20 euro maar je kan meer of minder zakgeld krijgen afhankelijk van je behaalde punten op je examen.
Maak een methode PocketMoney
.
Het standaard zakgeld is 20 euro. Dit bedrag kan vermeerderd of verminderd worden als volgt:
Als je punten meer dan 15 zijn, dan krijg je 60% meer zakgeld dan het standaard bedrag.
Als je punten meer dan 10 zijn maar minder of gelijk aan 15, krijg je ook meer zakgeld dan het standaard bedrag; namelijk 2 euro per punt dat je meer hebt dan 10.
Als je punten 10 zijn, dan krijg je het standaard zakgeld.
Als je punten minder dan 10 zijn maar meer dan 7, dan krijg je 30% minder zakgeld dan het standaardbedrag.
Als je punten 7 of minder dan 7 zijn maar meer dan 5, dan krijg je 3 euro minder voor elk punt dat je minder dan 10 hebt.
Als je punten 5 of minder zijn, dan krijg je 0 euro zakgeld.
- Conditionele functionaliteit
- Gebruik van de switch
We willen dat de gebruiker een menu ter beschikking heeft om eerst te kiezen uit welk hoofdstuk er een oefening moet gekozen worden en vervolgens welke oefening er moet uitgevoerd worden.
Maak in je klasse Program een hoofdmenu. Deze methode laat de gebruiker kiezen uit één van de hoofdstukken. Na de keuze wordt het scherm leeggemaakt en dan wordt de methode SubMenu
van de juiste klasse opgeroepen.
Elke klasse die je tot hiertoe in dit project gemaakt hebt, voorzie je dus van een methode SubMenu
, zodat de gebruiker kan kiezen uit de oefeningen (=methodes) binnen het gekozen hoofdstuk.