CSIS 113A
Friday, May 24, 2013
4. Repetition     Register Login
  • Home
  • 1. Introduction
  • 2. Data Types   
  • 3. Decisions      
  • 4. Repetition    
  • 5. Functions     
  • 6. Parameters
  • 7. Arrays       
  • 8. Pointers     
  • 9. Structures  
  • Syllabus
    • 3937
    • 3939
    • 3987

Repetition

Minimize
  • A. Introduction
  • B. Counted Loops
  • C. Indefinite Loops
  • D. C++ Jumps
  • E. Video Lectures
Introducing Loops

What is iteration ? Iteration is a Computer Science term that simply means repeating a set of actions. Iteration is also called repetition or looping . The statements that are used in iteration are called loops .

Iteration and Selection

Both iteration statements and selection statements are flow-of-control statements ; they control which code is executed in your program. Like the if statement, iteration is based upon evaluating a boolean -- true/false --condition, and then performing a set of actions if the test is true , and skipping them if the test is false . Thus a loop, like an if statement, has both a condition part --the test that is performed--and a body part --the actions that are taken.

Iteration, however, is not the same as selection. Beginning programmers often attempt to use a selection statement where they should use a loop, and vice versa. It is important to be able to distinguish the two, and equally important to be able to select the right control structure for the job.




The selection structure works much like the illustration shown here. Driving down a divided highway, you come to a rest stop, and you pull off. When you leave the rest stop, you rejoin the highway a little further down the road.

Once you rejoin the highway, you have no opportunity to go back, and revisit the rest stop again. Those who bypass the turnoff, skip the rest stop altogether.


A loop structure looks similar, but not the same. As you can see in this illustration, there is still a boolean test, as there is with selection. But, after you've had your break, the rest stop exit road "loops back" [hence the name], and you rejoin the highway right where you initially left it.

If you like, you can choose to enter the rest stop once again, even though the highway is one-way. In this sense, a loop also works a little bit like a cloverleaf interchange.



C++ and Iteration (Looping)


C++ has three loop statements, the while loop, the do - while loop, and the for loop. As you might expect, each of these loops varies in the way that it is used, and the place where it is most effectively employed.

One difference between the loops is where the test takes place--that is, the relative position of the loop test, and the actions contained in the loop body.

Where

One loop, the do - while loop, doesn't make it's test until after it has performed the actions in the loop body at least once.

This is called a "test at the bottom" loop. It is also sometimes called a hasty loop or an unguarded loop, because it "leaps before it looks".

{ // Loop body

}

Loop Test

Loop Test
{

// Loop body

}

The other two loops, the for loop and the while loop, both make their boolean test before performing the actions in the loop body.

With these loops, if the test condition is false , then the actions inside the loop body are never performed at all. Thus, they are both guarded loops.


Counted and Indefinite


Classifying loops according to where their condition is tested helps keep the C++ syntax straight in our minds, but it's not really as useful as classifying loops by the kind of bounds that they employ.

 A loop's bounds are the conditions under which it will repeat its actions. In a simple, counter controlled loop, the bounds might be expressed as "the counter has a value less than ten". In other, more complex loops, the bounds may be a combination of conditions involving ANDs and ORs.

There are two major kinds of loops that can be built using the basic building blocks [ for , while , and do - while ] provided by C++. Let's look at them briefly, before we start looking at code in the next lesson.

Counting or Counted Loops

A counting , [or counted ], loop is a loop that repeats a fixed number of times--a "gimme fifty pushups" kind of loop.

With a "pure" counting loop you can look at the code and tell how many times it should execute. In real life, however, things are not so clear-cut. You often won't know what the actual number of repetitions is until your program runs. The number of repetitions may be based upon the number of characters in a String , for instance, or some other number which is not computed until your program runs.

Indefinite Loops

With an indefinite loop, you can never tell how many times the loop will repeat by examining the code. An indefinite loop is a loop that tests for the occurrence of a particular event, not a count of the number of repetitions.

"Read characters until you encounter a period" is an example of an indefinite loop. The condition may occur after reading three characters, or it may occur after reading three-thousand. It's also possible that the period might be the first character read or, sometimes, that a period might not occur at all.

