0% found this document useful (0 votes)
43 views

Chapter XII

This document summarizes Chapter 12 of a programming textbook. The chapter introduces advanced control structures in C++, including: specialized features of for loops that can initialize and alter multiple variables; nested selection and looping; compound conditions using Boolean logic; input protection using compound decisions; and short-circuiting compound decisions. It provides examples of using for loops to count quarters and calculate their value, and to compute the average of a fixed number of grades or unknown number of grades entered until a flag value.

Uploaded by

Sam V
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views

Chapter XII

This document summarizes Chapter 12 of a programming textbook. The chapter introduces advanced control structures in C++, including: specialized features of for loops that can initialize and alter multiple variables; nested selection and looping; compound conditions using Boolean logic; input protection using compound decisions; and short-circuiting compound decisions. It provides examples of using for loops to count quarters and calculate their value, and to compute the average of a fixed number of grades or unknown number of grades entered until a flag value.

Uploaded by

Sam V
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 62

Chapter XII

Control Structures II

Chapter XII Topics


12.1 Introduction

12.2 The For Loop Revisited

12.3 Using the Best Loop Structure

12.4 Nested Selection

12.5 Nested Looping

12.6 Compound Conditions

12.7 Program Input Protection

12.8 Short-Circuiting Compound Decisions

12.9 Recursion, a Sneak Preview

12.10 Worked-Out Exercises

12.1 Introduction
You knew that this chapter was coming. Anytime that a chapter is titled Control
Structures I, there is guaranteed to come a sequel. You did not exactly have to wait very
long for this sequel. Hopefully, the Boolean chapter has given you some tools that can be
applied in this chapter. Frankly, the Boolean chapter by itself is difficult to justify. But
in the area of complex control structures, knowledge of Boolean logic is very useful.

This chapter introduces a variety of advanced control structure features. We start by


looking at some specialized features of the for loop structure. The next concern is to see
how control structures can be nested inside each other. Then comes the compound
condition section which draws heavily on the previous Boolean logic chapter. The
chapter then concludes with some practical input protection program examples that also
require understanding of Boolean logic and a brief section on short-circuiting compound
decisions.

When you are finished with this chapter, you will be able to start writing some rather
complex programs that are both challenging and interesting. Simple sequence programs,
and even programs with simple conditions, lack the flexibility that you can create with
the C++ programming tools shown in this chapter.

12.2 The For Loop Revisited

The for loop has many, many different capabilities. It is possible to create some real
convoluted code, which will probably invoke the wrath of thy teacher. Try not to be too
clever with obscure code that works. Be clever with clean, simple, readable code that
works.

Anyway, I digress. It is important to realize that multiple variables can be handled by the
for loop at the same time. This concept is planted as a seed at this stage. Why a seed,
and not a civilized plant? The really practical examples for such multiple variables
requires additional concepts that are introduced later. This for concept is shown now
with the control structures chapter, and later you will see some good use.
Program PROG1201.CPP shows that the for loop initializes two variables, and alters
two variables. The K variable counts up, and the L variable counts down. Serious
excitement is lacking from this program example, but at least you get a general flavor for
some of the exotic capabilities of the for loop.
// PROG1201.CPP
// This program demonstrates multiple variables in a
for loop.

#include <iostream.h>
#include <conio.h>

void main()
{
int K,L;
clrscr();
for (K=1,L=5; K <= 5; K++,L--)
cout << "K = " << K << " L = " << L << endl;
getch();
}

PROG1201.CPP OUTPUT

K = 1 L = 5
K = 2 L = 4
K = 3 L = 3
K = 4 L = 2
K = 5 L = 1

I will now make a modest attempt to show a program that makes use of the double
variable feature available with the for loop structure. The next program example will not
only count the quarters, but also add the value of the growing number of quarters.

One variable, Count, counts the quarters, and a second variable, Value, adds the monetary
values of the coins. Note how this program also demonstrates that it is possible to use an
int loop variable and a double loop variable in the same loop control structure.

// PROG1202.CPP
// This program demonstrates a practical example of
using multiple
// variable of a for loop. This program counts the
number of
// quarters, as well the value of the quarters.

#include <iostream.h>
#include <conio.h>
void main()
{
int Count;
double Value;
clrscr();
for (Count = 1, Value = 0.25; Count <= 20; Count+
+,Value+=0.25)
cout << Count << " Quarter(s) equals " << Value
<< endl;
getch();
}

PROG1202.CPP OUTPUT

1 Quarter(s) equals 0.25


2 Quarter(s) equals 0.5
3 Quarter(s) equals 0.75
4 Quarter(s) equals 1
5 Quarter(s) equals 1.25
6 Quarter(s) equals 1.5
7 Quarter(s) equals 1.75
8 Quarter(s) equals 2
9 Quarter(s) equals 2.25
10 Quarter(s) equals 2.5
11 Quarter(s) equals 2.75
12 Quarter(s) equals 3
13 Quarter(s) equals 3.25
14 Quarter(s) equals 3.5
15 Quarter(s) equals 3.75
16 Quarter(s) equals 4
17 Quarter(s) equals 4.25
18 Quarter(s) equals 4.5
19 Quarter(s) equals 4.75
20 Quarter(s) equals 5
12.3 Using the Best Loop Structure

You have been introduced to all the control structures, but hardly to all the nifty features
of all the control structures. However, each one of the basic loop and selection structures
have been introduced. More advanced processing with control structures is just around
the block. Right now we want to stop for a moment and decide which loop to use. It is
great that C++ supplies us with three types of loops, but when do you use which loop?

When to Use the for Loop

The for loop is ideal for loop structures that repeat some
process a known - or fixed - number of times.

Program PROG1203.CPP uses a for loop to compute the average of a set of grades.
Assume in this case that the quantity of the grades is known. Such a situation certainly
occurs in most classrooms with a fixed number of students. The program example
requests the number of grades to be averaged and then the loop structure accumulates the
grades on a growing sum. After the loop is finished, the average or Mean is computed
by dividing the Sum by the Count of the grades.

You may think that the loop is not fixed because you can specify the count of the grades.
Fixed means that the iterations of the loop are known before the loop starts. This is
precisely the case with the program example shown on the next page. Please note that
the accumulator, Sum, is initialized to 0. This small part is frequently forgotten and
causes many logic problems in a program.

Initialize Your Accumulators


Program loop structures frequently use variables that sum-up
entered values. Such a variable is called an accumulator.

Make sure that the accumulator is initialized before it is used


inside the loop structure.

// PROG1203.CPP
// This program computes the average for a fixed set of
grades
// using a for loop.

#include <iostream.h>
#include <conio.h>

void main()
{
int K; // loop counter
int Count; // quantity of numbers to be
average
int Grade; // individual grade entered from
the keyboard
int Sum = 0; // sum of the grades
double Mean; // grade average
clrscr();
cout << "How many grades will be averaged ===>> ";
cin >> Count;
for (K = 1; K <= Count; K++)
{
cout << "Enter grade ===>> ";
cin >> Grade;
Sum += Grade; // accumulator
}
Mean = (double) Sum/Count;
cout << endl;
cout << "Grade average: " << Mean << endl;
getch();
}

PROG1203.CPP OUTPUT

How many grades will be averaged ===>> 5


Enter grade ===>> 60
Enter grade ===>> 70
Enter grade ===>> 80
Enter grade ===>> 90
Enter grade ===>> 100

Grade average: 80

