V.
Arrays
A. Wat zijn arrays? Een array is een verzameling van variabelen. Ze hebben allen dezelfde naam en hetzelfde type. Men kan ze van elkaar onderscheiden door een volgnummer, index genoemd. Enkele voorbeeldjes maken dit duidelijk.
1)
Een array declareren
Stel dat u 15 tellers nodig heeft. Dat kunt u een array van tellers als volgt declareren: Dim Tellers(14) As Integer
' 15 elementen.
Tussen haakjes vermeldt u de grootte van het array. Maar vermits de laagste waarde steeds 0 is, heeft u dus één element meer.(1) Als u zoals hier 14 opgeeft voor de grootte, heb de beschikking over de variabelen Tellers(0), Teller(1),Tellers(2),…. Tot tellers(14). Dat zijn er dus 15! Elk van deze kunt u gebruiken als een integer getal. Andere voorbeelden: Dim Teksten(4) as String Dim Getallen(7) as Double
2)
' 5 elementen van het type string. ' 8 elementen van het type double.
Arrays gebruiken in het programma
In het programma kunt u deze tellers gebruiken door de index aan te geven. De index mag ook een variabele zijn van het type Integer of Long. Voorbeelden: Tellers(2) = 17 Teksten(3) = "En dit is het vierde!" Print Getallen(5) Of met een Integer variabele als index i = 3 Tellers(i)= 45 'Zet Tellers(3) = 45 Ø Oefening: Maak een nieuw project aan met als naam bijvoorbeeld OefArr1. Zet het weer in een aparte map. Ø Declareer de volgende arrays in het gedeelte (General) (Declarations) Option Explicit 'Declaraties van de arrays Dim tellers(9) As Integer Dim getallen(6) As Double 1
'10 gehele getallen ' 7 double getallen
Met de instructie Option Base kun je de laagste waarde ook op één zetten, i.p.v. nul.
Visual Basic
door ir. C.Daniels
V-1
Dim teksten(3) As String Dim bool(4) As Boolean
' 4 strings ' 5 boolean
Ø Plaats de onderstaande code in de events Form_Click en Form_Load: Private Sub Form_Click() Dim i As Integer ' teller voor de For-next 'integer array For i = 0 To 9 tellers(i) = 10 * i Print tellers(i); Next Print 'double array For i = 0 To 6 getallen(i) = 7.4589 * i Print getallen(i); Next Print 'string array teksten(0) = "Eerste" teksten(1) = "Tweede" teksten(2) = "Derde" teksten(3) = "En dit is het vierde!" Print teksten(0), teksten(1), teksten(2), teksten(3) 'boolean array For i = 0 To 4 bool(i) = i Print bool(i), Next End Sub Private Sub Form_Load() Form1.Caption = "Arrays" AutoRedraw = True End Sub Ø Laat het programma runnen, klik op het formulier en bekijk het resultaat.
Visual Basic
door ir. C.Daniels
V-2
Uit dit voorbeeld ziet u ook dat het type Boolean eigenlijk hetzelfde als een Integer is. Alleen de waarde 0 is False, alle andere waarden worden beschouwd als True.
Tip: Experimenteer zoveel mogelijk! Kent u bijvoorbeeld niet de betekenis van de losse Print-instructie in bovenstaand voorbeeld, of van de komma achteraan in de Print-instructie, laat die dan weg, en bekijk het resultaat! Of zoek het op in de Help van VB.
Ø Oefening: sorteren met bubblesort Getallen sorteren is en blijft een moeilijke klus voor computers. Er zijn talloze methoden uitgewerkt, en dikke boeken over geschreven. Een van de snelste methodes is de quicksort, maar is vrij ingewikkeld om te programmeren. De bubblesort is veel trager, maar wel vrij makkelijk te programmeren. We zullen eerst deze methode even uitleggen.
3)
Sorteren met bubblesort
Hoe werkt bubblesort? Om dit te illustreren het volgende voorbeeld. Stel dat we getallen 7 2 8 1 3 in gesorteerde volgorde van laag naar hoog willen verkrijgen. Daarom gaan we vooraan beginnen met telkens twee opeenvolgende getallen te vergelijken, staan ze verkeerd worden ze omgewisseld: 7
2
8
1
3
Vergelijk 7 en 2, staan verkeerd dus omwisselen
2
7
8
1
3
Vergelijk 7 en 8, staan goed, dus niets doen
2
7
8
1
3
Vergelijk 8 en 1,staan verkeerd dus omwisselen
2
7
1
8
3
Vergelijk 8 en 3, staan verkeerd dus omwisselen
2
7
1
3
8
Na één cyclus staat het grootste getal nu achteraan
We herhalen deze cyclus nog eens, het laatste getal moeten we niet meer beschouwen, dat staat al juist. 2
7
1
3
8
Vergelijk 2 en 7, staan goed
2
7
1
3
8
Vergelijk 7 en 1, staan verkeerd dus omwisselen
2
1
7
3
8
Vergelijk 7 en 3, staan verkeerd dus omwisselen
2
1
3
7
8
Het laatste getal stond reeds juist
Visual Basic
door ir. C.Daniels
V-3
Ook het voorlaatste getal, de zeven, staat nu juist. We vervolgen deze werkwijze tot alle getallen juist staan. Als alle getallen juist staan, moeten we tijdens een ganse cyclus geen omwisselingen meer uitvoeren. Hieronder staat de volgende cyclus 2
1
3
7
8
1
2
3
7
8
Alleen de 2 en de 1 worden nog omgewisseld. Met de andere cijfers moet niets meer gebeuren. Als we nu nog een cyclus zouden uitvoeren, wordt er niets meer omgewisseld, dus is de sortering voltooit. Het aantal omwisselingen dat we nodig hebben, hangt af van de originele getallen. De reeks 1 2 4 7 8 staat reeds juist, dus geen omwisselingen nodig, maar om de reeks 8 7 4 2 1 juist te krijgen zijn er heel wat nodig! Laten we nu een programma schrijven, dat een eenvoudige sortering zoals hierboven uitvoert. Ø Maak een nieuw project aan met de naam Sorteren1. Geef het een weer eigen map met dezelfde naam. Ø Plaats op het formulier twee knoppen, en geef deze objecten de volgende eigenschappen Object Formulier
Eigenschappen Name: Form1 Caption: Sorteren Font: Ms Sans Serif 10p Vet Heigth:6800 twips StartUpPosition:1-CenterOwner Width: 3000 twips
Button
Name:cmdNieuw Caption:Nieuw
Button
Name:cmdSorteren Caption:Sorteren
Het formulier Sorteren in de ontwerpfase
Visual Basic
door ir. C.Daniels
V-4
Ø Plaats in de declaratie-sectie de volgende code: Option Explicit Const Aantal = 7 'Aantal te sorteren getallen Dim getallen(Aantal) As Integer 'Array met getallen Ø Plaats in het event Form_Load de volgende code: Private Sub Form_Load() AutoRedraw = True cmdSorteren.Enabled = False 'Knop sorteren uitzetten Randomize End Sub Ø Plaats in het event cmdNieuw_Click de volgende code: Private Sub cmdNieuw_Click() Dim i As Integer ' hulpvariabele Cls ' Maak dit formulier schoon 'genereer de random getallen For i = 0 To Aantal - 1 Getallen(i) = Int(100 * Rnd) + 1 'random getal 1 tot 10 Print getallen(i); ' en druk ze af Next ' en druk ze af in het formulier Print: Print 'lege lijn cmdSorteren.Enabled = True ' zet de knop sorteren aan End Sub Ø Plaats in het event cmdSorteren_Click de volgende code: Private Sub cmdSorteren_Click() Dim i, j As Integer ' hulpvariabelen Dim Gesorteerd As Boolean ' gesorteerd? ja of nee Dim dummy As Integer 'hulpvariabele Gesorteerd = False
'Begin met gesorteerd onwaar te zetten
'Hier begint de cyclus tot als Gesorteerd waar is Do While Not (Gesorteerd) Gesorteerd = True ' Eerst aan zetten For i = 0 To Aantal - 2' Het voorlaatste heeft als index Aantal-2 If getallen(i) > getallen(i + 1) Then 'Vergelijk… dummy = getallen(i) ' Omwisselen getallen(i) = getallen(i + 1) getallen(i + 1) = dummy For j = 0 To Aantal - 1 'en afdrukken Print getallen(j); Next Print
Visual Basic
door ir. C.Daniels
V-5
Gesorteerd = False 'nog niet goed End If Next i ' streepje na één cyclus Print "----------------------------------" Loop 'herbegin de cyclus cmdSorteren.Enabled = False 'Zet de knop Sorteren uit End Sub
Ons programma is af! Test het uit met verschillende reeksen. Hoeveel maal moet u gemiddeld wisselen bij 10 testrondes?
Het programma Sorteren1 bij het opstarten.
Het programma Sorteren1 nadat op de knop Nieuw werd geklikt.
En na het klikken op de knop Sorteren. Tussen elke cyclus hebben we een lijntje getrokken. De laatste cyclus is leeg.
Ø Opgave: Verander de code in het programma zodat er van hoog naar laag wordt gesorteerd. Ø Pas het programma aan in de For-lus zodat het element achteraan, wat reeds gesorteerd is, niet meer in de lus wordt opgenomen. Kies een veranderlijke Laatste. Zet die eerst gelijk aan Aantal-2, en bij elke lus maakt u die één kleiner Ø Wat gebeurt er als u in de For-lus Aantal-2 vervangt door Aantal–1? Leg uit…
Visual Basic
door ir. C.Daniels
V-6
Als we grotere hoeveelheden gegevens gaan sorteren, is dat nog moeilijk te volgen. Grafisch kunnen we wat meer doen. Daarom hebben we de Line-instructie nodig. Hiermee kunt u lijnen, open rechthoeken, en opgevulde rechthoeken tekenen.
B. De Line-instructie Tekent een lijn, rechtboek, of opgevulde rechthoek (blok) in een formulier of PictureBox. Deze ziet er als volgt uit Line (x1,y1)-(x2,y2), kleur, optie
Uitleg over de parameters: - x1,y1 : x en y-coordinaat van het startpunt van de lijn of de linkerbovenhoek van de rechthoek - x2,y2 : x en y-coordinaat van het eindpunt van de lijn of de rechterbenedenhoek van de rechthoek - kleur: de kleur van de rand of van de opvulling (optioneel) - optie: B open rechthoek (van het engels: block) of BF opgevulde rechthoek (van het engels: block filled) (optioneel)
Laten we dit even toepassen in een eenvoudig voorbeeld Lijnen1. We kunnen hiermee willekeurige lijnen en rechthoeken laten tekenen.
Het project Lijnen1 in actie. Ø Oefening: Lijnen1 Maak een nieuw project aan met als naam Lijnen1. Plaats het in een aparte map Lijnen1. Noem het project Lijnen1.vbp, en het formulier Lijnen1.frm.
Visual Basic
door ir. C.Daniels
V-7
Ø Plaats de volgende objecten op het formulier:
cmdLijnen
cmdRechthoeken
cmdBlokken
PictureBox
Ø Geef de objecten de volgende eigenschappen:
Object Form
Button Button Button PictureBox
Eigenschap Name:Form1 Caption: Lijnen1 Heigth: 3600 twips Width:4800 twips Name: cmdLijnen Caption:Lijnen Name:cmdRechthoeken Caption: Rechthoeken Name:cmdBlokken Caption:Blokken Name: PictureBox1
Ø Plaats de volgende code in het event cmdBlokken_Click Private Sub cmdBlokken_Click() Dim Breedte, Hoogte, x1, y1, x2, y2, i As Integer ' Bepaal de breedte en de hoogte van de PictureBox Breedte = Picture1.ScaleWidth Hoogte = Picture1.ScaleHeight 'teken 10 willekeurige blokken Visual Basic
door ir. C.Daniels
V-8
For i = 1 To 10 x1 = Int(Breedte * Rnd) y1 = Int(Hoogte * Rnd) x2 = Int(Breedte * Rnd) y2 = Int(Hoogte * Rnd) Picture1.Line (x1, y1)-(x2, y2), QBColor(Int(Rnd * 16)), BF Next End Sub Ø Plaats de volgende code in het event cmdLijnen_Click Private Sub cmdLijnen_Click() Dim Breedte, Hoogte, x1, y1, x2, y2, i As Integer ' Bepaal de breedte en de hoogte van de PictureBox Breedte = Picture1.ScaleWidth Hoogte = Picture1.ScaleHeight 'teken 10 willekeurige lijnen For i = 1 To 10 x1 = Int(Breedte * Rnd) y1 = Int(Hoogte * Rnd) x2 = Int(Breedte * Rnd) y2 = Int(Hoogte * Rnd) Picture1.Line (x1, y1)-(x2, y2), QBColor(Int(Rnd * 16)) Next End Sub Ø Plaats de volgende code in het event cmdBlokken_Click Private Sub cmdRechthoek_Click() Dim Breedte, Hoogte, x1, y1, x2, y2, i As Integer ' Bepaal de breedte en de hoogte van de PictureBox Breedte = Picture1.ScaleWidth Hoogte = Picture1.ScaleHeight 'teken 10 willekeurige rechthoeken For i = 1 To 10 x1 = Int(Breedte * Rnd) y1 = Int(Hoogte * Rnd) x2 = Int(Breedte * Rnd) y2 = Int(Hoogte * Rnd) Picture1.Line (x1, y1)-(x2, y2), QBColor(Int(Rnd * 16)), B Next End Sub Ø Plaats de volgende code in het event Form_Load Private Sub Form_Load() AutoRedraw = True End Sub
Visual Basic
door ir. C.Daniels
V-9
Ø Het programma is klaar! Test het uit! Uitleg: ScaleWidth: geeft de breedte van de PictureBox in twips ScaleHeigth: geeft de hoogte van de PictureBox in twips Twip: Een twip is 1/20 van een punt van een printer (567 twips is gelijk aan één centimeter). Let er op dat de y-as haar nulpunt linksboven heeft, in grafische afbeeldingen:
QBColor(Nummer): kleureninstructie afkomstig uit een vroegere versie van basic: Quick Basic. Maar kan nog steeds gebruikt worden. Nummer kan de volgende waarden hebben Nummer
Kleur
Nummer
Kleur
0
Zwart
8
Grijs
1
Blauw
9
Licht Blauw
2
Groen
10
Licht Groen
3
Cyaan
11
Licht Cyaan
4
Rood
12
Licht Rood
5
Magenta
13
Licht Magenta
6
Geel
14
Licht Geel
7
Wit
15
Helder Wit
Met de instructie QBColor(Int(Rnd * 16)) reeks: 0 <= Rnd 0 <= Rnd*16 0 <= Int(Rnd*16)
Visual Basic
kiezen we dus een willekeurige kleur uit de <= 0,99999…. <=15,9999…. <=15
door ir. C.Daniels
V-10
Ø Oefening: Sorteren2 In deze oefening gaan we het sorteerproces grafisch voorstellen. Elk getal wordt voorgesteld door een horizontale lijn. De lengte komt overeen met de grootte van het getal. Het project ziet er bij uitvoering zo uit:
Na het opstarten
Na klikken op Nieuw
Midden in het sorteerproces
Gesorteerd
Ø Maak een nieuw project Sorteren2 aan in een nieuw map Sorteren2. Voeg onderstaande objecten aan het project toe: cmdNieuw
cmdSorteren
cmdSluiten
PictureBox
Visual Basic
door ir. C.Daniels
V-11
Ø Geef de objecten de volgende eigenschappen: Object Form
Eigenschappen Name:Form1 Caption:Bubble sort Borderstyle: 1- Fixed Single Heigth: 4050 Width: 4700
Button
Name:cmdNieuw Caption:Nieuw
Button
Name:cmdSorteren Caption: Sorteren
Button
Name:cmdSluiten Caption: Sluiten
PictureBox
Name: Picture1 Heigth: 200 ScaleMode: 3 – Pixel Width: 305
Ø Hieronder volgt de volledige code. Zet ze in de juiste events. Option Explicit Const Aantal = 200 'Aantal getallen Dim getallen(Aantal) As Integer
Private Sub cmdNieuw_Click() Dim i As Integer Dim Breedte As Integer Picture1.Cls 'Leeg maken Picture1.ForeColor = vbRed 'Kleur van de lijnen Breedte = Picture1.Width 'Maak de langste lijn zo breed als het beeld ' Getallen genereren For i = 0 To Aantal - 1 getallen(i) = Int(Breedte * Rnd) Picture1.Line (0, i)-(getallen(i), i) Next i cmdSorteren.Enabled = True 'Zet sorteerknop aan End Sub Private Sub cmdSluiten_Click() End End Sub Private Sub cmdSorteren_Click() Dim gesorteerd As Boolean Dim i, intHulp, Laatste As Integer
Visual Basic
door ir. C.Daniels
V-12
gesorteerd = False Laatste = Aantal - 2 'En nu sorteren... While Not (gesorteerd) gesorteerd = True 'Begin een cyclus For i = 0 To Laatste If getallen(i) > getallen(i + 1) Then gesorteerd = False ' een wisseling! dus sorteren niet gedaan 'beide lijnen wissen (= tekenen met achtergrondkleur) Picture1.ForeColor = vbWhite Picture1.Line (0, i)-(getallen(i), i) Picture1.Line (0, i + 1)-(getallen(i + 1), i + 1) 'verwisselen intHulp = getallen(i) getallen(i) = getallen(i + 1) getallen(i + 1) = intHulp 'lijnen tekenen in rood Picture1.ForeColor = vbRed Picture1.Line (0, i)-(getallen(i), i) Picture1.Line (0, i + 1)-(getallen(i + 1), i + 1) End If Next i Laatste = Laatste – 1 'elke cyclus waarde Laatste 1 verminderen Wend cmdSorteren.Enabled = False 'Zet sorteerknop uit End Sub Private Sub Form_Load() AutoRedraw = True Randomize 'Voor random-getallen cmdSorteren.Enabled = False 'Zet sorteerknop uit End Sub
Ø Oefening: Quicksort-methode bijvoegen Om de snelheid van sorteren te kunnen vergelijken gaan we ook sorteren volgens de veel snellere Quicksort-methode. Sla het project en het formulier eerst op in een nieuwe map met naam Quicksort, zodat de oude versie ongemoeid blijft. Ø Voeg een nieuwe knop toe met name = cmdQuickSort en Caption = Quicksort
Visual Basic
door ir. C.Daniels
V-13
Ø Voeg de volgende code toe aan het programma, bijvoorbeeld onder de sectie (General) (Deckarations). Achteraan vindt u een korte beschrijving van de werking. Option Explicit Const Aantal = 200 'Aantal getallen Dim getallen(Aantal) As Integer Public Sub vbQuickSort(vArray As Variant, l As Integer, r As Integer) Dim Dim Dim Dim Dim
i j X Y k
As As As As As
Integer Integer Integer Integer Long 'voor de vertraging
i = l j = r X = vArray((l + r) / 2) While (i <= j) While (vArray(i) < X And i < r) i = i + 1 Wend While (X < vArray(j) And j > l) j = j - 1 Wend If (i <= j) Then ' VERTRAGING 'For k = 0 To 500000 'Next 'lijnen wissen Picture1.ForeColor = vbWhite Picture1.Line (0, i)-(vArray(i), i) Picture1.Line (0, i + 1)-(vArray(i + 1), i + 1) Y = vArray(i) vArray(i) = vArray(j) vArray(j) = Y 'lijnen tekenen Picture1.ForeColor = vbRed Picture1.Line (0, i)-(vArray(i), i) Picture1.Line (0, i + 1)-(vArray(i + 1), i + 1) i = i + 1 j = j - 1 End If Wend
Visual Basic
door ir. C.Daniels
V-14
If (l < j) Then vbQuickSort vArray, l, j If (i < r) Then vbQuickSort vArray, i, r End Sub
Ø Voeg de volgende code toe aan het event cmdQuicksort_Click Private Sub cmdQuicksort_Click() Dim i As Integer 'roep de quicksort-methode aan vbQuickSort getallen, 0, Aantal - 1 'toon de gesorteerde reeks
Picture1.Cls For i = 0 To Aantal - 1 Picture1.Line (0, i)-(getallen(i), i) Next i End Sub Ø Zorg er ook voor dat de knop cmdQuicksort pas toegankelijk wordt als er op Nieuw is geklikt (eigenschap Enabled aan- en afzetten) Test de sorteermethode uit. Als een en ander te snel gaat, kunt u de vertraging inschakelen door de commentaar weg te laten in de code: (hoe hoger het getal, hoe langzamer) ' VERTRAGING For k = 0 To 500000 Next
Uitleg: De Quicksort is een van de snelste methodes om objecten te sorteren. De werking is kort gezegd als volgt. Men neemt ergens een middelste element uit de reeks. Dan worden de getallen aan weerszijden van dit element omgewisseld, alle getallen kleiner dan dit element komen naar voren, alle getallen groter dan dit element gaan naar de achterste helft. Als dit gebeurt is, zijn alle getallen in het gedeelte vooraan kleiner als dit middelste element, alle getallen achteraan groter dan dit element. Maar ze staan nog niet in de juiste volgorde. Dan wordt de quicksort-methode opnieuw los gelaten op het voorste deel, en daarna op het achterste deel. Telkens wordt elk gedeelte dus ongeveer in de helft gedeeld, totdat alle getallen zijn gesorteerd. We zien hier een voorbeeld van een procedure Public Sub vbQuickSort(vArray As Variant, l As Integer, r As Integer) … End Sub
Dit is een sub-functie die niet samengaat met een event, maar die aangeroepen wordt vanuit een ander gedeelte van het programma. Hoe dit werkt, zien we in het volgend hoofdstuk. Private Sub cmdQuicksort_Click() Dim i As Integer 'roep de quicksort-methode aan vbQuickSort getallen, 0, 199 … End Sub Visual Basic
door ir. C.Daniels
V-15