Visual Basic 2012 Voorbeelden
   

visual basic 2012 broncode voorbeelden

Blijf op de hoogte van de recente aanpassingen op vbvoorbeelden!

Microsoft Visual Studio 2012Microsoft Developers Network - Visual BasicMicrosoft .NET Framework

7.8. Aantal Elementen van een Dimensie Veranderen

Print Email Deel op Twitter Deel op Facebook

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.

7.8.1. ReDim Statement

Het kan voorkomen dat men toch reeds een arrayvariabele wenst te declareren, maar men nog niet weet hoe groot de array dient te zijn.  En men bijgevolg dus niet weet welke waarden als upperbound op te geven.

Een aantal oplossingen bieden zich hierbij aan :
- toch wachten met het declareren van de arrayvariabele (dit is niet altijd mogelijk wegens "scope" redenen (later hierover meer))
- de array zo groot maken dat je later zeker voldoende elementen hebt (dit heeft als nadeel geheugenverlies indien niet alle elementen zullen worden gebruikt)

De beste oplossing is hier bij het declareren van de arrayvariabele nog geen upperbounds op te geven.  Hiermee bekom je nog altijd (de declaratie van) een arrayvariabele, maar deze variabele wijst nog niet naar een arrayinstantie.

Op een later moment kan dan een grootte opgeven voor deze array.
Visual Basic 2012 Broncode - Codevoorbeeld 130
Module Example1
    Sub Main()
        Dim row() As Integer
        Dim matrix(,) As Integer        ' (1)
        '
        'row(5) = 5                     ' (2) impossible, no array instance
        'matrix(5, 5) = 5               ' (3) impossible, no array instance
        '
        ReDim row(9)                    ' (4)
        ReDim matrix(9, 9)              ' (5)
        '
        row(5) = 5
        matrix(5, 5) = 5
        '
        Console.WriteLine(row(5))
        Console.WriteLine(matrix(5, 5))
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
5
5
Zoals je merkt (regel (1)) moet je bij het declareren van een arrayvariabele die moet kunnen wijzen naar een twee dimensional tabel wel reeds in de dimensielijst aangeven wat het aantal dimensies is.  Door hier dus in die dimensielijst een komma te plaatsen geef je als het ware aan dat je voor 2 dimensies geen upperbound opgeeft, en dat de variabele matrix dus zal moeten kunnen verwijzen naar een twee dimensional tabel.

In bovenstaand voorbeeld zullen regels (2) en (3) niet functioneren (ze veroorzaken een uitvoeringsfout) omdat je dus verwijst naar een element van  de array die nog niet bestaat, tenslotte bestaat nog enkel maar de arrayvariabele en niet de array zelf.

Het opgeven van een grootte voor een tabel (dimensioneren van de tabel) kan door een ReDim statement te gebruiken, en wel in volgende vorm :
ReDim identifier(first-upperbound, second-upperbound, ...)
Het opgeven van een grootte gebeurt dus door tussen de haakjes upperbounds te definiëren.

Na het dimensioneren van de tabel, kan men nu wel tabelelementen (weliswaar op een bestaande index) aanspreken.

De declaratie :
Dim matrix(,) As Integer
Zou ook op volgende wijze kunnen gedefinieerd worden :
Dim matrix As Integer(,)
De haakjes bij een declaratie van een arrayvariabele zonder dimensionering van die array mogen ook na het datatype staan.  Je bekomt zo steeds hetzelfde resultaat : een declaratie van die arrayvariabele, zonder dat er een array zelf werd aangemaakt.

Geeft men echter wel een dimensie op bij het declareren van een arrayvariabele dan moet de dimensielijst na de arrayidentifier staan.

Niet alleen tabellen die nog niet gedimensioneerd waren kan je gaan dimensioneren (zoals in vorig voorbeeld), maar ook reeds gedimensioneerde tabellen kan je herdimensioneren (zoals in onderstaand voorbeeld).

In onderstaand voorbeeld wordt een tabel (met 3 rijen en 4 kolommen) geherdimensioneerd naar een tabel met 6 rijen en 10 kolommen.
Visual Basic 2012 Broncode - Codevoorbeeld 131
Module Example2
    Sub Main()
        Dim matrix(2, 3) As Integer
        '
        matrix(1, 1) = 10
        Console.WriteLine(matrix(1, 1))
        '
        ReDim matrix(5, 9)
        Console.WriteLine(matrix(1, 1))                                    ' (1)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
