CS (151) - INTRODUCTION TO PROGRAMMING C++
Teacher: Dr. Shrestha
Fall Semester, 2000
Class hour: 5:00 - 10:00 Monday
Materials for November 20, 2000
Chapter (3) (Contd.)
*****************************
********************
FUNCTIONS
Save days' work in your diskette !
PROMOTION HIERARCHY FOR BUILT-IN DATA TYPES One of the important feature of function prototypes is the coercion of
arguments, i.e. the forcing of arguments to the appropriate type. For
example, the math library function sqrt can be called with an
integer argument even though the function prototype in math.h
specifies a double argument, and the function will still work
correctly. The promotion rules based on the hierarchy below shows how
types can be converted to other types without losing data. Lower to
higher data type in the hierarchy is allowed but higher to lower not.
long double double float unsigned long int (unsigned long) long int (long) unsigned int (unsigned) int unsigned short int (unsigned short) short int (short) unsigned char short char
Header Files OLD STYLE HEADER FILES (extension h) <assert.h> <ctype.h> <float.h> <limits.h> <math.h> <stdio.h> <stdlib.h> <string.h> <time.h> <iostream.h> <iomanip.h> <fstream.h> NEW STYLE HEADER FILES <utility> <vector>, <list>, <deque>, <queue>,
<stack>, <map>, <set>, <bitset> <functional> <memory> <iterator> <algorithm> <exception>, <stdexcept> <string> <sstream> <locale> <limits> <typeinfo> PROGRAMMER-DEFINED HEADER FILES The programmer can create header files. These files should have an
extension .h A programmer-defined header file can be included by
using the #include preprocessor directive. Random Number Generation i = rand();
The rand function generates an integer between 0 and RAND_MAX
(some maximum number defined in the library e.g. 32767). If rand
truly produces integers at random, every number between 0 and RAND_MAX
has an equal chance or probability of being chosen each time rand
is called.The function prototype for the rand is in the library,
<stdlib.h>. SCALING EXAMPLE Provide a default case to catch errors even if you are certain that
you have no bugs. The rand function actually generates pseudo-random numbers
i.e., it repeats the same sequence of random numbers each time it is called.
It can be conditioned to produce a different sequence of random numbers for
each execution which is called randomizing, and is done with the standard
library function srand. The srand function takes an
unassigned integer argument and seeds the rand function to produce
a different sequence of random numbers for each execution of the program.
The function prototype for the srand function is in the header
file <stdlib.h>. EXAMPLE If we wish to randomize without the need for entering a seed each
time, we may use a statement like srand( time( 0 ) ); This causes the computer to read its clock to obtain the value for the
seed automatically. The time function (with the argument 0)
returns the current "calendar time" in seconds. This value is converted
to an unsigned integer and used as the seed to the random number
generator. The function prototype for time is in the header file
<time.h>. STORAGE CLASSES C++ provides 4 storage class specifiers: Storage class - determines the period during which that identifier
exists in memory Scope - determines if the identifier can be referenced in a program Linkage - determines for a mulitple-source-file program whether an
identifier is known only in the current source file or in any source file
with proper declarations. Automatic storage class The auto and register keywords are used to declare
variables of the automatic storage class. Such variables are created when
the block in which they are declared is entered, they exist while the
block is active, and they are destroyed when the block is exited. Example: register int counter = 1; Either write auto or register but not both to an
identifier. Static Storage Class The keywords extern and static are used to declare
identifiers for variables and functions of the static storage class. Such
variables exist from the point at which the program begins execution.
There are two types of identifiers with static storage class: external
identifiers (such as global variables and function names) and local
variables declared with the storage class specifier static. Global
variables and function names default to storage class specifier
extern. Global variables are created by placing variable
declarations outside any function definition. They retain their values
throughout the execution of the program. SCOPE RULES The portion of the program where an identifier has meaning is known as
its scope.
VARIOUS TYPES OF SCOPES FUNCTION SCOPE FILE SCOPE BLOCK SCOPE FUNCTION-PROTOTYPE SCOPE Example to illustrate various types of scopes RECURSION Example
THE FIBONACCI SERIES The Fibonacci series occurs in nature and, in particular, describes a
form of spiral. The ratio of successive Fibonacci numbers converges to a
constant value of 1.618.. This number, also, repeatedly occurs in nature
and has been called the GOLDEN RATIO or the GOLDEN MEAN. People find the
GOLDEN MEAN aesthetically pleasing. Architects often design windows,
rooms, and buildings whose length and width are in the ratio of the
golden mean. Postcards are often designed with a golden mean length/width
ratio. The Fibonacci series may be defined recursively as follows:
fibonacci( 0 ) = 0 Example of Fibonacci C++ Program The number of calls in these kind of recursive program rapidly gets
out of hand. So we need to be careful not to cause an exponential
explosion of call, often called as EXPONENTIAL COMPLEXITY.
RECURSION vs. ITERATION FUNCTIONS WITH EMPTY PARAMETER LISTS In C++, an empty parameter list is specified by writing either
void or nothing at all in parentheses. INLINE FUNCTIONS Example REFERENCES AND REFERENCE PARAMETERS Two ways to invoke functions: DEFAULT ARGUMENTS Function calls may commonly pass a particular value of an argument.
The programmer can specify that such an argument is a default argument,
and the programmer can provide a default value for that argument.
UNARY SCOPE RESOLUTION OPERATOR ( :: ) This allows an access to a global variable when a local variable of
the same name is in scope. Example FUNCTION OVERLOADING C++ enables several functions of the same name to be defined as long
as these functions have different sets of parameters. This capability is
called function overloading. Function overloading is commonly used to
create several functions of the same name that perform similar tasks, but
on different data types. Overloading functions that perform closely
related tasks can make programs more readable and understandable. Overloaded functions are distinguished by their signatures. A
signature is a combination of a function's name and its parameter types.
The compiler encodes each function identifier with the number and types of
its parameters. This is called name mangling or name
decoration.
FUNCTION TEMPLATES Function templates enable the creation of functions that perform the
same operations on different types of data, but the function template is
defined only once. Example An array is a consecutive group of memory locations that all have the
same name and same type. Example: Here c is an integer array containing 4 elements. Any one of these
elements may be referred to by giving the name of the array followed by
the position number of the particular element in square brackets. The
position number contained within the square bracket is called a SUBSCRIPT.
The type long double is a floating - point type much like
double but with much greater magnitude.
The type double is a floating-point type much like float,
but a variable of type double can store a value of much greater
magnitude with greater precision than float.
Used for specifying real numbers, i.e. numbers with decimal points.
The C++ language specification requires that a variable of type
unsigned long int or in short, unsigned long is stored in at least 4
bytes (32 bits), and thus, may hold a value at least in the range 0 to
4294967295.
This type of data is stored in at least 4 bytes and may hold a
value in the range of +/- 2147483647.
Unsigned int can have only positive values e.g. 50, 2034 etc.
An int is stored in at least two bytes of memory and can have
positive and negative values e.g. -1, 120 etc
The minimum range of values for this type is 32767.
The minimum range of values for short integers is +/- 32767
Used for long rows of character.
Synonomous with short int.
Used for specifying character data e.g. x, $, 7 etc.
- contains macros and information for adding diagnostics that aid program
debugging. The new version of this header file is <cassert>
- contains function prototypes for functions that test characters for
certain properties, and function prototypes for functions that can be
used to convert lowercase letters to uppercase letters and vice versa.
The new version of this header file is <cctype>
- contains the floating point size limits of the system. The new version
of this header file is <cfloat>
- contains the integral size limits of the system. The new version of
this file is <climits>
- contains function prototypes for math library functions. The new
version of this header file is <cmath>
- contains function prototypes for the standard input/output library
functions and information used by them. The new version of this header
file is <cstdio>
- contains function prototypes for conversions of numbers to text, text
to numbers, memory allocation, random numbers, and various other utility
functions. The new version of this header file is <cstdlib>
- contains function prototypes for C-style string processing functions.
The new version of this header file is <cstring>
- contains function prototypes and types for manipulating the time and
date. The new version of this header file is <ctime>
- contains function prototypes for the standard input and standard output
functions. The new version of this header file is <iostream>
- contains function protypes for the stream manipulator that enable
formatting of streams of data. The new version of this header file is
<iomanip>
- contains function prototypes for functions that perform input from
files on disk and ouput to files on disk. The new version of this file is
<fstream>
- contains classes and functions that are used by many standard library
header files
- contain classes that implement the standard library containers.
Containers are used to store data during a program's execution
- contains classes and functions used by algorithms of the standard
library
- contains classes and functions used by the standard library to allocate
memory to the standard library containers.
- contains classes for manipulating data in the standard library
containers.
- contains functions for manipulating data in the standard library
containers.
- contains classes that are for exception handling
- contains the definition of class string from the standard
library.
- contains function prototypes for functions that perform input from
strings in memory and output to strings in memory.
- contains classes and functions normally used by stream processing to
process data in the natural form for different languages.
- contains a class for defining the numerical data type limits on each
computer platform.
- contains classes for run-time type identification (determining data
types at execution time).
Element of chance- random number rand function in the standard
library
Sometimes we need to produce numbers in a range different than what
rand produces. In such a case, we scale the range as shown below:
rand() % 6
produces integers in the range 0 to 5. Here, the number 6 is called the
scaling factor. We can also shift the range of the numbers produced by
adding another number e.g. adding 1 to make the range from 1 to 6.
Let us develop a program to simulate 6000 rolls of a six-sided die and
print the value of each roll. If rand does what it is supposed to
do, each integer from 1 to 6 should appear approximately 1000 times.
//Roll a six-sided die 6000 times
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>
int main()
{
int frequency1 = 0, frequency2 = 0,
frequecny3 = 0, frequency4 = 0,
frequency5 = 0, frequency6 = 0,
face;
for ( int roll = 1; roll <=6000; roll++ ) {
face = 1 + rand() % 6;
switch ( face ) {
case 1:
++frequecny1;
break;
case 2:
++frequency2;
break;
case 3:
++frequency3;
break;
case 4:
++frequency4;
break;
case 5:
++frequency5;
break;
case 6:
++frequency6;
break;
default:
//The program should never get to the
//default because one of the face
//will certainly show up. But it is
//a good practice to put default.
cout << "should never get here!";
}
}
cout << "Face" << setw( 13 ) << "Frequency"
<< "\n 1" << setw( 13 ) << frequency1
<< "\n 2" << setw( 13 ) << frequency2
<< "\n 3" << setw( 13 ) << frequency3
<< "\n 4" << setw( 13 ) << frequency4
<< "\n 5" << setw( 13 ) << frequency5
<< "\n 6" << setw( 13 ) << frequency6
<< endl;
return 0;
}
//Randomizing die-rolling program
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>
int main()
{
unsigned seed;
cout << "Enter seed: ";
cin >> seed;
srand( seed );
for ( int i =1; i <=10; i++ ) {
cout << setw( 10 ) << 1 + rand() % 6;
if ( i % 5 == 0 )
cout << endl;
}
return 0;
}
AUTO, REGISTER, EXTERN, and STATIC
An identifier's storage class specifier helps determine its storage
class, scope, and linkage.
auto float x, y;
declares that float variables x and y are local
variables of automatic storage class, they exist only in the body of the
function in which the definition appears.
declares that the integer variable counter be placed in one of the
computer's register and be initialized to 1.
Labels (identifiers followed by a colon such as start:) are the only
identifiers with function scope. Labels can be used anywhere in the
function in which they appear, but cannot be referenced outside the
function body. Labels are used in switch structures (as case
labels).
An identifier declared outside any function has file scope. Such an
identifier is known in all functions from the point at which the
identifier is declared until the end of the file. Global variables have
file scope.
Identifiers declared inside a block have a block scope. Block scope
begins at the identifier's declaration and ends at the temininating right
brace (}) of the block. Local variables declared at the beginning
of a function have block scope as do function parameters.
The identifiers used in the parameter list of a function prototype have
function-prototype scope. Function prototypes do not require names in the
parameter list - only types are required.
// A scoping example
#inlcude <iostream.h>
void a( void ); // function prototype
void b( void ); // function prototype
void c( void ); // function prototype
int x = 1; // global variable
int main()
{
int x = 5; // local variable to main
cout <<"local x in outer scope of main is "
<< x << endl;
//5, global value 1 of x is hidden in main.
{ // start new scope
int x = 7;
cout <<"local x in inner scope of main is "
<< x << endl;
//7, reinitialized in next block, so hid old value.
} // end new scope
cout <<"local x in outer scope of main is "
<< x << endl;
//5, value 7 of x destroyed when the block is exited
// Program defines 3 functions a, b, and c - each
// takes no arguments and returns nothing. Function a
// defines automatic variable x and initializes it to
// 25. When a is called, the variable is printed,
// incremented, and printed again before exiting the
// function. Each time this function is called,
// automatic variable x is recreated and initialized
// to 25.
a(); // a has automatic local x
// Function b declares static variable x and
// initializes it to 50. Local variables declared as
// static retain their values even when they are out
// of scope. When b is called, x is printed,
// incremented, and printed again before exiting the
// function. In the next call to this function,
// static local variable x will contain the value 51.
b(); // b has static local x
// Function c does not declare any variables.
// Therefore, when it refers to variable x, the global
// x is used. When c is called, the global variable is
// printed, mulitplied by 10, and printed again before
// exiting the function. The next time function c is
// called, the global variable has its modified value,
// 10.
c(); // c uses global x
// Finally, the program prints the local variable x
// in main again to show that none of the function
// calls modified the value of x because the functions
// all referred to variables in other scopes.
a(); // a reinitializes automatic local x
b(); // static local retains its previous value
c(); // global x retains it value
cout <<"local x in main is "
<< x << endl;
return 0;
}
void a( void )
{
int x = 25; //initialized each time a is called
cout << endl
<<"local x in a is " << x
<<"after entering a" << endl;
++x;
//25
cout <<"local x in a is " << x
<<"before exiting a" << endl;
//26
}
void b( void )
{
static int x = 50; //Static initialization
//only first time b is
//called
cout << endl <<"local static x is " << x
<< "on entering b" << endl;
++x;
//50
cout << "local static x is " << x
<<"on exiting b " << endl;
//51
}
void c( void )
{
cout << endl <<"global x is " << x
<< "on entering c " << endl;
x+=10;
//1
cout <<"global; x is " << x
<<"on exiting c " << endl;
//10
}
A recursive function is a function that calls itself either directly or
indirectly through another function.
// Recursive Factorial function
#include
The Fibonacci series
0, 1, 1, 2, 3, 5, 8, 13, 21...
begins with 0 and 1 and has a property that each subsequent Fibonacci
number is the sum of the previous two Fibonacci numbers.
fibonacci( 1 ) = 1
fibonacci( n ) = fibonacci( n-1 ) + fibonacci( n-2 )
//Recursive Fibonacci Function
#include <iostream.h>
long fibonacci( long );
int main()
{
long result, number;
cout << "Enter an integer: ";
cin >> number;
result = fibonacci( number );
cout << "Fibonacci(" << number << ") = "
<< result << endl;
return 0;
}
//Recursive definition of function fibonacci
long fibonacci( long n )
{
if ( n == 0 || n == 1 ) // base case
return n;
else
return fibonacci( n-1 ) + fibonacci( n-2 );
}
Any problem that can be solved recursively can also be solved
iteratively. A recursive approach is normally chosen in preference to an
iterative approach when the recursive approach more naturally mirrors the
problem and results in a program that is easier to understand and debug.
Example:
void print();
void function1();
void function( void );
C++ provides inline functions to help reduce function-call overhead,
especially for small functions. With the use of inline function, the
compiler generates a copy of the function's code in place to avoid a
function call. Hence, using inline functions can reduce execution time,
but can increase program size.
//Using an inline function to calculate the
//volume of a cube.
#include
(1)call-by-value
- a copy of the argument's value is made and passed to the called
function. Changes to the copy do not affect the
original variable's value in the caller.
(2)call-by-reference
- the caller gives the called function the ability to directly access the
caller's data, and to modify that data if the called function so choses.
//Using the unary scope resolution operator
//To emphasize that the local and global
//versions of constant variable PI are distinct,
//the program declares one of the variables
//double and the other float.
#include <iostream.h>
#include <iomanip.h>
const double PI = 3.14159265358979;
int main()
{
const float PI = static_cast< float >( ::PI );
cout << setprecision( 20 )
<< " Local float value of PI = " << PI
// This print 3.14159.
<< "\nGlobal double value of PI = "
<< ::PI << endl;
// This prints 3.14159265358979.
return 0;
}
//Using a function template
#include <iostream.h>
template < class T >
T maximum( T value1, T value2, T value3 )
{
T max = value1;
if ( value2 > max )
max = value2;
if ( value3 > max )
max = value3;
return max;
}
int main()
{
int int1, int2, int3;
cout <<"Input three integer values: ";
cin >> int1 >> int2 >> int3;
cout << "The maximum integer value is: ";
<< maximum( int1, int2, int3 );
double double1, double2, double3;
cout << "\nInput three double values; ";
cin >> double1 >> double2 >> double3;
cout << "The maximum double value is: "
<< maximum( double1, double2, double3 );
char char1, char2, char3;
cout << "\nInput three characters: ";
cin >> char1 >> char2 >> char3;
cout << "The maximum character value is: "
<< maximum( char1, char2, char3 );
<< endl;
// The maximum for characters are evaluated by
// their place, e.g, C is maximum among A, C, and B.
return 0;
}
************************
c[0] = 3
c[1] = 10
c[2] = -5
c[3] = 21
THANKS FOR STOPPING BY !
TAKE CARE !
AFTER TODAY'S CLASS IS OVER, LOOK AT THE ASSIGNMENT.