Professional Documents
Culture Documents
Chapter XIII
Chapter XIII
Parameter Functions I
13.6 Scope
13.1 Introduction
Now back on task with computer science. In an earlier chapter on modularity you
were introduced to writing user-defined functions. All the functions presented
were void functions and the functions lacked parameters. In a later chapter we
looked at parameter passing to functions. You saw how both graphics functions
and math functions required, and used parameters. Parameters are a big deal and
now you will be pleased that two complete chapters will be devoted to this topic.
The goal of this chapter, and the next one, is to learn about writing your own
functions that use parameters. Soon you will realize why there are two chapters
to this unit. Functions are very powerful and there are many different types of
functions. We handle each type in turn and show many examples along the way.
Take it slow. Take it steady, and this function business will fall in place.
It would have been possible to introduce all of the parameter functions much
earlier. The delay is intentional. We now have control structures behind us and
with those tools in our bag it will be much easier to show meaningful examples of
parameter functions.
The importance of parameter functions is so great that this chapter will teach
function parameters as if the topic was introduced for the first time. Please do not
be insulted by this approach. Such an approach is for people who are confused by
this parameter business, and prefer a fresh start.
Consider the following two simple functions used for skipping lines. These two
functions are probably in your utility library and aid you in creating the proper
output that your picky teacher requires.
void Skip2()
{
cout << endl << endl;
}
void Skip4()
{
cout << endl << endl << endl << endl;
}
Functions Skip2 and Skip4 have served you well, but there are times when you
need to skip 3 lines, 5 lines, and even 6 lines or more. It is quite annoying to end
up putting ten different skip functions in your utility library, just for the sake of
being able to use any required skip routine. Perhaps you do not object to writing
ten different functions or more. You may argue that once they are in your library,
who cares? This is fine, but then you should consider that you are using a
considerable amount of memory and probably a large number of functions that
you will rarely use.
The earlier Modularity chapter introduced a function for swapping the values of
two variables. It had been shown primarily for the purpose of demonstrating an
example of a local variable. We have not yet run across some practical examples
of swapping variable values. Please take it on faith right now. Swapping is very
significant in the processing of data. Especially when data needs to be sorted. If
you have forgotten the Swap function, do not go back to the earlier chapter.
Function Swap is not that long. It is displayed again on the next page.
void Swap()
{
Function Swap exchanges the values of Nr1 and Nr2. This is real exciting, if you
have need for exchanging Nr1 and Nr2. Unfortunately, a little later in your
program you find that you must swap Nr3 and Nr4, and even later Value1 and
Value2 require exchanging. This is the same problem you experienced with
Skip, but even worse. It is not possible to create a utility library with every
conceivable Swap function.
And . . . it gets even more complicated. What would you call all of these Swap
modules? Names like Skip2, Skip4 and Skip5, etc. are logical names for
different Skip functions. But what do you call different Swap functions? Names
like SwapNr1_Nr2 or SwapVal1andVal2 becomes a little too involved.
What is the point anyway? The point is that both the Skip function and the Swap
function leave something to be desired, and examples can be found for other
functions that would have equal shortcomings.
Addressing and curing the shortcomings just mentioned, is the job of parameter
functions, and the main thrust of this chapter and the next chapter. Hang on, the
material in this chapter may get confusing. You have no reason to be concerned,
or feel dumb, if you do not understand everything right away. Read this chapter
again, and again, and ask questions. Experience has proven that only students
who give up never understand parameters.
Our goal is to eliminate multiple skip functions. We want not only to reduce
Skip2 and Skip4 to one function, but also add the capabilities of any other skip
capability that might be necessary. Consider the Skip function, shown on the
next page. Is that an improvement?
void Skip()
This Skip function will skip N number of lines. In other words, the value of N
will determine how many lines are going to be skipped. Where does function
Skip get this value for N? You guessed it. It comes from a parameter. It comes
from a function call like Skip(4). This type of function call is not so odd. After
all, you have worked with the parameter function calls for several chapters now.
What is new, is the function part itself. How does it handle this parameter
business? Check out the new, and improved Skip function below.
void Skip(int N)
{
int K; // loop counter
for (K = 1; K <= N; K++)
cout << endl;
}
It does not look so scary does it? The parenthesis, which often sit around empty
doing nothing, now contain information. Specifically, they contain parameter
information. In this case the information states that some integer value is going to
be passed to parameter N.
This makes N a local variable of function Skip, but it is a special kind of local
variable, enpowered with the ability to receive information from the outside
world. This type of variable is a parameter and because it copies the value of the
parameter in the function call, it is called a Value parameter.
We will kick off the program examples in this chapter with program
PROG1301.CPP. This first program takes the parameter function Skip and
demonstrates its use in a nonsense program designed specifically to skip a bunch
of lines. Yes, I know, once again you need to control your excitement.
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
cout << "WE WILL SKIP ONE LINE NOW" << endl;
Skip(1);
cout << "WE WILL SKIP TWO LINES NOW" << endl;
Skip(2);
cout << "WE WILL SKIP FOUR LINES NOW" << endl;
Skip(4);
cout << "SKIPPING LINES IS SUCH FUN" << endl;
getch();
}
void Skip(int N)
{
int K;
for (K = 1; K <= N; K++)
cout << endl;
}
PROG1301.CPP OUTPUT
You may be uncomfortable with the label value parameter. This is especially true
since you need to wait for the next chapter before we discuss other types of
parameters. Strictly teaching speaking, the label value does not need to be
mentioned here. I could have waited until the next chapter. The motivation for
the label is quite simple. This book is meant to be a tutorial for learning computer
science. But at the same time it is meant to be a reference that you can use to look
up information. From that point of view it helps if the table of contents
specifically states value parameter functions. And that is what this section will
do. A bunch of parameter functions will be shown to help you understand the
general syntax and to see a variety of examples.
Beep Function
Program PROG1302.CPP is quite similar to the previous program. In this case a
function is defined that has the ability to beep a specified number of times. The
ASCII value (7) generates a short beep from the computer. The process is the
same as the previous program example. Some integer value is passed to a
function, and then the value is used in a loop. The previous program repeated a
number of carriage returns. This program repeats a number of beep. Logically
speaking, there is no difference between the two program.
// PROG1302.CPP
// This program uses a Beep function that beeps a
// specified number of times.
#include <iostream.h>
#include <conio.h>
void main()
PROG1302.CPP OUTPUT
Center Function
Output format is a big deal. People buy products because they look nice and
people pay attention to displays that are attractive. Frequently, program output
needs to be centered. Centering is not a trivial task. Each string needs to be
counted, then you need to do some math and decide where to position the string.
This is precisely where functions, and especially parameter function shine. You
send a string to the clever Center function, and the function does all the
computation work for you automatically.
// PROG1303.CPP
// This program uses a function that centers output
strings.
void main()
{
clrscr();
Center("PARAMETERS");
Center("IS WHAT MAKES");
Center("FUNCTIONS FUNCTION");
getch();
}
void Center(apstring S)
{
int Len,Tab;
Len = S.length(); // apstring string-length
function
Tab = (80 - Len) / 2;
cout << setw(Tab) << "" << S << endl;
}
PROG1303.CPP OUTPUT
PARAMETERS
IS WHAT MAKES
FUNCTIONS FUNCTION
The Center function uses a feature that has not been used before. It is a special
function that determines the length of a string. In this case, it is the length of
string S. The syntax is S.length(); This is the same syntax that was used with the
introduction of object oriented programming in Chapter XI. Since length is a
member function of the apstring class, any object of the class must be accessed
with the dot.function notation.
After the length of the string parameter (S) is determined, the value (Len) is
subtracted from 80. This leaves the number of spaces not used on one screen line.
This leftover amount is then divided by two to compute the number of spaces that
should be displayed on either side of the string. Finally, function setw is used to
move an empty string over to the location the string needs to start.
The next function example is not in the practical category of a center function.
The intention of the Rectangle function is to show a function with multiple
parameters. You have used a Rectangle function before. The earlier Rectangle
function used some fancy graphics that will not be explained here. This function
example displays a text-style rectangle. Not practical yes, but it will help to
explain some important parameter concepts. Take a look at the program example
and see if you note any important differences from the previous examples.
// PROG1304.CPP
// This program displays a text-style rectangle.
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
TextRectangle(20,5,40,10);
getch();
clrscr();
TextRectangle(10,5,70,20);
getch();
}
Do you see the difference? Look at the function heading and the parameters.
There are four parameters, and that is not so odd. Displaying a rectangle requires
four pieces of information. The unusual feature is that every parameter requires a
data type.
Four similar integer variables anywhere in a program are usually defined like:
PROG1304.CPP OUTPUT
####################
####################
####################
####################
####################
####################
####################
Function TextRectangle is called twice. After the first call the screen is cleared
when the program user presses the <Enter> key. The continued output caused by
the second function call to TextRectangle is shown on the next page.
PROG1304.CPP CONTINUED OUTPUT
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
###########################################################
You just saw multiple parameters listed in a function heading. Each one of these
parameters was an integer (int) data type. Now you need to see what happens
when multiple parameters are not the same data type. We can add one more twist,
and one more parameter, to the Rectangle function with a character (char)
parameter. The extra parameter can be used to indicate what type of character
will be used to display the rectangle.
Do not look real hard for something spectacular and different. The extra
parameter is tagged on to the end with a comma separator. It really does not
behave any different from any other parameter. It just happens to be preceded by
a different data type.
// PROG1305.CPP
// This program displays a text-style rectangle
// with mixed parameter types.
#include <iostream.h>
#include <conio.h>
void TextRectangle(int X1, int Y1, int X2, int Y2, char
C);
void main()
{
clrscr();
TextRectangle(20,5,40,10,'$');
getch();
TextRectangle(20,5,40,10,'&');
getch();
}
void TextRectangle(int X1, int Y1, int X2, int Y2, char
C)
{
int X,Y;
for (Y = Y1; Y <= Y2; Y++)
for (X = X1; X <= X2; X++)
{
gotoxy(X,Y);
cout << C;
}
PROG1305.CPP OUTPUT
$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$
The mixed parameters show another difference between defining regular variables
and defining variables that are parameters. The parameter list can continue with a
separation of a comma. That is not a possibility for regular variable definitions.
Consider the following two types of variable definitions:
Four integer variables and one character variable defined anywhere in a program
are defined like:
Four integer value parameters and one character variable in a function heading are
defined like:
Title Function
Students at Berkner High School love this function. Picky old, annoying, Mr.
Schram (me) requires a title heading at the start of each function execution. This
heading helps to identify the function being executed and checks the global flow
------------------------------------------------------------------------------
========================== PROCESSING DATA ===============================
------------------------------------------------------------------------------
This type of heading certainly is somewhat of a pain to create. The name has to
be centered, and every title has to be the same length. Students have no great
fondness for this particular program requirement.
What comes to the rescue now is a highly functional, and specialized function that
automatically creates such a title heading. The Title function is also a good
example of combining various control structures to create a useful application.
This function is not a possibility without control structures. The title function
may seem fairly complicated, but keep in mind that several items need to be
checked and altered depending on circumstances. A string with an even number
of characters will get the exact same number of ( = ) characters on each side of
the title string. A string with an odd number of characters requires one extra ( = )
to one side of the string.
// PROG1306.CPP
// This program uses a function that automatically
creates a
// title heading for a function or program segment.
#include <iostream.h>
#include <conio.h>
#include <iomanip.h>
#include "APSTRING.H"
void main()
{
clrscr();
Title("EXECUTION BEGINS");
cout << endl << endl;
Title("PROCESSING DATA");
cout << endl << endl;
Title("EXECUTION TERMINATED");
getch();
}
void Title(apstring S)
PROG1306.CPP OUTPUT
------------------------------------------------------------------------------
========================== EXECUTION BEGINS ==============================
------------------------------------------------------------------------------
------------------------------------------------------------------------------
========================== PROCESSING DATA ==============================
------------------------------------------------------------------------------
------------------------------------------------------------------------------
======================== EXECUTION TERMINATED ============================
------------------------------------------------------------------------------
Students who are required to use a function title heading will rapidly add the Title
function to their utility library of useful goodies. Please keep in mind the point of
this chapter. The purpose is to learn how to use and define functions with
parameters. This is not a chapter on useful and clever tools to make your
programming life simpler. Hopefully, you will discover a variety of functions
that are useful, and even better, you may create some functions yourself.
Every function that you have created so far has been a void function. The earlier
Program Modularity chapter used void functions without parameters and now
parameters have been introduced with void functions. There must be some other
type of function floating around that is not void. There is and this section will
look at these so-called return functions.
Understanding the difference between the two functions is very vital. The syntax
of defining the two functions is different. The manner in which the two functions
are called is different. The purpose of the two functions is also different. It does
not take a genius to figure out that there are ample opportunities to confuse the
syntax and the use of these functions.
Void Functions
Return Functions
Frankly, C++ did something weird with math functions. At least, I think it is
weird that there is a floor function and there is a ceil function, but there is not a
round function. We now have a candidate for a user-defined function.
Round Function
Check out program PROG1307.CPP and look closely for the difference between
the syntax of the earlier void functions and the return function that is presented
here. What is the same, and what is different?
// PROG1307.CPP
// This program uses a Round function.
#include <iostream.h>
#include <conio.h>
#include <math.h>
void main()
{
double RealNumber;
int IntNumber;
clrscr();
cout << "Enter a number ===>> ";
cin >> RealNumber;
IntNumber = Round(RealNumber);
cout << RealNumber << " Rounded off becomes "
<< IntNumber << endl;
getch();
}
PROG1307.CPP OUTPUT #1
PROG1307.CPP OUTPUT #2
We will examine the difference between the two types of functions by showing
the Skip function and the Round function side by side for ease of comparison.
Similarities:
Both functions have a function name followed by a parameter list. Information
passed to the function with parameters is done in the precise same way. Each
function also needs a function body that is enclosed between braces { } .
Differences:
The void function starts with the reserved word, void to indicate that no value will
be returned. The return function starts with the data type of the value that will be
returned by the function. The return function has a special return statement at
the conclusion of the function body that indicates which value will be returned.
Differences:
Void functions are called as stand-alone program statements. Only the function
name with the parameter list is used. The return function call is done by using the
function name as a value in a program statement.
NextInteger Function
The next return function example also has a practical value. This function returns
the next integer of the value parameter. This type of function can be used in a
word processor footer or header, which prints the page number. Each function
call, increments the page number.
// PROG1308.CPP
// This program uses a function that returns the next
integer.
#include <iostream.h>
#include <conio.h>
void main()
PROG1308.CPP OUTPUT
Convert Function
This convert function shows a pattern for a group of function that can be used to
convert values between the English measurement system and the Metric system.
This particular function changes Kilograms to Pounds.
// PROG1309.CPP
// This program uses a function that converts Kilograms
to Pounds.
#include <iostream.h>
#include <conio.h>
void main()
{
double Kilos, Pounds;
clrscr();
cout << "Enter weight in Kilograms ===>> ";
cin >> Kilos;
PROG1309.CPP OUTPUT
Return functions can return a wide variety of data types, including our newly
acquired friend bool. Such a function becomes ideal for checking proper program
user input. The next program checks if the correct password is entered. Notice
that the data type being returned by the function does not need to be the same as
the data type of any parameter passed to the function.
// PROG1310.CPP
// This program uses a Boolean function to determines
if the
// entered password is correct.
#include <iostream.h>
#include <conio.h>
#include "BOOL.H"
#include "APSTRING.H"
void main()
{
PROG1310.CPP
#include <iostream.h>
#include <conio.h>
#include "BOOL.H"
void main()
{
char Letter;
clrscr();
cout << "Enter a lower-case letter ===>> ";
cin >> Letter;
cout << endl;
if (OkChar(Letter))
cout << "Lower-case letter entered is " << Letter
<< endl;
else
cout << "You did not enter a lower-case letter"
<< endl;
getch();
}
PROG1311.CPP OUTPUT
UpCase Function
#include <iostream.h>
#include <conio.h>
#include "BOOL.H"
void main()
{
char Letter;
clrscr();
cout << "Enter a lower case letter ===>> ";
cin >> Letter;
cout << endl;
if (OkChar(Letter))
cout << "Upper-case letter is " << UpCase(Letter)
<< endl;
else
cout << "You did not enter a lower case letter"
<< endl;
getch();
}
Upper-case letter is A
You may be confused how the statement . . . return (Ltr - 32); . . . managed to
convert a lower-case letter to an upper-case letter. Remember that all characters
are stored as integers. The stored integer is the ASCII value of the character.
Now the upper-case letters have the sequence 65, 66, 67, 68, etc. for the letters A,
B, C, D, etc. The lower-case letters have the ASCII sequence 97, 98, 99, 100, etc.
for the letters a, b, c, d, etc.
Notice that the ASCII value of 65 for A is 32 less than the value 97 for a. This
same difference applies for all the letter characters. The result is that subtracting
32 from any lower-case letter will return the corresponding upper-case letter.
GCF Function
Many years ago, Euclid cleverly invented an algorithm for computing the Greatest
Common Factor of two integers. The algorithm uses the following steps:
5. Goto step 1
Divide Nbr1 by Nbr2 108 / 12
// PROG1313.CPP
// This program demonstrates a GCF function.
// This program also creates a function warning because
// the return statement is not the last function
statement.
#include <iostream.h>
#include <conio.h>
void main()
{
int Number1,Number2;
int GCF;
clrscr();
cout << "Enter integer 1 ===>> ";
cin >> Number1;
cout << "Enter integer 2 ===>> ";
cin >> Number2;
GCF = ComputeGCF(Number1,Number2);
cout << endl;
cout << "GCF of " << Number1 << " and " << Number2
<< " is " << GCF << endl;
getch();
}
PROG1313.CPP OUTPUT
This program works fine but you may be disturbed by the compiler warning. You
really prefer to get a success message, and any type of message that indicates
something is wrong is not a good message. The message is a warning, and the
warning indicates something is wrong with the return statement. The return
statement is just fine, but the compiler gets excited because the return statement is
not the last statement in the function.
The solution to this problem (if warnings bother you) is to create a local variable
in function ComputeGCF. The local variable, GCF, is used inside the loop for
the value of the GCF. After the loop is finished, it is this value that is returned by
the function. You may also argue that not only did the warning message
disappear, but also a second improvement was made in readability. The statement
GCF = Nr2; does improve the clarity of the function. Furthermore, the
statement return GCF also helps to explain what the purpose of the function is.
// PROG1314.CPP
// This program demonstrates a GCF function.
// This program cures the warning problem with a local
variable.
#include <iostream.h>
#include <conio.h>
void main()
{
int Number1,Number2;
int GCF;
clrscr();
cout << "Enter integer 1 ===>> ";
cin >> Number1;
cout << "Enter integer 2 ===>> ";
cin >> Number2;
GCF = ComputeGCF(Number1,Number2);
cout << endl;
cout << "GCF of " << Number1 << " and " << Number2
<< " is " << GCF << endl;
getch();
}
PROG1314.CPP OUTPUT
Scope Definition
Are you now totally clear on the meaning of scope? Probably not. The definition
is short and straight-forward because the concept of scope is straight-forward.
However, that does not translate into clarity in your brain.
Each one of the mentioned agencies is a law enforcement agency. The difference
between the agencies is jurisdiction. Jurisdiction is the part of the country where
an agency has the legal right to enforce the law. A Dallas policeman does not
take a vacation in New York city and suddenly start arresting drug dealers. The
Dallas officer does not have jurisdiction in New York city.
This is fine with law enforcement but you are dealing in the world of C++. I
believe that the concept of scope can be explained by looking at two very strange
programs. These programs have a variable defined and initialized all over the
place. There is plenty more to say about this issue. Right now check out the first
program and look closely at the output execution.
#include <iostream.h>
#include <conio.h>
int X1 = 100;
void Function1();
void Function2();
void main()
{
clrscr();
cout << "Global X1 = " << X1 << endl;
int X2 = 200;
cout << endl;
cout << "Main Function X2 = " << X2 << endl;
Function1();
cout << endl;
cout << "Main Function X2 = " << X2 << endl;
Function2();
getch();
}
void Function1()
{
int X3 = 300;
cout << endl;
cout << "Function1 X3 = " << X3 << endl;
if (X3 == 300)
{
int X4 = 400;
cout << endl;
cout << "Very Local X4 = " << X4 << endl;
}
cout << endl;
cout << "Function1 X3 = " << X3 << endl;
PROG1315.CPP OUTPUT
Global X1 = 100
Function1 X3 = 300
Function1 X3 = 300
Global X1 = 100
You did see four variables, X1, X2, X3 and X4. Each one of the variables was
defined for a different scope of the program. X1 has global scope and can be used
anywhere in the program. X2 has a scope that is limited to the main function. X3
has a scope that is limited to Function1, and X4 is a peculiar - very local - variable
that is limited to the body of the if statement.
So what does that show about scope? Everything . . . if you understand scope and
probably nothing if you have not heard of scope before. Hang on, clarity is
around the corner because we had to set the stage properly for the next program.
Program PROG1316.CPP is very similar to the previous program. And the
output is completely identical. The interesting feature is that this identical output
is accomplished with the same variable identifier everywhere. Yet the output
proves that the same identifier represents the same four different variables of the
earlier program. How is this possible? Scope is the answer.
The program is designed to demonstrate scope and you may need to go back and
forth between the explanation and the program. Check everything carefully. This
program shows not only scope, but also the concept that a local variable takes
// PROG1316.CPP
// This program demonstrates scope with the same
identifier.
#include <iostream.h>
#include <conio.h>
void Function1();
void Function2();
void main()
{
clrscr();
cout << "Global X = " << X << endl;
void Function1()
{
int X = 300; // function1 scope X
cout << endl;
cout << "Function1 X = " << X << endl;
if (X == 300)
{
int X = 400; // very local scope X
cout << endl;
void Function2()
{
cout << endl;
cout << "Global X = " << X << endl;
}
PROG1316.CPP
Global X = 100
Function1 X = 300
Function1 X = 300
Global X = 100
The program starts with the definition of the global X. In the main function the
value of 100 is displayed.
X is defined locally inside the main function with value 200. This local definition
supersedes the global X. Keep in mind that it does not alter the global X. It just
means that inside the main function X = 200 takes over.
You now have seen X defined 4 times and initialized four times with a different
value. Now comes the interesting part. In backward order we return to the
previous X values, and what do you know? All the values are present as they
were. The redefining Xs have not altered anything. Every X has politely stayed
out off the scope of another X. Frequently multiple X identifiers are in the same
scope, but this is OK. For instance, the very first X = 100 is global and has global
scope. However, in the main function X = 200 is local and precedes the first X
value.
All this scope business makes for good table conversation. You may assume that
you do not need to be concerned with this nonsense, because there is no way that
you will write a program that has identical identifiers floating all over the place.
With different variable names, everything falls in place and confusion is avoided.
True, you do avoid confusion, and true again you definitely should not write
programs with identical identifiers everywhere. But, false, you do need to
understand scope. Consider the next short program example. Program
PROG1317.CPP is a short innocent program designed to enter five numbers
from the keyboard. After the loop is finished, the final number is displayed.
// PROG1317.CPP
// This program demonstrates problems with scope.
// The program does not compile because of the scope
// limitation of the variable.
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int X;
for (X = 1; X <= 5; X++)
{
int Y;
cout << "Enter a number ===>> ";
cin >> Y;
}
PROG1317.CPP OUTPUT
The real solution to the scope problem of the previous program is knowing where
to define variables. Program PROG1318.CPP is almost identical to the previous
program. One small - but significant - change is made. The Y variable is defined
early in the main function, and not inside the loop body.
// PROG1318.CPP
// This program demonstrates how to solve the scope
problem
// of the previous program by defining the Y variable
early
// in the program.
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int X,Y;
for (X = 1; X <= 5; X++)
{
cout << "Enter a number ===>> ";
PROG1318.CPP OUTPUT
You have used functions for quite some time. True, functions with parameters
may be new, but the concept of breaking down a program into separate modules is
something you learned many chapters ago. At this stage in C++ you know how to
If functions are the building blocks of a program then these blocks must all work
correctly. The correctness of a program relies on the correctness of the individual
functions used by a program. One small function, incorrectly written, used by a
very large program can easily crash the program. Program reliability is at the
very top of the program requirement list.
// PROG1319.CPP
// This program uses a function without preconditions.
// The program will result in a runtime error for
// negative numbers.
#include <iostream.h>
#include <conio.h>
#include <math.h>
void DisplaySquareRoot(double N)
void main()
{
clrscr();
double Number;
cout << "Enter a number ===>> ";
cin >> Number;
DisplaySquareRoot(Number);
getch();
}
PROG1319.CPP OUTPUT #1
PROG1319.CPP OUTPUT #2
The first output of PROG1319.CPP does not show any difficulties. A number is
entered and the square root of the number is displayed. The second output is a
different story. This time -100 is entered and the square root function cannot
digest the negative input. Some type of runtime error will occur. Function
DisplaySquareRoots does its job, but there needs to be a better way.
In the next program example you will note that a comment has been added to
function DisplaySquareRoots. The comment is a so called precondition, and the
condition states that parameter N must be greater than 0. Now do not get
confused, stating a precondition does not guarantee that the precondition will be
true. The whole point is that the precondition explains what must be true before
the function executes. Frequently, void functions may only indicate preconditions
// PROG1320.CPP
// Function DisplaySquareRoots has a precondition and a
// conditional statement to protect against erroneous
// parameter values.
#include <iostream.h>
#include <conio.h>
#include <math.h>
void DisplaySquareRoot(double N)
// precondition: n > 0
{
cout << endl << endl;
if (N > 0)
{
double Result = sqrt(N);
cout << "The square root of " << N << " is "
<< Result << endl;
}
else
{
cout << "ERROR" << endl;
cout << "Incorrect parameter value" << endl;
}
}
void main()
{
clrscr();
double Number;
cout << "Enter a number ===>> ";
cin >> Number;
DisplaySquareRoot(Number);
getch();
}
PROG1320.CPP OUTPUT #1
PROG1320.CPP OUTPUT #2
ERROR
Incorrect parameter value
You may never have thought must about the reliability of the humble Skip
function. The usual Skip function is shown in the next program - comments -
with the precondition version. Now the nature of the for loop is such that a
negative N value will not cause any problems. The loop will simply not execute
at all, and no lines are skipped. You might also argue that it is good to know if
some negative parameter is passed to this function. Such a Skip function is
shown below complete with error message for erroneous parameter values.
// PROG1321.CPP
// This program demonstrates how to make function
// Skip more reliable.
#include <iostream.h>
#include <conio.h>
#include <math.h>
//void Skip(int N)
//{
// for (int K = 1; K <= N; K++)
// cout << endl;
//}
void Skip(int N)
// precondition: 0 < N < 50
{
if (N > 0 && N < 50)
{
for (int K = 1; K <= N; K++)
cout << endl;
}
else
{
cout << "ERROR" << endl;
cout << "Incorrect parameter value" << endl;
}
}
void main()
{
PROG1321.CPP OUTPUT #1
PROG1321.CPP OUTPUT #2
// PROG1322.CPP
// This program demonstrates a function that returns the
// upper-case of an entered lower-case letter.
// Protection against erroneous parameter value is provided.
#include <iostream.h>
void main()
{
char Letter;
clrscr();
cout << "Enter a lower case letter ===>> ";
cin >> Letter;
cout << Letter << " becomes " << UpCase(Letter) << endl;
cout << endl;
getch();
}
PROG1322.CPP OUTPUT #1
PROG1322.CPP OUTPUT #2
// PROG1323.CPP
// This program demonstrates the GCF function with
// preconditions and postconditions.
#include <iostream.h>
#include <conio.h>
void main()
{
int Number1,Number2;
int GCF;
clrscr();
cout << "Enter integer 1 ===>> ";
cin >> Number1;
cout << "Enter integer 2 ===>> ";
cin >> Number2;
GCF = ComputeGCF(Number1,Number2);
cout << endl;
cout << "GCF of " << Number1 << " and " << Number2
<< " is " << GCF << endl;
PROG1323.CPP OUTPUT #1
PROG1323.CPP OUTPUT #2
You may or may not find it very practical to return a value of zero. The virtue of
that return value is not the issue here. You do have the ability to use that value in
some way that makes the program behave appropriately without crashing. It is
very common in the computer science world to have functions return a variety of
different codes when a function does not work correctly. Different codes can be
used for different purposes.
The worked-out exercises in this chapter will deviate from the exercises that were
presented in earlier chapters. Previous chapters presented complete programs. In
this chapter, and future chapters, you will more likely see a single function
presented. In each case you will be asked to determine the output of the function,
if it is a void function. You may also be asked to figure out the value returned by
the function, if it is a return function. You can assume that all necessary libraries
have been included for the program statements in the function to compile
properly. Variable trace tables will be used, as before, but the focus is strictly on
the variables used in each function.
Exercise 01
void Ex1301(int N)
{
if (N % 2 == 0)
cout << endl << endl;
else
cout << endl;
}
Ex1301(10);
N N % 2 == 0 Output
10 true 2 <CR>
Exercise 02
void Ex1302(apstring Name, double HW, double HR)
{
double GrossPay = HW * HR;
double Deductions = GrossPay * 0.15;
double NetPay = GrossPay - Deductions;
cout << "Pay to the order of " << Name << " $"
<< NetPay << endl;
}
Ex1302("Thomas Phillips",20,6.35);
Name HW HR GrossP Deduct NetPay
ay ns
Thomas 20 6.35 127.00 19.05 107.95
Exercise 03
Ex1303(5,10);
P Q P>Q P+Q
5 10 false
15 25
Exercise 04
void Ex1304(int N)
{
int Temp = 1;
for (int K = N; K >= 1; K--)
Temp *= K;
cout << "Temp = " << Temp << endl;
}
Ex1304(5);
N Temp K
5 1 5
5 4
20 3
60 2
120 1
120
Exercise 05
void Ex1305(int P, int Q, int R)
{
int X = P;
if (Q > X)
X = Q;
if (R > X)
X = R;
cout << X << endl;
}
Exercise 06
int Ex1306(int P, int Q)
{
while (P < Q)
{
P++;
Q--;
}
return P + Q;
}
Ex1306(7,25);
P Q return P + Q
7 25
8 24
9 23
10 22
11 21
12 20
13 19
14 18
15 17
16 16 32
Ex1307(5,10);
P Q Q%P return P + Q
5 10 0
6 4
7 3
8 2
9 1
9 0
10 19
Exercise 08
int Ex1308(int N)
{
int Temp = 1;
for (int K = 1; K <= N; K+=K)
Temp += K;
return Temp;
}
Ex1308(15);
N K Temp return Temp
15 1
1 2
2 4
4 8
8 16
16 16
Exercise 09
Ex1309(6);
N K Temp return Temp
6 1
1 2
2 4
3 8
4 16
5 32
6 64 64
Exercise 10
int Ex1310(int N)
{
int Temp = 100;
for (int K = N; K > 0; K--)
Temp -= Temp;
return Temp;
}
Ex1310(10);
N K Temp return Temp
10 100
10 0
9 0
8 0
7 0
6 0
5 0