You will note that the for loop did a nice job averaging our numbers. This type of
situation is ideal for the for loop. The number of repetitions is fixed and fixed repetitions
are performed very easily with C++’s for loop structure.

Now let us keep going with this average business, but alter the scenario. It is now college
time in a Freshman history class. Roughly 600 students are in the same class, and they
have just finished taking the midterm exam. The instructor needs the class average to
decide on the curve. The class size cannot be assumed, even though the total number of
students enrolled is known.

It is very likely that out of 600 students more than 20 have missed the exam because of
illness or dropping the class. The instructor is not enthusiastic to first count all the
scantron sheets and then handle the same scantrons a second time for grade entry. There
must be a better way. Why not let the computer do the counting?

The trick with such a system is to use some type of flag to let the computer know when
the loop is finished. The instructor decides to use -999. Such a number is a very unlikely
grade for any student and the number is easy to remember. In other words, grades will be
entered until -999 is entered and then the loop stops. This certainly is not a fixed loop
situation. The loop required will be conditional. The condition changes when the value -
999 is entered. In this situation it is better to use either the while loop or the do...while
loop. Either loop is ideal for a conditional exit.

You will note in the following program example that a counter must be used as well as
the accumulator, and both must be initialized. Also note that Grade is initialized, which
is necessary to enter the loop properly for the first time.

// PROG1204.CPP
// This program computes the average for an unknown
quantity of
// grades using a while loop.

#include <iostream.h>
#include <conio.h>

void main()
{
int K = 0; // loop counter
int Grade = 0; // individual grade entered from
the keyboard
int Sum = 0; // sum of the grades
double Mean; // grade average
clrscr();
while (Grade != -999)
{
cout << "Enter grade ===>> ";
cin >> Grade;
K++; // counter
Sum += Grade; // accumulator
}
Mean = (double) Sum/K;
cout << endl;
cout << "Grade average: " << Mean << endl;
getch();
}

PROG1204.CPP OUTPUT

Enter grade ===>> 60


Enter grade ===>> 70
Enter grade ===>> 80
Enter grade ===>> 90
Enter grade ===>> 100
Enter grade ===>> -999

Grade average: -99.833333

The first conditional loop example is intentionally wrong. A very common - yet subtle -
logic error is introduced. The average should be 80 and the answer is negative. The
while loop body shows the problem. Every grade that is entered is counted and
accumulated. Remember the all-important-big-deal counter and accumulator. Our
clever flag to exit, -999, is counted as one of the grades, and is also accumulated to the
total sum. This is not the intention of an average program. Actually, programs have few
intentions, but we like to think that programmers intend for programs to work correctly.

There are various approaches to solving this problem. One approach is shown with
program PROG1205.CPP. A special if statement (as shown in the program segment
below) is used to make sure that only grades are counted and accumulated if they are not
-999.

if (Grade != -999)
{
K++;
Sum += Grade;
}

Also keep in mind that the braces are absolutely vital. You want both the statements that
count and accumulate to be controlled by the if condition. With this special segment
added, the program works as expected.

// PROG1205.CPP
// This program computes the average for an unknown
quantity of
// grades using a while loop, and fixes the logic
problem

#include <iostream.h>
#include <conio.h>

void main()
{
int K = 0; // loop counter
int Grade = 0; // individual grade entered from
the keyboard
int Sum = 0; // sum of the grades
double Mean; // grade average
clrscr();
while (Grade != -999)
{
cout << "Enter grade ===>> ";
cin >> Grade;
if (Grade != -999)
{
K++;
Sum += Grade;
}
}
Mean = (double) Sum/K;
cout << endl;
cout << "Grade average: " << Mean << endl;
getch();
}
PROG1205.CPP OUTPUT

Enter grade ===>> 60


Enter grade ===>> 70
Enter grade ===>> 80
Enter grade ===>> 90
Enter grade ===>> 100
Enter grade ===>> -999

Grade average: 80

The same averaging - in a conditional way - can be done with the do...while loop. This
postcondition loop also needs to make sure that the flag does not get counted nor
accumulated. Strictly for the sake of the average program, there does not appear to be
much difference between while and do...while.

// PROG1206.CPP
// This program computes the average for an unknown
quantity of
// grades using a do...while loop.

#include <iostream.h>
#include <conio.h>

void main()
{
int K = 0; // loop counter
int Grade = 0; // individual grade entered from
the keyboard
int Sum = 0; // sum of the grades
double Mean; // grade average
clrscr();

do
{
cout << "Enter grade ===>> ";
cin >> Grade;
if (Grade != -999)
{
K++;
Sum += Grade;
}
}
while (Grade != -999);
Mean = (double) Sum/K;
cout << endl;
cout << "Grade average: " << Mean << endl;
getch();
}

PROG1206.CPP OUTPUT

Enter grade ===>> 60


Enter grade ===>> 70
Enter grade ===>> 80
Enter grade ===>> 90
Enter grade ===>> 100
Enter grade ===>> -999

Grade average: 80

When to Use the while and do...while Loop

The while loop and do...while loop are ideally used for
repetition that depends on a certain condition to be true.
This is not necessarily a counting condition. The loop may
exit when a certain value is entered.

Flag is the term used in computer science to detect if a certain


value is entered or altered to change the loop exit condition.
The value that is entered is called the Flag.

Essentially, a case has been made for fixed iteration and conditional iteration. The C++
tool of choice for fixed iteration is the for loop. The C++ tools for conditional iteration
are the while loop and do...while loop. This should leave the nagging question about the
need for two conditional loops. Apparently, they both do the same job.
In the averaging example, you will not observe the need for two conditional loop
structures. Once again, this is an example where more time will be needed to truly see
the difference. Right now consider the following.

The do...while loop forces a minimum of one program execution. This situation is
precisely what you want for a program that checks someone’s password or any other
input that must be done at least once.

The while loop does not necessarily execute at all. This is also desirable. A program that
is designed to retrieve the contents of a file and display them, should not do anything if
the file is totally empty.

This explanation is very skimpy. Good program examples require more sophisticated C+
+ knowledge. That will come. Right now, in this chapter you need to be concerned with
the proper syntax and some fundamental differences between the loop structures.

12.4 Nested Selection

Chapter 10 was so nice and clean. Selection structures and loop structures were
uncomplicated. There were no compound conditions, and there certainly was nothing
called “nesting.” Nesting a structure actually is not that bad. Essentially, it means that a
conditional statement is nested inside another conditional statement. The program
example below starts with one conditional statement to determine if a bonus will increase
for exceeding a sales quota. Now the generous boss decides to add yet another bonus for
years worked for the company. There is a catch; this extra bonus is only for employees
who meet the yearly sales goal. This means that the conditional statement for “years
worked” needs to be placed inside the condition for meeting the sales quota.

// PROG1207.CPP
// This program demonstrates nested one-way selection.

#include <iostream.h>
#include <conio.h>

void main()
{
float Bonus = 500;
float Sales;
int Years;
clrscr();
cout << "Enter your yearly sales ===>> ";
cin >> Sales;
cout << endl;

if (Sales >= 250000)


{
cout << "Your bonus will be increased by
$1000.00" << endl;
Bonus += 1000;
cout << "Enter years worked with the company
===>> ";
cin >> Years;
if (Years > 10)
{
cout << "Your bonus will be increased by
$250.00"
<< endl;
Bonus += 250;
}
}
cout << endl;
cout << "Your year-end bonus will be: " << Bonus;

getch();
}

PROG1207.CPP OUTPUT #1

