Arrays
A simple Visual Basic variable can be assigned a single value. An array variable is a collection of variables, all having the same type, to which a list of values can be assigned. Each member of an array is known as an array element, and is identified by a number in parentheses immediately following the array variable name. For example, the statement:
Student(5) = "Fred Smith"
assigns the string "Fred Smith" to the fifth element in the array Student(). The number inside the parentheses is known as an array subscript. An array variable is declared as follows:
Dim arrayName(1 to n) As varType
This will create n variables of the type varType.
Array elements can be assigned values and used in a program in the same way as any other variable. The main benefits of using arrays include the ability to use a single statement to create a range of variables, and the use of subscripts in loops to access each element of an array variable in turn.
Example 1
The following code fragment creates a string array consisting of the names of students in a class, and assigns values to each array element.
Dim Students(1 To 4) As String
Students(1) = "Stephanie Brown"
Students(2) = "Colin Casey"
Students(3) = "John Evans"
Students(4) = "Linda Hunter"
Data for large arrays is often stored in data files and read into the array using Input statements. To illustrate this, create a text file called "Results.txt" to hold the names of students and their examination results, as shown below:
| The contents of the "Results.txt" text file |
| "Charlie Brown", 53 |
| "Colin Carruthers", 66 |
| "John Walker", 42 |
| "Betty Rubble", 95 |
| "Andy Capp", 32 |
| "James Beam", 80 |
| "Thomas Petty", 63 |
| "Ruby Murray", 59 |
We are going to create a program that reads the names of students and their examination results from the "Results.txt" file and assigns the values read to suitable array variables. The program will display a list of student names and exam results, and calculate and display the average mark for the group. A string array will be created to hold the names of the students, and a numeric array will be created to hold their examination scores. The first element of each array holds data for the first student, the second element holds data for the second student, and so on. Note that the two arrays can be created using a single Dim statement.
Open a new Visual Basic project, save it to a new folder, and create a form similar to the one illustrated below.
| The Student Exam Result Form Controls | |||
| Control | Name | Caption | Additional Properties |
| Form | Form1 | Student Exam Results | |
| Button | cmdList | List Results | |
| PictureBox | picList | ||
| Button | cmdAverage | Calculate Average | |
| PictureBox | picAverage | ||
Enter the following code in the form's code window:
Option Explicit
Dim Students(1 To 8) As String * 20
Dim Results(1 To 8) As Integer
Dim Counter As Integer
Private Sub cmdList_Click()
picList.Cls
Open App.Path & "\Results.txt" For Input As #1
For Counter = 1 To 8
Input #1, Students(Counter), Results(Counter)
picList.Print Students(Counter); Results(Counter)
Next
Close #1
End Sub
Private Sub cmdAverage_Click()
Dim total As Integer
Dim Average As Single
picAverage.Cls
total = 0
For Counter = 1 To 8
total = total + Results(Counter)
Next
Average = total / 8
picAverage.Print Average
End Sub
Run the program and click the List Results button to see the list of students and their results, then click the Calculate Average button to see the average score. The result should be similar to the screen shot below.
In the above example, we know the number of exam results in the file, and can dimension the arrays accordingly. In real life, we often don't know in advance how many array variables our program may be called upon to deal with. The number may well vary from one situation to another. In Visual Basic, we can set the size of an array using a statement like:
ReDim arrayName(1 to n) As varType
ReDim can accept either variables or expressions as subscripts (whereas Dim cannot). The only constraint is that ReDim statements can only be used inside procedures.
Example 2
Re-write the code for the previous example as shown below.
Option Explicit
Dim numStudents As Integer, sTemp As String, Score As Integer, Total As Integer
Private Sub cmdList_Click()
Dim n As Integer, Counter As Integer
picList.Cls
numStudents = 0
Total = 0
Open App.Path & "\Results.txt" For Input As #1
Do While Not EOF(1)
Input #1, sTemp, Score
numStudents = numStudents + 1
Total = Total + Score
Loop
Close #1
n = numStudents
ReDim Students(1 To n) As String, Results(1 To n) As Integer
Open App.Path & "\Results.txt" For Input As #1
For Counter = 1 To n
Input #1, Students(Counter), Results(Counter)
picList.Print Students(Counter); Results(Counter)
Next
Close #1
End Sub
Private Sub cmdAverage_Click()
Dim Average As Single
picAverage.Cls
Average = Total / numStudents
picAverage.Print Average
End Sub
Form level (General) declarations can contain Dim statements of the form:
Dim arrayName() As varType
where the subscripts of the array are unspecified. The array cannot be used
until a ReDim statement is executed in a procedure that establishes the subscript range to
be used (the "As varType" clause can be omitted from the
ReDim statement). Note that any reference within a procedure to an array subscript
outside the defined range will result in an error message. Note also that the
elements of an array will have a default value until they are initialised, or
have a value assigned to them by the program. For numeric array variables, the
default value is 0. For string array variables, the default value is "" (the
empty string).
An array created with a ReDim statement is said to be dynamic.
A dynamic array can be resized with another ReDim
statement, although the resized array loses all information unless it is
resized with the words ReDim Preserve,
in which case as much information as possible is retained.
Arrays may be ordered (in ascending or descending order) or unordered. Arrays
of numerical variables are ordered by numerical value, while string arrays are
ordered using their ASCII character code values. Ordered arrays are easier to
search, since a search for an element having a specific value will end either
when the element is found, or an element is found whose value is greater than
the value being sought. A search of an ordered array will, on average, only
need to examine half of the array elements.
In some circumstances, an array must be dimensioned before the number of data
items it will hold is known. In most cases, however, it should be possible plan
for all reasonable contingencies by making the array suitably large. A counter
variable is often used in such cases to keep track of the number of data items
actually stored in the array.
Example 3
Open a new Visual Basic project, save it to a new folder, and create a form similar to the one illustrated below.
| The Student Register Form Controls | |||
| Control | Name | Caption | Additional Properties |
| Form | Form1 | Student Register | |
| TextBox | InputBox | ||
| Button | cmdAdd | Add Student | |
| PictureBox | picList | ||
The code for the program is shown below. An array large enough to hold ten students is created, and the names of students can be added by typing them into the text box at the top of the application window, and clicking on the Add Student button. Once the array is full, the program will not accept any more entries.
Option Explicit
Dim Students(9) As String
Dim Counter As Integer
Dim n As Integer
Private Sub cmdAdd_Click()
If InputBox.Text = "" Then
MsgBox "You must enter a student name.", , "Student Register"
ElseIf Counter > 9 Then
MsgBox "No space to record additional Students.", , "Student Register"
InputBox.Text = ""
Else
picList.Cls
Students(Counter) = InputBox.Text
InputBox.Text = ""
For n = 0 To Counter
picList.Print Students(n)
Next
Counter = Counter + 1
End If
End Sub
Private Sub Form_Load()
Counter = 0
End Sub
Control Arrays
Visual Basic allows the construction of arrays of text boxes, labels, command buttons, and other Visual Basic controls. Such arrays are called Control arrays. At least one element of a control array is created when the form is designed. The remaining elements can be created either at the same time, or at run time.
Example 4
To illustrate the use of control arrays, we are going to create a simple calculator program. Open a new Visual Basic project, save it to a new folder, and create a form similar to the one illustrated below.
The controls for the calculator are defined below (note that the dimensions of all buttons are 480 x 480).
| The Calculator Form Controls | ||||
| Control | Name | Caption | Index | Additional Properties |
| Form | Form1 | Calculator | Width = 3390, Height = 3375 | |
| Button | Number | 0 | 0 | Left = 120, Top = 2400 |
| Button | Number | 1 | 1 | Left = 120, Top = 1800 |
| Button | Number | 2 | 2 | Left = 720, Top = 1800 |
| Button | Number | 3 | 3 | Left = 1320, Top = 1800 |
| Button | Number | 4 | 4 | Left = 120, Top = 1200 |
| Button | Number | 5 | 5 | Left = 720, y = 1200 |
| Button | Number | 6 | 6 | Left = 1320, Top = 1200 |
| Button | Number | 7 | 7 | Left = 120, Top = 600 |
| Button | Number | 8 | 8 | Left = 720, Top = 600 |
| Button | Number | 9 | 9 | Left = 1320, Top = 600 |
| Button | Decimal | . | Left = 720, Top = 2400 | |
| Button | Operator | / | 0 | Left = 2640, Top = 1800 |
| Button | Operator | + | 1 | Left = 2020, Top = 1200 |
| Button | Operator | X | 2 | Left = 2020, Top = 1800 |
| Button | Operator | - | 3 | Left = 2640, Top = 1200 |
| Button | Operator | = | 4 | Left = 1320, Top = 2400 |
| Button | Cancel | C | Left = 2020, Top = 600 | |
| Button | CancelEntry | CE | Left = 2640, Top = 600 | |
| Button | Percent | % | Left = 2640, Top = 2400 | |
| Label | Readout | 0. | Alignment: 1 - Right Justify Appearance: 1 - 3D BackColor: &H00FFFFFF& BorderStyle: 1 - Fixed Single Left = 120, Top = 100 Width = 3000, height = 375 |
|
The ten buttons (0-9) with the name Number
are members of an array, as are the five buttons (+, -, x, /, =) with the name
Operator. When you have created the first button in each array, find the
Index
property in the Properties window, which is initially blank, and change it to
0 (zero).
Once the first element in a control array has been created, you can create as
many copies as you need using copy and paste commands. Visual basic will
automatically assign the next available index number to each copy created. All
you need to do is to change the caption to the correct text, and place the new
button in the correct position on the form. The properties that are common to
all controls in a control array should be set for the first element created
before
it is used to create additional array elements, which will make the process of
creating the array more efficient.
The code for the Calculator program is shown below. Note that, although there
are several buttons with the name Number, the value of the
Index
property for the button actually clicked will be sent to the sub routine
Number_Click(). The same thing applies to the buttons that share the name
Operator, and the sub routine Operator_Click(). In other words, the
Index
property is used to tell the program which command button in a control array
consisting of several command buttons has been clicked on by the user. As a
general rule, therefore, event procedures for a control array have an
additional parameter (Index As Integer).
Option Explicit
Dim Op1, Op2
Dim DecimalFlag As Integer
Dim NumOps As Integer
Dim LastInput
Dim OpFlag
Dim TempReadout
Private Sub Cancel_Click()
Readout = Format(0, "0.")
Op1 = 0
Op2 = 0
Form_Load
End Sub
Private Sub CancelEntry_Click()
Readout = Format(0, "0.")
DecimalFlag = False
LastInput = "CE"
End Sub
Private Sub Decimal_Click()
If LastInput = "NEG" Then
Readout = Format(0, "-0.")
ElseIf LastInput <> "NUMS" Then
Readout = Format(0, "0.")
End If
DecimalFlag = True
LastInput = "NUMS"
End Sub
Private Sub Form_Load()
DecimalFlag = False
NumOps = 0
LastInput = "NONE"
OpFlag = " "
Readout = Format(0, "0.")
End Sub
Private Sub Number_Click(Index As Integer)
If LastInput <> "NUMS" Then
Readout = Format(0, ".")
DecimalFlag = False
End If
If DecimalFlag Then
Readout = Readout + Number(Index).Caption
Else
Readout = Left(Readout, InStr(Readout, Format(0,
".")) - 1) + Number(Index).Caption + Format(0, ".")
End If
If LastInput = "NEG" Then
Readout = "-" & Readout
End If
LastInput = "NUMS"
End Sub
Private Sub Percent_Click()
Readout = Readout / 100
LastInput = "Ops"
OpFlag = "%"
NumOps = NumOps + 1
DecimalFlag = True
End Sub
Private Sub Operator_Click(Index As Integer)
TempReadout = Readout
If LastInput = "NUMS" Then
NumOps = NumOps + 1
End If
Select Case NumOps
Case 0
If
Operator(Index).Caption = "-" And LastInput <> "NEG" Then
Readout
= "-" & Readout
LastInput
= "NEG"
End If
Case 1
Op1 = Readout
If
Operator(Index).Caption = "-" And LastInput <> "NUMS" And OpFlag <> "=" Then
Readout
= "-"
LastInput
= "NEG"
End If
Case 2
Op2 = TempReadout
Select Case OpFlag
Case
"+"
Op1
= CDbl(Op1) + CDbl(Op2)
Case
"-"
Op1
= CDbl(Op1) - CDbl(Op2)
Case
"X"
Op1
= CDbl(Op1) * CDbl(Op2)
Case
"/"
If
Op2 = 0 Then
MsgBox
"Can't divide by zero", 48, "Calculator"
Else
Op1
= CDbl(Op1) / CDbl(Op2)
End
If
Case
"="
Op1
= CDbl(Op2)
Case
"%"
Op1
= CDbl(Op1) * CDbl(Op2)
End
Select
Readout
= Op1
NumOps = 1
End Select
If LastInput <> "NEG" Then
LastInput = "OPS"
OpFlag = Operator(Index).Caption
End If
End Sub
Sorting an Array
A sort is an algorithm that puts the elements of an array into numerical or alphabetical order. One common sorting technique is the bubble sort. The bubble sort algorithm compares adjacent items, and swaps those that are out of order. If the process is repeated enough times, the list will eventually be ordered. The steps for each pass through the array are as follows:
- Compare the first and second elements, and if out of order, swap them.
- Compare the second and third items, and if out of order, swap them.
- Repeat the process for all remaining pairs. The final comparison is between the last two elements in the array.
The first pass through the array checks each successive pairing in turn, after which the last item will be in its correct place in the array. The second pass repeats the process, but can ignore the last item. After the second pass, the last two items in the array will be in their correct places. Each successive pass therefore has one less comparison to make. The total number of passes required to ensure that all of the array elements are correctly ordered is one less than the number of elements in the array.
Example 5
We are going to create a program that takes a randomly ordered list of names from a file and sorts them into alphabetical order. Here is the unsorted file, "Unsorted.txt".
| The contents of the "Unsorted.txt" text file |
| Warsaw |
| Paris |
| New York |
| Amsterdam |
| Berlin |
| London |
| Brussels |
| Rome |
Open a new Visual Basic project, save it to a new folder, and create a form similar to the one illustrated below.
| The European Cities Form Controls | |||
| Control | Name | Caption | Additional Properties |
| Form | Form1 | European Cities | |
| Button | cmdSort | Sort Alphabetically | |
| PictureBox | picList | ||
The bubble sort algorithm uses two nested loops. The inner loop performs a single pass, while the outer loop controls the number of passes made. The code for the program is shown below.
Option Explicit
Dim Counter As Integer, sTemp As String
Dim Cities() As String
Private Sub cmdSort_Click()
Dim n As Integer, Pass As Integer, tempString As String
ReDim ListIndex(1 To Counter) As Integer
picCity.Cls
For Pass = 1 To Counter - 1
For n = 1 To Counter - Pass
If Cities(n) > Cities(n + 1) Then
tempString
= Cities(n)
Cities(n)
= Cities(n + 1)
Cities(n
+ 1) = tempString
End If
Next n
Next Pass
For n = 1 To Counter
picCity.Print Cities(n)
Next
End Sub
Private Sub Form_Load()
Dim n As Integer
Counter = 0
Open App.Path & "\Unsorted.txt" For Input As #1
Do While Not EOF(1)
Input #1, sTemp
Counter = Counter + 1
Loop
Close #1
ReDim Cities(1 To Counter) As String
Open App.Path & "\Unsorted.txt" For Input As #1
Form1.Show
For n = 1 To Counter
Input #1, Cities(n)
Me.picCity.Print Cities(n)
Next
Close #1
End Sub
Searching an Array
If we had an alphabetical list of several hundred names and wanted to find out
whether a particular person's name was on the list, we could simply check each
item in the list in turn until a match was found. This kind of search is known
as a sequential search. A search for a name beginning with "A", therefore, would bear fruit much
faster than a search for a name beginning with "Z". For very long lists, such a
search could be somewhat time-consuming. If we are talking about a sorted
array, however, there is a much quicker method of searching called a
binary search.
A binary search starts looking for the search term by determining which half of
the array contains the item. This half of the array is then dealt with as if it
was the entire array, and the process is repeated. This goes on until the item
is found. The algorithm for a binary search carries out the following steps:
- Assign variables first and last to hold the subscript values of the first and last items in the array respectively, and create a Boolean variable flag with an initial value of False that will become True if the search item is found.
- Compare the middle element of the current array with the search term. This
element will have the subscript middle, and is calculated as:
middle = (first + last) / 2 - If the middle element matches the search term, then flag is set to True, and the search is finished.
- If the middle element is greater than the search term, then the search term can only be in the first half of the array, so the new value of last will be middle - 1, and the value of first will be unchanged.
- If the middle element is less than the search term, then the search term can only be in the second half of the array, so the new value of first will be middle + 1, and the value of last will be unchanged.
- Repeat steps 2 - 5 until the search term is found or until the entire list has been searched (in which case first will be greater than last, and the search term is not in the array).
Example 6
We are going to create a program that reads an alphabetically ordered list of UK towns and cities from a text file and puts them into an array. The user can then enter the name of a town or city, and the program will determine whether or not the town or city entered is in the file. Here are the contents of the text file, "Locations.txt":
| UK Towns and Cities | |
| Aberdeen | Leicester |
| Bath | Liverpool |
| Belfast | London |
| Birmingham | Manchester |
| Bradford | Merthyr Tydfil |
| Brighton | Middlesbrough |
| Bristol | Newcastle |
| Cambridge | Northampton |
| Cardiff | Norwich |
| Crewe | Nottingham |
| Chichester | Oldham |
| Derby | Oxford |
| Dublin | Plymouth |
| Dundee | Portsmouth |
| Durham | Preston |
| Edinburgh | Sheffield |
| Exeter | Southampton |
| Glasgow | Stoke |
| Gloucester | Sunderland |
| Halifax | Swansea |
| Hull | Swindon |
| Leeds | York |
Open a new Visual Basic project, save it to a new folder, and create a form similar to the one illustrated below.
| The Location Search Form Controls | |||
| Control | Name | Caption | Additional Properties |
| Form | Form1 | Location Search | |
| Button | cmdSearch | Search | |
| TextBox | txtLocation | ||
The code for the program is shown below. Note that the built-in Visual Basic function UCase is used in the program to convert the characters in the strings being compared to upper case, so the algorithm will work whether the user types in "London" or "LONDON".
Option Explicit
Dim First As Integer, Last As Integer, Middle As Integer
Dim Locations() As String, sTemp As String, searchTerm As String
Dim Counter As Integer
Dim Flag As Boolean
Private Sub cmdSearch_Click()
Flag = False
searchTerm = UCase(txtLocation.Text)
If searchTerm = "" Then
MsgBox "You must enter the name
of a town or city.", , "Search"
Else
First = 1
Last = Counter
Do Until Flag = True Or First > Last
Middle
= Int((First + Last) / 2)
If
searchTerm = UCase(Locations(Middle)) Then
Flag
= True
ElseIf
searchTerm > UCase(Locations(Middle)) Then
First = Middle + 1
ElseIf
searchTerm < UCase(Locations(Middle)) Then
Last
= Middle - 1
End If
Loop
If Flag = True Then
MsgBox
txtLocation.Text & " is in the list.", , "Search"
Else
MsgBox
txtLocation.Text & " is NOT in the list.", , "Search"
End If
End If
End Sub
Private Sub Form_Load()
Dim n As Integer
Counter = 0
Open App.Path & "\Locations.txt" For Input As #1
Do While Not EOF(1)
Input #1, sTemp
Counter = Counter + 1
Loop
Close #1
ReDim Locations(1 To Counter) As String
Open App.Path & "\Locations.txt" For Input As #1
For n = 1 To Counter
Input #1, Locations(n)
Next
Close #1
End Sub
Two-Dimensional Arrays
The arrays dealt with so far have been one-dimensional, in the sense that they have held a single list if items, indexed by a single array subscript. A two-dimensional array can hold the contents of a table having a number of rows and columns by employing a second array subscript. The range of the first subscript is determined by the number of rows in the table, and the range of the second subscript is determined by the number of columns. Two dimensional arrays will be the subject of a later tutorial.