The While Loop


The while loop is similar to a for loop in that both have the typical characteristics of a loop: the code inside each continues to iterate until a condition becomes false. The difference between them is in the parentheses following the for and while keywords.

The parentheses following the for keyword consists of three expressions, initialization, condition, and update. By contrast, the parentheses following the while keyword consists only of the condition; you have to take care of any initialization and update elsewhere in the code.

This difference is illustrated by the following program that outputs the numbers between 1 and 10. Chapter 7 included the following program that outputs the numbers between 1 and 10 using the for loop.

 #include <iostream> using namespace std; int main(void) {  for (int num = 1; num <= 10; num++)  cout << num << " ";  return 0; } 

The same program using the while loop could be

 #include <iostream> using namespace std; int main(void) {  int num = 1;  while (num <= 10)  {  cout << num << " ";  num++;  }  return 0; } 
Note  

The two statements in the body of the while loop could have been combined into one statement, cout << num++. Two statements are used instead to make this example easier to understand by eliminating the precedence issue in the one statement between the stream insertion and increment operators.

With the while loop, the integer variable num had to be declared and initialized before the loop since this cannot be done inside the parentheses following the while keyword. Further, num was updated inside the code of the loop using the increment operator. This update also can be done inside the parentheses following the while keyword as shown by an example later in this section.

The update of the variable is particularly important with the while loop. Without that update, the loop would be infinite. For example, in the following excerpt from this program, if num is not incremented, the loop would be infinite. The value of num would not change from 1, so the condition num < = 10 always would remain true.

 int num = 1;  while (num <= 10)  cout << num << " "; 

Forgetting to update the value of the variable you are using in the condition is a common mistake with a while loop. Forgetting the update is less common with a for loop because that update is the usual purpose of the third expression in the parentheses following the for keyword.

Otherwise, the syntax rules discussed in Chapter 7 concerning the for loop apply equally to the while loop. For example, if more than one statement belongs to the while loop, then the statements must be contained within curly braces. That is why in the program that outputs the numbers between 1 and 10 using the while loop, the two statements in the body of the while loop are contained within curly braces.

 while (num <= 10)  {  cout << num << " ";  num++;  } 

In the program we just analyzed , the update of the value of num was done within the body of the loop. The update could also be done within the condition itself:

 #include <iostream> using namespace std; int main(void) {  int num = 0;  while (num++ < 10)  cout << num << " ";  return 0; } 

Updating the counter within the condition requires two changes from the previous code. First, the value of num has to be initialized to 0 instead of to 1 because the increment inside the parentheses during the first iteration of the loop would change that variable s value to 1. Second, the relational operator in the condition is < rather than <= because the value of num is being incremented before it is outputted.

Updating the counter within the condition raises the question: Given the condition num++ < 10, which comes first, the comparison or the increment? Since the increment is postfix, the answer is the comparison.

The counter also could be updated within the condition using a prefix increment. However, then the condition should be ++num < = 10 to obtain the desired output.

As with the for loop, the statement or statements following the while keyword and parentheses will not execute if the parentheses is followed by a semicolon, as that would be interpreted as an empty statement. Test yourself on this; what would be the output if we placed a semicolon after the while condition as in the following code fragment?

 while (num <= 10);  cout << num++ << " "; 

The only number that would output is 11. The reason is that the loop continues, and the empty statement executes, until the condition fails when num is 11, at which time the statement following the loop executes and the value of num (11) is outputted.

Comparison of for and while Loops

The practical difference between the for and while loops is not apparent in a program with a predictable number of iterations, such as the program we have been discussing thus far that outputs the numbers between 1 and 10. Rather, a while loop is a superior choice to a for loop in a program where the number of iterations is unpredictable, depending on user input during runtime.

For example, in the following program, the program asks the user to enter a positive number, and in a loop continues that request until the user does so. The number of times this loop may execute is unpredictable. It may never execute if the user enters a positive number the first time, or it may execute many times if it takes the user several tries to enter a positive number.

 #include <iostream> using namespace std; int main(void) {  int num;  cout << "Enter a positive number: ";  cin >> num;  while (num <= 0)  {  cout << "Number must be positive; please retry: ";  cin >> num;  }  cout << "The number you entered is " << num << " ";  return 0; } 

Here is some sample input and output:

 Enter a positive number: 0 Number must be positive; please retry: -1 Number must be positive; please retry: 3 The number you entered is 3 

This program would be more difficult to write with a for loop. While it could be done, the for loop is designed for situations in which the number of iterations is predictable.

Using the break Keyword

Even though the while loop is a better choice than a for loop for this program, which requires the user to enter a positive number, there are two problems with this program: one minor and one major.

The minor problem is that there is some repetition of code; the user is requested both before and inside the loop to enter a positive number. A do while loop, which is explained in the following section, avoids this repetition, but repeats other code (there are tradeoffs in loops as well as in life).