There are three commonly encountered types of indefinite loops that you should be aware of. Each of these indefinite loops uses a different sort of bounds:

  • Data loop. A data loop is a loop that keeps going until there is no more data . This is used when reading files or sending Web pages over the Net. We'll cover data loops in more detail in Unit 14, "Streams and Files."
  • Sentinel loop . A sentinel loop is an indefinite loop that looks for the presence of a special marker contained within its input. In the "read characters until you encounter a period" example, the period is the sentinel; this kind of loop is a sentinel loop . Sentinel loops are often used in searching, but have other uses as well.
  • Limit loop. Limit loops are loops that end when another repetition of the loop won't get you any closer to your goal. Limit loops are often used in scientific calculations and other numeric algorithms, when stating a precise termination condition is not possible. Often this involves monitoring the difference between two variables, and stopping the loop when the difference passes a predetermined threshold.
A Loop Building Strategy


Writing perfect code the first time is something of a "Holy Grail" among programmers. By that I mean that most programmers long to do it, but the vast majority consider its attainment to be the stuff of legend.

Writing loops is one area where programming errors often crop up. Several years ago, however, I happened upon a technique developed by Doug Cooper, the Berkeley professor of " Oh! Pascal " fame, for building loops. This technique really does increase your chances of building correct loops the first time, and it's worth your time to learn it.

The Three Faces


 

If you put a loop inside a program, as we've done with this top-tested loop, you can see that there are
  • actions that occur before the loop is encountered
  • actions that occur inside the loop body
  • actions that occur after the loop is complete.
// Before
Loop Condition
{
// Inside
}
// After

Bounds and Goal


The first step in building a successful loop is to be able to describe [and separate] the loop's bound from the loop's goal .

Here's an example:

    Count the characters in a String until a period is encountered. Every String will contain at least one period.
  • The goal of this loop is to count the characters that precede a period [that is, a sentence].
  • The bounds of the loop are "a period was encountered."

We can use the same bounds with a different goal: Print each character in a String until a period is encountered. Here, the bounds is the same, but the goal is different. We're not counting, we're printing.

Step 1 Determine the Bounds


If you've ever bought a new appliance or a new software package, what's the first thing you need to learn? How to stop it once it gets going.

That's where you should always start writing your loops; ask yourself: "What will make this loop quit?"
"How do I get out of here?" Making sure your loops can quit is the single most important thing that you can do. Let's take our first example in the previous section, and write the loop bounds in psuedocode:


Step 1: The Bounds
// BEFORE

WHILE C IS NOT A PERIOD
{
// INSIDE
}

// AFTER


Step 2: The Preconditions


Step 1, writing the bounds, makes sure that it is possible to get out of the loop. When you write this portion you'll have to make sure your boolean condition is not unavoidable or impossible, just as you did with selection statements.

Now that you've convinced yourself that it's possible to exit the loop, you have to write the statements that make it possible to enter the loop. Step 1 asks "How do I get out?" , while Step 2 asks "How do I get in?"

Precondition statements usually involve creating variables and initializing them to some reasonable state. In our example, we have two variables C , which is a character, and S , which is a String .

Before you encounter the loop bounds, you must make sure that C holds one of the characters in S , otherwise, you have no assurance that you will ever enter the loop--the value in C will be unknown.

In pseudocode, we could write this as:

Step 2: The Bounds Precondition
S IS A STRING INPUT FROM THE KEYBOARD
C IS A CHARACTER
ASSIGN FIRST CHARACTER IN S TO C

WHILE C IS NOT A PERIOD
{
// INSIDE
}

// AFTER



Advance The Loop
Now that you've written the bounds and preconditions, it's time to advance the loop. Advancing the loop means that you add statements to the loop body that move you closer toward the loop bounds.

 Suppose, for instance that we didn't put any statements inside the loop body used here. What would happen?

  1. If the String S began with a period, the loop would not be entered and the program would perform correctly.
  2. Otherwise, when the loop body was entered, nothing in the body would change the value of C , so you would have no way out of the loop; it would simply repeat over and over, endlessly. Such endless loops are very, very common.

To avoid an endless or "dead" loop, you must make sure that the statements on the inside of the loop body change something that is tested in the loop bounds.

In this case, that's as simple as storing the next character in the String S in the variable C , like this:

Step 3: Advancing the Loop
S IS A STRING PASSED AS AN ARGUMENT
C IS A CHARACTER
ASSIGN FIRST CHARACTER IN S TO C

WHILE C IS NOT A PERIOD
{
ASSIGN NEXT CHARACTER IN S TO C
}

// AFTER


Step 4: The Goal


At this point, the mechanical portion of your loop--the part that makes it "work", so to speak--is finished. You should be able to compile your code [provided you wrote it in a programming language, of course], and it should run correctly.

The whole purpose of a loop, however, is to get some real work done, to accomplish the goal. Up until now, we've ignored the goal portion entirely, because we want to make sure the loop works , before we put it to work .