Enter your yearly sales ===>> 300000

Your bonus will be increased by $1000.00


Enter years worked with the company ===>> 15
Your bonus will be increased by $250.00

Your year-end bonus will be: 1750

PROG1207.CPP OUTPUT #2

Enter your yearly sales ===>> 500000


Your bonus will be increased by $1000.00
Enter years worked with the company ===>> 5

Your year-end bonus will be: 1500

PROG1207.CPP OUTPUT #3

Enter your yearly sales ===>> 100000

Your year-end bonus will be: 500

Program PROG1208.CPP is another nested selection example. This time the if...else is
nested. In this program example, a student is admitted based on SAT performance.
There is also the question of financial aid. For this program, financial aid is determined
by family income. However, it is not necessary to consider financial aid unless the
student is admitted. The solution is to nest the financial aid condition inside the college
admission condition.

When you look closely at the nested control structure examples, you will note that
nothing really new is introduced. The syntax and the logic of the conditional statements
are the same. Using braces with multiple statements is also the same. The only
difference is an appearance of complexity because you see one conditional statement
inside another control structure. Anytime that you are bothered by complexity, focus on
a smaller, less complex part. Digest only what you can handle and computer science
becomes much easier. This is important advice because programs in the real world and in
the second year course are considerably more complex than the program examples and
assignments that you are doing currently. This is fine. When you get to the more
complex programs, you will be ready for them.

// PROG1208.CPP
// This program displays an admission message based on
an entered
// SAT score. It also determines financial need with a
nested
// if...else structure.

#include <iostream.h>
#include <conio.h>

void main()
{
int SAT;
float Income;
clrscr();
cout << "Enter your SAT score ===>> ";
cin >> SAT;
cout << endl;
if (SAT >= 1100)
{
cout << "You are admitted" << endl << endl;
cout << "Enter your family income ===> ";
cin >> Income;
if (Income <= 20000)
cout << endl << "You will receive financial
aid" << endl;
else
cout << endl << "You will not receive financial
aid"
<< endl;
}
else
{
cout << endl << "You are not admitted" << endl;
}
getch();
}
PROG1208.CPP OUTPUT #1

Enter your SAT score ===>> 1500

You are admitted

Enter your family income ===>> 10000

You will receive financial aid

PROG1208.CPP OUTPUT #2

Enter your SAT score ===>> 1200

You are admitted

Enter your family income ===>> 75000

You will not receive financial aid

PROG1208.CPP OUTPUT #3
Enter your SAT score ===>> 800

You are not admitted

The next program example uses multiple nested if...else statements to control multiple
selections. Now switch is specifically designed to handle multiple selection. True, but
switch has limitations. Consider the situation that is illustrated with the next program
example. You need to convert numerical scores to a letter grade. Using switch requires
a precise value. Now realize that every value in the 90.000 ... 100.000 range becomes an
A. It is not possible to handle that by using switch. If you are willing to use an
incredibly large number of cases, you might argue that switch works. Even if you are
willing to go that route, C++ will not except the use of a real number for a switch
variable.

The logical course of action is to use the multiple nested if...else statements that are
shown in program PROG1209.CPP. Please note the special indentation style that is
traditionally used with multiple if...else statements. Lining up all the if statements is both
readable and it makes it easier to fit the statements on the screen and on paper.

// PROG1209.CPP
// This program assigns grades 'A'..'F' based on
numerical scores
// using multiple nested if..else statements.

#include <iostream.h>
#include <conio.h>

void main()
{
float Score;
char Grade;
clrscr();
cout << "Enter your numerical score ===>> ";
cin >> Score;
if (Score >= 90.0)
Grade = 'A';
else if (Score >= 80.0)
Grade = 'B';
else if (Score >= 70.0)
Grade = 'C';
else if (Score >= 60.0)
Grade = 'D';
else
Grade = 'F';
cout << "Your grade will be: " << Grade << endl;
getch();
}

PROG1209.CPP OUTPUT #1

Enter your numerical score ===>> 100


Your grade will be: A

PROG1209.CPP OUTPUT #2

Enter your numerical score ===>> 90.5


Your grade will be: A

PROG1209.CPP OUTPUT #3

Enter your numerical score ===>> 83.756


Your grade will be: B

PROG1209.CPP OUTPUT #4

Enter your numerical score ===>> 79.999


Your grade will be: C

PROG1209.CPP OUTPUT #5

Enter your numerical score ===>> 60


Your grade will be: D

PROG1209.CPP OUTPUT #6

Enter your numerical score ===>> 59.999


Your grade will be: F
12.5 Nested Looping

Decision structures are not the only control structures that can be nested. The loop
structures can be nested as well. Each one of the three loop structures will be shown with
the same type of program. The mission of each program is to display a variety of
multiplication tables. It requires one loop structure to display a multiplication table, and
it takes another loop structure to display additional multiplication tables. The output of
each program is identical, and shown below.
PROG1210.CPP, PROG1211.CPP & PROG1212.CPP OUTPUT

1 * 11 = 11
2 * 11 = 22
3 * 11 = 33
4 * 11 = 44
5 * 11 = 55

1 * 12 = 12
2 * 12 = 24
3 * 12 = 36
4 * 12 = 48
5 * 12 = 60

1 * 13 = 13
2 * 13 = 26
3 * 13 = 39
4 * 13 = 52
5 * 13 = 65

// PROG1210.CPP
// This program displays several multiplication tables
using
// nested for loop structure

#include <iostream.h>
#include <conio.h>

void main()
{
int K;
int Table;
clrscr();
for (Table = 11; Table <= 13; Table++)
{
for (K = 1; K <= 5; K++)
cout << K << " * " << Table << " = " << K *
Table
<< endl;
cout << endl;
}
getch();
}
// PROG1211.CPP
// This program displays several multiplication tables
using
// nested while loop structure.

#include <iostream.h>
#include <conio.h>

void main()
{
int K;
int Table;
clrscr();
Table = 11;
while (Table <= 13)
{
K = 1;
while (K <= 5)
{
cout << K << " * " << Table << " = " << K *
Table
<< endl;
K++;
}
cout << endl;
Table++;
}
getch();
}

// PROG1212.CPP
// This program displays several multiplication tables
using
// nested do...while loop structure.

#include <iostream.h>
#include <conio.h>

void main()
{
int K;
int Table;
clrscr();
Table = 11;
do
{
K = 1;
do
{
cout << K << " * " << Table << " = " << K *
Table
<< endl;
K++;
}
while (K <= 5);
cout << endl;
Table++;
}
while (Table <= 13);
getch();
}
Nested looping shows a pattern that was seen earlier with nested decision structures.
The syntax, and logic are identical to a single loop. The for loop is probably the easiest
loop for nesting. The while loop can be tricky, if you are not careful about initializing
the loop condition variables. Consider the following program segment EXAMPLE1.

// EXAMPLE 1
Row = 0;
Col = 0;
while (Row < 10)
{
Row++;
while (Col < 10)
{
Col++;
cout << Row << ” , ” << Col << endl;
}
cout << endl;
}

Both Row and Col are giving the initial values of 0. These values are assigned before
any loop body is entered. The problem is that after the inner loop is executed once, it will
not execute a second time. The second time that the outer loop with Row executes, Col
still has value 10, and the inner loop does not execute anymore. The proper approach is
to make sure that the loop condition variable of the inner loop is initialized inside the
outer loop. This initialization correction is shown in EXAMPLE2 below.
// EXAMPLE 2