The major problem is that the user is trapped inside the loop until they enter a positive number. That is not a good programming design. While the user should be required to enter good data if they are going to enter any data at all, they should have the option, when told the data entered was not valid, of quitting the data entry.

The following modification of the program uses the break keyword to provide the user with the option of quitting the data entry:

 #include <iostream> using namespace std; int main(void) {  int num;  char choice;  cout << "Enter a positive number: ";  cin >> num;  while (num <= 0)  {  cout << "Number must be positive; try again (Y/N): ";  cin >> choice;  if (choice == 'Y')  {  cout << "Enter number: ";  cin >> num;  }  else  break;  }  cout << "The number you entered is " << num << " ";  return 0; } 

Here is some sample input and output when the user eventually enters a positive number:

 Enter a positive number: 0 Number must be positive; try again (Y/N): Y Enter number: -1 Number must be positive; try again (Y/N): Y Enter number: 3 The number you entered is 3 

Here is some sample input and output when the user does not enter a positive number but instead decides to quit:

 Enter a positive number: -2 Number must be positive; try again (Y/N): N The number you entered is -2 

Flags

The flags modification is an improvement because the user no longer is trapped inside the loop until they enter a positive number, but instead has the option of quitting data entry. However, the second sample input and output, in which the user quits data entry, illustrates a problem. The final cout statement outputs the number entered, even if the number is invalid data.

Ideally, we would only want to output the data if it were valid. If the data were not valid, then we would want to output that fact instead. However, the code thus far does not enable us to differentiate whether the while loop ended because the user entered valid data or because the user decided to quit after entering invalid data.

In Chapter 7, I recommended that you use the break keyword sparingly because it created multiple exit points for the for loop, making your code more difficult to understand and increasing the possibility of logic errors. That advice also applies to the while loop. I recommended then, and recommend now, as an alternative the use of a logical operator. The following program modification adopts that alternative.

 #include <iostream> using namespace std; int main(void) {  int num;  char choice;  bool quit = false;  cout << "Enter a positive number: ";  cin >> num;  while (num <= 0 && quit == false)  {  cout << "Number must be positive; try again (Y/N): ";  cin >> choice;  if (choice != 'Y')  {  cout << "Enter number: ";  cin >> num;  }  else  quit = true;  }  if (quit == false)  cout << "The number you entered is " << num << " ";  else  cout << "You did not enter a positive number";  return 0; } 

Here is some sample input and output when the user eventually enters a positive number:

 Enter a positive number: -3 Number must be positive; try again (Y/N): Y Enter number: 3 The number you entered is 3 

Here is some sample input and output when the user does not enter a positive number but instead decides to quit. This time the final output is not of the number entered, but rather that the user did not enter a positive number:

 Enter a positive number: 0 Number must be positive; try again (Y/N): Y Enter number: -1 Number must be positive; try again (Y/N): N You did not enter a positive number 

This program modification, in addition to using the logical && operator, uses a Boolean variable named quit. This Boolean variable is used as a flag. A flag is a Boolean variable whose value indicates whether a condition exists.

In this program, the while loop continues to loop as long as the data entered is invalid and the user wants to keep going. Accordingly, the while keyword is followed by two conditions, joined by the logical && operator.

Note  

A common programming mistake in a while condition using a logical operator is to use && when you should use or vice versa. While the logical && operator may seem the obvious choice in this example, the correct choice in other situations may be less intuitive. For example, if you want to loop while a number is not between 1 and 10, would the loop be while (num < 1 && num > 10) or while (num < 0 num > 10)? The answer is the latter; the condition always would be false using the && operator since a number cannot be both less than 1 and greater than 10. If you wanted to use the && operator, the condition instead would be while (num >= 1 && num <= 10).

The first condition is if num < = 0. If this expression is false, the data is valid, so the issue of whether the user wants to quit does not arise. Accordingly, the second condition, whether quit is true, is not even evaluated. As discussed in Chapter 7, with a logical && operator, the right expression is evaluated only if the left expression is true. Therefore, the while loop ends with the value of quit being false, its initialized value, and code execution continues with the if / else statement following the while loop.

However, if num < = 0 is true, then the data is invalid, and the second condition, whether quit is true, is evaluated.

The value of quit may be true under either of two possibilities. The first possibility is that this is the user s first attempt to enter data and the data was invalid. In this case, the user has not yet been asked whether they want to quit. It is assumed they don t, so they have the opportunity to answer whether they want to retry. Therefore, the quit variable is initialized to the value of false when it is declared.

The second possibility is that this is the user s second or later attempt to enter data and the data was invalid. In this case, the user has already been asked whether they want to quit, so the value of quit is based on the user s answer.

If the value of quit is false, the while loop continues. However, if the user wants to quit, then the right expression quit == false will be false because the value of quit is true. Therefore, the while loop ends with the value of quit being true, and code execution continues with the if / else statement following the while loop.