When writing the code to carry out the goal of the loop, you start at the precondition, move to the loop body, and then deal with the post condition. You don't have to worry about the post condition while programming the mechanical operation of the loop, but it is often significant when it comes to the loop's goal.

Here's what to do:

  1. The precondition involves creating and initializing the variables necessary to carry out the goal of the loop. In our case, the goal is to count the characters in the first sentence, so we need a counter variable initialized to zero.
  2. The statements inside the loop body usually update the variables created in the precondition. For this example, we merely increment our counter every time through the loop.
  3. In the post condition, you often must check one of the bounds conditions to see how to proceed. In our case, that's not necessary, because, if we never enter the loop, our counter will be zero. If the goal of our loop was to average a set of numbers, however, we would first need to check to make sure that the loop had been entered before calculating and printing an average.

Here's the finished pseudocode for our loop:

Step 4: Carry Out the Goal
S IS A STRING PASSED AS AN ARGUMENT
C IS A CHARACTER
ASSIGN FIRST CHARACTER IN S TO C

COUNTER IS AN INTEGER, INITIAL VALUE ZERO

WHILE C IS NOT A PERIOD
{
ADD ONE TO COUNTER
ASSIGN NEXT CHARACTER IN S TO C

}

COUNTER HOLDS NUMBER OF CHARACTERS IN SENTENCE

Counted Loops

The first loop we're going to look at is the for loop. Both Pascal and Basic have for loops, as do C and C#. Like those languages, the for loop in C++ is designed for writing counted loops--loops that repeat a specified number of times.

Unlike the Pascal or Basic for loop, however, the for loop in C++ can do much more than simple counted loops. The for loop in C++ is a general purpose, "test at the top" loop, that makes writing counted loops very straightforward, but can be used for other purposes




As mentioned previously, the body of the for loop follows the loop's test condition; you test first, then, if the test evaluates to true, you enter the loop body, as you can see in the illustration. [click image to enlarge]
The for loop's condition involves more than a simple boolean test, however. In fact, it involves three different expressions:

  • The initialization expression
  • The test expression
  • The update expression
