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 type
should 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 type
should 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