PROGRAM LOOPS - An Information Systems Approach to Object ...

8 downloads 49 Views 2MB Size Report
Some of the methods that allow you to control what you see inside a ..... The next three sections discuss three different C# iteration keywords that may be used to ...
CHAPTER 8

PROGRAM LOOPS In the Essentials section you will learn: 

How to use ListBoxes



How to construct a well-behaved loop



How to use while, for, and foreach loops



When to break out of a loop



How to write while loops with compound and complex conditions



How to use recursion

 

How to write nested loops When to use continue

In the Bonus section you will learn:

Some business problems require you to repeat a sequential (complex) process on multiple sets of data, whereas other problems involve using a repetitive process to get the desired result. As you’ve already learned, the computer can process complex computations very quickly. This chapter shows how the computer can be an even more useful tool when you have to perform a complex process repeatedly. You will learn the benefit of writing a complex process once and placing it inside a loop, so that the loop applies the process to all sets of data. You will also use ListBoxes to allow the user to store, display, and interact with lists of data.

8-1

8-2

Chapter 8 – Program Loops

ESSENTIAL TOPICS You know by now that writing a computer program to solve a problem involves some effort. If you need to solve that problem again with different input, you simply run the program again. However, if you need to solve fifteen such problems, running the program fifteen times would seem somewhat tedious. There is a better way. If you could gather all fifteen sets of input data, you could run the program once and solve the problem for all sets of input through the use of a loop. To make this solution possible, you need to have a way to hold multiple input data. In this chapter, we use a ListBox on a Windows Form for this purpose. In later chapters, you will learn to use arrays, collections, text files, and databases for storing and retrieving lists of data.

LIST BOXES The ListBox is a Windows Forms control that allows you to store and display multiple pieces of data in a list format. After values are displayed in a list, the user may select one or more items. If the amount of space in the ListBox is not big enough to display all of the list items at once, the ListBox automatically displays a vertical scrollbar that allows you to scroll up and down through the list items. If the width of the ListBox is too small, however, you should assign the HorizontalScrollbar property of the ListBox the value true to scroll left and right. You have probably used ListBoxes in several common Windows applications. For example, Figure 8-1 shows the Paste Special dialog box from Microsoft Word. Notice that it contains a ListBox labeled “As:” to identify the various types of formats that may be used to paste the data contained in the clipboard.

Figure 8-1 ListBox from Paste Special dialog in Microsoft Word

Why Use ListBoxes When you place a ListBox on a form, you are creating an object instance of the .NET ListBox class. Your ListBox object can take advantage of several properties and methods of the ListBox class to simplify programming. For example, by simply setting the Sorted property to true or false, you can control whether the items in the list appear in the order in which they were added to the list or sorted alphabetically. The ListBox class has an Items property that is of type ObjectCollection, which means that each ListBox instance contains a collection of items, usually strings. A collection is a group of related objects that share the same name. Grouping items together as a collection gives you a convenient way to refer to the group as if it were a single object with its own methods and An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

Chapter 8 – Program Loops

8-3

properties. Collections are discussed in more detail in Chapter 9. In this chapter, we use the Items property of the ListBox.ObjectCollection class to gain access to some useful methods that control the contents of the ListBox’s collection. The general syntax for getting access to the ListBox collection through the Items property is as follows: ListBoxName.Items.methodName(); Notice that this notation uses multiple dot operators. Remember that the dot operator is the key to getting inside the object. An object instance appears before the dot, and a property or method appears after the dot. In the preceding example, the first dot (in ListBoxName.Items) allows you to gain access to a specific ListBox object’s collection through the Items property. This collection is also an object to which you can apply a method. Therefore, the second dot (just before methodName) applies the method’s action to the collection object referenced as ListBoxName.Items. Some of the methods that allow you to control what you see inside a ListBox are discussed in the following sections.

