|
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
7.8.1. ReDim StatementHet 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 2010 Broncode Module Example1 Sub Main() Dim row() As Integer Dim matrix(,) As Integer ReDim row(9) ReDim matrix(9, 9) row(5) = 5 matrix(5, 5) = 5 Console.WriteLine(row(5)) Console.WriteLine(matrix(5, 5)) Console.ReadLine() End SubEnd ModuleDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 2010 Broncode 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)) Console.ReadLine() End SubEnd ModuleDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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. boven
7.8.2. ReDim PreserveWenst 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 2010 Broncode Module Example3 Sub Main() Dim matrix(2, 3) As Integer matrix(1, 1) = 10 Console.WriteLine(matrix(1, 1)) ReDim Preserve matrix(2, 9) Console.WriteLine(matrix(1, 1)) ReDim Preserve matrix(5, 9) Console.ReadLine() End SubEnd ModuleDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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. boven
7.8.3. OefeningOpgave :
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 2010 Broncode 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 End Select Loop End SubEnd ModuleDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
boven
7.8.4. Intelligent Vergroten van ArraysAls 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 2010 Broncode 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 SubEnd ModuleDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
|