Shortcuts and Repetition

So far we know how:

to create simple programs
use functions to delegate subtasks
use the if statement to execute lines selectively

Neither of these techniques, however, will help us solve problems similar to this:

Example: Create a program to print out the first three positive integers, together with their squares.

Actually, we of course can write such a program. Here is an example:

int main(void)
{
   int i = 1;
   cout << i << "\t" << i*i << "\n"; i="2;" cout << i << "\t" << i*i << "\n"; i="3;" cout << i << "\t" << i*i << "\n"; return 0; } 
But, of course this is not very nice looking. In particular, what if we asked to see the first 10, or 100, or 1000 integers with their squares ?

In fact, we will next learn a technique for helping with such repetition. For now, please note that anytime there is one or more lines in your programs that are the same, or very similar, it is probably a bad program - you should have used some programming technique to make the statement repeat, rather then repeat it "by hand".

Here is syntax for our first repetition statement, the for loop:

The for Loop

The for is a C++ constructions to allow you to repeat a statement, or group of statements, for a known number of times. You don't actually need to know the number of times to repeat the statements, but you must - in prinicple - be able to figure them out ahead of time. The syntax for the for loop is as follows:

   for (initialization;
        continuation-test;
        modification)
      statementBlock;
where
initialization declares and initializes the loop control variable, for example int i = 0
continuation-test is a test that will stop the loop as soon as it is false. Or, in other words, the repetition will continue as long as the test is true. The test must involve the loop control variable declared before, for example i <10
modification is a statement that modifies the loop control variable appropriately, for example: i = i+1
statementBlock is either a single statement or a group of statements inside the grouping symbols { ... }
Example: Create a program that prints out the first 10 positive
integers, together with their squares.

If i was an integer between 1 and 10, then the statement to print it out would be, as before:

   cout << i << "\t" << i*i << "\n"; 
Now, we will use the for loop to make sure that i will indeed go from 1 to 10. Here's the code:
int main(void)
{
   for (int i = 1; i <11; i="i" + 1) cout << i << "\t" << i*i << "\n"; return 0; } 
You can see the three pieces that make out the for loop. i is declared as an integer and initialized to 1. Then, since the test i <11 is true, the cout statement executes, and the statement i = i + 1 forces i to be increased by 1 - in other words it is now 2. The test is still true, so the cout statement executes again. That will go on until i is 10. Since the test is still true, the cout statement is still executed. But then, i is increased to 11 - and since now the test i <11 is false, the loop is over and the next line after the cout line will execute, i.e. the return 0 line.

This example comes in many varieties:

Example: Write a program that prints out all positive odd integers between 1 and 100, together with their squares.

The program is similar to the above; except, this time we will simply add two to i instead of just 1. Here's the code:

int main(void)
{
   for (int i = 1; i <101; i="i" + 2) cout << i << "\t" << i*i << "\n"; return 0; } 
Example: Write a program that prints out all positive even integers between 1 and 100, together with their squares.

Again, the program is as before, but we simply start the loop at 2 instead of at 1 to catch all even integers. Here's the code:

int main(void)
{
   for (int i = 2; i <101; i="i" + 2) cout << i << "\t" << i*i << "\n"; return 0; } 
Let's do one more, slightly more exciting, program:

Example: Write a program that finds the sum of the first 100 positive integers.

Clearly we need to use a loop, where some variable goes from 1 to 100. But, how are we to keep track of the sum ? We'll introduce another variable that keeps a running total. Here is what we want to do:

Start with sum = 0
Start a loop with i = 1
Add i to sum, and save the result back into sum (now sum is 1)
Add one to i (now it is 2)
Add i to sum, and save the result back into sum (now sum is 3)
Add one to i (now it is 3)
Add i to sum, and save the result back into sum (now sum is 6)
Add one to i (now it is 4)
... etc ...
until i reaches 100.
Here is the code that will accomplish this:

int main(void)
{
   int sum = 0;
   for (int i = 1; i <101; i="i" + 1) sum="sum" + i; cout << "Sum is: " << sum << "\n"; return 0; } 

We have now seen many statements where a variable appears on both
sides of an assignment. That's nothing special (remember, first the
right side is evaluated, then the value is assigned to the left side)
- in fact, it appears so frequently that C++ has shortcuts for those
situations.

ShortCuts

C++ has several shortcuts for situations when a variable appears on either side of an assignment. Here is a list:

Shortcut Example Meaning
++ i++ i = i + 1 (called increment)
-- i-- i = i - 1 (called decrement)
+= x+=5 x = x + 5
-= x-=5 x = x - 5
*= x*=5 x = x * 5
/= x/=5 x = x / 5
Using these shortcuts, let's rewrite some of the previous programs.
Each time, the old and the new shortcut is in bold. But before we start,
let's modify the previous programs - no program should contain 
contain actual numerical constants; instead, you should declare
a named constant (at the beginning) and use that named constant
instead of the actual numerical value:

First, here's the simple one to print a list of the first positive integers, together with their squares:

Without shortcuts With shortcuts
int main(void)
{
   cont int MAX = 101;
   for (int i = 1; i i = i + 1)
      cout << i << "\t" << i*i << "\n"; return 0; } 
int main(void)
{
   cont int MAX = 101;
   for (int i = 1; i i++)
      cout << i << "\t" << i*i << "\n"; return 0; } 

Next, here's the same program, just printing every odd integer:

Without shortcuts With shortcuts
int main(void)
{
   cont int MAX = 101;
   for (int i = 1; i i = i + 2)
      cout << i << "\t" << i*i << "\n"; return 0; } 
int main(void)
{
   cont int MAX = 101;
   for (int i = 1; i i+=2)
      cout << i << "\t" << i*i << "\n"; return 0; } 

Finally, here's the last example of finding the sum of the first 100 integers:

Without shortcuts With shortcuts
int main(void)
{
   cont int MAX = 101;
   for (int i = 1; i i = i + 1)
      sum = sum + i;
   cout << "Sum is: " << sum << "\n"; return 0; } 
int main(void)
{
   cont int MAX = 101;
   for (int i = 1; i i++)
      sum += i;
   cout << "Sum is: " << sum << "\n"; return 0; } 

Note: This increment and decrement shortcuts (i.e. ++ and --) should always be used when possible. In other words, no program of yours should contain a line similar to x = x + 1. After all, the language we are using is called C++, which means that it increments the language C (which is another, closely related programming language).

Using any of the other shortcuts is, as far as I am concerned, optional, and depends entirely on your own preferences.

There is another repetition statement that is frequently used. It is
acutally more general than the for loop, but it is also easier
to make a mistake using it.

The while statement

The while is a C++ constructions to allow you to repeat a statement, or group of statements, for an unknown number of times. You do not need to know the number of times to repeat the statements. The syntax for the while loop is simple:

   wile (test)
      statementBlock;
where

The statement or statements will continue to execute as long as the test returns true, or in other words, the loop will quit when the test returns false.
statementBlock is either a single statement or a group of statements inside the grouping symbols { ... }
Acutally, this syntax is deceptively simple. In reality, a while
loop will (almost) always contain three parts:

   initialization;
   while (test)
   {
      statements;
      modification;
      statements;
   }
In other words, every while loop consists of an 
  1. initialization, usually just before the actual while statement
  2. the test that is part of the while syntax
  3. a modification statement somewhere inside the loop
Example: Suppose we drop a ball from a given height. Each 
time the ball bounces back to half the previous height. Write a 
program that displays the heights for each bounce. Use height 100
as an example.

Here is an example, first without an actual program:

Originial height: 100
After bounce 1: height 50
After bounce 2: height 25
After bounce 3: height 12.5
... etc ...
So, we can see that this will - theoretically - go on forever, so
the program is not well-phrased. Let's rephrase the original task:
Write a program that displays the heights for each bounce, until
the program is within 0.001 meters of the ground.

Now, we can see that the program will stop, but it is difficult to figure out how many bounces will occur. So, we will use a while loop for this (actually, we could use a for loop, since that only requires us to know in principle how often the loop executes).

int main(void)
{
   const double STARTING = 100;
   const double GROUND_LEVEL = 0.001;

   double height = STARTING;
   
   while (height > GROUND_LEVEL)
   {
      cout << "Height: " << height << "\n"; height="height" / 2; } return 0; } 
Note that we could have also used the shortcut height /= 2 instead of height = height / 2. Also, it may not be immediately clear whether this program will print out the original height, or start with half of it, and whether it will stop when the ball has reached 0.001, or has actually dropped below that height.

There are two ways to find out the details:

  1. "hand-trace" the program by writing the value of all variables as the program progresses.
  2. just run the program, and see what happens
Often, in fact, when writing a while loop, the loop is off
by one, or runs once too many. A simple "test" execution will tell you,
or you could hand-trace the program - as we'll do in the next lecture.

(bgw)