How to Add an Item to a ListBox Before you can actually use the ListBox, you must first place data inside its collection. At this point, this data can come from either computing values programmatically or from asking the user to provide input. In later chapters, you will retrieve data from text files and database tables to populate the ListBox. After you know the source of the data, you can place a copy of the data value inside the ListBox’s collection. If the Sorted property is false, then each newly added value appears after the last item in the list .If Sorted is true, the value appears in the proper place to preserve alphabetical order. Keep in mind that if you are adding numbers to a sorted ListBox, the alphabetical ordering will place 57 after 123541, because these values are being compared as strings, not numbers. For the purpose of discussion, let’s assume that the user provides the input data through a text box called txtName. To place the content of txtName inside the ListBox named lstNames, use the Add method of the ListBox.Items property: lstNames.Items.Add(txtName.Text); If you want to control where to add an item in an unsorted ListBox, you may use the Items.Insert method instead of the Items.Add method. In addition to specifying the value to be added, you need to include the location where it should be placed. The location is referred to as the item’s index within the list. Figure 8-2 shows a ListBox containing five values and the corresponding index of each value. The indexing for a ListBox is referred to as zero-based because the first item’s index location is 0 and not 1.

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

8-4

Chapter 8 – Program Loops

Figure 8-2 Index locations for items in a ListBox If you have a list of ten names, the first name’s index is 0, the second name’s index is 1, and the last name’s index is 9. If you want to add an eleventh name to the middle of the list, you need to specify an index of 5 using the following code: lstNames.Items.Insert(5, "Logan"); Figure 8-3 illustrates the addition of an eleventh name (Logan) to the middle of an original list of five girls’ names and five boys’ names.

Figure 8-3 Adding a name to the middle of an unsorted list through the Items.Insert method

How to Determine Which Item in a ListBox Is Selected A user may select one or more items in a ListBox. When this happens, it is sometimes helpful to know which item the user selected. To get the value of the selected item, use the SelectedItem property. The SelectedItem property returns a reference of type System.Object, so you must cast the returned value to the appropriate data type: string selectedName; selectedName = (string)lstNames.SelectedItem; To get the index of the item, use the SelectedIndex property, which returns an int: int selectedNameIndex; selectedNameIndex = lstNames.SelectedIndex; An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

Chapter 8 – Program Loops

8-5

