COIT29222-Programming Principles Lecture Week 10

Download Report

Transcript COIT29222-Programming Principles Lecture Week 10

COIT29222-Structured Programming
Lecture Week 10
Reading: Study Guide Book 2, Module 12
Study Guide Book 3, Module 2
This week, we will cover the following
topics:
Multi-file program development
Code Reuse
Multi-file program development: Separating
a program into files
Each program we have written so far has been
encapsulated in a project and saved as a single
file with a .cpp file name extension
But we can separate parts of a program into
different files.
The most common way to do this for a small
program is to separate it into 3 parts:
– The main
– Function prototypes and any globally defined
constants
– The function definitions
Separating a program into three files
Header file
has function
prototypes
Encapsulated in a
C++ project
Function definition
file has definitions of
functions used by main
Main file
contains the main
program
Why separate a program into multiple
files?
If we can separate the main from the function
definitions then it allows us to make a collection
of functions that can be used by more than one
program.
It allows us to reuse code (functions) that have
been previously written.
It means we do not need to re-invent the wheel by
re-writing functions that others have spent a lot of
time writing
Standard Library functions
We already know that C++ comes with standard
functions that are stored in standard libraries.
For Example:
 To use cout and cin we #include <iostream>
 To use strings we #include <string>
 To use isspace() we #include <cctype>
 The #include precompiler directive causes the