10
0
Merk op (aan de output van regel (1)) dat alle elementen na het herdimensioneren terug de defaultwaarde van het datatype (van de Asclausule uit de declaratie van de array) bevatten.

Bij het (her)dimensioneren van een tabel via het ReDim statement wordt immers een nieuwe tabel in het geheugen aangemaakt.  De tabel die je dan zogezegd herdimensioneert, verwijst dan gewoon naar de nieuwe tabel die is aangemaakt.  De oude tabel (als geen andere arrayvariabelen hiernaar nog verwijzen) zal dan uit het geheugen worden verwijderd.

(Her)dimensioneren via ReDim is een "zware" operatie.  Een volledig nieuwe arrayinstantie moet in het geheugen worden aangemaakt.

Opgelet : bij het (her)dimensioneren via ReDim kan men enkel de upperbounds van de dimensies aanpassen.  Dus enkele het aantal elementen per dimensie kan gewijzigd worden, dit kunnen meer of minder elementen worden.  Het aantal dimensies kan bijvoorbeeld ook niet worden aangepast.

Ook het datatype van de elementen kan niet worden gewijzigd, in een ReDim statement staat tenslotte geen nieuwe As clausule die het nieuwe datatype van de elementen zou kunnen aangeven.

7.8.2. ReDim Preserve

Wenst men toch de oude waarden bij het zogenaamde herdimensioneren te behouden dan kan het keyword Preserve toevoegen aan het ReDim statement ( zoals in regel (1) van onderstaand voorbeeld).

Hierbij wordt dan niet alleen een nieuwe array in het geheugen aangemaakt, met die (in het ReDim statement) opgeven dimensies, maar zullen de oude waarden worden overgenomen in deze nieuwe tabel :
Visual Basic 2012 Broncode - Codevoorbeeld 132
Module Example3
    Sub Main()
        Dim matrix(2, 3) As Integer
        '
        matrix(1, 1) = 10
        Console.WriteLine(matrix(1, 1))
        '
        ReDim Preserve matrix(2, 9)                                        ' (1)
        Console.WriteLine(matrix(1, 1))                                    ' (2)
        '
        ReDim Preserve matrix(5, 9)                                        ' (3)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
10
10
Regel (2) geeft nu toch als output 10, wat ook de oude waarde was van dat element.

Men is echter beperkt bij het gebruiken van het ReDim statement, men kan hier enkel de upperbound van de laatste dimensie aanpassen.  De aantal rijen uit de oorspronkelijke matrix tabel (3 rijen) kan dus bijvoorbeeld niet worden aangepast.  We hebben hier 2-dimensies, dus kan enkel de upperbound van de tweede dimensie worden gewijzigd (enkel het aantal kolommen dus).  Opnieuw kunnen het meer of minder elementen zijn.

Regel (3) zou hier een uitvoeringsfout veroorzaken die aangeeft dat de nieuw gedimensioneerde tabel niet kan gebruikt worden.

ReDim Preserve is een nog "zwaardere" operatie dan een gewone ReDim.  Niet alleen moet een nieuwe arrayinstantie in het geheugen worden aangemaakt, ook moeten de oude waarden worden overgenomen.
Het spreekt voor zich dat men het aantal ReDims en zeker het aantal ReDim Preserves in een algoritme moet proberen te beperken, zeker indien men met grote arrays aan het werken is.

7.8.3. Oefening

Opgave :

Maak een programma om de namen van personeelsleden en de afdelingen waarin ze werken te beheren.