Remember that the indexing is zero-based, so if the first item is selected, the SelectedIndex property returns the value 0. If nothing is selected, the value -1 is returned. If you write code that uses the selected value in a ListBox, it is a good idea to add checks to ensure that the user indeed made a selection: if (selectedNameIndex == -1) { // display a "nothing was selected" error message return; } The example in Figure 8-4 illustrates how to get both the value and index of a selected item. This information is displayed in a multiline text box. (Set the MultiLine property of the text box to true using the Properties Window.) When we create the message, we also use "\r\n" to force a line break between the name and the index of the text that is displayed when a name is selected. 1 2 3 4 5 6 7 8 9 10 11 12 13

int selectedIndex; string selectedName; selectedIndex = lstNames.SelectedIndex; selectedName = (string) lstNames.SelectedItem; if (selectedIndex != -1) { txtMsg.Text = "Selected Name: " + selectedName + "\r\n" + "Index: " + selectedIndex.ToString(); } else { txtMsg.Text = "Please select a name and try again."; }

Figure 8-4 Displaying the value and index of a selected ListBox item Using the Environment NewLine for Readability Because it may not be obvious when reading the code that "\r\n"causes a new line to be added to a string, you may wish to use the longer alternative of Environment.NewLine to make the code more readable. Look at the revised code for line 7 from Figure 8-3 and decide for yourself whether you prefer the abbreviated "\r\n" or more descriptive Environment.NewLine: 7

txtMsg.Text = "Selected Name: " + selectedName + Environment.NewLine +

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

8-6

Chapter 8 – Program Loops

How to Remove an Item from a ListBox After you have added many items to a ListBox’s Items collection, you may have a need to remove a particular item from the list. The Items.Remove and Items.RemoveAt methods are used for this purpose. You identify the item to be removed by providing its index value or providing a reference to the object that was added that you now want to delete. Figure 8-5 shows sample code that uses lstNames from the above example to progressively remove three names from the ListBox. 1 2 3 4 5 6 7 8

// Remove the currently selected item lstNames.Items.Remove(lstNames.SelectedItem); // Remove the third item (index is 2) lstNames.Items.RemoveAt(2); // Remove the item with value "Wilson" lstNames.Items.Remove("Wilson");

Figure 8-5 Removing items through the Items.Remove and Items.RemoveAt methods

How to Clear the Contents of a ListBox If you decide that you need to remove everything from the list, you could use the preceding steps until all items had been removed, but there is an easier way. The Items.Clear method removes all items at once (see Figure 8-6):

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

Chapter 8 – Program Loops

8-7

// Remove all items from the list lstNames.Items.Clear();

Figure 8-6 Removing all items from a list through the Items.Clear method

How to Count Items in a ListBox Sometimes when working with data in a ListBox’s Items collection, it is useful to know how many items there are. This is accomplished using the Items.Count property of the Listbox.Items object. Refer to Figure 8-7 for an example that counts items in a list. int nameCount; nameCount = lstNames.Items.Count; txtMsg.Text = "Your class has " + nameCount.ToString() + " students";

Figure 8-7 Counting all items in a list through the Items.Count property

How to Sort Items in a ListBox At the beginning of this section, we described how you can sort ListBox items alphabetically using the Sorted property. If you try to control the order programmatically, you need to keep in mind that once you sort the list, if you change the Sorted property back to false, the current contents of the ListBox remain sorted, but any newly added items are placed at the bottom of the list. Figure 8-8 illustrates the effect of starting with an unsorted list, sorting it, adding a name, then stopping the sort and adding another name. As you can see, when the Sorted property is true, An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

8-8

Chapter 8 – Program Loops

names are placed in the list in the correct location to preserve alphabetical order. After the Sorted property is changed, the current list items are left as is and all newly added items are placed at the end of the list. Unsorted list at start

After clicking Sort Names

Unsorting (same)

Adding name

Adding a Name

Figure 8-8 ListBox contents based on changing the Sorted property

How to Select an Item in a ListBox Although the user can select one or more items in a ListBox using the mouse or keyboard, your program can also control the selection of list items. The SelectionMode property determines both how many items may be selected simultaneously and how to do multiple selections. By default, the ListBox’s SelectionMode property is set so only one item may be selected at a time. However, the SelectionMode property may be changed to either MultiExtended or MultiSimple. Using MultiSimple allows the user to select or deselect individual items in the list by using a mouse click or by pressing the Spacebar. Using MultiExtended allows the user to select a contiguous group of items by holding down the Shift key and using the mouse or arrow keys to identify the end of the block of items to be selected. If the group of items to be selected is not contiguous, the user can hold down the CTRL key to select all desired items in the list individually. You have already used the SelectedIndex property in a preceding section to find out which item was selected by the user. However, you can change or set an item’s selection by assigning a value to this property. For example, if the ListBox had ten items and you wanted the fourth An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

Chapter 8 – Program Loops

8-9

item to be selected, you would need to assign the value 3 to the SelectedIndex property (because index locations start at 0, so the fourth item’s index is 3): lstNames.SelectedIndex = 3;

You can also get the value of a particular list item if you know its index value. For example, if you want to display a particular name (from the lstNames ListBox) in the text box txtNameOfInterest and the location of that name is stored in the variable indexOfInterest, then use the following code: txtNameOfInterest.Text = (string)lstNames.Items[indexOfInterest];

A ListBox Program Example To practice using everything you have learned so far, let’s create a class list manager program that allows the teacher to add names, remove names, sort the list, count the students, and identify the middle name in the list. The design for the form should look something like the sample shown in Figure 8-9. The properties that you need to change at design time are shown in Table 8-1.

Figure 8-9 Design for a sample Class List Manager form

Table 8-1

Objects properties of a sample Class List Manager form

Object type

Name

Property

Value

ListBox

lstNames

TabStop

False

Label

label1 label2 label3

Text Text Text

Class List: Name to Add: Middle:

Text box

txtName txtMiddleName

Text Text ReadOnly TabStop

empty empty True False

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

8-10

Chapter 8 – Program Loops

Button

btnAdd btnRemove btnSort btnUnsort btnMiddle btnClear btnClose

Text Text Text Text Text Text Text

Add Name Remove Name Sort List Stop Sorting Find Middle Clear Close

In order to make it easier for the teacher to keep adding names, after processing any add, remove, clear, sort, or stop sort request, you should erase the contents of txtName and place the cursor in that text box. To find the middle name in the list, use the Count property to determine how many names are in the list. Once you know how many names are in the list, divide the count by two, then find the largest whole number that is less than or equal to the resulting quotient. To get this result, you can use the Math.Floor method, which was discussed in Chapter 4. This value is the index of the middle name you need to display. To make sure this algorithm for finding the middle name works correctly, consider the following example. Our find-the-middle-name algorithm works perfectly for lists that contain an odd number of items, but when the list contains an even number of items, there are actually two middle names. As long as one of these two names is displayed, the algorithm is acceptable for our needs. For example, if you have five names, the middle name that you want to display is the third name in the list, which has an index of 2. Following the logic we just reviewed, 5 divided by 2 is 2.5. Using the Floor method with an argument of 2.5 returns the value 2. If you have ten names, then you have two middle names. The fifth and sixth names have indices 4 and 5 respectively. Using the algorithm, you would divide 10 by 2 to get 5, and the floor of 5 is 5. Because that is one of the two middle names, it is acceptable to display that value. You should test this logic on different list sizes to verify for yourself that it works correctly. After you are satisfied that it does work, go ahead and try to write the program.(You will learn much more as you read this text if you try to write your own code for the solution to a problem before reading our solution.) When you finish writing your version, compare it to our sample code shown in Figure 8-10. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

private void btnClear_Click(object sender, System.EventArgs e) { lstNames.Items.Clear(); txtName.Text = ""; txtMiddleName.Text = ""; txtName.Focus(); } private void btnAdd_Click(object sender, System.EventArgs e) { // Make sure there is a name to be added. if (txtName.Text == "") { messageBoxOK("Please enter a name to add it to the class list."); txtName.Focus(); return; } lstNames.Items.Add(txtName.Text); txtMiddleName.Text = ""; txtName.Text = ""; txtName.Focus(); } private void btnRemove_Click(object sender, System.EventArgs e) { // Make sure that a name has been selected.

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

Chapter 8 – Program Loops 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

8-11

if (lstNames.SelectedIndex == -1) { messageBoxOK("Please select a name to remove it from the class list."); lstNames.Focus(); return; } lstNames.Items.Remove(lstNames.SelectedItem); txtMiddleName.Text = ""; txtName.Focus(); } private void btnMiddle_Click(object sender, System.EventArgs e) { int nbrItems; int midLocation; // Find out how many names are in the list. nbrItems = lstNames.Items.Count; // Make sure there is at least one name. if (nbrItems == 0) { messageBoxOK("There is no middle name in an empty class list."); return; } // Find the index of the middle name. midLocation = (int) Math.Floor(nbrItems/2); txtMiddleName.Text = lstNames.Items[midLocation].ToString(); txtName.Focus(); } private void btnSort_Click(object sender, System.EventArgs e) { lstNames.Sorted = true; } private void btnUnsort_Click(object sender, System.EventArgs e) { lstNames.Sorted = false; }

Figure 8-10 Sample Class List Manager program code listing

CONSTRUCTING LOOPS Now that you have a way of keeping a collection of items in a ListBox, you are ready to begin using program loops. Loops are program structures that represent a set of program statements that are usually processed one or more times. When you have written a program to perform a complex computation for one piece of data, and then discover that you have several more pieces of data that need to be processed in the same manner, you can modify your program by embedding the processing steps you already wrote inside a loop. Using a loop enables you to run the program once for all the data, saving you time. For example, below is an algorithm for computing a person’s final restaurant bill after adding a 6% sales tax and 15% tip: 1. Get the base food/drink price.

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

8-12

Chapter 8 – Program Loops

2. Find the sales tax by multiplying the base price by 6%. 3. Find the tip by multiplying the base price by 15%. 4. Find the sum of the base price, sales tax, and tip. 5. Pay your server. If you went out to dinner with nine of your friends, you would repeat the above process for each person to get the total amount your party owed. Because there are ten people, the algorithm would involve fifty steps! However, if you recognize that all of you are doing the same thing, you could embed the similar steps inside a loop and use the following shorthand for a loop-based algorithm: 1. For each diner: a) Get the base food/drink price. b) Find the sales tax by multiplying the base price by 6%. c) Find the tip by multiplying the base price by 15%. d) Find the sum of the base price, sales tax, and tip. e) Add this to your party’s total. 2. Pay your server the final party total. The preceding algorithm repeats Steps 1a to 1e ten times. Each cycle through the loop is also known as iteration. When you write loops in your programs, you use one of the available iteration statements. However, be careful when using loops. If you create a loop carelessly, your program could continue looping forever.(Loops that get stuck and fail to terminate are called infinite loops or continuous loops.) One way to avoid this problem is to write well-behaved loops, which are discussed in the next section.

