6.2. Processing Lists of Data with Do LoopsOne of the main applications of programming is the processing of lists of data. Do loops are used to display all or selected items from lists, search lists for specific items, and perform calculations on the numerical entries of a list. This section introduces several devices that facilitate working with lists. Counters calculate the number of elements in lists, accumulators sum numerical values in lists, flags record whether certain events have occurred, and the Peek method can be used to determine when the end of a text file has been reached. Nested loops add yet another dimension to repetition. Peek MethodData to be processed are often retrieved from a file by a Do loop. Visual Basic has a useful method that will tell us if we have reached the end of the file from which we are reading. Suppose a file has been opened with a StreamReader object named sr. At any time, the value of sr.Peek is the ANSI value of the first character of the line about to be read with ReadLine. If the end of the file has been reached, the value of sr.Peek is 1. One of the programs I wrote when I got my first personal computer in 1982 stored a list of names and phone numbers and displayed a phone directory. I stored the names in a file so I could easily add, change, or delete entries. Example 1. |
The following program displays the contents of a telephone directory. The names and phone numbers are contained in the file PHONE.TXT. The loop will repeat as long as there is still data in the file. PHONE.TXT contains the following eight lines: Bert 123-4567 Ernie 987-6543 Grover 246-8321 Oscar 135-7900
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim name, phoneNum AsString Dim sr As IO.StreamReader = IO.File.OpenText("PHONE.TXT") lstNumbers.Items.Clear() DoWhile sr.Peek <> -1 name = sr.ReadLine phoneNum = sr.ReadLine lstNumbers.Items.Add(name & " " & phoneNum) Loop sr.Close() End Sub [Run, and press the button.]
|
The program in Example 1 illustrates the proper way to process a list of data contained in a file. The Do loop should be tested at the top with an end-of-file condition. (If the file is empty, no attempt is made to input data from the file.) The first set of data should be input after the Do statement, and then the data should be processed. Figure 6.5 contains the pseudocode and flowchart for this technique.
Text files can be quite large. Rather than list the entire contents, we typically search the file for a specific piece of information.
The following program modifies the program in Example 1 to search the telephone directory for a name specified by the user. If the name does not appear in the directory, the user is so notified. We want to keep searching as long as there is no match and we have not reached the end of the list. Therefore, the condition for the Do While statement is a compound logical expression with the operator And. After the last pass through the loop, we will know whether the name was found and will be able to display the requested information.
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim name As String = "", phoneNum AsString = "" Dim sr As IO.StreamReader = IO.File.OpenText("PHONE.TXT") DoWhile (name <> txtName.Text) And (sr.Peek <> -1) name = sr.ReadLine phoneNum = sr.ReadLine Loop If (name = txtName.Text) Then txtNumber.Text = name & " " & phoneNum Else txtNumber.Text = "Name not found." EndIf sr.Close() End Sub [Run, type "Grover" into the text box, and press the button.]
|
A counter is a numeric variable that keeps track of the number of items that have been processed. An accumulator is a numeric variable that totals numbers.
The following program counts and finds the value of coins listed in a file. The file COINS.TXT contains the following entries, one per line: 1, 1, 5, 10, 10, 25. The fifth and sixth lines of the event procedure are not needed, since the counter numCoins and the accumulator sum have the initial value 0 by default. However, since these default values show the starting points for the two variables, the two assignment statements add clarity to the program.
Private Sub btnAnalyze_Click(...) Handles btnAnalyze.Click Dim numCoins AsInteger, coin As String Dim sum As Double Dim sr As IO.StreamReader = IO.File.OpenText("COINS.TXT") numCoins = 0 sum = 0 DoWhile (sr.Peek <> -1) coin = sr.ReadLine numCoins += 1 'Add 1 to the value of numCoins sum += CDbl(coin) 'Add the value of the current coin to the sum Loop sr.Close() txtValue.Text = "The value of the " & numCoins & _ " coins is " & sum & " cents." End Sub [Run, and press the button.]
|
The value of the counter, numCoins, was initially 0 and changed on each execution of the loop to 1, 2, 3, 4, 5, and finally 6. The accumulator, sum, initially had the value 0 and increased with each execution of the loop to 1, 2, 7, 17, 27, and finally 52.
A flag is a variable that keeps track of whether a certain situation has occurred. The data type most suited to flags is the Boolean data type. Variables of type Boolean can assume just two values: True and False. (As a default, Boolean variables are initialized to False.) Flags are used within loops to provide information that will be utilized after the loop terminates. Flags also provide an alternative method of terminating a loop.
The following program counts the number of words in the file WORDS.TXT and then reports whether the words are in alphabetical order. In each execution of the loop, a word is compared to the next word in the list. The flag variable, called orderFlag, is initially assigned the value True and is set to False if a pair of adjacent words is out of order. The technique used in this program will be used in Chapter 7 when we study sorting. Note: The first time through the loop, the value of word1 is the empty string. Each word must first be read into the variable word2. WORDS.TXT contains the following winning words from the U.S. National Spelling Bee, one word per line: cambist, croissant, deification, hydrophyte, incisor, maculature, macerate, narcolepsy, shallon.
Private Sub btnAnalyze_Click(...) Handles btnAnalyze.Click 'Count words. Are they in alphabetical order? Dim orderFlag As Boolean, wordCounter As Integer Dim word1 As String = "", word2 As String Dim sr As IO.StreamReader = IO.File.OpenText("WORDS.TXT") orderFlag = True DoWhile (sr.Peek <> -1) word2 = sr.ReadLine wordCounter += 1 'Increment the word count by 1 If word1 > word2 Then 'Two words are out of order orderFlag = False EndIf word1 = word2 Loop sr.Close() txtNumber.Text = CStr(wordCounter) [Run, and press the button.]
|
The statements within a Do loop can contain another Do loop. Such a configuration is referred to as nested loops and is useful in repeating a single data-processing routine several times.
The following program allows the user to look through several lists of names. Suppose we have several different phone directories, the names of which are listed in the file LISTS.TXT. (For instance, the file LISTS.TXT might contain the entries CLIENTS.TXT, FRIENDS.TXT, and KINFOLK.TXT.) A sought-after name might be in any one of the files. The statements in the inner Do loop will be used to look up names as before. At least one pass through the outer Do loop is guaranteed, and passes will continue as long as the name is not found and phone lists remain to be examined.
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim foundFlag As Boolean Dim fileName As String Dim name As String = "" Dim phoneNum As String = "" Dim sr1 As IO.StreamReader = IO.File.OpenText ("LISTS.TXT") |
In Appendix D, the section "Stepping through a Program Containing a Do Loop: Chapter 6" uses the Visual Basic debugging tools to trace the flow through a Do loop.
When flagVar is a variable of Boolean type, the statements
If flagVar = True Then and If flagVar = False Then
can be replaced by
If flagVar Then and If Not flagVar Then
Similarly, the statements
Do While flagVar = True and Do While flagVar = False
can be replaced by
Do While flagVar and Do While Not flagVar
1. | Determine the output of the following program, where the three lines of the file SCORES.TXT contain the scores 150, 200, and 300: Private Sub btnCompute_Click(...) Handles btnCompute.Click 'Find the sum of a collection of bowling scores Dim sum, score As Double |
2. | Why didn't the preceding program produce the intended output? |
3. | Correct the preceding program so it has the intended output. |
In Exercises 1 through 10, determine the output displayed when the button is clicked.
1. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim flag As Boolean, word As String Dim sr As IO.StreamReader = IO.File.OpenText("DATA.TXT") Do While (sr.Peek <> -1) word = sr.ReadLine If word.IndexOf("A") <> -1 Then flag = True End If Loop sr.Close() If flag Then txtOutput.Text = "At least one word contains the letter A." Else txtOutput.Text = "No word contains the letter A." End If End Sub (Assume that the four lines of the file DATA.TXT have the following entries: AL, GORE, VIDAL, SASSOON.) |
2. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim name As String Dim sr As IO.StreamReader = IO.File.OpenText("DATA.TXT") Do While (sr.Peek <> -1) name = sr.ReadLine txtOutput.Text &= name Loop sr.Close() End Sub (Assume that the two lines of the file DATA.TXT contain the following entries: Ben, son.) |
3. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click 'Display list of desserts Dim dessert As String Dim sr As IO.StreamReader = IO.File.OpenText("DESSERTS.TXT") Do While (sr.Peek <> -1) dessert = sr.ReadLine lstOutput.Items.Add(dessert) Loop sr.Close() End Sub (Assume that the three lines of the file DESSERTS.TXT contain the following entries: pie, cake, melon.) |
4. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim city As String, pop As Double Dim sr As IO.StreamReader = IO.File.OpenText("CITYPOPS.TXT") Do While (sr.Peek <> -1) city = sr.ReadLine pop = CDbl(sr.ReadLine) If pop >= 3 Then lstOutput.Items.Add(city & " "& pop) End If Loop sr.Close() End Sub (Assume that the eight lines of the file CITYPOPS.TXT contain the following data, where each pair of lines gives a city and its population in millions: New York, 8.1, Los Angeles, 3.8, Chicago, 2.9, Houston, 2.0.) |
5. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim firstLetter As String = "", fruit As String = "" Dim sr As IO.StreamReader = IO.File.OpenText("DATA.TXT") Do While (sr.Peek <> -1) fruit = sr.ReadLine If fruit.Substring(0, 1) <> firstLetter Then If firstLetter <> "" Then lstOutput.Items.Add("") End If firstLetter = fruit.Substring(0, 1) lstOutput.Items.Add(" "& firstLetter) End If lstOutput.Items.Add(fruit) Loop sr.Close() End Sub (Assume that the eight lines of the file FRUITS.TXT contain the following entries: Apple, Apricot, Avocado, Banana, Blueberry, Grape, Lemon, Lime.) |
6. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click 'Display list of numbers Dim num As Double Dim sr As IO.StreamReader = IO.File.OpenText("DATA.TXT") num = CDbl(sr.ReadLine) Do While (sr.Peek <> -1) lstOutput.Items.Add(num) num = CDbl(sr.ReadLine) Loop sr.Close() End Sub (Assume the four lines of the file DATA.TXT contain the entries 2, 3, 8, 5.) |
7. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim animal As String = "", groupName As String = "" InputAnimal(animal) If animal <> "" Then SearchList(animal, groupName) DisplayResult(animal, groupName) End If End Sub Sub DisplayResult(ByVal anml As String, ByVal gName As String) If gName = "" Then txtOutput.Text = "Animal not found." Else txtOutput.Text = "A "& gName & " of "& anml & "s." End If End Sub Sub InputAnimal(ByRef anml As String) 'Request the name of an animal as input anml = InputBox("Please enter the name of an animal.") End Sub Sub SearchList(ByVal anml As String, ByRef gName As String) Dim creature, groupName As String creature = "" Dim sr As IO.StreamReader = IO.File.OpenText("ANIMALS.TXT") Do While (creature <> anml) And (sr.Peek <> -1) creature = sr.ReadLine groupName = sr.ReadLine Loop If (sr.Peek = -1) Then gName = "" Else gName = groupName End If sr.Close() End Sub (The six lines of the file ANIMALS.TXT contain the following entries: lion, pride, duck, brace, bee, swarm. Each pair of lines give an animal and the name of a group of those animals. Assume that the response is "duck".) |
8. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim excerpt As String excerpt = "I think I can. " Duplicate30(excerpt) excerpt = "We're off to see the wizard, " & _ "the wonderful wizard of Oz." Duplicate30(excerpt) End Sub Sub Duplicate30(ByVal sentence As String) Dim flag As Boolean flag = False 'Flag tells whether loop has been executed Do While sentence.Length < 30 flag = True sentence &= sentence Loop If flag = True Then lstOutput.Items.Add(sentence) Else lstOutput.Items.Add("Loop not executed.") End If End Sub |
9. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim word As String = "", cWord As String = "" Dim sr As IO.StreamReader = IO.File.OpenText("WORDS.TXT") Do While (sr.Peek <> -1) word = sr.ReadLine If word.Substring(0, 1) = "c" Then cWord = word End If Loop sr.Close() txtOutput.Text = cWord End Sub (Assume that the 11 lines of the file WORDS.TXT contain the following items: time, is, a, child, idly, moving, counters, in, a, game, Heraclitus.) |
10. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim max, value, rowMax As Double Dim sr As IO.StreamReader = IO.File.OpenText("DATA.TXT") Do While (sr.Peek <> -1) value = CDbl(sr.ReadLine) rowMax = 0 (Assume that the 12 lines of the file DATA.TXT contain the following entries: 5, 7, 3, 2, 10, 12, 6, 4, 2, 1, 9, 2.) In Exercises 11 through 14, identify the errors. |
11. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim num As Double Dim sr As IO.StreamReader = IO.File.OpenText("DATA.TXT") Do While (sr.Peek <> -1) And (num > 0) num = CDbl(sr.ReadLine) lstOutput.Items.Add(num) sr.Close() End Sub (Assume that the five lines of the file DATA.TXT contain the following entries: 7, 6, 0, 2.) | |||||||||||||||||||
12. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim flag As Boolean, num, sum As Double Do While flag = False num = CDbl(InputBox("Enter a number")) sum += num If num * num < 0 Then flag = True End If Loop txtOutput.Text = CStr(num) End Sub | |||||||||||||||||||
13. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click 'Display names of four U.S. Presidents Dim president As String Dim sr As IO.StreamReader = IO.File.OpenText("PRES.TXT") president = sr.ReadLine (Assume that the lines of the file PRES.TXT contain the following entries: Lincoln, Washington, Kennedy, Jefferson.) | |||||||||||||||||||
14. |
Private Sub btnDisplay_Click(...) Handles btnDisplay.Click Dim num As Double Dim sr As IO.StreamReader = IO.File.OpenText("DATA.TXT") If (sr.Peek = -1) Then num = 0 Else num = CDbl(sr.ReadLine) End If Do While 1 < num < 5 lstOutput.Items.Add(num) If (sr.Peek = -1) Then num = 0 Else num = CDbl(sr.ReadLine) End If Loop sr.Close() End Sub (Assume that the five lines of the file DATA.TXT contain the following entries: 3, 2, 4, 7, 2.) | |||||||||||||||||||
15. | Write a program to find and display the largest of a collection of positive numbers contained in a text file. (Test the program with the collection of numbers 89, 77, 95, and 86.) | |||||||||||||||||||
16. | Write a program to find and display those names that are repeated in a text file. Assume that the file has already been sorted into alphabetical order. When a name is found to be repeated, display it only once. | |||||||||||||||||||
17. | Suppose that the file FINAL.TXT contains student grades on a final exam. Write a program that displays the average grade on the exam and the percentage of grades that are above average. | |||||||||||||||||||
18. | Suppose that the file BIDS.TXT contains a list of bids on a construction project. Write a program to analyze the list and report the two highest bids. | |||||||||||||||||||
19. | Suppose that the file USPRES.TXT contains the names of the United States presidents in order from George Washington to George W. Bush. Write a program that asks the user to type a number from 1 to 43 into a text box and then, when the user clicks a button, displays the name of the president corresponding to that number. | |||||||||||||||||||
20. | Table 6.1 shows the different grades of eggs and the minimum weight required for each classification. Write a program that processes the text file EGGS.TXT containing a list of the weights of a sample of eggs. The program should report the number of eggs in each grade and the weight of the lightest and heaviest egg in the sample. Figure 6.6 shows a possible output of the program. Note: Eggs weighing less than 1.5 ounces cannot be sold in supermarkets.
| |||||||||||||||||||
21. | Write a program to request a positive integer as input and carry out the following algorithm. If the number is even, divide it by 2. Otherwise, multiply the number by 3 and add 1. Repeat this process with the resulting number and continue repeating the process until the number 1 is reached. After the number 1 is reached, the program should display how many iterations were required. Note: A number is even if int(num/2) = num/2. (Test the program with the numbers 9, 21, and 27.) | |||||||||||||||||||
22. | Suppose that the file USPRES.TXT contains the names of all United States Presidents, and the file USSENATE.TXT contains the names of all former and present U.S. Senators. Write a program with nested loops that uses these files to display the names of all Presidents who served in the Senate. | |||||||||||||||||||
23. | Suppose that the file SONNET.TXT contains Shakespeare's Sonnet #18. Each entry in the file consists of a line of the sonnet. Write a program using nested loops to analyze this file line by line and report the average number of words in a line and the total number of words in the sonnet. | |||||||||||||||||||
24. | Suppose that the file SALES.TXT contains information on the sales during the past week at a new car dealership. The file contains the following information for each salesperson at the dealership: the name of the salesperson, pairs of numbers giving the final sales price and the dealer cost for each sale made by that salesperson, and a pair of zeros to indicate the end of data for that salesperson. The first fourteen lines of the file contain the following data: Tom Jones, 18100, 17655, 22395, 21885, 15520, 14895, 0, 0, Bill Smith, 16725, 16080, 0, 0. Write a program to display the name of each salesperson and the commission earned for the week. Assume that the commission is 15% of the profit on each sale. | |||||||||||||||||||
25. | Write a program that uses a flag and does the following:
| |||||||||||||||||||
26. | The salespeople at a health club keep track of the members who have joined in the last month. Their names and types of membership (Bronze, Silver, or Gold) are stored in the text file NEWMEMBERS.TXT. Write a program that displays all the Bronze members, then the Silver members, and finally the Gold members. | |||||||||||||||||||
27. | Table 6.2 gives the prices of various liquids. Write a program that requests an amount of money as input and displays the names of all liquids for which a gallon could be purchased with that amount of money. The information from the table should be read from a file. As an example, if the user has $2.35, then the following should be displayed in the list box: You can purchase one gallon of any of the following liquids: Bleach Gasoline Milk |
Liquid | Price | Liquid | Price |
---|---|---|---|
Apple Cider | 2.60 | Milk | 2.30 |
Beer | 6.00 | Gatorade | 4.20 |
Bleach | 1.40 | Perrier | 6.85 |
Coca-Cola | 2.55 | Pancake Syrup | 15.50 |
Gasoline | 2.25 | Spring Water | 4.10 |
1. | 350 |
2. | When the third score was read from the file, sr.Peek assumed the value -1 With sr.peek = -1,the loop terminated and the third score was never added to sum. |
3. |
Private Sub btnCompute_Click(...) Handles btnCompute.Click 'Find the sum of a collection of bowling scores Dim sum, score As Double Dim sr As IO.StreamReader = IO.File.OpenText("SCORE.TXT") Do While (sr.Peek <> -1) score = CDbl(sr.ReadLine) sum += score |