Row = 0;
while (Row < 10)
{
Row++;
Col = 0;
while (Col < 10)
{
Col++;
cout << Row << ” , ” << Col << endl;
}
cout << endl;
}

12.6 Compound Conditions

Chapter 11 did have a reason for existing. You are about to use the Boolean logic that
was presented there. Many situations in life present compound conditions and we will
start by looking at two programs that decide if a person should be hired. The hiring
criteria is based on years of education and years of work experience.

The first program example uses a logical or to decide if somebody should be hired. In
this case somebody is qualified if they have the required education or they have the
required work experience. C++ uses two vertical lines ( || ), which are located above the
<Enter> key to indicate the logical or.

// PROG1213.CPP
// This program demonstrates compound decisions with or
( || ).

#include <iostream.h>
#include <conio.h>

void main()
{
int Education; // years of education
int Experience; // years of work experience

clrscr();
cout << "ENTER YEARS OF EDUCATION ===>> ";
cin >> Education;
cout << "ENTER YEARS OF WORK EXPERIENCE ===>> ";
cin >> Experience;
cout << endl;

if ((Education >= 16) || (Experience >= 5))


cout << "YOU ARE HIRED";
else
cout << "YOU ARE NOT QUALIFIED";

cout << endl << endl;


cout << "HAVE A NICE DAY FROM XYZ EMPLOYMENT
SERVICES";

getch();
}

PROG1213.CPP OUTPUT #1

ENTER YEARS OF EDUCATION ===>> 16


ENTER YEARS OF WORK EXPERIENCE ===>> 5

YOU ARE HIRED

HAVE A NICE DAY FROM XYZ EMPLOYMENT SERVICES

PROG1213.CPP OUTPUT #2

ENTER YEARS OF EDUCATION ===>> 16


ENTER YEARS OF WORK EXPERIENCE ===>> 3

YOU ARE HIRED

HAVE A NICE DAY FROM XYZ EMPLOYMENT SERVICES


PROG1213.CPP OUTPUT #3

ENTER YEARS OF EDUCATION ===>> 12


ENTER YEARS OF WORK EXPERIENCE ===>> 5

YOU ARE HIRED

HAVE A NICE DAY FROM XYZ EMPLOYMENT SERVICES

PROG1213.CPP OUTPUT #4

ENTER YEARS OF EDUCATION ===>> 12


ENTER YEARS OF WORK EXPERIENCE ===>> 3

YOU ARE NOT QUALIFIED

HAVE A NICE DAY FROM XYZ EMPLOYMENT SERVICES

The four output samples of PROG1213.CPP show three hire situations and one “not
qualified” response. These four outputs closely resemble the appearance of the truth
tables, which was first introduced with or.

The next example, program PROG1214.CPP, is identical but now the compound
statement is decided by a logical and. C++ uses two ampersands ( && ) to indicate a
logical and.

Logical Operators in C++

C++ uses || to indicate a logical or.

C++ uses && to indicate a logical and.

C++ uses ! to indicate a logical not.


The logical and is far more demanding. There are four possible hiring combinations, and
just like the truth table, only one will qualify. A person must have the proper education
and also the required work experience.

// PROG1214.CPP
// This program demonstrates compound decisions with
and ( && )

#include <iostream.h>
#include <conio.h>

void main()
{
int Education; // years of education
int Experience; // years of work experience

clrscr();
cout << "ENTER YEARS OF EDUCATION ===>> ";
cin >> Education;
cout << "ENTER YEARS OF WORK EXPERIENCE ===>> ";
cin >> Experience;
cout << endl << endl;

if ((Education >= 16) && (Experience >= 5))


cout << "YOU ARE HIRED";
else
cout << "YOU ARE NOT QUALIFIED";

cout << endl << endl;


cout << "HAVE A NICE DAY FROM XYZ EMPLOYMENT
SERVICES";

getch();
}

PROG1214.CPP OUTPUT #1

ENTER YEARS OF EDUCATION ===>> 16


ENTER YEARS OF WORK EXPERIENCE ===>> 5
YOU ARE HIRED

HAVE A NICE DAY FROM XYZ EMPLOYMENT SERVICES

PROG1214.CPP OUTPUT #2

ENTER YEARS OF EDUCATION ===>> 16


ENTER YEARS OF WORK EXPERIENCE ===>> 3

YOU ARE NOT QUALIFIED

HAVE A NICE DAY FROM XYZ EMPLOYMENT SERVICES

PROG1214.CPP OUTPUT #3

ENTER YEARS OF EDUCATION ===>> 12


ENTER YEARS OF WORK EXPERIENCE ===>> 5

YOU ARE NOT QUALIFIED

HAVE A NICE DAY FROM XYZ EMPLOYMENT SERVICES

PROG1214.CPP OUTPUT #4

ENTER YEARS OF EDUCATION ===>> 12


ENTER YEARS OF WORK EXPERIENCE ===>> 3

YOU ARE NOT QUALIFIED

HAVE A NICE DAY FROM XYZ EMPLOYMENT SERVICES


12.7 Program Input Protection

Chapter 11 introduced Boolean Algebra laws. This chapter could get really tedious if a
program example is shown for each one of the Boolean laws. The focus here will be on
one of the most important Boolean laws in introductory computer science, DeMorgan’s
Law.

Let us start by looking at program PROG1215.CPP, which shows one approach that
uses Boolean logic properly. The purpose of the program is to make sure that proper
input is entered from the keyboard. This program example could be part of any type of
survey or record that asks the program user to enter his or her sex. The program is
expected to prevent any entry, except an M or an F.

The compound decision first considers what the proper input should be. Then a set of
parenthesis is placed around the desired M or F condition. The not decides if the
condition is not the desired one. Check the program out on the next page and notice the
combination of the or and the not.

// PROG1215.CPP
// This program demonstrates compound decision with a
do...while
// loop. The program checks for proper data entry.

#include <iostream.h>
#include <conio.h>

void main()
{
char Sex;

clrscr();
do
{
cout << "Enter sex [M/F] ===>> ";
cin >> Sex;
}
while (!((Sex == 'M') || (Sex == 'F')));
cout << endl;
cout << "Your sex is " << Sex << endl;

getch();
}
PROG1215.CPP OUTPUT

Enter your sex [M/F] ===>> Q


Enter your sex [M/F] ===>> A
Enter your sex [M/F] ===>> 1
Enter your sex [M/F] ===>> 2
Enter your sex [M/F] ===>> m
Enter your sex [M/F] ===>> f
Enter your sex [M/F] ===>> F

Your sex is F

Program PROG1216.CPP is very similar to the previous program. Close, but


significantly different. A very important set of parenthesis is left out. The result is that
the not only applies to the Sex == ’M’ component of the condition. This results in a
logic error.

This type of logic error alters the input protection so that only M is accepted as keyboard
input. Does it make sense why that is the only correct input? Put on your best logic hat
and see if you figure out what is happening.

// PROG1216.CPP
// This program demonstrates compound decision with a
do...while
// loop with logic problems due to missing parenthesis.

#include <iostream.h>
#include <conio.h>

void main()
{
char Sex;

clrscr();
do
{
cout << "Enter sex [M/F] ===>> ";
cin >> Sex;
}
while (!(Sex == 'M') || (Sex == 'F'));
cout << endl;
cout << "Your sex is " << Sex << endl;

getch();
}

PROG1216.CPP OUTPUT

Enter your sex [M/F] ===>> D