De vereisten zijn dat je slechts 1 meer dimensionale tabel hiervoor gebruikt en dat deze tabel nooit meer elementen bevat dan hoogst-noodzakelijk.
Console Application Output
No Employees.
MENU : <a> Add Employee / <r> Remove Last Employee / <x> Exit : a
Name        : John
Department : Management
Employees Overview :
John (Management)
MENU : <a> Add Employee / <r> Remove Last Employee / <x> Exit : A
Name        : Paul
Department : Marketing
Employees Overview :
John (Management)
Paul (Marketing)
MENU : <a> Add Employee / <r> Remove Last Employee / <x> Exit : b
Employees Overview :
John (Management)
Paul (Marketing)
MENU : <a> Add Employee / <r> Remove Last Employee / <x> Exit : r
Employees Overview :
John (Management)
MENU : <a> Add Employee / <r> Remove Last Employee / <x> Exit : R
No Employees.
MENU : <a> Add Employee / <r> Remove Last Employee / <x> Exit : a
Name        : Jane
Department : Management
Employees Overview :
Jane (Management)
MENU : <a> Add Employee / <r> Remove Last Employee / <x> Exit : X
Oplossing :
Visual Basic 2012 Broncode - Codevoorbeeld 133
Module Exercise1Solution
    Sub Main()
        Dim menu As Char
        Dim employees As String(,)
        Dim count As Integer
        Dim index As Integer
        Do Until menu = "x"c OrElse menu = "X"c
            If count > 0 Then
                Console.WriteLine("Employees Overview :")
                For index = 0 To count - 1
                    Console.WriteLine(employees(0, index) & _
                                      " (" & employees(1, index) & ")")
                Next
            Else
                Console.WriteLine("No Employees.")
            End If
            Console.Write("MENU : <a> Add Employee / " & _
                          "<r> Remove Last Employee / " & _
                          "<x> Exit : ")
            menu = Console.ReadLine()
            Select Case menu
                Case "a"c, "A"c
                    ReDim Preserve employees(1, count)
                    Console.Write("Name        : ")
                    employees(0, count) = Console.ReadLine()
                    Console.Write("Department : ")
                    employees(1, count) = Console.ReadLine()
                    count += 1
                Case "r"c, "R"c
                    If count > 0 Then
                        ReDim Preserve employees(1, count - 1)
                        count -= 1
                    End If
                Case "x"c, "X"c
                    ' doe niets
            End Select
        Loop
    End Sub
End Module

7.8.4. Intelligent Vergroten van Arrays

Als men een grote collectie moet beheren, zou men ervoor kunnen opteren om meteen een array te creëren met "voldoende" elementen.  Hierbij vermijdende dat men steeds een "zware" ReDim Preserve dient toe te passen.
Natuurlijk heeft dit als nadeel dat deze grote array (te)veel geheugenruimte in beslag zal nemen.

Een goed alternatief is het werken met een steeds verdubbelende capaciteit.
Hierbij vermijdt men het al te vaak herdimensioneren van de tabel, en zal ook niet al te veel geheugenruimte verkwist worden.
Visual Basic 2012 Broncode - Codevoorbeeld 134
Module Example4
    Sub Main()
        Dim capacity As Integer = 2
        Dim count As Integer
        Dim numbers(capacity - 1) As Integer
        '
        Do
            Dim index As Integer
            Console.Write("Numbers (capacity " & capacity & _
                          ", count " & count & ") : ")
            For index = 0 To count - 1
                Console.Write(numbers(index) & " ")
            Next
            Console.WriteLine()
            Console.Write("Number ? : ")
            Dim number As Integer = Console.ReadLine()
            count += 1
            If count > capacity Then
                capacity *= 2
                ReDim Preserve numbers(capacity - 1)
            End If
            numbers(count - 1) = number
        Loop
    End Sub
End Module
Console Application Output
Numbers (capacity 2, count 0) :
Number ? : 1
Numbers (capacity 2, count 1) : 1
Number ? : 2
Numbers (capacity 2, count 2) : 1 2
Number ? : 3
Numbers (capacity 4, count 3) : 1 2 3
Number ? : 4
Numbers (capacity 4, count 4) : 1 2 3 4
Number ? : 5
Numbers (capacity 8, count 5) : 1 2 3 4 5
Number ? : 6
Numbers (capacity 8, count 6) : 1 2 3 4 5 6
Number ? : 7
Numbers (capacity 8, count 7) : 1 2 3 4 5 6 7
Number ? : 8
Numbers (capacity 8, count 8) : 1 2 3 4 5 6 7 8
Number ? : 9
Numbers (capacity 16, count 9) : 1 2 3 4 5 6 7 8 9
Number ? :
Het programma blijft hier oneindig vragen om de invoer van een getal.

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.