Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Een veelvoorkomende manier van while-loops gebruiken is waarbij je een bepaalde teller bijhoudt die je telkens met een bepaalde waarde verhoogt. Wanneer de teller een bepaalde waarde bereikt moet de loop afgesloten worden.
Bijvoorbeeld volgende code om alle even getallen van 0 tot 10 te tonen:
Met een for-loop kunnen we deze veel voorkomende code-constructie verkort schrijven.
De syntax van een for
-loop is de volgende:
setup: In het setup gedeelte zetten we de "wachter-variabele" op de begin waarde. De wachter-variabele is de variabele die we tijdens de loop in het oog zullen houden en die zal bepalen hoe vaak de loop moet uitgevoerd worden.
finish test: Hier plaatsen we een booleaanse expressie die de wachter-variabele uit de setup gebruikt om te testen of de loop-code moet uitgevoerd worden.
update: Hier plaatsen we wat er moet gebeuren telkens de loop z'n codeblock heeft uitgevoerd. Meestal zullen we hier de wachter-variabele verhogen of verlagen.
Gebruiken we deze kennis nu, dan kunnen we de eerder vermelde code om de even getallen van 0 tot en met 10 tonen als volgt:
Voor de setup-variabele kiest men meestal i, maar dat is niet noodzakelijk. In de setup wordt dus een variabele op een start-waarde gezet. De finish test zal aan de start van iedere loop kijken of de finish test nog waar is, indien dat het geval is dan wordt een nieuwe loop gestart en wordt i met een bepaalde waarde, zoals in update aangegeven, verhoogd.
Lees zeker deze for tutorial na want er zijn nog enkele subtiliteiten in for-loops die we hier niet behandelen.
Als je in Visual Studio for
typt en dan tweemaal op [tab] duwt krijg je kant en klare for-loop code.
Je kan loops (alle types) altijd vroegtijdig stopzetten door het break
keyword. Het gebruik hiervan ligt soms in de schemerzone van misbruik. Probeer dus eerst je probleem anders op te lossen voor je break
begint te gebruiken.
Om iemand op StackOverflow te quoten:
When used at the start of a block, as first checks made, they act like preconditions, so it's good. When used in the middle of the block, with some code around, they act like hidden traps, so it's bad."
Bron StackOverFlow: Are break
and continue
bad programming practices?
Lees meer over het gebruik van break
hier.
Een extra grote hoop oefeningen om je loops te drillen (originele bron). De oefeningen zijn gerangschikt naar moeilijkheid, je moet deze allemaal met loops oplossen! Hoe ver geraak je?
Probeer niet alle oefeningen met hetzelfde type loop te doen, wissel tussen while
, do...while
en for
.
Indien er sprake is van n in de opgave dan is dit een getal dat je eerst aan de gebruiker moet vragen.
Opgelet: de oplossing van dit soort oefeningen vindt je overal. Weersta hier aan, en probeer ZELF de oplossing te vinden. Dat is de enige manier om dit te leren.
Toon alle natuurlijke getallen van 1 tot n.
Toon alle natuurlijke getallen van n tot 1.
Toon alle even getallen tussen 1 en 100.
Toon alle oneven getallen tussen 1 en 100.
Toon de som van alle getallen van 1 tot n (dus 1+2+3+4+...+n).
Toon de som van alle even getallen van 1 tot n.
Toon de som van alle oneven getallen van 1 tot n.
Schrijf een programma dat het aantal digits in een getal telt (het getal 12348 heeft bijvoorbeeld 5 digits).
(PRO) Schrijf een programma dat een ingevoerd getal als tekst uitschrijft. Als de gebruiker dus 123 invoert zal de uitvoer zijn: honderd drie en twintig.
Schrijf een programma dat alle ascii karakters en hun waarde toont van 10 tot n (tip: char c = Convert.ToChar(65);
zal hoofdletter A
tonen)
Toon het alfabet van a tot z.
Schrijf een programma dat de macht van een getal toont. De gebruiker voor eerst het getal in, gevolgd door de macht (bv 2 en 4 zal als resultaat 16 geven (2 tot de 4e)).
Schrijf een programma een getal n ontbindt in factoren. Factoren zijn de getallen waardoor je n kan delen zonder rest (van bijvoorbeeld het getal 100 zijn de factoren 1,2,4,5,10,20,25,50,100 ).
Toon de reeks van Fibonacci tot n termen.
lussen gebruiken om een resultaat op te bouwen
Je krijgt een getal van de gebruiker. Je moet nagaan of dit een priemgetal is, d.w.z. of het precies 2 gehele delers heeft.
Elk geheel getal vanaf 2 heeft minstens 2 gehele delers: 1 en zichzelf. Als dat de enige delers van het gegeven getal zijn, is het priem. Je kan dus nagaan of een getal een priemgetal is door alle getallen vanaf 1 tot het getal zelf te overlopen en na te gaan of deze delers zijn van het getal. (Eigenlijk volstaat het minder getallen te checken maar daar draait het hier niet om.)
console applicatie
geneste lussen gebruiken om een meerdere resultaten te laten zien
Je krijgt een getal van de gebruiker. Je moet alle priemgetallen kleiner of gelijk aan dit getal laten zien.
Je kan het idee uit de vorige oefening herbruiken, maar nu zijn de getallen die je controleert niet afgeleverd door de gebruiker. Je moet ze zelf genereren in een for
-lus. Als je in de vorige oefening een for
-lus hebt gebruikt, zal je dus twee for
-lussen moeten nesten.
console applicatie
Vanaf nu zul je véél meer oefeningen voorgeschoteld krijgen dan je kan afwerken in 1 labo tijd (I dare you ;). Selecteer zelf de oefeningen die je wenst te doen en sla die over waarvan je overtuigd bent ze al te kunnen. De oefening zijn , in de mate van het mogelijke, gerangschikt op moeilijkheid.
Bekijk maak de oefeningen 8 tot en met 13 van hoofdstuk 4 in volgende pdf
Ter info: Dit document staat ook in de lijst onderaan bij de nuttige extra's hier.
Indien niet expliciet vermeld mag je kiezen met wat voor loop (for, while, do while) je het probleem zal oplossen.
Gebruik de kracht van loops om pijlsnel alle tafels van 1 tot en met 10 van vermenigvuldigen op het scherm te tonen (dus van 1x1 tot 10x10 en alles daartussen)
DNA heeft steeds een RNA-complement (DNA is het gevolg van RNA transscriptie). Schrijf een programma dat een ingevoerde DNA-string omzet naar een RNA-string. De gebruiker voert steeds 1 DNA-nucleotide in per keer en duwt op enter, de RNA string wordt steeds groter. De omzetting is als volgt:
G wordt C
C wordt G
T wordt A
A wordt U
Als de gebruiker dus ACGTGGTCTTAA
heeft ingevoerd moet het resultaat: UGCACCAGAAUU
zijn.
Ga er van uit dat de gebruiker letter per letter invoert (telkens dus enter na een letter) en je de omgezette string doet groeien (m.b.v +=
).
Een getal is een narcistisch getal of armstronggetal als het de som is van zijn eigen cijfers elk tot de macht verheven van het aantal cijfers.
9 is een Armstrong nummer, want 9 = 9^1 = 9
10 is geen Armstrong nummer, want 10 != 1^2 + 0^2 = 1
153 is een Armstrong nummer, want: 153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153
154 is geen Armstrong nummer, want: 154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190
Schrijf een programma dat aan de gebruiker een getal vraagt en vervolgens toont of het ingevoerde getal een Armstrong-nummer is of niet.
Je zou deze oefening kunnen oplossen door het ingevoerde getal als string op te splitsen in individuele char's. Maar ik raad je aan om de "wiskunde" weg te volgen zodat je terdege leert met loops te wiskunde.*
Tip 1: Stel dat je het getal 4560 hebt:
Eerst deel je 4563 door 1000. Dit geeft 4.
We trekken 4x1000 van 4563 af. Dit geeft 563.
Deel 563 door 100. Dit geeft 5.
We trekken 5x100 van 563 af. Dit geeft 63.
Deel 63 door 10. Dit geeft 6.
We trekken 6 x 10 van 63 af. Dit geeft 3
Tip 2: Je kan aan een string vragen hoe groot deze is als volgt:
Je kan dan nu met Math.Pow(10,lengte-1)
berekenen vanaf welke exponent van 10 we moeten beginnen werken.
Maak volgende opdracht van projecteuler.net:
Indien we alle natuurlijke getallen van 0 tot en met 10 oplijsten die een meervoud van 3 of 5 zijn, dan krijgen we de getallen 3,5,6,9 en 10. De som van deze 4 getallen is 33. Maak nu een programma dat de som van alle veelvouden van 3 of 5 weergeeft onder van 0 tot 1000 (dit zou 234168) moeten geven.
Tip: module is je grote held hier. Een getal is een veelvoud van x indien getal%x
0 als resultaat geeft.
Schrijf een programma dat de volgende output geeft , gegeven dat de gebruiker een maximum waarde invoert , dus als hij 4 ingeeft dan zal de driehoek maximum 4 breed worden. Gebruik enkel forloops!
Schrijf een programma dat de volgende output geeft (zie ook WhileDoordenker van vorige labo), gegeven dat de gebruiker een maximum waarde invoert die opgeeft uit hoeveel lijnen de boom bestaat. Maak enkel gebruik van for-loops.
een taak herhaaldelijk uitvoeren met een lus
Maak een 'boekhoud-programma': de gebruiker kan continu positieve en negatieve getallen invoeren. Dit programma houdt volgende zaken bij:
de totale balans
de som van de positieve getallen
de som van de negatieve getallen
het gemiddelde
Voor de eerste drie zaken kom je toe met een variabele. Voor de laatste is dit lastiger, omdat elk nieuw getal een kleiner effect heeft om het gemiddelde dan het vorige. Je houdt beter een teller bij met het aantal ingevoerde getallen. Dan is het gemiddelde de totale balans gedeeld door het aantal ingevoerde getallen.
console applicatie
(Dit programma kan blijven verder lopen zo lang je wil.)
een taak herhaaldelijk uitvoeren met een lus
Maak een applicatie waarbij de gebruiker steen-schaar-papier met de computer kan spelen. De gebruiker kiest telkens steen, schaar of papier en drukt op enter. Vervolgens kiest de computer willekeurig steen, schaar of papier.
Vervolgens krijgt de winnaar 1 punt:
Steen wint van schaar, verliest van papier
Papier wint van steen, verliest van schaar
Schaar wint van papier, verliest van steen
Indien beide hetzelfde hebben wint niemand een punt.
De eerste (pc of gebruiker) die 10 punten haalt wint.
Genereer een willekeurig getal tussen 1 en 3 om de computer te laten kiezen.
Teken een flowchart!
console applicatie
(Helemaal op het einde)
of
Herhalingen (loops) creëer je wanneer bepaalde code een aantal keer moet herhaald worden. Hoe vaak de herhaling moet duren is afhankelijk van de conditie die je hebt bepaald.
In het vorige hoofdstuk leerden we hoe we met behulp van beslissingen onze code konden branchen, aftakken zodat andere code werd uitgevoerd afhankelijk van de staat van bepaalde variabelen of invoer van de gebruiker. Wat we nog niet konden was terug naar boven vertakken. Soms willen we dat een heel stuk code 2 of meerdere keren moet uitgevoerd worden tot aan een bepaalde conditie wordt voldaan. "Voer volgende code uit tot dat de gebruiker 666 invoert."
Door herhalende code met loops te schrijven maken we onze code korter en bijgevolg ook minder foutgevoelig en beter onderhoudbaar.
Van zodra je dezelfde lijn(en) code onder elkaar in je code ziet staan (door bijvoorbeeld te copy pasten) is de kans zéér groot dat je dit korter kunt schrijven met loops.
Er zijn verschillende soorten loops:
Definite of counted loop: een loop waar het aantal iteraties vooraf van gekend is. (bv. alle getallen van 0 tot en met 100 tonen)
Indefinite of sentinel loop: een loop waarvan op voorhand niet kan gezegd worden hoe vaak deze zal uitgevoerd worden. Input van de gebruiker of een interne test zal bepalen wanneer de loop stopt (bv. "Voer getallen in, voer -1 in om te stoppen" of "Bereken de grootste gemene deler")
Oneindige loop: een loop die nooit stopt. Soms gewenst (bv. de game loop) of, vaker, een bug.
Er zijn 3 manieren om zogenaamde loops te maken in C#:
while
: zal 0 of meerdere keren uitgevoerd worden
do while
: zal minimaal 1 keer uitgevoerd worden
for
: een alternatieve iets compactere manier om loops te beschrijven
Voorts zullen we ook een speciale loop variant zien in het volgende semester wanneer we arrays en objecten leren kennen:
Het moet hier alvast even uit m'n systeem. goto
is weliswaar een officieel C# keyword, toch zal je het in deze cursus nooit zien terugkomen in code. Je kan alle problemen in je algoritmes oplossen zonder ooit goto
nodig te hebben. Voel je toch de drang: don't! Simpelweg, don't. Het is het niet waard. Geloof me. NEVER USE GOTO.
Door een flowchart op te stellen is het vaak veel eenvoudiger om een programma ofwel te analyseren (van code naar idee) ofwel om een programma te schrijven (van idee naar code).
Een flowchart (letterlijk: stroomkaart) of stroomdiagram is een schematische beschrijving van een proces. Met een flowchart kan je vaak ingewikkelde stukken code visualiseren waardoor het geheel plots niet meer zo ingewikkeld is.
Een flowchart bestaat uit een aantal elementen:
Pijl: een pijl geeft aan naar welk volgende blok wordt gegaan. Indien boven de pijl een bepaalde waarde staat wil dit zeggen dat deze pijl enkel wordt gevolgd als de uitkomst van het vorige blok de getoonde waarde geeft.
Start en einde: aangegeven met een cirkel met daarin de woorden "Start" of "Einde"
Verwerk-stap: een statement zoals "Voeg 1 toe aan X" wordt in een rechthoek geplaatst. Alle code die geen invoer nodig heeft zet je in een rechthoek.
Input/output: Een parallellogram gebruik je om in-of uitvoer van de gebruiker of scherm te tonen. Bv "Verkrijg X van gebruiker" of "Toon volgende zin op het scherm".
Condities en beslissingen: Een ruit wordt gebruikt wanneer een beslissing moet genomen worden. De condities van if en while-loops zet je dus in een ruit. De pijlen die eruit volgen geven aan welke pijl moet gevolgd worden gegeven een bepaalde waarde van de conditie.
We tonen nu kort de verschillende program flow elementen en hoe ze in een flowchart voorkomen.
Door de eerder beschreven elementen nu samen te voegen kunnen we een programma als een flowchart voorstellen. Stel dat we een programma "Faculteit" maken. Hierin is het de bedoeling om de faculteit van een gegeven getal N dat door de gebruiker wordt ingevoerd, te berekenen (bijvoorbeeld N=5 geeft dan 5! = 5x4x3x2x1 = 120
). De finale flowchart ziet er als volgt uit:
Zoals verteld kunnen we een flowchart in beide richtingen gebruiken. We hebben de flowchart hiervoor gemaakt, gebaseerd op onze oplossing van het vorige labo. Maar stel dat je deze flowchart krijgt, dan kan je dus ook deze chart rechtstreeks omzetten in C#.
Via de website en app "Code2flow" (site) kan je heel eenvoudig een flowchart genereren van pseudocode.
Wanneer we 1 of meerdere loops in een andere loop plaatsen dan spreken we over geneste loops. Geneste loops komen vaak voor, maar zijn wel een ras apart wanneer je deze zaken wilt debuggen en correct schrijven.
We spreken steeds over de outer loop als de omhullende of "grootste" loop. Waarbij de binnenste loops de inner loop(s) zijn.
Volgende code toont bijvoorbeeld 2 loops die genest werden:
De uitvoer hiervan zal als volgt zijn:
Begrijp je hoe we aan deze uitvoer komen? (tip: analyseer de inner en outer loop apart)
Om te tellen hoe vaak de 'inner' code zal uitgevoerd worden dien je te weten hoe vaak iedere loop afzonderlijk wordt uitgevoerd. Vervolgens vermenenigvuldig je al deze getallen met elkaar.
Een voorbeeld: Hoe vaak zal het woord Hallo
op het scherm verschijnen bij volgende code?
De outer loop zal 10 maal uitgevoerd worden (i zal de waarden 0 tot en met 9 krijgen). De inner loop zal 5 maal (j zal de waarden 0 tot en met 4 krijgen) uitgevoerd worden. In totaal zal dus 50 maal Hallo
op het scherm verschijnen (5x10).
Let er op dat break
je enkel uit de huidge loop zal halen. Indien je dit dus gebruik in de inner loop dan zal de outer loop nog steeds voortgaan. Nog een reden om zéér voorzichtig om te gaan in het gebruik van break
.
De syntax van een while loop is eenvoudig:
Waarbij, net als bij een if
statement, de conditie uitgedrukt wordt als een booleaanse expressie met 1 of meerdere relationele operatoren.
Zolang de conditie true
is zal de code binnen de accolades uitgevoerd worden. Indien dus de conditie reeds vanaf het begin false
is dan zal de code binnen de while
-loop niet worden uitgevoerd.
Telkens wanneer het programma aan het einde van het while
codeblock komt springt het terug naar de conditie bovenaan en zal de test wederom uitvoeren. Is deze weer true
dan wordt de code weer uitgevoerd. Van zodra de test false
is zal de code voorbij het codeblock springen en na het while
codeblok doorgaan.
Het diagramma is duidelijk:
Een voorbeeld van een eenvoudige while loop:
Zolang myCount
kleiner is dan 100 (myCount < 100
) zal myCount met 1 verhoogd worden en zal de huidige waarde van myCount getoond worden. We krijgen met dit programma dus alle getallen van 1 tot en met 100 op het scherm onder elkaar te zien.
Daar de test gebeurt aan het begin van de loop wil dit zeggen dat het getal 100 nog wel getoond zal worden. Begrijp je waarom? Test dit zelf!
In tegenstelling tot een while loop, zal een do-while loop sowieso minstens 1 keer uitgevoerd worden. Ongeacht de opgegeven conditie zal de do-while loop zijn code 1 keer uitvoeren. We herhalen deze zin uitdrukkelijk 2x zodat het verschil tussen beide type loops duidelijk blijft.
Vergelijk volgende diagramma van de do while
:
met die hierboven van de while
.
De syntax van een do-while is eveneens verraderlijk eenvoudig:
Merk op dat achteraan de conditie een puntkomma na het ronde haakje staat. Dit is een véél voorkomende fout. Bij een while is dit niet! Daar de test van een do-while achteraan de code van de loop gebeurt is het logisch dat een do-while dus minstens 1 keer wordt uitgevoerd. Het volgende eenvoudige aftelprogramma toont de werking van de do-while loop.
Begrijp je wat dit programma zal doen?
Uiteraard mag de conditie waaraan een loop moet voldoen complexer zijn door middel van de relationele operatoren.
Volgende while
bijvoorbeeld zal uitgevoerd worden zolang teller
groter is dan 5 en de variabele naam
van het type string
niet gelijk is aan "tim":
Indien de loop-conditie nooit false
wordt dan heb je een oneindige loop gemaakt. Soms is dit gewenst gedrag (bijvoorbeeld bij de gameloop) soms is dit een bug en zal je dit moeten debuggen.
Volgende twee voorbeelden tonen dit:
Een bewust oneindige loop:
Een bug die een oneindige loop veroorzaakt:
Probeer er altijd zeker van te zijn dat de variabele(n) die je gebruikt in je test-conditie ook in de loop aangepast worden. Als deze in de loop constant blijft dan zal ook de test-conditie dezelfde blijven en heb je dus een oneindige loop gemaakt.
Let er op dat de scope van variabelen bij loops zeer belangrijk is. Indien je een variabelen binnen de loop definieert dan zal deze steeds terug "gereset" worden wanneer de volgende cyclus van de loop start. Volgende code toont bijvoorbeeld foutief hoe je de som van de eerste 10 getallen (1+2+3+...+10) zou maken:
De correcte manier om dit op te lossen is te beseffen dat de variabele som enkel binnen de accolades van de while-loop gekend is. Op de koop toe wordt deze steeds terug op 0 gezet en er kan dus geen som van alle teller-waarden bijgehouden worden:
Dankzij loops kunnen we nu ook eenvoudiger omgaan met foutieve input van de gebruiker. Stel dat we volgende vraag hebben:
Met een loop kunnen we nu deze vragen blijven stellen tot de gebruiker een geldige input geeft:
Zolang (while) de gebruiker niet "a"
OF "b"
OF "c"
invoert zal de loop zichzelf blijven herhalen.
Merk op dat we de variabele string input
VOOR de do while
moeten aanmaken. Zouden we die IN de loop pas aanmaken dan zou de variabele niet als test kunnen gebruikt worden aan het einde van de loop.
Je ziet dat het stuk
} while(input...);
achteraan buiten de accolades van de loop ligt en dus een andere scope heeft).
.
Merk op dat bij if en if-else de flow niet naar een eerder punt in de code gaat. Dit is dus de manier om een while/do while te herkennen: er wordt naar een eerder punt in de code gegaan, een punt waar we reeds geweest waren