Enter your sex [M/F] ===>> Q
Enter your sex [M/F] ===>> F
Enter your sex [M/F] ===>> M

Your sex is M

The logical or makes a compound statement true if either one of the two conditions is
true. Without the parenthesis the condition (Sex == ’F’) is not controlled by the not.
This means that entering F makes the condition true and the loop body is executed. This
is not desirable because the loop body asks to enter Sex again. In other words, F will not
stop the loop. Entering M does stop the loop. The not does apply to the (Sex == ’M’)
condition and the loop works properly for that portion of the overall statement. To make
sure that you do understand the difference, the two statements are shown together. The
correct statement is shown first followed by the wrong statement.

while (!((Sex == 'M') || (Sex == 'F'))); // correct

while (!(Sex == 'M') || (Sex == 'F')); // wrong

Other compound decision problems can crop up in programs. The next program example
uses a totally different approach and checks if the input is not correct for Male or not
correct for Female. You may think that the loop is logically correct, and you expect it to
provide proper protection against erroneous keyboard input. Check the program output
to see if you are right.

// PROG1217.CPP
// This program demonstrates incorrect use of negative
compound
// decision structure.

#include <iostream.h>
#include <conio.h>

void main()
{
char Sex;

clrscr();
do
{
cout << "Enter sex [M/F] ===>> ";
cin >> Sex;
}
while ((Sex != 'M') || (Sex != 'F'));
cout << endl;
cout << "Your sex is " << Sex << endl;

getch();
}

PROG1217.CPP OUTPUT

Enter your sex [M/F] ===>> D


Enter your sex [M/F] ===>> Q
Enter your sex [M/F] ===>> F
Enter your sex [M/F] ===>> M
Enter your sex [M/F] ===>> f
Enter your sex [M/F] ===>> m

Loop never exits. No value satisfies the compound condition.

Something is definitely wrong. The loop does not go anywhere, except right back to
where it started. This happens no matter what you enter. The problem is caused by the
logical or combined with some negative conditions. You are seeing an example of not
using Boolean logic properly. In particular DeMorgan’s law is ignored. Let us look at
DeMorgan’s Law again.

DeMorgan’s Law

not(A or B) is equivalent to not(A) and not(B)

not(A and B) is equivalent to not(A) or not(B)

Note that removal of the parenthesis is not simply a matter of distributing the not to A
and B. The logical operator is altered. Failure to change the operator is a very common
mistake and results in the faulty program logic.

We showed an earlier program - that worked properly - with the following conditional
statement:

while (!((Sex == 'M') || (Sex == 'F'))); // correct


Then another program was shown with identical logic. The main difference is that the
program did not use so many parenthesis. The condition was simplified and probably
looked perfectly correct.

while ((Sex != 'M') || (Sex != 'F')); // incorrect

According to DeMorgan we have just committed a serious nono and the program will
not work correctly. Evidence of a logic problem cropped up immediately when we were
stuck in an infinite loop. Some people have a hard time seeing this type of logic. You
really must use the and operator. Input is wrong if the input is not male and at the same
time the input is not female. The problem with the or operator is that not male includes
female, just as not female includes male. Using or means that the condition will always
be satisfied and the loop goes round and round. It is not possible to find any input that
will stop the loop.

The next program example alters the logical operator from or to and which outputs good
results. Our good friend DeMorgan will be pleased that we have seen, and hopefully
understood the error of our ways. Boolean logic shall not be ignored without
consequences to the results of your program, not to mention the results to your computer
science grades.
// PROG1218.CPP
// This program demonstrates correct use of negative
compound
// decision structure using DeMorgan's Law.

#include <iostream.h>
#include <conio.h>

void main()
{
char Sex;

clrscr();
do
{
cout << "Enter sex [M/F] ===>> ";
cin >> Sex;
}
while ((Sex != 'M') && (Sex != 'F'));
cout << endl;
cout << "Your sex is " << Sex << endl;

getch();
}

PROG1218.CPP OUTPUT #1

Enter your sex [M/F] ===>> Q


Enter your sex [M/F] ===>> W
Enter your sex [M/F] ===>> M

Your sex is M

PROG1218.CPP OUTPUT #2

Enter your sex [M/F] ===>> F

Your sex is F

// PROG1219.CPP
// This program demonstrates using a boolean data type
// with an input protection loop.

#include <iostream.h>
#include <conio.h>
#include "BOOL.H"

void main()
{
char Sex;
bool Correct;

clrscr();
do
{
cout << "Enter sex [M/F] ===>> ";
cin >> Sex;
Correct = (Sex == 'M') || (Sex == 'F');
if (!Correct)
cout << "Incorrect input; please re-enter" <<
endl;
}
while (!Correct);
cout << endl;
cout << "Your sex is " << Sex << endl;

getch();
}

PROG1219.CPP

Enter sex [M/F] ===>> Q


Incorrect input; please re-enter
Enter sex [M/F] ===>> D
Incorrect input; please re-enter
Enter sex [M/F] ===>> m
Incorrect input; please re-enter
Enter sex [M/F] ===>> f
Incorrect input; please re-enter
Enter sex [M/F] ===>> M

Your sex is M
Using Boolean Data Types with Input Protection
The bool data type exists for the purpose of readability. In the area of variety bool is
seriously lacking. There are only two values for bool, and that is true and false. Yet
with those two small data values we can create programs that are much nicer because
they create such excellent readability.

Program PROG1220.CPP continues the tired saga of preventing erroneous keyboard


input. A little excitement and improvement is added because now lower-case m and f
will also work with the program.

The main focus of the program is on the Boolean data type. In this case the loop
continues while the condition is !Correct. Now that is very readable. Inside the loop
there is also a statement that says if (!Correct) and then a message follows. The beauty
of the Boolean data type is that we can make our programs closer to English. This is not
important the day that you write the program. But next week, next month, and especially
next year you will not always remember the meaning of some program code. At such
times you will appreciate any extra readability that you added to your program source
code.

// PROG1220.CPP
// This program demonstrates using a boolean data type
// with an input protection loop.
// It also shows a compound condition to exit the loop.
// A user has to enter a PIN and is given only three.

#include <iostream.h>
#include <conio.h>
#include "BOOL.H"

void main()
{
char Sex;
bool Correct;
clrscr();
do
{
cout << "Enter sex [M/F] ===>> ";
cin >> Sex;
Correct = (Sex == 'M') || (Sex == 'F') ||
(Sex == 'm') || (Sex == 'f');
if (!Correct)
cout << "Incorrect input; please re-enter" <<
endl;
}
while (!Correct);
cout << endl;
cout << "Your sex is " << Sex << endl;
getch();
}

PROG1220.CPP OUTPUT #1

Enter sex [M/F] ===>> Q


Incorrect input; please re-enter
Enter sex [M/F] ===>> q
Incorrect input; please re-enter
Enter sex [M/F] ===>> Q
Incorrect input; please re-enter
Enter sex [M/F] ===>> f

Your sex is f

PROG1220.CPP OUTPUT #2

Enter sex [M/F] ===>> F

Your sex is F

PROG1220.CPP OUTPUT #3

Enter sex [M/F] ===>> m

Your sex is m

PROG1220.CPP OUTPUT #4

Enter sex [M/F] ===>> M

Your sex is M
The next program example shows protection against a variety of potentially erroneous
inputs. You have certainly seen enough protection against wrong characters. Program
PROG1221.CPP protects against a wrong Password (apstring), a wrong Age (integer),
and a wrong GPA (real number). The logic is similar, but note that each loop is
specialized for the data type and the conditions required of the particular variable.

