With the For...Next type of programming loop the number of iterations is known when it begins. If not known explicitly, it is known by a variable that resolves to an integer that sets its ending value. The loop iterates that many times unless exited on a condition that arises inside the loop. There may be situations, however, where it cannot be known in advance exactly how many times to execute the statements -- to what value the ending value should be set.
The While...End While Loop
The While...End While loop is designed for these situations. Its general format is shown below.
A While...End While loop does not execute a fixed number of times. It executes as long as a condition test at the beginning of the loop remains True. It could be that the condition is False at the start of the loop, in which case it doesn't get executed at all. Of course, it is important that somewhere inside the loop the condition becomes True; otherwise, the loop never ends. Whereas a For...Next loop presents a condition for ending the loop, a While...End While presents a condition for continuing the loop.
Before a more practical application is presented, take a look at how a While...End While loop can be set up to resemble a For...Next loop. As in a previous illustration an array is loaded with values and a loop displays its contents.
Sub Get_Fruit (Src As Object, Args As EventArgs) Dim Fruit() As String = {"apples","oranges","lemons","grapes","beer"} Dim i As Integer = 0 While i <= Fruit.Length - 1 FruitOut.Text &= Fruit(i) & " " i += 1 End While End Sub <asp:Button Text="Get Fruit" OnClick="Get_Fruit" runat="server"/> <asp:Label id="FruitOut" EnableViewState="False" runat="server"/>
It is important to notice two requirements for setting up the loop. First, the condition to be tested is established and initialized before the loop begins. In this case variable i is declared and initialized to 0 (since it is used to increment through the array, beginning with element 0). Second, provision is made inside the loop for ending the loop. In this case the counter i is incremented, ensuring that the loop will eventually end when it reaches the Length - 1 of the array. These provisions must be met for all While...End While loops.
Loading an Array from a File
More realistically, an array is loaded from an external data store -- a file or database table -- containing information that can be added to, changed, or deleted without have to revise the script that contains the array. In the following example, two arrays (StatesArray() and CodesArray()) are loaded from an external text file (StateCodes.txt). This is a file of state names and state codes for all 50 states. In the following script these arrays are defined globally for access by other subprograms which perform processing against the arrays.
<SCRIPT runat="server"> Dim StatesArray(0) As String Dim CodesArray(0) As String Sub Page_Load Dim FileReader As StreamReader Dim LineIn As String Dim FieldArray() As String FileReader = File.OpenText("e:\WebSite\tutorials\vbnet\vbnet04\StateCodes.txt") LineIn = FileReader.ReadLine() While LineIn <> "" FieldArray = Split(LineIn, ",") StatesArray(UBound(StatesArray)) = FieldArray(0) CodesArray(UBound(CodesArray)) = FieldArray(1) LineIn = FileReader.ReadLine() If LineIn <> "" Then ReDim Preserve StatesArray(StatesArray.Length) ReDim Preserve CodesArray(CodesArray.Length) End If End While FileReader.Close() End Sub </SCRIPT>
The statements shown in bold are crucial to setting up the loop to work properly. The condition for continuing the loop is that a record has been read from the file (LineIn <> "" -- a retrieved record is not null). First, then, an initial read is made prior to the loop so the condition can be tested at the beginning of the loop. As long as a record has been read from the file it is processed. After processing, a look-ahead read from the file takes place (LineIn = FileReader.ReadLine()), providing a condition to test when control returns to the top of the loop and ensuring that eventually the condition for ending the loop will occur. An initial file read before the loop and follow-on reads at the bottom of the loop is the typical structure for reading a file.
Splitting a String into an Array
Each record in the file contains a state name and a state code separated by a comma (Alabama,AL). One of the tasks is to parse this line into two separate components so that the state name can be placed in the StatesArray array and the state code placed in the CodesArray array. Although there are string methods that can be used, the easiest way to divide a string into separate substrings is with the Visual Basic Split() function.
A string is any sequence of characters that is to be divided into separate substrings. The delimiter is the single character used to identify the substrings and marks where the string will be split. The space character (" ") is the default delimiter; any other character can be identified as the delimiter. In the current example a comma is the delimiter character. Of course, the delimiter cannot be the same as other characters that are part of the substrings.
When the Split() function is applied to the string, each identified substring is written as a separate element into an array. Only an array name and type needs to be supplied; the array does not have to be dimensioned since its size is determined by the Split() method. Following the split, the array contains as many elements as there are substrings. In the current example, array FieldArray contains two elements -- one containing the state name (index 0) and the other containing the state code (index 1).
Dim FieldArray() As String ... While LineIn <> "" FieldArray = Split(LineIn, ",") ... End While
Array FieldArray is created anew each time the Split() method is applied, in this case each time a line is read from the file. New elements are not added to the existing array; each split recreates the array with two elements.
Determining Array Boundaries
Once this two-element array with a state name and state code is created, these separate data items can be added to the StatesArray and CodesArray arrays.
StatesArray(UBound(StatesArray)) = FieldArray(0) CodesArray(UBound(CodesArray)) = FieldArray(1)
The name and code are always added to the last element in the arrays. You do not need to know the exact element index. This value is given by the UBound(array) function. It returns the index of the last element in an array -- the Upper Boundary of the array. Since these arrays are initially dimensioned with one element each, the first time these assignments are made the two values are copied to elements with index 0.
So, the first time through the While...End While loop an initial record has been read from the file, the record string has been split into two substrings, and the two data items are written as the initial entries in the StatesArray and CodesArray arrays.
This processing needs to continue for as many records as there are in the file. Therefore, a look-ahead read of the file is performed prior to returning to the start of the loop.
Redimensioning Arrays
Before switching control to the top of the loop a decision needs to be made about whether to expand the sizes of arrays StatesArray and CodesArray. If a next record is available for processing (if the look-ahead read did not encounter the end of the file), then a new state-name and state-code pair of values will be available for adding to the arrays. However, these arrays are not large enough to hold these values. They were dimensioned with only one element each.
No problem. The ReDim statement can be used to dynamically change the sizes of these arrays, in this case adding one addition element to each for storing the values from the next record.
Normally, when arrays are redimensioned they are rebuilt, causing loss of data from the current array. The keyword Preserve ensures that the new array contains data from the old array. A redimensioned array also needs to be given a new size. For the current application the size needs to be one addition element beyond the size of the old array.
If LineIn <> "" Then ReDim Preserve StatesArray(StatesArray.Length) ReDim Preserve CodesArray(CodesArray.Length) End If
The Lengths of the current arrays are used to redimension the new arrays. This appears to make the new arrays the same size as the old arrays. However, with 0-based indexing the Length is always one more than the index of the last element.
Now, everything is in order to return to the top of the loop to continue processing of the next record, with the same steps completed for as many records as there are in the file. Eventually, the end of the file is encountered (a null record is returned from a read), and the condition for continuing the loop is False. At this point control skips to the statement following End While, where the file is closed and the subprogram ends.
Using the Arrays
In this example, the Page_Load subprogram loads the StatesArray and CodesArray arrays, so the current page has these arrays available to it. Just to put a finishing touch on this discussion, a couple of things can be done with the arrays.
Array Lookup
Since the two arrays have corresponding element values they can be used as corresponding arrays for table look-up.
Sub Get_The_Code (Src As Object, Args As EventArgs) If State.Text <> "" Then Dim i As Integer For i = 0 To UBound(StatesArray) If StatesArray(i) = State.Text Then Code.Text = CodesArray(i) Exit For End If Next End If End Sub <b>State: </b><asp:TextBox id="State" Size="12" runat="server"/> <asp:Button Text="Get Code" OnClick="Get_The_Code" runat="server"/> <b>Code: </b><asp:Label id="Code" EnableViewState="False" runat="server"/>
State: Code:
Collection Lookup
If you prefer, the StatesArray and CodesArray arrays can be loaded into a collection to provide keyed access for a state code look-up. This is probably redundant, but it does illustrate that arrays can be used for many different purposes. The following code is added to the Page_Load procedure, following loading of the arrays, to create the StateCodes collection (defined globally for access by the separate search procedure).
Dim StateCodes As New Collection Sub Page_Load ...Load arrays Dim i As Integer For i = 0 To UBound(CodesArray) StateCodes.Add(CodesArray(i),StatesArray(i)) Next End Sub
A For...Next loop iterates from 0 through the last index of the CodesArray array (the StatesArray array also could be used to establish the end value of the loop). Corresponding elements from the two arrays are added as values and keys for the elements of the collection.
Now, a search procedure similar to the array look-up can be used to return state codes from entered state names.
Sub Get_The_Code (Src As Object, Args As EventArgs) If State.Text <> "" Then On Error Resume Next Code.Text = StateCodes.Item(State.Text) End If End Sub <b>State: </b><asp:TextBox id="State" Size="12" runat="server"/> <asp:Button Text="Get Code" OnClick="Get_The_Code" runat="server"/> <b>Code: </b><asp:Label id="Code" EnableViewState="False" runat="server"/>
Drop-Down Lookup
Rather than having the user enter the name of a state to look up its code, the StatesArray and CodesArray arrays can serve as data sources for creating a drop-down list whereby state codes are produced by choosing a name from the list.
State: Alabama Alaska Arizona Arkansas California Colorado Connecticut Deleware Florida Georgia Hawaii Idaho Illinois Indiana Iowa Kansas Kentucky Louisiana Maine Maryland Massachusetts Michigan Minnesota Mississippi Missouri Montana Nebraska Nevada New Hampshire New Jersey New Mexico New York North Carolina North Dakota Ohio Oklahoma Oregon Pennsylvania Rhode Island South Carolina South Dakota Tennessee Texas Utah Vermont Virginia Washington West Virginia Wisconsin Wyoming Code:
Sub Create_DropList Dim i As Integer For i = 0 To UBound(States) StatesList.Items.Add(New ListItem(StatesArray(i),CodesArray(i))) Next End Sub Sub Get_The_Code (Src As Object, Args As EventArgs) Code.Text = StatesList.SelectedItem.Value End Sub <b>State: </b><asp:DropDownList id="StatesList" runat="server"/> <asp:Button Text="Get Code" OnClick="Get_The_Code" runat="server"/> <b>Code: </b><asp:Label id="Code" EnableViewState="False" runat="server"/>
An <asp:DropDownList> control is populated from the arrays. State names are used for display in the list; state codes are their corresponding values.
In summary, arrays are useful data stores for a multitude of purposes. Arrays with dynamic, changing data values are best populated from external sources such as files and databases. Arrays are loaded from these data sources with the While...End While loop. Everything is connected.