Welcome to Lesson 12!


Learning Objectives
By the end of today's class, you should know...
  • What are 4 applications of while loops?
  • What are some common errors that are made when writing while loops?
  • What is a counting loop?
  • What are the three important components of a counting loop?
  • What is a for loop and why was it designed?
  • How does a for loop differ from a while loop?
  • What is an off-by-one error and how can you avoid this type of error?

Announcements

  • Quiz 4 after the break

Review Activity

With a partner, answer the following questions:

  • Label the different parts of the following while loop as: update statement, initialization or test condition.

int count = 1;

while (count <= 10) {

    cout << count << endl;

    count++;

}

  • Correct the loops below. What will happen if you run the code BEFORE making the corrections?

Loop 1:

string repeat = "y";

while (repeat == "y") {

    cout << "Playing an exciting game!\n\n";

    cout << "Want to play again? (y/n): ";

        }

Loop 2:

    int counter = 1;

  while (counter <= 10) {

      cout << counter << endl;

  }


Applications of Loops

  • Let's look at 4 common loop applications:

1. Indefinite Loops

Recall our looping application that simulated the play of an exciting game


#include <iostream>
using namespace std;

int main() {
    string repeat = "y";
    while ("y" == repeat) {
        cout << "\nPlaying an exciting game!\n";
        cout << "Do you want to play again? (y/n) ";
        cin >> repeat;
    }
    cout << "\nThanks for playing!\n";

    return 0;
}
  • Loops of this type are called indefinite loops because you do not know in advance how many time the loop will execute
  • This behavior is different from a counting loop where you know how many times the loop will execute before the loop starts
  • With an indefinite loop we can solve a new set of problems
  • Most problems solved with indefinite loops make use of while statements


2. Processing a Sequence of Inputs
  • Another common use for indefinite loops is to process a sequence of inputs
  • As an example, let us add up (sum) a series of numbers
  • Every number is added to the sum
  • We use a loop to repeat the input until the user decides to stop
  • Since we do not know how many number the user will enter, we use an indefinite loop as shown below

#include <iostream>
using namespace std;

int main() {
    double input = 1;
    double sum = 0;
    string repeat = "y";

    cout << "I will add up numbers for you\n\n";
    while ("y" == repeat) {
        cout << "So far, sum = " << sum << endl;
        cout << "Enter a number: ";
        cin >> input;
        sum = sum + input;

        cout << "Another number? (y/n) ";
        cin >> repeat;
    }
    cout << "Ending sum: " << sum << endl;

    return 0;
}

3. Terminating the Input with a Sentinel

  • Whenever we read a sequence of input values, we need to have some way of terminating the input loop
  • We could use a separate variable and input statement as we have done before:
    string repeat = "y";
    while ("y" == repeat) {
        // ... statements to repeat
        cin >> repeat;
    }
    
  • However, when entering numbers (or other data) repeatedly, answering an extra question each time through the loop becomes annoying
  • One way to avoid asking an extra question is to use a sentinel value
  • sentinel is guard who watches for something to happen

        image source

  • Similarly, a sentinel in a program watches for a specific sentinel value that signals termination of a loop
  • To use a sentinel value, we must have a special value in the input
  • Some commonly used sentinel values for numeric input are 0 or -1
  • The following program is an update of the previous program to use a sentinel value to end the loop
    • Question: What is the sentinel value for this loop?

Example Application Using a Sentinel Value for the Loop Test

#include <iostream>
using namespace std;

int main() {
    double input = 1;
    double sum = 0;

    cout << "I will add up numbers for you\n\n";
    while (input != 0) {
        cout << "So far, sum = " << sum << endl;
        cout << "Enter a number or 0 to exit: ";
        cin >> input;
        sum = sum + input;
    }
    cout << "Ending sum: " << sum << endl;

    return 0;
}


4. Error Checking: Input Validation

  • Another common use for indefinite loops is input validation
  • Input validation combines a loop with one or more if statements
  • The input statement is placed inside the loop
  • The if-statement tests for an incorrect input value
  • The loop repeats while the user's input contains an error
  • Since we do not know how many times the loop must execute ahead of time, the loop is indefinite
  • For example, the following program uses a loop to ensure a user enters a positive number
  • The if statement is used to decide when to output an error message

Example of Input Validation Using a Loop


#include <iostream>
using namespace std;