do . . . while and Input Protection

You will see do...while used frequently for input protection


loops. The post-condition loop makes sense for checking
erroneous input because you want the program to enter the
loop at least one time.

// PROG1221.CPP
// This program demonstrates a variety of input
protection
// with an input protection loop.
// It also shows how to handle upper and lower case
input.

#include <iostream.h>
#include <conio.h>
#include "BOOL.H"
#include "APSTRING.H"

apstring Password;
int Age;
float GPA;

void EnterPassword();
void EnterAge();
void EnterGPA();
void DisplayData();
void main()
{
clrscr();
EnterPassword();
EnterAge();
EnterGPA();
DisplayData();
getch();
}

void EnterPassword()
{
bool CorrectPassword;
clrscr();
do
{
cout << "Enter password ===>> ";
cin >> Password;
CorrectPassword = Password == "QWERTY";
}
while (!CorrectPassword);
}

void EnterAge()
{
bool CorrectAge;
cout << endl << endl;
do
{
cout << "Enter age ===>> ";
cin >> Age;
CorrectAge = (Age >= 0) && (Age <= 130);
}
while (!CorrectAge);

void EnterGPA()
{
bool CorrectGPA;
cout << endl << endl;
do
{
cout << "Enter GPA ===>> ";
cin >> GPA;
CorrectGPA = (GPA >= 0) && (GPA <= 4);
}
while (!CorrectGPA);

void DisplayData()
{
cout << endl << endl;
cout << "PASSWORD: " << Password << endl;
cout << "AGE: " << Age << endl;
cout << "GPA: " << GPA << endl;
}

PROG1221.CPP OUTPUT

Enter password ===>> AARDVARK


Enter password ===>> QWERTY

Enter age ===>> 150


Enter age ===>> 52

Enter GPA ===>> 7.785


Enter GPA ===>> 3.999

PASSWORD: QWERTY
AGE: 52
GPA: 3.999

We will finish the section by looking at a practical situation that occurs in real life.
Individuals entering a password to login to a network, or people entering a PIN to use an
ATM card should not just be able to enter data forever. Somebody who has stolen an
ATM card or somebody who has no business logging in as a different user, should not
have unlimited access to trying to enter the system.
There have been a variety of movies where clever young kids hook up a computer
program to some data base and the computer takes all night methodically trying to crack
into the system by trying millions of different passwords. Now this looks cute on
television or in a movie, but do give me a break. Anybody who uses a program that sits
around waiting for millions of break-in attempts deserves to get trouble. There has to be
a limit on input attempts.

Our final program in this section shows just such a situation. It is also another nice
example of using a compound condition. Program PROG1222.CPP shows part of a
program that checks the proper PIN (Personal Identification Number) of an ATM
(Automatic Teller Machine) card. The compound condition has been set up to accept
three attempts at entering the correct PIN. After three tries it is over. In such a case the
machine can also do fun things like keep the card.

// PROG1222.CPP
// This program shows the need for a practical compound
condition
// used with an input protection loop. The program
request the
// user PIN, but rejects access after three tries.

#include <iostream.h>
#include <conio.h>

void main()
{
int PIN;
int Tries = 0;
clrscr();
do
{
cout << "Please enter your PIN ===>> ";
cin >> PIN;
Tries++;
}
while ((PIN != 8423) && (Tries < 3));
if (PIN == 8423)
cout << "Your PIN is correct" << endl;
else
cout << "You have exceeded your PIN entries" <<
endl;
getch();
}
PROG1222.CPP OUTPUT #1

Please enter your PIN ===>> 4325


Please enter your PIN ===>> 4326
Please enter your PIN ===>> 4327
You have exceeded your PIN entries

PROG1222.CPP OUTPUT #2

Please enter your PIN ===>> 4325


Please enter your PIN ===>> 4326
Please enter your PIN ===>> 8423
Your PIN is correct

12.8 Short-Circuiting Decisions

C++ is pretty clever and takes advantage of something called short circuiting. The name
is very appropriate if you think why we use the term short circuit with electricity.
Electric current takes a path that travels to some appliance like a freezer, television or a
light bulb. The path traveled by the electricity through the wires and the appliance is
called a circuit. The appliance will only operate properly is a complete circuit exists.
Sometimes, wires may be faulty and insulation is missing that causes a short circuit.
Current jumps across the wires and a circuit is completed before the appliance is reached.
In such a case a fuse burns or a circuit breaker is switched off to prevent fire damage
from the overheated circuits.
The concept applies to computer science decisions as well. A situation exists that stops
the normal path in favor of a shorter path. Consider the following, rather complicated
Boolean expression:

A and ( (A or B) and (B or C) and (A or C) or ((B and C) or (A and B)))

This expression can be quite an unpleasant truth table. Now suppose that it is known that
A equals false, is it necessary to evaluate the entire expression? No, it is not because
the and logical operator guarantees that the final outcome will always be false. In this
case we can short circuit the evaluation. Similar logic applies with or. If it is given that
A equals true then the entire expression will evaluate to true. Once again it is not
necessary to consider the rest of the expression.

A or ( (A or B) and (B or C) and (A or C) or ((B and C) or (A and B)))

Program PROG1223.CPP uses the short circuit principle. If the first condition, N1 % 2
== 0 equals false then it is not necessary to consider the value of the second condition,
N2 % 2 == 0. It is entirely possible that you are totally unimpressed by this program.
You do appreciate that C++ utilizes short-circuiting, but little evidence is shown to you
about the process.

// PROG1223.CPP
// This program uses "short circuiting" but it is not
// noticeable at all.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int N1,N2;
cout << "Enter two positive integers ===>> ";
cin >> N1 >> N2;
if (N1 % 2 == 0 && N2 % 2 == 0)
cout << "Both numbers are even" << endl;
else
cout << "Both numbers are not even" << endl;
getch();
}

PROG1223.CPP OUTPUT #1

Enter two positive integers ===>> 12 24


Both numbers are even

PROG1223.CPP OUTPUT #2

Enter two positive integers ===>> 11 24


Both numbers are not even

PROG1223.CPP OUTPUT #3
Enter two positive integers ===>> 24 11
Both numbers are not even

The next two program examples will not only involve compound decisions, but they will
also demonstrate that short circuiting is performed by C++. Each program call uses a
function, called IsEven, shown below. This function is called from the conditional
statement. Calling a function inside a conditional statement is perfectly legal since it is a
return function. Return functions return values. You have seen return functions that
return integers and real numbers. Function IsEven returns true or false, since it is a
Boolean function. The purpose of the function is to return true if the function argument
Number is even and false if Number is odd. The function intentionally displays some
output so that you can see that the function is called.

bool IsEven(int Number)


{
cout << endl;
cout << "Calling IsEven Function" << endl;
cout << endl;
if (Number % 2 == 0)
return true;
else
return false;
}

You have not yet learned how to write the type of function that you are viewing above.
At this stage this does not matter. You have used plenty of functions without a clue how
those functions work. The bottom line is that a function is called that displays a message,
letting you know it is called, and the function returns true if the parameter is even.

In program PROG1224.CPP two integers are requested from the keyboard, as before.
The entered numbers are used in the parameters of the two IsEven function calls. Now
C++ claims that it will not consider evaluating a complete compound condition if true or
false can be guaranteed without moving on. In other words, if the first condition is false
and a logical and is used, then the whole condition will be false. We can test this theory
by running the program several times. Each call to function IsEven is noticed because it
displays output. When the first number entered is odd, you should only observe one
function call.

// PROG1224.CPP
// This program uses "short circuiting" and uses the
IsEven
// function to demonstrate short circuiting with
logical and.

#include <iostream.h>
#include <conio.h>
#include "BOOL.H"

bool IsEven(int Number)


{
cout << endl;
cout << "Calling IsEven Function" << endl;
cout << endl;
if (Number % 2 == 0)
return true;
else
return false;
}

void main()
{
clrscr();
int N1,N2;
cout << "Enter two positive integers ===>> ";
cin >> N1 >> N2;
if ( IsEven(N1) && IsEven(N2) )
cout << "Both numbers are even" << endl;
else
cout << "Both numbers are not even" << endl;
getch();
}

PROG1224.CPP OUTPUT #1

Enter two positive integers ===>> 12 24

Calling IsEven Function

Calling IsEven Function

Both numbers are even

PROG1224.CPP OUTPUT #2
Enter two positive integers ===>> 11 24

Calling IsEven Function

Both numbers are not even

PROG1224.CPP OUTPUT #3

Enter two positive integers ===>> 24 11

Calling IsEven Function

Calling IsEven Function

Both numbers are not even

The output of program PROG1224.CPP does not disappoint us. As anticipated, only the
first part of the compound condition, (IsEven(N1) && IsEven(N2)) is evaluated
when it is established that the whole condition must be false. This is proven by the single
call to the IsEven function when the first number entered is an odd number.

The next program example is very similar to the previous program, and it uses the same
IsEven function. This time short circuiting is tested with a logical or. The concept of
short circuiting is the same, but in this case C++ stops evaluating when it is established
that the first condition is true.

You will find in future chapters that short circuiting becomes a useful tool in preventing
incorrect program executions. In particular, short circuiting with the logical and will be
used frequently. It is appropriate to introduce the concept in a chapter that introduces
compound conditions that are evaluated with Boolean logic laws. Practical use of this
concept will need to be postponed to a later chapter.

// PROG1225.CPP
// This program uses "short circuiting" and uses the
IsEven
// function to demonstrate short circuiting with
logical or.

#include <iostream.h>
#include <conio.h>
#include "BOOL.H"
bool IsEven(int Number)
{
cout << endl;
cout << "Calling IsEven Function" << endl;
cout << endl;
if (Number % 2 == 0)
return true;
else
return false;
}

void main()
{
clrscr();
int N1,N2;
cout << "Enter two positive integers ===>> ";
cin >> N1 >> N2;
if ( IsEven(N1) || IsEven(N2) )
cout << "One or more numbers are even" << endl;
else
cout << "Neither numbers are even" << endl;
getch();
}

PROG1225.CPP OUTPUT #1

Enter two positive integers ===>> 11 23

Calling IsEven Function

Calling IsEven Function

Neither numbers are even

PROG1225.CPP OUTPUT #2

Enter two positive integers ===>> 11 24

Calling IsEven Function


Calling IsEven Function

One or more numbers are even

PROG1225.CPP OUTPUT #3

Enter two positive integers ===>> 24 11

Calling IsEven Function

One or more numbers are even

12.9 Recursion, a Sneak Preview

The title of this section is very appropriate. The real recursion show comes later.
Recursion is a very important topic in computer science and you will be exposed to this
topic many, many times. The intention at the end of this chapter is to plant a seed for a
future topic. The hope is that the seed will find fertile ground in your brain and maybe
become a small plant by the time we return to the topic. So what is recursion anyway,
and what is the big deal? The big deal has to wait, but the basic essence of recursion is
very appropriate in a chapter on control structures. Is this a recurring theme or what?
Every time you learn something, you are told to hang loose for more information in the
future. Relax, this is intentional and it is all part of the Exposure scheme of learning. If
you received all the information about a particular topic in one concentrated introduction,
you would probably be severely overwhelmed and possibly throw in the towel.

Recursion Definition

Recursion is the process of a function calling itself.


This certainly is a meager, skimpy definition. It is very skimpy, but it is very true. A
function is executed by calling it. Now we have seen that functions can be called from
the main function and functions can be called from other functions. Well, why not call a
function from the same function? Weird? Perhaps. Check out program
PROG1226.CPP. This program calls a function that counts numbers. Each time that
the function is called, the value of X is incremented and displayed. There is one call in
the main function to get the ball rolling. After that, function Count takes care of business
and happily calls itself.

// PROG1226.CPP
// This program introduces recursion as an alternative
to
// repetition. This example creates an infinite loop.

#include <iostream.h>
#include <conio.h>

int X = 1000;

void Count();

void main()
{
clrscr();
Count();
getch();
}

void Count()
{
X++;
cout << "X = " << X << endl;
Count();
}

PROG1226.CPP OUTPUT

X = 1001
X = 1002
X = 1003
X = 1004
X = 1005
X = 1006
X = 1007
X = 1008
X = 1009
X = 1010
........

DOES NOT END

Your suspicions about this Schram guy are becoming more valid. Now the guy
introduces a new computer science concept that cleverly sends a program into an infinite
loop. Fine, you now see the purpose for recursion in this chapter. Without using a loop
structure you can simulate repetition. Make a function call itself and it goes round and
round. You can then watch numbers flash on by the monitor until you get tired.

But let us hold on here for a moment. Is it not very easy to create an infinite loop with
other control structures? If the loop condition variable does not change properly a loop
may never exit. Every loop structure that has been introduced has some kind of condition
that determines when the loop is finished. In all fairness we need to give recursion the
same courtesy and allow a condition to control its destiny as well. The next program
counts once again, but now we feel that counting 15 times is sufficient. The recursive
call is only made as long as the condition if (X < 1015) is true.

Important Recursion Warning

It is easy to write programs with recursive functions that


repeat in an infinite pattern of recursive calls. Some special
condition must be tested before each recursive call is made.

// PROG1227.CPP
// This program introduces recursion as an alternative
to
// repetition. This example solves the infinite
recursion
// problem with a conditional statement before the
recursive call.
#include <iostream.h>
#include <conio.h>

int X = 1000;

void Count();

void main()
{
clrscr();
Count();
getch();
}

void Count()
{
X++;
cout << "X = " << X << endl;
if (X < 1015)
Count();
}

PROG1227.CPP OUTPUT

X = 1001
X = 1002
X = 1003
X = 1004
X = 1005
X = 1006
X = 1007
X = 1008
X = 1009
X = 1010
X = 1011
X = 1012
X = 1013
X = 1014
X = 1015

Please realize that this was a very brief introduction to recursion. There will be several
chapters on this topic in the future. Some students like to play around with recursion and
see what it does. For now the important idea is that you know an alternative to regular
loop structures.
Recursion Notes

Recursion is the process of a function calling itself.

Recursion simulates repetition.

Recursion requires some condition that exits the recursive


calling to prevent infinite repetition. The special condition
that stops the recursive calls is called the base case.

You will find in some future topics that there exist a variety
of programming problems that are easier to solve with
recursive structures than with iterative loop structures.

12.10 Worked-Out Exercises

The exercises that follow will be in the same pattern as the exercises presented in Chapter
X. Each exercise presents a brief program with the mission to determine the program
output. The essence of the exercise revolves around tracing the variable values as they
change during program execution. This time the exercises will be more challenging with
the addition of nested control structures and compound conditions.

Exercise 01
#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
for (int X = 1; X < 2; X++)
for (int Y = 1; Y < 3; Y++)
cout << X << Y << endl;
getch();
}

