3.1 & 3.2 Introduction
A C++ function is a named module (a block of program
statements) for performing a given task.
Class is an Object-Oriented (OO) way for writing
reusable modular programs in C++.
3.3 Math Library Functions
#include <math.h>
#include <iostream.h>
int main()
{ float f;
f = sqrt(16.0);
// calling/invoking a function,
cout << f;
cout << sqrt(64);
return 0;
}
Fig 3.2: ceil, cos, exp, ...
/* Testing the math library functions */
#include <iostream.h>
#include <iomanip.h>
#include <math.h>
int main()
{
cout << setiosflags( ios::fixed
| ios::showpoint )
<<
setprecision( 1 )
<<
"sqrt(" << 900.0 << ") = " << sqrt( 900.0 )
<<
"\n sqrt(" << 9.0 << ") = " << sqrt( 9.0 )
<<
"\n exp(" << 1.0 << ") = " << setprecision( 6 )
<<
exp( 1.0 ) << "\nexp(" << setprecision( 1 ) << 2.0
<<
") = " << setprecision( 6 ) << exp( 2.0 )
<<
"\n log(" << 2.718282 << ") = " << setprecision( 1 )
<<
log( 2.718282 ) << "\n log(" << setprecision( 6 )
<<
7.389056 << ") = " << setprecision( 1 )
<<
log( 7.389056 ) << endl;
cout << "log10(" << 1.0
<< ") = " << log10( 1.0 )
<<
"\n log10(" << 10.0 << ") = " << log10( 10.0 )
<<
"\n log10(" << 100.0 << ") = " << log10( 100.0 )
<<
"\n fabs(" << 13.5 << ") = " << fabs( 13.5 )
<<
"\n fabs(" << 0.0 << ") = " << fabs( 0.0 )
<<
"\n fabs(" << -13.5 << ") = " << fabs( -13.5 ) <<
endl;
cout << "ceil(" << 9.2
<< ") = " << ceil( 9.2 )
<<
"\n ceil(" << -9.8 << ") = " << ceil( -9.8 )
<<
"\n floor(" << 9.2 << ") = " << floor( 9.2 )
<<
"\n floor(" << -9.8 << ") = " << floor( -9.8 ) <<
endl;
cout << "pow(" << 2.0 <<
", " << 7.0 << ") = "
<<
pow( 2.0, 7.0 ) << "\npow(" << 9.0 << ", "
<<
0.5 << ") = " << pow( 9.0, 0.5 )
<<
setprecision(3) << "\nfmod("
<<
13.675 << ", " << 2.333 << ") = "
<< fmod( 13.675, 2.333 ) << setprecision(
1 )
<<
"\n sin(" << 0.0 << ") = " << sin( 0.0 )
<<
"\n cos(" << 0.0 << ") = " << cos( 0.0 )
<<
"\n tan(" << 0.0 << ") = " << tan( 0.0 ) << endl;
return 0;
}
3.4 Functions
Software Reusability (Code Reuse)
f = sqrt(16.0);
Five points about using a function:
#include <iostream.h>return-value-type function-name(parameter-list)int cube( int y ); // A function prototype: tells the compiler about the interface of the function.
// It's prototye must be given before a function can be used.
// Prototypes of library functions are given in the head files (.h files)int main()
{
int x, z;
z = cube(10); // function invocation, argument, return value
cout << "The cubic of 10 is " << z;
cout << "Please enter an integer : " << endl;
cin >> x;
z = cube(x);
cout << "The cubic of " << x << "is " << z << endl;x = 20;
cout << "The cubic of " << x << "is " << cube( x ) << endl;return 0;
}// function definition
int cube( int y ) // function header
{ // start of the function body
int z;
z = y * y * y;
return z;
} // end of the function body
// Finding the maximum of three integersCoercion of arguments: promotion of argument type.
#include <iostream.h>int maximum( int, int, int ); // function prototype
int main()
{
int a, b, c, r;
cout << "Enter three integers: ";
cin >> a >> b >> c;
// a, b and c below are arguments to
// the maximum function call
r = maximum( a, b, c );
cout << "The maximum is: " << r << endl;return 0;
}// Function maximum definition
// x, y and z below are parameters to
// the maximum function definition
int maximum( int x, int y, int z )
{
int max = x;
if ( y > max ) max = y;
if ( z > max ) max = z;
return max;
}
3.7 Header Files
Header files are text files containing function prototypes
.
myheader.h
int maximum( int, int, int );
// function prototype
main.cpp
#include <iostream.h> // < > for system header filesCreating a VC++ project with multiple source files to find maximum.
#include "myheader.h" // " " for programmer defined header files
// The preprocessor copies the contents of the header files here.
// # are preprocessor directives.
int main()
{
int a, b, c, r;
cout << "Enter three integers: ";
cin >> a >> b >> c;
// a, b and c below are arguments to
// the maximum function call
r = maximum( a, b, c );
cout << "Maximum is: " << r << endl;return 0;
}maximum.cpp
// Function maximum definition
// x, y and z below are parameters to
// the maximum function definition
int maximum( int x, int y, int z )
{
int max = x;
if ( y > max ) max = y;
if ( z > max ) max = z;
return max;
}
3.8 Random Number Generation
int rand( );
// random number generator
void srand(int seed);
// further randomize the output of rand() between different runs.
Run the following program a few times
to compare the differences between the outputs.
#include <iostream.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i;
i = rand( );
// 0 <= i <= RAND_MAX (symbolic constant: 32767).
cout <<"rand() \t\t"
<< i << endl;
i = rand( ) % 6;
// scaling, 0 <= i <= 5.
cout << "rand()
% 6 \t\t" << i << endl;
i = 1 + rand( ) % 6;
// shift: 1 <= i <= 6.
cout << "1 + rand()
% 6 \t\t" << i << endl;
unsigned int seed;
// MIN = 0; MAX = 65535.
cout << "Please
enter a seed number :";
cin >> seed;
srand(seed);
// seed rand().
cout <<"\n\n Seeded
rand() by "<< seed <<". " << endl;
i = rand( );
// 0 <= i <= RAND_MAX (symbolic constant: 32767).
cout <<"rand() \t\t"
<< i << endl;
i = rand( ) % 6;
// scaling, 0 <= i <= 5.
cout << "rand()
% 6 \t\t" << i << endl;
i = 1 + rand( ) % 6;
// shift: 1 <= i <= 6.
cout << "1 + rand()
% 6 \t\t" << i << endl;
seed = time(0);
// calendar time in seconds.
srand(seed);
// seed rand().
cout <<"\n\n Seeded
rand() by "<< seed <<". " << endl;
i = rand( );
// 0 <= i <= RAND_MAX (symbolic constant: 32767).
cout <<"rand() \t\t"
<< i << endl;
i = rand( ) % 6;
// scaling, 0 <= i <= 5.
cout << "rand()
% 6 \t\t" << i << endl;
i = 1 + rand( ) % 6;
// shift: 1 <= i <= 6.
cout << "1 + rand()
% 6 \t\t" << i << endl;
return 0;
}
3.9 "enum"
"enum" creates a user defined type with enumeration constants representing the possible values of the type.
enum Months { JAN = 1, FEB, MAR, APR,
MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
Months x,y;
x = FEB; y = DEC;
cout << x;
// 2
cout << y;
//12
Note:
3.10 Storage Classes
An identifier (a variable or a function)
has three attributes: storage class, scope, linkage.
Storage class determines the
period during which an identifier exists in memory. (when)
Scope determines where an identifier
can be referenced in a program. (where)
Linkage determines which source
files an identifier is known. (which file)
Storage Classes: automatic & static
int main ()
{
cout << "\n 1st call to func \n";
func();
cout << "\n 2nd call to func \n";
func();
cout << "\n 3rd call to func \n";
func();
return 0;
}
void func(void)
{
auto int i = 0;
static int j = 0;
i++;
j++;
cout << " i = " << i << ";";
cout << " j = " << j << endl;
}
Scope: the portion of the program where an identifier has meaning.
Five scopes: block scope, function scope, function-prototype scope,
file scope, class scope.
Local variables: variable declared within a scope (block, function,
...).
The are valid only within the scope in which they are declared.
Global variables: variable declared outside any scope (block, function,
...).
The are valid everywhere. They are created at compile time and are never
destroyed.
Example:
Summary:// Fig. 3.12: fig03_12.cpp
// A scoping example
#include <iostream.h>void a( void ); // function prototype
void b( void ); // function prototype
void c( void ); // function prototypeint x = 1; // global variable
int main()
{
int x = 5; // variable local to main
cout << "x local to main: " << x << endl;
{ // start a new scope
cout << "x local to main still valid: " << x << endl;int x = 7; // x local to the block overides the x in main.
cout << "x local to the block: " << x << endl;
} // end of the block, x local to the block destroyed.
cout << "x llocal to main resumes " << x << endl;
a(); // a has automatic local x
b(); // b has static local x
c(); // c uses global x
a(); // a reinitializes automatic local x
b(); // static local x retains its previous value
c(); // global x also retains its value
cout << "x local to main: " << x << endl;
cout << "global x: " << ::x << endl; // scope resolution operator ::
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++;
cout << "local x in a is " << x
<< " before exiting a" << endl;
}void b( void )
{
static int x = 50; // Static initialization done only when the first time b is invoked.
cout << endl << "local static x is " << x
<< " on entering b" << endl;
x++;
cout << "local static x is " << x
<< " on exiting b" << endl;
}void c( void )
{
cout << endl << "global x is " << x
<< " on entering c" << endl;
x *= 10;
cout << "global x is " << x << " on exiting c" << endl;
}
External linkage links a global
variable defined in another source file and allocates no additional storage.
keyword: extern
Internal linkage forces a global
variable only valid within the source file it is defined.
keyword: static
Examples:
1. In source file F1, we define
the global variable x outside all functions as:
int x; // x is a
global variable that can be externally linked in other source files;
// storage allocation and initialization occurs when F1 is loaded.
2. In source file F2, we declare
the variable as:
extern int x; // x is
an external linkage, no storage is allocated within F2;
//x “refers” to a memory location allocated by another module.
3. In source file F1, we define
the global variable y outside all functions as:
static int y; //
y is a global variable that cannot be externally linked, it is an
internal linkage;
// storage allocation and initialization occurs when F1 is loaded.
4. In source file F2, we cannot
declare the external linkage to y as:
extern int y; //
Error, y is an internal linkage in F1.
3.12 Recursion
A recursive function
is a function that calls itself either directly or indirectly through another
function.
e.g. compute the
factorial of 3.
Key: Every time a recursive function is invoked, the compiler makes a new activation record for the function.3! = 3*2*1
2! = 2*1
3! = 3 * 2!n! = n * (n-1)!
1! = 1
0! = 1#include <iostream.h>
unsigned long factorial( unsigned long );
int main()
{
cout << "3! = " << factorial( 3 ) << endl;
return 0;
}// Recursive definition of function factorial
unsigned long factorial( unsigned long n )
{ unsigned long pf;if ( n <= 1 ) // base case
pf = 1;
else // recursive case
pf = n * factorial( n - 1 );
return pf;
}_____________________________________________________
First call to factorial() from main: n = 3
pf = 3 * factorial (2);
// pf = 3 * 2;
Second call to factorial() from factorial(): n = 2
pf = 2 * factorial (1);
// pf = 2 * 1
Third call to factorial() from factorial(): n = 1
pf = 1;
Summary of Recursion:
Summary of inline functions:// Using an inline function to calculate the volume of a cube.
#include <iostream.h>inline float cube(float f );
int main()
{
cout << "Enter the side length of your cube: ";
float side;cin >> side;
cout << "Volume of cube with side "
<< side << " is " << cube( side ) << endl;
cout << "Enter the side length of your cube: ";
cin >> side;
cout << "Volume of cube with side "
<< side << " is " << cube( side ) << endl;
return 0;
}
float cube(float s ) { return s * s * s; }
int main()Call-by-value: the value of the argument is passed to the called function.
{
int x = 3;
int &y = x; // y is a reference to x or an alias for x. (y is x).
cout << "x = " << x << endl << "y = " << y << endl;
y = 7;
cout << "x = " << x << endl << "y = " << y << endl;
x = 8;
cout << "x = " << x << endl << "y = " << y << endl;
return 0;
}
// Comparing call-by-value and call-by-referenceSummary of References
#include <iostream.h>int squareByValue( int x);
void squareByReference( int & y);
int main()
{
int x = 2, z = 2;cout << "x = " << x << " before squareByValue\n";
cout << "Value returned by squareByValue: " << squareByValue( x ) << endl
cout << "x = " << x << " after squareByValue\n" << endl;cout << "z = " << z << " before squareByReference" << endl;
squareByReference( z );
cout << "z = " << z << " after squareByReference" << endl;return 0;
}int squareByValue( int a )
{
return a *= a; // caller's argument not modified
}void squareByReference( int &cRef )
{
cRef *= cRef; // caller's argument modified
}
// Using default arguments3.20 Function Overloading
#include <iostream.h>// int boxVolume( int length = 1, int width = 1, int height = 1 );
int boxVolume( int length, int width = 1, int height = 1 );int main()
{
cout << "The default box volume is: " << boxVolume() // (1,1,1)
<< "\n\nThe volume of a box with length 10,\n"
<< "width 1 and height 1 is: " << boxVolume( 10 ) //(10,1,1)
<< "\n\nThe volume of a box with length 10,\n"
<< "width 5 and height 1 is: " << boxVolume( 10, 5 ) //(10,5,1)
<< "\n\nThe volume of a box with length 10,\n"
<< "width 5 and height 2 is: " << boxVolume( 10, 5, 2 )
<< endl;return 0;
}// Calculate the volume of a box
int boxVolume( int length, int width, int height )
{
return length * width * height;
}
Functions of the same name have different sets of parameters.
// Using overloaded functionsSummary of Function Overloading
#include <iostream.h>// function prototypes are omitted since functions are defined before usage.
int square( int x ) { return x * x; } //@square$qi
double square( double x ) { return x * x; } //@square$qdint main()
{
cout << "The square of integer 7 is " << square( 7 )
<< "\nThe square of double 7.5 is " << square( 7.5 )
<< endl;
return 0;
}
3.21 Function TemplatesFunctions of the same name have different sets of parameters. Compilers treat overloaded functions as different functions and identify them using name mangling (function names are encoded by their parameter types and the number of parameters). Return type is not used in name mangling. Function name is overloaded, it is used by different functions.
Parameterized type selection.
// Using a function template
#include <iostream.h>template < class T > // T is the type parameter and is replaced at each function call.
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 ); // int versiondouble double1, double2, double3;
cout << "\nInput three double values: ";
cin >> double1 >> double2 >> double3;
cout << "The maximum double value is: "
<< maximum( double1, double2, double3 ); // double versionchar char1, char2, char3;
cout << "\nInput three characters: ";
cin >> char1 >> char2 >> char3;
cout << "The maximum character value is: "
<< maximum( char1, char2, char3 ) // char version
<< endl;return 0;
}Summary of Template Functions
- Parameterized type (one function for all types).
- Template functions need to be defined before invocation.
- No prototyping for template function (variable type).
- Can have variables of non parameterized type.
e.g.:
template < class T >
T power (int n, T value) { ... }
Problem Solving Strategies
(1) Understand the problem statements fully.
(2) Design a solution for the problem using pseudo code.
(2.a) Modify a similar solution if there is one.
(2.b) Or, write a new solution.
(3) Implement the solution using C++.
(4) Hand trace the source code with imaginary input data.
(5) Fix logical errors.
(6) Compile and fix syntax errors.
(7) Test the program with different input data values.
(8) Hand-trace the source code with the input data that breaks the program and fix the problems found.
(9) Use cout to display variable values to help the hand trace.
(10) Keep a record of all the mistakes that you have made in the program.
Multiple source files and IDE projects
Global variables and external linksThree steps of "compilation".
(1) Preprocessing:(2) Compiling:
- Copying header file contents into the source file (e.g.: #include <math.h>).
- Substituting symbolic constants with numbers (e.g.: #define MAXCOUNT 4).
- Removing white spaces in source code.
- # represents preprocessor directives.
(3) Linking:
- Checking for syntax errors.
- Translating source code into object code.
- One .obj file for each .cpp file.
- linking all the object files and libraries together to form the final binary executables.
- Resolving all function calls.
- Resolving all references to external global variables.
More on the three attributes of a variable: storage class, scope, linkage.
- Local variables have no external linkages.
- Static global variables have no external linkages.
- Global variables have static storage class.
- Global variables can be initialized at only one place.
F1 int glob = 10; // glob is created in F1, definition
F2 extern int glob; // glob can be used in F2, declarationThe following declaration confuses the compiler
F2 extern int glob = 10; // glob is created in F2