int main() {
    double input = 0.0; // initialize value
    while (input <= 0) {
        cout << "Enter a positive number: ";
        cin >> input;
        if (input <= 0.0) {
            cout << "You must enter a positive number\n";
        }
    }
    cout << "You entered: " << input << endl;

    return 0;
}
  • We will explore all of these applications in our programs as we continue to write loops.


Activity 12.1: Guessing Game Redux (10 pts)

  • Copy the following program into a text editor, save it as loopy.cpp, and then compile and run the starter program to make sure you copied it correctly.
    #include <iostream>
    using namespace std;
    
    
    int main() {
        int guess = 0;
        cout << "I'm thinking of a number between"
             << " 1 and 10.\nCan you guess it?\n\n"
             << "Enter your guess: ";
        cin >> guess;
    
        if (7 == guess)
        {
            cout << "*** Correct! ***\n";
        }
        else
        {
            cout << "Sorry, that is not correct.\n";
            cout << "Try again.\n";
        }
        return 0;
    }
    
  • Add the following code after the statement int guess = 0; and before the cout statement:
    string repeat = "y";
    

    This is the initialization code that we will use for the test condition that comes next.

  • We want to repeat all the rest of the code in our program. For this we need to add a while statement such as:
    while ("y" == repeat) {
        // Place the rest of the code after the initialization
        // and before the return 0 between these curly braces.
    }
    

    Statements inside the curly braces repeat while the test condition in the parenthesis, ("y" == repeat), evaluates to true. 

  • Inside the while loop we need some way to change the test condition. We change the test condition by letting the user enter a value for the repeat variable by adding the following code at the end of the loop just before the closing curly brace:
    cout << "\nDo you want to play again? (y/n) ";
    cin >> repeat;
    

    Without these two statements our loop would have no way to exit. A loop with no way to exit is known as an infinite loop

  • Formatting a loop is important. Indent all the code within the curly braces of the while loop. 
  • As a final part of our program, we add the infamous phrase: "Game Over". Add the following statement after the closing curly brace of the while loop:
    cout << "Game over\n";
    
  • Compile and run your program again and verify the output looks like:
    I'm thinking of a number between 1 and 10.
    Can you guess it?
    
    Enter your guess: 3
    Sorry, that is not correct.
    Try again.
    
    Do you want to play again? (y/n) y
    I'm thinking of a number between 1 and 10.
    Can you guess it?
    
    Enter your guess: 7
    *** Correct! ***
    
    Do you want to play again? (y/n) n
    Game over
    
  • Submit your program source code to Catalyst.
  • If you finish early, answer today's learning questions under Wrap Up or work on your Lab 6

Completed Program

  • When finished, your application should look like the following. Note especially the extra indentation within the curly braces of the while loop.


Common Loop Pitfalls

  • Loops have many pitfalls for the unwary
  • The following are the most common problems you should look out for

Infinite Loops

  • Common error: unintentional infinite loop
  • For example, what is wrong with the following code?
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;

int main() {
    string repeat = "y";
    while ("y" == repeat) {
        cout << "\nPlaying an exciting game!\n";
        cout << "Do you want to play again? (y/n) ";
    }
    cout << "\nThanks for playing!\n";

    return 0;
}

Missing Curly Braces

  • Technically, the while loop executes a single statement after the parenthesis of the test condition
  • However, we usually use curly braces { } to expand the single statement
  • The curly braces let us put multiple statements in them
  • For example, what is wrong with the following code?
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;

int main() {
    string repeat = "y";
    while ("y" == repeat)
        cout << "\nPlaying an exciting game!\n";
        cout << "Do you want to play again? (y/n) ";
        cin >> repeat;
    cout << "\nThanks for playing!\n";

    return 0;
}

Empty Statements

  • Remember that statements are terminated by a semicolon
  • Is the following a legal statement?
    ;
  • This is known as an empty or null statement
  • Empty statements are a common source of infinite loops
  • For example, what is wrong with the following code?


#include <iostream>
using namespace std;

int main() {
    string repeat = "y";
    while ("y" == repeat); {
        cout << "\nPlaying an exciting game!\n";
        cout << "Do you want to play again? (y/n) ";
        cin >> repeat;
    }
    cout << "\nThanks for playing!\n";

    return 0;
}    