X Y Output
1 1 11
1 2 12

Exercise 02
#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
for (int X = 1; X < 3; X++)
{
for (int Y = 1; Y < 4; Y++)
cout << X * Y << " ";
cout << endl;
}
getch();
}

X Y Output
1 1 1
1 2 12
1 3 123
2 1 2
2 2 24
2 3 246

Exercise 03
#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int X = 5;
int K,Y;
while (X <= 8)
{
Y = 1;
while (Y <= 7)
{
Y++;
K = X + Y;
}
X += Y;
}
cout << "K = " << K << endl;
getch();
}

Y K X Output
5
1
2 7
3 8
4 9
5 10
6 11
7 12
8 13 13
K = 13

A common mistake with this type of output is to stop when Y equals 7. At that time the
inner while loop is still continued since the loop condition checks to see if Y is less than
or equal to 7. Failure to execute that last iteration through a loop structure causes an
error than is called an OBOB.

OBOB Warning

An OBOB is an Off By One Bug error. This problem occurs


at the boundaries of control structures. Carefully check
your program code at the boundaries to avoid OBOBs.
Exercise 04
#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int A = 1, B = 2, C = 3, D = 4;
while (A < B && C < D)
{
A = C + D;
C = A + B;
}
cout << A << B << C << D << endl;
getch();
}