Three Conditions of a Well-Behaved Loop If you have a way of determining the number of iterations your program needs to complete, you can write a well-behaved loop that counts each loop cycle. A well-behaved loop has three basic conditions: 1. There is an initial state of the data before the start of the loop. 2. During each iteration, some data item must change its state. 3. Before the next iteration begins, the state of the data is checked to determine whether another iteration of the loop is necessary. If a loop violates any of these three conditions, it is considered an ill-behaved loop and could cause your program to crash or produce incorrect results. In the case of the restaurant example, the state could be keeping track of the diner by number. After each diner’s total bill is processed, the number of diners is increased by one. You keep repeating the process until all ten diners’ total bills have been processed. To relate this to the three conditions of a well-behaved loop, you follow these steps: 1. Start with the first diner (initial state is dinerCount = 1). 2. After completing the processing for the current diner, prepare for the next diner (change state by adding 1 to dinerCount). 3. Before the next iteration begins, check the value of the dinerCount to make sure it does not exceed 10. An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

Chapter 8 – Program Loops

8-13

If you wrote the loop starting with dinerCount = 10, you would process only the last diner’s bill, resulting in insufficient money to pay off the bill. This ill-behaved loop violates the first condition. If you forgot to change dinerCount after handling the first diner’s bill, you would end up processing the first diner’s bill a second time, then a third time, and so on, forever! Forgetting to change the state of the data violates the second condition and results in a never-ending or infinite loop. Using Visual Studio to Terminate an Infinite Loop During the program development process, you might accidentally write code that creates an infinite loop. When your program executes, it gives the appearance that the program is stuck and you can’t get control back; however, Visual Studio provides a way to terminate program execution when you suspect there is a problem, such as an infinite loop. Simply select the Break All or Stop Debugging option from the Debug menu. To locate the problem, you should use the Break All option and then step through program execution one statement at a time to help pinpoint the error.

