510 likes | 697 Views
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.
E N D
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 Function definition file has definitions of functions used by main Header file has function prototypes Encapsulated in a C++ project 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: • statsHeaders.h – contains function prototypes • statsDefs.cpp – contains function definitions • 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
Header file must be included in this file include "statsHeaders.h" void findFreq(int scores[], int frequency[], int &mode) { for(int i=0;i<size;i++) ++frequency[scores[i]]; } float aveScores(int scores[]) { float total = 0.0; for(int i = 0; i<size;i++) total = total + scores[i]; return (total/size); } int findMode(int frequency[]) { int mode = 0; for(int i = 1; i<7;i++) if(frequency[i]>mode) mode = i; return mode; } Contents of statsDefs.cpp file
Contents of statsMain.cpp file Header file included in this file #include <iostream> using namespace std; #include "statsHeaders.h" 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 • 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 aparticular 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
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
Advantages of Dynamic over Static Libraries • Changes to (the implementation part of) a dynamic library do not require re-generation 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 efficientthan 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
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 & case- conversion 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 intin 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 = 6,// sides on a die MAX_ROLLS = 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> // for cout, endl #include <cstdlib> // for rand(), srand() #include <ctime> // 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// givenDia. #endif
#ifndef, #define & #endifdirectives • 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