At some point (hopefully) the while loop will end, either because the user has entered a valid number or has not and decided to quit trying. Code execution then continues with the if / else statement following the while loop.

The value of quit being false necessarily indicates that the user entered valid data, because if they were still trying to do so, the loop would not have ended. Conversely, the value of quit being true necessarily indicates that the user entered invalid data.

Accordingly, we use the value of quit in the if /else statement after the while loop to differentiate whether the while loop ended because the user entered valid data or instead decided to quit after entering invalid data.

Thus, inside the while loop, quit is a flag whose value indicates whether the user wants to try again, and after the while loop ends, quit is a flag whose value indicates whether the user entered valid data.

While (true)

In Chapter 7, we discussed the use of the for loop with the omission of the condition that is the second expression, such as for (; ;). There, an infinite loop was avoided by using the break keyword inside the loop. While I did not recommend this use of the for loop, I mentioned it because you may encounter it as programmers do use the for loop this way.

Similarly, programmers sometimes make the condition of the while loop always true, such as while (true) or while (1), and break out of the while loop with, you guessed it, the break keyword. Here is an example that is a modification of the program we have been using that asks the user to enter a positive number.

 #include <iostream> using namespace std; int main(void) {  int num;  char choice;  bool quit = false;  while (true)  {  cout << "Enter a positive number: ";  cin >> num;  if (num > 0)  break;  else  {  cout << "Number must be positive; try again (Y/N): ";  cin >> choice;  if (choice != 'Y')  {  quit = true;  break;  }  }  }  if (quit == false)  cout << "The number you entered is " << num << " ";  else  cout << "You did not enter a positive number";  return 0; } 

The one advantage of this modification is that it renders unnecessary having to prompt the user both before and inside the loop to enter a positive number. However, the use of the while (true) syntax has the disadvantage of making your code less readable because the condition that stops the loop cannot be discerned from the parentheses following the while keyword. The do while loop (explained later in this chapter) avoids this disadvantage and would be a preferable choice.

The continue Keyword

You can use the continue keyword in a while loop just as you can in a for loop. As discussed in Chapter 7, the continue keyword, like the break keyword, is used within the code of a loop, commonly within an if / else structure. If the continue statement is reached, the current iteration of the loop ends, and the next iteration of the loop begins.

Chapter 7 demonstrated the use of the continue keyword in a program in which the user is charged $3 an item, but not charged for a baker s dozen , so every 13 th item is free ”that is, the user is only charged the price for a dozen items, even though they receive 13. The following is a modification of that program using a while loop.

 #include <iostream> using namespace std; int main(void) {  int num, counter = 0, total = 0;  cout << "How many items do you want to buy: ";  cin >> num;  while (counter++ < num)  {  if (counter % 13 == 0)  continue;  total += 3;  }  cout << "Total for " << num << " items is $" << total;  return 0; } 
Note  

The % ( modulus ) operator is used if the remainder is 0, 13, or a multiple of 13 items.

While this use of the continue keyword certainly works, as I cautioned in Chapter 7, you should use it (as well as the break keyword) sparingly. Normally, each iteration of a for loop has one end point. However, when you use a continue statement, each iteration has multiple end points. This makes your code more difficult to understand, and can result in logic errors.

I suggested in Chapter 7, in an example using the for loop, that you could use the logical ! (Not) operator as an alternative to using the continue keyword. Here is how you could do so using the while loop.

 #include <iostream> using namespace std; int main(void) {  int num, counter = 0, total = 0;  cout << "How many items do you want to buy: ";  cin >> num;  bool keepgoing = true;  while (counter++ < num)  {  if (! (counter % 13 == 0))  total += 3;  }  cout << "Total for " << num << " items is $" << total;  return 0; } 
Note  

You also could use the relational != (not equal) operator, changing the if statement to if (counter % 13 != 0).

Nesting While Loops

In Chapter 7, I showed you how you can nest one for loop inside another. Similarly, you can nest one while loop inside another. You also can nest a while loop inside of a for loop, or a for loop inside of a while loop.

Chapter 7 demonstrated nested for loops with a program that prints 5 rows of 10 X characters . The following is a modification of that program using nested while loops.

 #include <iostream> using namespace std; int main(void) {  int x = 0;  while (x++ < 5)  {  int y = 0;  while (y++ < 5)  cout << "X";  cout << '\n';  }  return 0; } 

The variable y, used as a counter in the inner while loop, needs to be reinitialized in the outer while loop. The variable y could be declared outside the loops, but it needs to be assigned (or reassigned) the value of zero inside the outer loop since the inner loop goes through all of its iterations for each iteration of the outer loop.

Since each loop has a predictable number of iterations, using nested for loops is somewhat simpler than using nested while loops. However, both work.




C++ Demystified(c) A Self-Teaching Guide
C++ Demystified(c) A Self-Teaching Guide
ISBN: 72253703
EAN: N/A
Year: 2006
Pages: 148

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net