Counting Loops

  • Counting is a common task in our lives.
  • In programming, counting is also very common.
  • In programming we often use loops to count when we know exactly how many times we want a specific piece of code to repeat.
  • In fact, counting is such a common programming task, that a special type of loop was designed specifically for counting.
  • This loop is called a for loop, and we will be learning more about it in class today.

For Statements
  • As previously mentioned, counting is a very common use for loops.
  • Loops that are controlled by a counter variable are called counter-controlled loops.
  • We can visualize a counter-controlled loop as a series of steps to reach a goal.

small picture of someone climbing numbered steps of a stair

Image source.

  • A counter-controlled while loop has the form:
    int i = start;
    while (i < end) {
        ...
        i++;
    }
    
  • Where:
    • i: the name of a counter variable
    • start: the initial starting value
    • end: the final ending value

  • We can write this same counting loop as a for loop:
    for (int i = start; i < end; i++) {
        ...
    }
  • The for loop was especially designed for counting tasks.
    • Notice its compact syntax compared to the while loop.
    • All the conditions which define the loop are on a single line.

  • When writing a counting loop, we often have a choice of using either a for or a while loop, as both will accomplish the same task.
    • However the compact syntax of the for loop makes it preferable.
  • The following example shows the same loop written as both a while loop and a for loop:
//counting from 10 to 20 using a while loop
int i = 10; 
while (i <= 20)
{
    cout << i << endl;
    i++;
}

//counting from 10 to 20 using a for loop
for (int i = 10; i <= 20; i++)
{
    cout << i << endl;
}
  • What differences do you notice in the two loops above?
  • What are the starting values for the loops? Where are they located?
  • Test conditions?
  • Update statements?
  • Notice the use of the semi-colons in the for loop. Which statements end with semi-colon and which do not?

Another For Loop Example

#include <iostream>
using namespace std;

int main()
{
    int max = 0;
    cout << "This program uses a loop to count!\n";
    cout << "Enter the maximum number: ";
    cin >> max;

    for (int i = 1; i <= max; i++)
    {
        cout << i << endl;
    }
}

Anatomy of the For Loop

  1. When for loop is reached, execute the initialize statement (starting point).
    1. This initialization step occurs only once.
    2. Note that i is the most common choice for our counting variable.
    3. Ex above: int i = 1;
  2. Check if condition is true.
    1. This occurs right after initialization, and after every iteration. 
    2. Ex above: i <= max;
    3. if true then continue with Step 3
    4. Otherwise it is false  continue with Step 6
  3. Execute the block containing the statements to repeat (body)
  4. When the end of each iteration of the loop body is reached, execute the update statement.
    1. This occurs at the end of every completed iteration.
    2. Ex above: i++;
  5. Return to Step 2
  6. The loop is finished when the test condition becomes false
    1. Continue with statements after the loop


Diagram of for Loop Operation

C++ for loop

Image source.


Group Activity: Altering a For Loop
  • With your partner: Copy and paste the below for loop into CodeBlocks
  • Name your file loopy.cpp
  • Now, try altering the for loop to see if you can achieve the following results:
    • Can you make the loop print out the numbers from 0 up to an including the max?
    • Can you make it print out the numbers from 0, up to, but not including, the max?
    • Can you make it count up by 2s to the max?
    • Can you make the loop count down from the max to 0?
#include <iostream>
using namespace std;

int main()
{
    int max = 0;
    cout << "This program uses a loop to count!\n";
    cout << "Enter the maximum number: ";
    cin >> max;

    for (int i = 1; i <= max; i++)
    {
        cout << i << endl;
    }
}



Activity 12.2: Counting Down Part 3 (10 pts)
  • Find a partner for pair programming
  • Open up your countdown.cpp file from last class in CodeBlocks.
  • Locate the while loop in your code.
  • Alter this while loop to be a for loop.
  • Hint: Make sure that your for loop has 3 parts:
    • initialization (where do you want to start counting)
    • test condition (when should the loop fail?)
    • update statement (are you counting up or down here?)
  • Compile and run your program and verify that you still get the following output:
NASA Mission Control readying for liftoff.
Initializing countdown from 10...
10
9
8
7
6
5
4
3
2
1
We have liftoff!
  • Submit your program to Catalyst when you are finished.

Wrap Up
  • With your partner, answer the questions from today's learning objectives

Upcoming Assignments
  • Assignment 12 due Tuesday at 3:20pm on Catalyst
  • Lab 6 due Friday at midnight