If your test compared dinerCount against 9 instead of 10, your total would still be too low. If you compared it to 100, the program would produce an error as soon as it tried to process the eleventh diner. If you checked something other than dinerCount, you could potentially have another infinite loop. All of these problems violate the third condition. If you structure the loop correctly, you have a well-behaved loop that should produce the correct results. The restaurant bill example also illustrates a counting loop, which is discussed in the next section.

THE COUNTING LOOP The counting loop is a well-behaved loop that uses a loop counter variable to manage its state. Counting loops are used when your program can determine how many iterations of the loop should be executed. We can define the three conditions of a well-behaved counting loop as follows: 

Initialize the loop counter—The loop counter receives an initial value.



Change the state of the loop counter—The loop counter is always incremented or decremented by a fixed amount.



Check the state of the loop counter for the next iteration—After the value of the loop counter is beyond the final value, the loop is terminated.

The next three sections discuss three different C# iteration keywords that may be used to create counting loops: while, for, and foreach. These unique keywords identify the type of program loop, and curly braces { } are used to surround the statement(s) that are to be repeated in the loop’s statement block. The left curly brace { identifies the start of the loop statement block, whereas the right curly brace } identifies the end of the loop statement block. The statements inside the curly braces are referred to as the loop body or loop statement block. As you review the following sections that cover writing each of these loop structures, pay careful attention to how you can ensure that all three conditions to make the loop well-behaved have been considered.

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2009 Kyle Lutes & Alka Harriger

8-14

Chapter 8 – Program Loops

The while Loop The while loop is a conditional loop that takes the general form shown in Figure 8-11:

Figure 8-11 General form of a while loop The testCondition on the while statement is any Boolean expression. The loop body is executed repeatedly until the given testCondition evaluates to false. Although the while loop can do more than count (as you will see in later chapters), in this section we describe only how to use the while loop as a counting loop to allow you to compare it to the for and foreach loops. The state initialization step occurs before the while statement, often the statement immediately before the while statement. It frequently looks like an assignment of an initial value to a variable that is used in the testCondition of the loop such as: loopCounter = startingValue; When the while statement is encountered, and before the loop begins execution, the testCondition is checked. The testCondition typically looks like a comparison of a variable (assigned in the initial value) to an ending value such as: while (loopCounter

Suggest Documents