A B C D Output

1 2 3 4
7 9
7294

This example uses a compound condition in the while loop. The trace shows that both
conditions become false. Keep in mind that this is not a requirement for a logical and.
As long as one of the condition becomes false, the loop will exit.

Exercise 05
#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int A;
int B = 2;
for (int K = 0; K < 4; K++)
{
A = K;
B += K;
while (A < B)
{
cout << A << " " << B << endl;
A += B;
B += K;
}
}
getch();
}

K A B Output
2
0 0 2 02
2 2
1 1 3 13
4 4
2 2 6 26
8 8
3 3 11 3 11
14 14

Exercise 06
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int A = 0;
int B = 10;
for (int K = A; K < B; K++)
{
A++;
B--;
cout << A << " " << B << " " << K << endl;
}
getch();
}

K A B Output
0 10
0 1 9 190
1 2 8 281
2 3 7 372
3 4 6 473
4 5 5 554
5

You need to be careful with this type of exercise. The for loop condition checks to see if
K < B and this condition changes. The value of B is not constant for the duration of the
loop. Initially the value of B equals 10, but then decrements each time the loop is
repeated.

If we want to use the for loop as a fixed iteration loop, this style of programming should
be discouraged. You may realize that the for loop can be manipulated in such a way that
it behaves in the same manner as a while loop.

Exercise 07
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int T = 0;
for (int P = 1; P <= 4; P++)
for (int Q = 1; Q <= 4; Q++)
T++;
cout << "T = " << T << endl;
getch();
}

P Q T Output
0
1 1 1
2 2
3 3
4 4
2 1 5
2 6
3 7
4 8
3 1 9
2 10
3 11
4 12
4 1 13
2 14
3 15
4 16
T = 16

Exercise 08
// EX1208.CPP
#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int T = 0;
for (int P = 0; P < 10; P++)
for (int Q = 1; Q < 10-P; Q++)
T++;
cout << "T = " << T << endl;
getch();
}

P Q T Output
0
0 1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
1 1 10
2 11
3 12
4 13
5 14
6 15
7 16
8 17
2 1 18
2 19
3 20
4 21
5 22
6 23
7 24
3 1 25
2 26
3 27
4 28
5 29
6 30
4 1 31
2 32
3 33
4 34
5 35
5 1 36
2 37
3 38
4 39
6 1 40
2 41
3 42
7 1 43
2 44
8 1 45
T = 45

The trace of the last program is quite tedious. Hopefully, you can see that there is a
pattern that makes the output easier to determine. The inner loop iterates 9 times during
the first pass, 8 times during the second pass, and once during the last pass. There are 9
passes from 9 down to 1 inner repetitions. This means that the inner loop repeats an
average of 5 times. If you multiply 9 times 5 you get 45.

Did the shortcut explanation make any sense? To some students it probably made sense
right away. To some other students, this may be another story. Keep in mind that you
can always use the long trace approach. It may be tedious, but it is accurate and you do
not have to play guessing games.

The main point is that you get out some paper and pencil and trace through the program
either one step at a time, recording each variable value, or you determine some type of
pattern that helps you predict the outcome.

Exercise 09
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int N1, N2, N3;
N1 = N2 = N3 = 1;
for (int K = 3; K <= 10; K++)
{
N3 = N1 + N2;
N1 = N2;
N2 = N3;
}
cout << "N3 = " << N3 << endl;
getch();
}

K N3 N1 N2 Output
1 1 1
3 2 1 2
4 3 2 3
5 5 3 5
6 8 5 8
7 13 8 13
8 21 13 21
9 34 21 34
10 55 34 55
N3 = 55

The program above computes the Fibonacci Sequence. This is a sequence of integers,
such that each integer in the sequence is the sum of the two previous integers. The output
in this case is the 10th number in the sequence.

Exercise 10
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int A = 5;
int B = 10;
int C = 13;
while (A < B && B != C)
{
A += 2;
B++;
if ((A + B) % 2 == 0)
C++;
}
cout << A << " " << B << " " << C << endl;
getch();
}

A B C A<B B != C Output
5 10 13 true true
7 11 14 true true
9 12 true true
11 13 15 true true
13 14 true true
15 15 16 false true
15 15 16
Exercise 11
// EX1211.CPP

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int A, B , C;
if (A < B)
if (B < A)
C = 1000;
else
C = 2500;
else
if (B > A)
C = 2000;
else
C = 2500;
cout << "C = " << C << endl;
getch();
}

A B C Output
? ? ?
C = 2500

This problem may at first appear like it cannot have a solution. A normal trace with
changing variable values does not apply. On the other hand, you can apply logic to
determine the output of this program.

Assume that A < B is true. It is not possible at the same time that B < A is also true.
This means that the flow continues to the first "nested else" and C = 2500.

Now if A < B is false, execution flows jumps to the "outer else" and checks to see if B >
A is true. With A < B false it must also be the case that B > A is false and execution flow
continues to the second "nested else" where C = 2500.

This means that the values of the variables are not important. Regardless of any starting
values the output will always be that C = 2500.
Exercise 12
#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
for (int X = 1; X <= 4; X++)
{
for (int Y = 1; Y <= 4; Y++)
cout << X + Y << " ";
cout << endl;
}
getch();
}

X Y X+Y Output
1 1 2 2
1 2 3 23
1 3 4 234
1 4 5 2345
2 1 3 3
2 2 4 34
2 3 5 345
2 4 6 3456
3 1 4 4
3 2 5 45
3 3 6 456
3 4 7 4567
4 1 5 5
4 2 6 56
4 3 7 567
4 4 8 5678
2345
3456
4567
5678

The output is shown as each number is added to the display. In reality, that view will not
be seen, unless you stop the output. The final completed output is shown at the very end
to show the complete display.
APCS Examination Alert

Computers are not used during an APCS Examination.


You will need to determine the correct program execution
of program segments and functions throughout the test.

The ability to "play computer" and trace systematically


through program code in the same manner as program
execution is a value skills. For the remainder of the
course you will be exposed to many different types of
tracing situations.

You might also like