compiler to look for functions which we have used in
our program but defined externally (in a separate
file), to be inserted into our program.
User-defined function library
In the same way that standard libraries
are created and used, we can create our
own function library which will contain
functions that can be reused (used by more
than one program
Once we have the function library we can
#include its name in our program whenever
we use any function contained in this
library
How is it done ?
 Download stats.cpp from the course web page
- a program that used an array to calculate
the average, frequency and mode of a set of
scores.
 Compile and run it.
 We’re going to break this program into 3
files:
1. statsHeaders.h – contains function prototypes
2. statsDefs.cpp – contains function definitions
3. statsMain.cpp – the main
Contents of statsHeaders.h file
//Prototypes for the stats functions
void findFreq(int scores[], int frequency[], int &mode);
float aveScores(int scores[]);
int findMode(int frequency[]);
const int size = 20; // globally defined constant
include "statsHeaders.h"
void findFreq(int scores[], int frequency[], int &mode)
{
for(int i=0;i<size;i++)
++frequency[scores[i]];
}
Header file must be
float aveScores(int scores[])
included in this file
{
float total = 0.0;
for(int i = 0; i<size;i++)
total = total + scores[i];
return (total/size);
Contents of
}
statsDefs.cpp
int findMode(int frequency[])
file
{ int mode = 0;
for(int i = 1; i<7;i++)
if(frequency[i]>mode)
mode = i;
return mode;
}
Contents of statsMain.cpp file
#include <iostream>
Header file included
using namespace std;
#include "statsHeaders.h"
in this file
void main(void)
{
int scores[size] = {1,5,6,3,4,2,6,5,3,5,2,4,5,6,6,6,3,1,2,6};
int frequency[7] = {0},mode = 0;
float average = 0.0;
average = aveScores(scores);
cout <<"The average score is "<<average<<endl<<endl;
findFreq(scores, frequency, mode);
for(int i=1;i<7;i++)
cout<<"The frequency of score "<<i<<" is =
"<<frequency[i]<<endl;
mode = findMode(frequency);
cout << "\nMode is "<< mode<<endl;
}
Putting it all together
1.
2.
3.
4.
5.
In Visual C++, all files must be placed in a
project for the program to work
Then the function library files ( statsDefs.cpp in
our case) are compiled in turn
The main program (also called the driver) is then
compiled
The project is then built – in this process, the
compiled object codes from the function
libraries are linked to the main
Resulting executable code is then run!
Try it out
 The three files
– statsHeaders.h
– statsDefs.cpp
– statsMain.cpp
for the project are on the course web page.
 Download them and use the above procedures to
put the program together and then run it.
Your project should look like the one
shown here
Header file is
included
in main()
Program consists of 3 files in
the form of a project
Software Reuse
Software reuse is the reuse of some previously
constructed software item in a new context.
Can be applied to all facets of the software development
process, including:
Project plans/strategies, system designs/models,
skeletons for documentation, testing plans, etc.
Code reuse
"pluggable" components/executable objects,
libraries, routine reuse within/across modules
Software Reuse
Why reuse software items?
Use for efficiency and thus profitability
Capitalise on the similarity of software systems,
rather than build systems from scratch
Advantages of software reuse
Reduction in development costs
Reduction in maintenance costs
Increased system reliability (or quality)
Assuming the item being reused has been
rigorously tested in its original context
Effective Software Reuse
Requires organisation and a budget
Requires a policy involving all levels of the
software development life cycle to:
Identify & reuse existing components
Build reusable components
Time consuming & costly
But investment repaid with each reuse of a
component & whenever it undergoes
maintenance, since all uses reap the benefits
Code Reuse
Modularisation is at the heart of code
reuse
The process of breaking a system up
into smaller, more manageable chunks
Allows a programmer to concentrate on
the details of a particular task while
thinking only abstractly about the other
"chunks" that make up the entire system
Enables software developers to better
manage the inherent complexity of the
overall system
Modularisation: Decomposition into
Sub-tasks
Sub-tasks in a system
A sub-task has 2 logically separate parts:
Interface
Describes what the sub-task does & how its
service can be used by other sub-tasks in the
system
Visible to other sub-tasks in the system
Implementation
Defines the steps involved in achieving the
functionality of the sub-task
Ideally hidden from other sub-tasks in the
system
Modular decomposition in C++
Decomposition into sub-tasks (in this
course) occurs at the level of C++ functions:
– called functional decomposition
C++ functions:
– interface:
function prototype
– implementation:
function implementation
Libraries
Reusable code is generally held in libraries:
Standard libraries
Usually part of the programming language
definition
Provide functionality common to many
programs
Third-party libraries
Portability issues must be considered prior
to acquisition
Libraries developed “in house”
A software project
A software project will generally consist of:
A set of libraries
The code stored in libraries is generally compiled
code or object code
Code written to accomplish the project’s task
Usually separated into discrete files called
compilation units
Compilation units are compiled into object code with
a program called a compiler
Compilation
 A large project will typically consist of:
 a set of compilation units, compiled into
object code
 a set of object code libraries
Linkage
A project’s object files (compilation units &
libraries) are linked into a single executable
program.
Static linkage
Object files linked prior to program
execution
Dynamic linkage
Performed after a program has been loaded
into memory for execution
Dynamic/shared libraries e.g. dll’s
Compilation & (Static) Linkage for
a Project
Advantages of Dynamic over Static
Libraries
Changes to (the implementation part of) a
dynamic library do not require regeneration of a project's executable file
One copy of a dynamically linked library
can be shared by many running programs
Dynamic libraries are more storage
efficient than static libraries
C++ Standard Libraries
The C++ standard libraries form part of the
C++ programming environment.
Incorporated into the ISO/ANSI C++
language standard
They provide common fundamental data
structures together with fundamental
algorithms to be used on them
Code reuse  use C++ standard library
functions instead of writing new functions
Categorisation of C++ Standard
Libraries
Include header files to use C++
library services
The interfaces to a group of related C++ library
services are gathered together into a header file.
To use a particular library service, its associated
header file must be included in the client program Example:
#include <iostream>
// required for use of cout
using namespace std;
void main(void)
{
cout << "Hello there!\n";
}
// use of object, cout
Include header files to use C++
library services
The header file associated with a particular
service contains the declarations &/or
definitions required to use the service.
The include directive includes those
declarations &/or definitions in the client program
at the position of the directive.
If the iostream header file is not included in the
program of the previous slide, the object cout
would be undefined  a compile-time error.
The std namespace
The names/identifiers in the C++ standard
libraries are defined in the std namespace.
An identifier in a C++ program is visible (can be
used) in a certain scope.
Different uses of the same identifier in a scope
can cause a conflict.
Namespaces  a means of avoiding such
conflicts.
Each namespace itself has a name and it defines a
scope for identifiers in that namespace
An identifier can be uniquely specified by qualifying
it with its namespace name.
The std namespace
To make all the names in the std namespace global:
using namespace std;
considered poor programming practice, especially in large
programs
Alternatively, names can be qualified with their
namespace identifier:
#include <iostream>
// required for use of cout
void main(void)
{
std::cout << "Hello there!\n";
}
The std namespace
Alternatively, explicit using statements can be
used:
#include <iostream>
// make the name, cout, from the std
// namespace, global
using std::cout;
void main(void)
{
cout << "Hello there!\n";
}
Using C++ Standard Library
Services
Before using a C++ library function be sure
you understand its interface:
What needs to be passed into the
function via its parameter list
What the function returns, via its
parameter list &/or as the function
return value
Note which header file must be included to
use the library service.
Character testing & caseconversion functions
To use these functions, include the
header file:
#include <cctype>
The character-handling functions take an int
parameter representing the character to be
tested:
Valid arguments are in the range 0..255 & EOF
Passing an argument of type char to these
functions may yield unpredictable results
toupper() function
Function prototype: int toupper(int ch);
– if ch is a lower-case letter, returns the
upper-case equivalent, else returns ch
– Example:
// loop until user enters Y,y,N or n
do
{
// display prompt and get response
cout << "Continue (Y/N)?";
cin >> Response;
// convert Response to upper case
UpperCaseResponse = toupper(Response);
…/cont’d
toupper() function
// display error message if response
// was invalid
if (UpperCaseResponse != YES &&
UpperCaseResponse != NO)
cout << "Enter Y, y, N or n"
<< endl;
} while (UpperCaseResponse != YES &&
UpperCaseResponse != NO);
isspace(), isalpha() & isdigit()
functions
int isspace(int ch);
returns non-zero (indicating true) if ch is a white
space character (space, tab, newline etc), otherwise
zero (indicating false)
int isalpha(int ch);
returns non-zero (true) if ch is a letter, otherwise
zero (false)
int isdigit(int ch);
 returns non-zero ( true)if ch is a digit,
otherwise zero (false)
Example: isspace(), isalpha() &
isdigit()
// read the first character
ch = cin.get();
// loop until a non-white space char read
while (!isspace(ch))
{
// if char is a digit, increment NumDigits
if (isdigit(ch))
NumDigits++;
else
// if char alphabetic, incr. NumAlpha
if (isalpha(ch))
NumAlpha++;
// read the next character
ch = cin.get();
}
Random Number Generation
The element of chance is common to applications
which simulate coin tossing, card playing, dice
rolling and the random occurrences in computer
games.
The element of chance introduced into computer
programs by random number generation. Egs:
A random number in the range 1..6 can simulate
the roll of a die
2 random numbers in ranges 1..13 (value) & 1..4
(suit) can simulate the random draw of a
playing card
Random Number Generation
 To introduce the element of chance into C++ programs, use
the rand() & srand() functions from <cstdlib> library
#include <cstdlib>
int rand(void);
Returns a random number as an int in the range 0 to
RAND_MAX (a named constant defined in the
<cstdlib> header file).
void srand(unsigned int seed);
Sets the starting point for generating a series of
random integers
A seed argument of 1 reinitialises the generator
Any other value for seed sets the generator to a
random starting point
Random Number Generation
For a given application, the required range of
randomly generated values will differ – E.g.:
– range: 1..6, when throwing a die
– range: 0..1, when tossing a coin
The modulus operator (%) can be used to map the
values generated from the rand() function (0 ..
RAND_MAX) onto the set of valid random values
for the current application. For Example
rand() % 6- will return values in the range 0..5
rand() % 6+1-will return values in the range 1..6
Example: random rolls of a die
#include <iostream> // for cout, endl
#include <cstdlib> // for rand(), srand()
using std::cout;
using std::endl;
const int MAX_DIE
MAX_ROLLS
= 6, // sides on a die
= 10; // times rolled
void main( void )
{
// Display MAX_ROLLS rolls of a die
for (int i = 0; i < MAX_ROLLS; i++ )
cout << (rand() % MAX_DIE + 1) << "
}
cout << endl;
";
Seeding the random number
generator
The srand() library routine is used to seed the
rand() function  a different sequence of
random numbers generated with each execution of
the program.
Commonly achieved by passing the current time in
seconds (according to the system clock) as argument to
the srand() function.
The time() function from the <ctime> library can be
used for this purpose. The expression:
static_cast<unsigned>(time(NULL))
is passed to the srand() function
Example: random rolls of a die
#include <iostream>
#include <cstdlib>
#include <ctime>
// for cout, endl
// for rand(), srand()
// for time()
using std::cout;
using std::endl;
const int MAX_DIE
= 6, // sides on a die
MAX_ROLLS = 10; // times rolled
void main( void )
{
// Seed the random number generator
srand(static_cast<unsigned>(time(NULL)));
// Display MAX_ROLLS rolls of a die
for (int i = 0;i < MAX_ROLLS; i++ )
cout << (rand() % MAX_DIE + 1) << " ";
cout << endl;
}
C++ #include directive
The C++ pre-processor replaces an #include
directive with the contents of the specified file.
#include directive takes 2 forms:
#include "path_and_file"
Path specified relative to the current
directory
#include <path_and_file>
Path specified relative to the directory to
which the compiler is configured to look for
the standard library header files
Example: areas compilation unit interface (areas.h)
// interface: calc. areas of geometric shapes
#ifndef AREAS_H // avoid multiple inclusions
#define AREAS_H // of this file
const float PI = 3.142F; // named const. for pi
// function interfaces (prototypes)
float AreaSquare(float Side); // area square
// of given Side
float AreaCircle(float Diameter); //area circle
// given Dia.
#endif
#ifndef, #define & #endif
directives
 These directives used to prevent multiple inclusion of
given header file in a compilation unit.
 The first time an attempt is made to include areas.h:
#ifndef AREAS_H is true (AREAS_H not defined) 
compilation of code up to #endif directive
#define AREAS_H, defines AREAS_H
 Subsequent attempts to include areas.h:
#ifndef AREAS_H is false  code to #endif ignored
Example: areas compilation unit –
implementation (areas.cpp)
#include "areas.h"
// include interface
float AreaSquare(float Side)
{
}
// area of square
// of given Side
return(Side * Side);
float AreaCircle(float Diameter) // area circle
// given Dia.
{
float Radius;
}
Radius = Diameter / 2.0;
return(PI * Radius * Radius);
Summary
In this lecture, we have covered the following things:
• Reasons for separating a program into multiple
files
• What is involved in the separation process
• How this separation process is done in Visual C++
• How (why) to reuse software/code
• How to use standard libraries and include
directives
• How to generate random numbers