Each of these three expressions is separated from the others by a semicolon . You can omit any--or all--of the expressions, but the semicolons are required. [Make sure you don't accidentally use commas instead of semicolons. When you do so, the C++ compiler is not particularly helpful with its error messages]

The loop body following the loop condition is usually enclosed in braces, although, technically, braces are not required if the loop body consists of a single statement. As a practical matter, though, you'll almost always use braces, and, since they don't hurt--even when not strictly required--you should always put them in as a matter of course.

Let's return to the for loop condition, and take a closer look at each of its three expressions


The Initialization Expression

When a for loop is encountered, the first part of the loop condition, the initialization expression, is executed. It is always executed, regardless of the other parts of the for statement, almost as if it occurred on the previous line.

The initialization expression is evaluated only once, and is usually used to define the counter variable that will control your loop, like this

The for Loop Initialization Expression
for ( int counter = 0; ... ; ...)
{
// Can use counter here
}
// Cannot use counter here

Variables declared inside the for loop initialization section, like counter , shown here, are local to the body of the for loop. Once the loop is finished, the variable goes out of scope and can no longer be used.


The Boolean Test

The second section of the for loop is called the test condition . The test condition is a boolean expression which is evaluated immediately after the initialization expression.

If the test condition is true , [when it is evaluated], then execution begins with the first statement in the loop. If it is false , then the entire loop body is skipped, and execution continues at the first statement following the loop body.

To continue our example, we can test the value of counter , checking to make sure it is less than ten:

The for Loop Test Expression
for (int counter = 0; counter < 10 ; ...)
{
// Can use counter here
}
// Cannot use counter here

Using counter like this insures that the loop will execute ten times. This is a common idiom in C++ programming:

  • start counter at 0
  • test that counter is less than the upper bounds

An idiom is just a common and widely accepted way of "phrasing" a particular operation. This particular idiom works well, because you can immediately tell how many times the loop will execute just by glancing at the test condition.

The Update Expression

In Lesson A, "Introduction to Loops", you learned to make sure that every repetition of a loop moves closer to the loop bounds. But, in the for loop shown here, there are no statements that move toward the bounds; in fact, as written, this example is an endless loop ! Since counter is never updated, it always remains at zero.

Updating the counter is the responsibility of the third part of the for loop condition--the update expression . The update expression is evaluated after the body of the loop is finished, but before the test expression is evaluated for the next repetition.

For a counted loop, you'll use the test expression to update your counter like this:

The for Loop Update Expression
for (int counter = 0; counter < 10 ; ++counter )
{
// Can use counter here
}
// Cannot use counter here

Counting Variations

You've probably noticed that this loop doesn't really do anything; the portion that we've written simply repeats ten times. However, you can use this basic skeleton for any loop that needs to repeat a fixed number of times. Simply replace 10 with the number of times you want to repeat, and you're all set.

In addition to acting as a loop control, you can also use your counter variable to process different pieces of information during each repetition of the loop. Here, for instance, is a loop that sums the ascii values for all the characters in a String :


0
  • Move
  • Close

#include <iostream>
#include <string>

using namespace std; 

int main()
{
    string str;

    cout << "Enter a string and I will sum all of the characters " << endl;
    getline(cin, str);
 
    int sum = 0;
    for(int i = 0; i < str.length(); i++)
    {
        sum+= static_cast<int>(str[i]);
    } 
    cout << "The sum of all the characters is " << sum  << endl;
    return 0;
}

1
Code Review
The above code uses getline to get a line of text from the keboard and store it in the string variable calles str. A variable called sum is created to act as an accumulator to hold the sum of all the ascii values within the string. The for loops starts at 0 and loops to the length of the string. Inside the body of the loop the each character is cast to an int and added to the sum. Finally, the sum of all of the ascii values in the string is printed to the screen.

Counting Down
When you create a counted loop using for , you are responsible for initializing the counter in the initialization expression, and for updating it in the update expression. There's no law that says you have to start at zero, and there's nothing to stop you from counting down rather than up. Here is the above code modified so that it will sum the values in reverse order:

Not only can you count up and count down, you can also count by values other than 1, simply by changing the value in the update expression. The Basic language allows you do do this via its STEP clause, but the C++ for loop allows you to use any expression you like, not just different constant values.

Here, for instance, is how you could calculate the sum of all the even numbers less than 100:

Counting By Steps
int sum = 0;
for (int i = 0; i < 100; i += 2)
{
Sum += i;
}


Code Review

Notice that i is set to str.length() - 1? This is because everything in computer science is 0 based and str.length() returns the number of characters. For instance the string "test" has 4 characters in it and that is what length() would return but these chracaters are indexed 0 to 3 which also gives us for characters. Also notice the test condition is i >= 0 this is becuse we want to count the 0th character. If you run the program both ways you will see that the result is the same.

Counting By Steps

Not only can you count up and count down, you can also count by values other than 1, simply by changing the value in the update expression. The Basic language allows you do do this via its STEP clause, but the C++ for loop allows you to use any expression you like, not just different constant values.

Here, for instance, is how you could calculate the sum of all the even numbers less than 100:

Counting By Steps
int sum = 0;
for (int i = 0; i < 100; i += 2)
{
   Sum += i;
}

And, here's a loop that displays exponential growth. How many numbers do you think that this will print?



Video - for Loops

The For loop
The For loop
  • Move
  • Close
Counted Loops With while

The for loop makes writing counted loops very easy because it puts the pieces you need--a place to initialize your counter, a place to test your counter, and a place to update your counter--all within easy reach.

You can do exactly the same thing with C++'s simpler, but more general-purpose while loop. It's just not quite as convenient.



To use the while statement to build a counted loop, you must do three things:

  1. Create a counter variable, and initialize it before the loop starts. This takes the place of the initialization expression in the for loop.
  2. Test the counter variable inside the while condition.
  3. Update your counter at the end of the loop body. This takes the place of the update expression in the for loop.
Here's the basic skeleton for a counted loop, written with while

A Counted Loop Skeleton with while
int counter = 0;
while ( counter < 10 )
{
// Loop body statements

// Update loop counter
counter++;
}


Caveats
There are three common errors that often occur when writing counted loops using while . By learning what they are, and then checking for each one when you write your loops, you increase your chances of writing a correct loop the first time.

Expired Counters

When using the for loop, you usually create and initialize your counter variables inside the initialization expression of the for loop. If you forget to do so, the for loop condition usually looks "empty", which acts as a reminder.

For the while loop, however, you must define and initialize your counter outside the while loop. This has several implications:

  • In the for loop, the scope of the counter variable is restricted to the body of the for loop. That is not true for the while loop.
  • If you have several while loops, and each of them use the same variable name, then you cannot re-declare the variable for each new loop. All of your loops will use the same variable.
  • You must, however, remember to reinitialize the counter before each loop, even though you can't re-declare it. Forgetting to do this often leads to the case of the expired counter . If a counted while loop is preceded by another, and both use the same counter variable, you may forget to reinitialize the counter for the second loop. This doesn't create a syntax error, but it does give you the wrong answer.
There are two possible solutions to the expired counter problem.
  1. If you give all of your counters unique names, you won't run into the problem. Sometimes, however, this is hard to do. Thinking up a new name when you really want to use the common counter names like i , idx , or counter , can be difficult.
  2. A better solution is to train yourself to always initialize your counter on the line immediately preceding the while condition . After a bit, a missing initialization starts to look as "empty" as the missing initialization section in a for loop.

Endless Loops

The problem of endless loops is not unique to while loops. You can create endless loops in a variety of ways. [For instance, if you change the bounds of the exponential for loop shown at the end of the previous section to 100000 from 10000, it will become an endless loop. Can you tell why?]

A counted while loop lends itself to endless loops in a way that the others don't. Because the while loop places the counter update expression at the bottom of the loop--which may be far removed from the while loop condition by the time all of the intervening statements have been added--it is easy to forget it.

With the for loop, leaving out the update expression creates an "empty" looking loop condition, but not with the while loop.

The easiest solution to this problem is to use the loop-building strategy presented in Lesson A, "Introduction to Loops". If you start by first writing the "mechanics" of the loop--bounds, precondition, and update--you are less likely to get distracted by the "real" statements and forget to add the update expression at the end of the loop.

Phantom Semicolon

This last problem is also not restricted to while loops; it affects selection statements and for loops as well.

If you put a semicolon after the condition of a while [or for ] loop, the body of the loop becomes the null statement. Here's an example:

Because of the semicolon, you are saying "As long as cups is less than ten, do nothing". This creates two problems:

  1. If cups was originally less than ten, you will have an endless loop. Because nothing in the null body changes the value of cups , it will remain at its initial value.
  2. If cups was greater-than or equal-to ten, you will not have an endless loop, but the statements that were intended to be executed as part of the loop body will be executed exactly once.

Video Counted Loops
Counted Loops
Counted Loops
  • Move
  • Close
Where To Now?
After reading the preceding section, you might be wondering why anyone would bother with while at all. The for loop seems so much more capable.

That's true for counted loops; if you are going to write loops that are controlled by a counter, you should probably use the for loop. But, not all loops, or even most loops, are counter-controlled. Event controlled loops are much more common, and there, the while loop reigns.


Practice Problem

A number is called a perfect number if by adding all the positive divisors of the number (except itself), the result is the number itself.

Six is the first perfect number. Its divisors (other than the number itself: 6) are 1, 2, and 3 and 1 + 2 + 3 equals 6. Other perfect numbers include 28, 496 and 8128.

Using a counted loop can you check to see if a number is a perfect number? Check your solution with the video below

Perfect Number
Perfect Number
  • Move
  • Close
Still Not Sure?
See what XoaX.net says about the for loop
Indefinite Loops

In this lesson, you'll learn how to write loops that monitor events, rather than loops that use a simple counter to control their execution. To accomplish this, you'll return to the while loop which you met at the end of the last lesson.

Why while?

Although the for loop is the undisputed champ in the counted-loop arena, the while loop really comes into its own when the loop test condition is a little less clear-cut.

Here is a code example of an indefinite loop. Take a look at this loop, and see if you can guess how many times it will execute.

 Random Number

 

Code Review

A couple of new things here. First, the rand() function returns a pseudo-random number in the range from 0 to RAND_MAX. RAND_MAX is a constant that is defined in stdlib.h. Files with the extension .h are called header files and they contain definitions. You would normally include it the same way you do iostream

#include <stdlib.h>

You may be thinking that you don't see this file included anywhere within the code. The truth is that iostream references it so it is like you have included it yourself. The default value of RAND_MAX is dependent upon the machine it is on. We can generate a random between 0 and whatever number you choose by using the % (modulus) operator. In the code above random numbers are being generated in a range between 0 and 99. This is something you should try to remember is that you always want to add 1 to the max number you want to get. If I wanted numbers between 0 and 100 I would have to % the number with 101.

The code:

srand(time(0))

is a way to seed the random number generator. The random number generator uses a mathematical equation to calculate random numbers. If you were to print out enough random numbers using the rand() function, you would notice that at some point the numbers repeat and that there is a pattern to them. To generate more randomness into the formula, we can seed the random number generator. This is what the srand function does. You can pass almost any value to the random number generator but you can make it more random by seeding it with the tick of the time of day clock. This is where the time() function comes in.

To use the time function you must first include ctime. it is also part of the C++ standard library. So the line of code:

srand(time(0))

says seed the random number generators mathematical calculation with a number generated by the time of day clock.

Back To Loops

Can you tell how many times this loop will execute? Probably not, unless you have some kind of psychic powers. That's why this kind of loop is called an indefinite loop. You can't tell by reading the source code how many repetitions it will make.

Even though this is not a counted loop, the body of the loop must still contain code that advances the loop's bound. If it does not, then, once entered, the loop will repeat for ever. In this example, we advance toward the loop's bound by calculating a new random number .

Sentinel Bounds

This particular indefinite loop is an example of a sentinel loop. A sentinel loop is a loop that looks for some special value to end the loop. The special value is called the sentinel . As mentioned earlier, sentinels are commonly used in two situations:

  • When searching through text to find a character or word.
  • When used as an "out-of-bounds" value that marks the end of input.

In the above example, the sentinel is the number 50, generated by the random number generator, and it is used to mark the end of valid input.

Sentinel Ranges

A sentinel doesn't always have to be a single value; it may include a range of values. For instance, here is a problem statement that calls for a sentinel loop, but a simple sentinel value would be insufficient

A Positive Mean
Accept integer numbers until a negative number is entered. Display the sum, count and average of the numbers entered.

Rather than just reading ahead, why don't you see if you can apply what you learned in Lesson A, "A Loop-building Strategy", to create a loop that meets these requirements. When you're done, come on back here and we'll tackle it together.

Here are the questions you should ask yourself:

  1. What is the loop's bounds?
  2. What are the necessary bounds preconditions?
  3. What are the necessary actions to advance toward the bounds?
  4. What is the goal?
  5. What are the goal preconditions?
  6. What actions are necessary in the body to carry out the goal?
  7. What postcondition actions are necessary to carry out the goal?
A Solution

Let's look through the answers together:

  • What is the loop's bounds?
    The loop's bound is that a negative number was entered. The C++ loop condition should look like this:
    while (num >= 0)
  • What are the necessary bounds preconditions?
    The only precondition is that num holds a value. The value could come from reading a network stream, could be entered from the keyboard, or could be generated by a random number generator. The only hard-and-fast requirement is that num must be initialized in such a way that it is possible to either enter or to avoid the loop.
    int num = 0;
  • What are the necessary actions to advance toward the bounds?
    Inside the loop body, the value of num must change. You should read another number from the keyboard, or from the network stream, or, as we've done, generate another random number.

At this point, you should be able to test the mechanics of your loop, and make sure that it "works." Once the loop works, you can turn your attention to the loop's goal.

  • What is the goal?
    The loop's goal is simple. It should display the number of positive integers entered, the sum of the integers, and their average.
    • What are the goal preconditions?
      To meet the goal, you must have a counter, and a variable that can hold the sum. The counter can be an int , but the sum should be a double . Using an int for the sum would be inappropriate because summing just two very large integers would cause the variable to overflow.
      • What actions are necessary in the loop body to carry out the goal ?
        • Each positive number should be added to the sum of the numbers.
        • The count should be incremented for each number entered.
      • What postcondition actions are necessary to carry out the goal?
        • You must first check for a count of zero. If count is zero then no numbers were entered and you can't compute the average or sum.
        • If count is greater than zero, then compute and display the sum, average, and count of numbers entered.

      Here's a program that follows this strategy to calculate the average of a stream of numbers. This example is a little different than the first example because, instead of using a single sentinel--the number zero, for instance--it uses a range of sentinels--any number less than zero--to mark the end of valid input.

      0
      • Move
      • Close

      #include <iostream>
      #include <ctime>
      using namespace std;

       

      int main()
      {

      // Precondition
      int     count = 0;
      double  sum   = 0.0;
      int num = 0;

       

         cout << "Enter an integer, negative to quit" << endl;
         cin >> num; 
         while (num >= 0) 
         {      
      // Loop actions 
             ++count;
             sum += num; 
             cout << "Enter an integer, negative to quit" << endl;
             cin >> num; 
         }
      // Postcondition 
         if (count > 0) 
         { 
            cout << "Count = " << count << " Sum = " << sum << " Avg = ";
            cout << sum/count << endl; 
         } 
         else 
         { 
             cout << "No numbers entered" << endl ; 
         } 
         
      return 0;

      }

       

       

      1
      Primed And Inline Tests

      So far, all of the indefinite sentinel loops we've looked at have been primed loops:

      • we've set up the value of the variable
      • tested the value against the sentinel in the loop condition
      • processed the variable as needed in the loop body
      • updated the variable's value at the end of the loop body, just before returning to the loop test for the next repetition
      Initialize variable to be tested
      Test variable against sentinel value
      Process variable as needed
      Update variable to be tested

      Because assignment is an operator in C++, and not a statement, there is a much shorter and more concise way to write the same kind of sentinel loop. A loop employing an inline test is an extremely common C++ idiom, and you should become familiar with it, even if you prefer the longer, more traditional primed loop.

      Using an inline test, the loop in the first program can be rewritten like this:



      Now, you only have to initialize num once--during the loop test--and not twice--before and at the end of the loop.

      Note the additional set of parentheses surrounding the assignment operation:

      (num = rand() % 100)

      The parentheses are required because the precedence of the relational operator [ >= ] is higher than the precedence of the assignment operator. If you omit the parentheses, C++ will compare the number it returns with zero, generating a boolean value. When it comes time to assign the boolean value to the variable num , however, C++ will choke because num is an int , and you cannot assign a boolean value to an int .


      Intentional & Necessary Bounds

      Sentinel bounds are often used to search for a particular value in a set of data, such as looking for a particular word or character in a document. When used like this, however, sentinel-controlled loops have one great failing: they can't ensure that the value will actually be found.

      To handle this problem, you need to add an additional item to your loop-building toolkit--you must learn to differentiate between intentional and necessary bounds. Here's the difference.

      Suppose you want to search the String s , for the character c , and return the position where the value is found. Using a simple sentinel loop you could write:

      while ( (ch = s[i++]) != c )

      This bounds, ch != c , is your intentional bounds , it is the sentinel value that will end your loop if all goes well. You can't just assume that all will go well, however. It is possible that:

      1. The character c might not occur in the String s
      2. The String s may have no characters
      The bounds used to handle these kinds of conditions are called the necessary bounds . Writing the necessary bounds for a loop almost always involves writing a compound boolean condition using the logical operators.

      In this example, we can handle the first necessary bounds by changing the loop condition like this:

      while ( (ch = s[i++]) != c && i < strlen(s)))

      Adding necessary bounds to a loop condition means that the loop can end for two [or more] reasons, not just one. When you write the loop postcondition statements, you have to take this into account.

      For instance, after this loop terminates, you can determine whether the character c was found by testing ch , to see if it is equal to c . If ch == c , then the character c was found in the String s .

      NOTE:

      The above example makes use of C strings and the strlen function. Don't concern yourself with it at this point. We are coming to this real soon so it doesn't hurt you any to see it.

      Bottom Testing

      In addition to the for and while loops, C++ also has a loop that performs it's boolean test after the loop body, instead of before. This loop, the do - while loop, illustrated here, will always execute the statements inside its body at least once.



      The body of the do - while loop appears between the keywords do [which precedes the loop body] and while . Like all loops, the body of the do - while loop can be a single statement, ending with a semicolon, or it can be a compound statement enclosed in braces. As with the other loops, you'll have a more fulfilling life if you train yourself to always use a compound [brace-delimited] loop body.

      The do - while loop's boolean condition follows the while keyword. As with all selection and iteration statements in C++, the boolean condition must be enclosed in parentheses, which are part of the statement syntax. In the do - while loop, the boolean condition is followed by a semicolon. [Unlike the while loop, where following the condition with a semicolon can lead to subtle, hard to find bugs.]

      The do - while loop is often employed by beginning programmers, because, for some reason, it seems more natural. If you find yourself in this situation, however, you should think twice. 99% of the time, a for loop or a while loop can be employed to better effect than using a do - while . In fact, except for salting your food, which should always be done before tasting, I can't think of a single situation where a test-at-the-bottom strategy is superior to "looking before you leap."

      Video - Using Indefinite Loops
      Indefinite Loops
      Indefinite Loops
      • Move
      • Close
      Practice Problem
      Below is the output of a simple puzzle that asks the user to guess the pattern. Can you recreate the code for this puzzle? What you should know is that the pattern never changes and the solution is -1. You should also limit the amount of guesses to 5.



      Compare your answer with the solution shown in the video below.
      Practice Problem
      Practice Problem
      • Move
      • Close
      Solves the practice problem to use a sentinel loop to guess the pattern
      Still Not Sure?


      See what XoaX.net says about the while and do while loop

      Also

      See what they say about random numbers
      C++ Jumps

      C++'s selection and iteration statements are called flow-of-control statements because they provide a highly structured method of conditionally and repeatedly executing a particular section of code.

      In days past, however, before the control structures we use today, programmers still needed the equivalent of if statements and loops. Rather than relying on built-in language features, though, those iron-age programmers constructed their own flow of control statements, using the jump .

      The jump statement often uses another name; even programmers who have never heard of the jump have heard of its nom de plum, the goto statement. The goto is one of C++'s reserved words, but it isn't actually implemented as part of the language.

      If your dream is to arbitrarily jump willy-nilly hither-and-yon through your code, you'll have to find another programming language to accommodate you. When it comes to loop control, however, C++ hasn't abandoned the jump altogether. C++ has two statements-- break and continue --that let you do your jumping in a controlled fashion.


      Break Statement


      The break statement is used in two different circumstances, but both circumstances are quite similar.

      The break statement allows you to jump out of :

      • a switch statement [as you saw in Lesson 2]
      • a loop
      When a break statement is encountered in the body of a loop, your program jumps to the statement immediately following the loop body, as you can see in the illustration shown here. Any remaining statements within the loop body are skipped. The test expression is not re-evaluated; the termination occurs regardless of the value the test expression would have.

      Although it can be misused, allowing you to write code that is as convoluted as any produced by the goto statement, the break can sometimes be used to make your loops simpler and clearer.

      Here's an example, that shows how the break statement can be used to simulate a sentinel loop that stops when the number 50 has been reached. Note that the loop bounds does not need to test for the sentinel value.


      0
      • Move
      • Close

       

      #include <iostream>
      #include <ctime>
      using namespace std;

       

      int main()
      {
         int num = 0,i; 
         srand(time(0));  

         num = rand() % 101;
         for(i = 0; i < 100; i++)
         {
            if(num == 50)
               break;
            cout << "Random Number is " << num << endl;
            num = rand() % 101;
          }

         if(i < 100)
            cout << "The number 50 was encountered at iteration " << i << endl;
         else
             cout << "The number 50 did not come up " << endl;

       

         return 0;
      }

       

       

       

       

       

      1
      The continue Statements


      The continue statement is a jump statement like break , but unlike break , the continue jumps back to the loop condition.
      Exactly what that means depends upon the loop you're using:

      • For the while loop and the do - while loop, the continue statement jumps to the boolean test, skipping backward [ while ] or forward [ do - while ] as necessary.
      • With the for loop, control jumps to the update expression.

      The code below asks the user to input characters from the keyboard. If a digit is encountered, it gets converted and added to the sum. If the character entered is not a digit then the continue statement takes the flow of control back to the top of the loop.

      0
      • Move
      • Close

      #include <iostream>

       

      using namespace std;

       

      int main()
      {
      char c;
      int sum = 0;

       

         for(int i = 0; i < 10; i++)
         {
            cout << "Enter and integer to sum " << endl;
            cin >> c;

            if(!isdigit(c))
               continue;

       

             sum += (int)c - '0';
          }

       

          cout << "The sum of the digits entered is: " << sum << endl;
          return 0;
      }

      Code Review

      The for loop in the above code will execute 10 times. Each time a character is entered at the keyboard, it is checked to see if it is a digit. The check uses the standard C++ library character function isdigit() which returns true if the character entered is between '0' and '9'. Remember that everything entered into the keyboard is a character, which is different from a number.

      9 and '9' are different

      The isdigit() returns a boolean true if the character is a digit, false otherwise.

      If the character entered is a digit then it gets converted to a number by subtracting the character '0' from the character entered. The character '0' has an ascii value of 48. So the above code is equivalent to subtracting 48 from the character entered. In any case, subtracting 48 from the digit will give us the actual binary value of the character representation.

      Once the character is converted, it gets added to the sum of the values.


      Nested Loops
      One of the problems with nested loops, is that the break and continue statements stop "working." Actually, they don't stop working, exactly; they just don't work quite the way you'd like. Here's the problem.

      Both break and continue work on the current loop. That means, when you are in an inner loop, a break statement only exits the inner loop, it doesn't get you out of the outer loop.

      If you need to break out of both inner and outer loops, then you will have to write some logic to handle it.

      Video - Using The break Statement
      break Statement
      break Statement
      • Move
      • Close
      How to use the c++ break statement
      For Loop
      For Loop
      • Move
      • Close
      While Loop and Random Numbers
      While Loop and Random Numbers
      • Move
      • Close
      2010 By Glenn Stevenson   |   Privacy Statement   |   Terms Of Use
      MSJC Programming