Arrays in Visual Basic
By Herbert J. Bernstein
© Copyright 1999 Herbert J. Bernstein
Arrays are a means of giving multiple data items a single name. Individual data items are identified by combining the name of the array one or more numeric indices. If there is one index, it indicates which item in a single row of array elements is desired. If there are two indices, they indicate by row and column which element is desired. More indices are allowed.
There are two ways to declare storage for an arrays in Visual Basic:
Dim variable( ilo TO ihi ) As type Dim variable( ilo TO ihi, jlo TO jhi ) As type Dim variable( ilo TO ihi, jlo TO jhi, klo TO khi ) As type ...
is used to declare an array when the dimensions are known constants. If the lower index for any dimension is zero, it may be omitted.
ReDim variable( ilo TO ihi ) As type ReDim variable( ilo TO ihi, jlo TO jhi ) As type ReDim variable( ilo TO ihi, jlo TO jhi, klo TO khi ) As type ...
is used to declare an array within a procedure when any of the dimensions are computed from variables or are different from the original declaration. The number of indices must be the same as in the original declaration.
If an array is to be known to all subprocedures, a declaration
Dim variable() As typeshould appear in the (General) section of the code.
When passing an array as an argument
variable()should appear in the list of actual arguments in the call and
variable() As typeshould appear in the list of formal parameters in the subprocedure or function definition.
The following code uses an array to sort names with a simple bubble sort:
Rem Sample of a Bubble Sort Rem H. J. Bernstein, 7 November 1999 Rem Requires a Form with an output text box Text1 Rem an input text box Text2 Rem with properties Rem ScrollBars 2 (Vertical) Rem Multiline True Rem an enter button EnterButton Rem a sort button SortButton Dim Names$(1 To 2000) Dim NameCount As Integer Private Sub EnterButton_Click() NameCount = NameCount + 1 Names(NameCount) = Text2.Text Text1.Text = Text1.Text & Text2.Text & Chr(13) & Chr(10) Text2.Text = "" End Sub Private Sub Form_Load() NameCount = 0 Text1.Text = "" Text2.Text = "" End Sub Private Sub SortButton_Click() Dim Done As Integer Dim Icount As Integer Dim Temp As String Do Done = 1 For Icount = 2 To NameCount If (UCase(Names(Icount - 1)) > UCase(Names(Icount))) Then Temp = Names(Icount) Names(Icount) = Names(Icount - 1) Names(Icount - 1) = Temp Done = 0 End If Next Icount Loop Until (Done = 1) Text1.Text = "" For Icount = 1 To NameCount Text1.Text = Text1.Text & Names(Icount) & Chr(13) & Chr(10) Next Icount End Sub
This can be redone using a Shell sort:
Rem Sample of a Shell Sort Rem H. J. Bernstein, 7 November 1999 Rem Requires a Form with an output text box Text1 Rem an input text box Text2 Rem with properties Rem ScrollBars 2 (Vertical) Rem Multiline True Rem an enter button EnterButton Rem a sort button SortButton Dim Names$(1 To 2000) Dim NameCount As Integer Private Sub EnterButton_Click() NameCount = NameCount + 1 Names(NameCount) = Text2.Text Text1.Text = Text1.Text & Text2.Text & Chr(13) & Chr(10) Text2.Text = "" End Sub Private Sub Form_Load() NameCount = 0 Text1.Text = "" Text2.Text = "" End Sub Private Sub SortButton_Click() Dim Done As Integer Dim Range As Integer Dim Icount As Integer Dim Temp As String Range = Int(NameCount/2) Do While (Range > 0) Do Done = 1 For Icount = 1+Range To NameCount Step Range If (UCase(Names(Icount - Range)) > UCase(Names(Icount))) Then Temp = Names(Icount) Names(Icount) = Names(Icount - Range) Names(Icount - Range) = Temp Done = 0 End If Next Icount Loop Until (Done = 1) Range = Int(Range/2) Loop Text1.Text = "" For Icount = 1 To NameCount Text1.Text = Text1.Text & Names(Icount) & Chr(13) & Chr(10) Next Icount End Sub
The following is a sort done by merging into an ordered list. The ordered list is managed with a dope vector array. WARNING This version of the code has a bug. If you hit an infinite loop, you may need the Break key to terminate. We will discuss the bug after presenting the preliminary version.
Rem Sample of a Sort by Merging Into a Sorted List Rem H. J. Bernstein, 7 November 1999 Rem *** WARNING -- This version may loop forever *** Rem Requires a Form with an output text box Text1 Rem an input text box Text2 Rem with properties Rem ScrollBars 2 (Vertical) Rem Multiline True Rem an enter button EnterButton Rem a sort button SortButton Rem **** This is an untested, undebugged version **** Dim Names$(1 To 2000) Dim NameOrder(1 To 2000) Dim NameCount As Integer Private Sub EnterButton_Click() NameCount = NameCount + 1 Names(NameCount) = Text2.Text Text1.Text = Text1.Text & Text2.Text & Chr(13) & Chr(10) Text2.Text = "" End Sub Private Sub Form_Load() NameCount = 0 Text1.Text = "" Text2.Text = "" End Sub Private Sub SortButton_Click() Dim Range As Integer Dim Icount As Integer Dim Klo As Integer Dim Khi As Integer Dim Temp As String Dim Ordered as Integer Dim Iget as Integer NameOrder(1) = 1 Ordered = 1 For Iget = 2 to NameCount If (UCase(Names(Iget)) >= UCase(Names(NameOrder(Ordered)))) Then Ordered = Ordered+1 NameOrder(Ordered) = Iget ElseIf (UCase(Names(Iget)) <= UCase(Names(NameOrder(1)))) Then For Icount = Ordered To 1 Step -1 NameOrder(Icount+1) = NameOrder(Icount) Next Icount Ordered = Ordered+1 NameOrder(1) = Iget Else Range = Int(Ordered/2) Klo = 1 Khi = Ordered Do While (Range > 0) If (UCase(Names(Iget)) = UCase(Names(NameOrder(Klo+Range-1)))) Then Klo = Klo+Range-1 Exit Do End If If (UCase(Names(Iget)) <= UCase(Names(NameOrder(Klo+Range-1)))) Then Khi = Klo+Range-1 Else Klo = Klo+Range-1 End If Range = Int((Khi-Klo)/2) Loop For Icount = Ordered to Klo+1 Step -1 NameOrder(Icount+1) = NameOrder(Icount) Next Icount Ordered = Ordered+1 NameOrder(Klo+1) = Iget End If Next Iget Text1.Text = "" For Icount = 1 To NameCount REM Originally: ... & Names(Icount) ... which gave the unsorted list Text1.Text = Text1.Text & Names(NameOrder(Icount)) & Chr(13) & Chr(10) Next Icount End Sub
Now let us turn to the bug. One of the most difficult aspects of algorithms based on binary searches is being certain of the boundary conditions. This code may loop forever if we get to the case Khi = Klo+2. In that case, Range will be set to 1 for the next pass. If that pass sets Klo to Klo+Range-1, we repeat the same values forever. Let us redo the code with comments to help guide what we are doing.
REM Version of code which will not loop infinitely, and which REM sets Klo to a string which can be placed below the REM string at Iget REM We enter this code knowing that there are at least two REM items in the sorted list. If there are exactly 2, we are REM done; we place the new item between them. If there are REM 3 items, we need to examine the middle item, so, in REM contrast to the prior version, we look at Klo+Range REM rather than Klo+Range-1 REM We change the initial calculation of the Range so 1 and 2 REM give a Range of 0, and we change all references to Range-1 REM to be references to Range Range = Int((Ordered-1)/2) Klo = 1 Khi = Ordered Do While (Range > 0) REM If the item falls on the break, stop here If (UCase(Names(Iget)) = UCase(Names(NameOrder(Klo+Range)))) Then Klo = Klo+Range Exit Do End If REM Shrink the range to the half containing the item If (UCase(Names(Iget)) <= UCase(Names(NameOrder(Klo+Range)))) Then Khi = Klo+Range Else Klo = Klo+Range End If Range = Int((Khi-Klo)/2) Loop REM Move everything above Klo up by 1 For Icount = Ordered to Klo+1 Step -1 NameOrder(Icount+1) = NameOrder(Icount) Next Icount Ordered = Ordered+1 NameOrder(Klo+1) = Iget