+ All Categories
Home > Documents > C++: A Comprehensive Introduction

C++: A Comprehensive Introduction

Date post: 24-Dec-2021
Category:
Upload: others
View: 0 times
Download: 0 times
Share this document with a friend
246
C++: A Comprehensive Introduction
Transcript

C++ A Comprehensive Introduction

How to Use this User Guide

This handbook accompanies the taught sessions for the course Each section contains a brief overview of a topic for your reference and then one or more exercises

Exercises are arranged as follows

A title and usually a brief overview of the tasks to be carried out

A set of tasks together with a brief description of each

A set of steps that will achieve each task

Additionally there may be extra instructional notes for example some of the incomplete solutions contain notes in the form of code comments

PLUSPLUS As we get a broad mix of attendees on our courses we have occasionally added advanced or more technically in-depth asides labelled PLUSPLUS (all of which lie outside the scope of this introductory class) These are intended to challenge and inform just those students who already possess a more solid programming background

Exercises particularly those within the same section often assume that you have completed earlier exercises If you have any problems with the text or the exercises please ask the lecturer or one of the demonstrators (if any) for help

Note well

1 This course is mainly an introduction to the C++ that in the main attendees are most likely working with ie legacy or some might call it classic C++ With the introduction of C++11C++14C++17 modern up-to-date C++ can sometimes present itself as an almost new language (indeed this is extended further with the upcoming release of C++20) Therefore as this course is mainly aimed at those using existing C++ code we will only cover some of the changes made with the introduction of C++11 and later versions To find out more about C++11 and other versions eg C++17 please watch the relevant presentations found here channel9msdncomEventsGoingNative

2 The slides used by your lecturer do not necessary cover all the material required to complete the exercises ie there is extra information and sometimes a more detailed explanation in the notes or within the comments in code examples Also some slides may NOT be presented ndash in which case they are there for reference only

3 Additionally we do not expect attendees to complete very many of the large number of exercises provided during the course itself From their descriptions and subject matter select those that you feel able to complete Also you should feel free to work on your own project or problem if you would rather

Files and Folders

All of the files and folders you need to interact with should be located in the course folder on your machines desktop

Solutions to the exercises are located in folders named

(exercise solut ion) ProjectName

Where ProjectName will have previously been stated in the course notebook For example the folder called

(exercise solut ion) Sorts

contains the s ln file (Visual Studio solution file) which is the file you would open to see the solution to the Sorts exercise To open the solution you can either double-cl ick on the s ln file or open it via the File menu in Visual Studio NOTE if the file extension s ln is not visible just double-click on the file whose descr ipt ion reads Microsoft Visual

Studio Solut ion

The course folder also contains other C++ solutions in separate folders that again are usually referenced from the text In the main these are demonstrations andor contain code that might be useful to you after this course (but considered beyond the scope of this introduction to C++)

A quick note about Solutions and Projects in Visual Studio

In the real commercial world a full solution to a given problem may involve the creation of many constituent projects (possibly involving a variety of programming languages) A Visual Studio Solution (s ln file) mimics this approach and is really a container for separate constituent Visual Studio Projects files (vcxproj files)

All of our solutions contain single projects ndash and these may be opened in preference to opening the solution files For example in the (demonstrat ion) Ackermann

folder you will find a (demonstration) Ackermanns ln and a (demonstration) Ackermannvcxproj file you may open either file to work on the cpp code in the project

Copyright

This document is Copyright copy 2019 by Dr P Morris All rights are reserved No part of this publication may be reproduced transmitted transcribed stored in a retrieval system or translated into any language or computer language in any form or by any means without the prior written permission of the author

Version Date Author Comments

19 15 October 2019 Peet Morris

Please let us know if you find typos or errors in our course book and code

Contents

1 Introduction 1

11 What you should already know 1

12 What you will learn 1

13 Where can I get a copy of the softwaretools used 1

2 Things to understand 1

21 Compilers new and old 1

22 The C++ Standard Template Library (STL) 2

23 Visual Studio 2019 3

Creating your first program in Visual Studio 2019 6

Explanation 10

Your projects default code template 13

Arithmetic Operators 15

Characters 16

Header (include) Files 17

Strings 18

The LF (Line Feed) Problem and Reading Keys 20

Casts 22

Other Cast Types 24

3 Basic Control Flow 28

Selection - ifhellipelse statement 28

Selection - switch multiple selection statement 30

Repetition ndash while dohellipwhile and for loops 30

4 Logical and Bitwise Operators 35

41 Logical 35

42 Bitwise 37

Shifts 38

XOr 38

5 Introduction to Functions 39

Creating a function 41

52 Algorithms 49

Functions and Pass by Reference 51

Returning values from functions 53

Side effects 55

6 Classes and Objects 64

Creating your first class 65

Member functions and Passing parameters 67

Data Members 68

Constructors 70

Separating use from declaration and definition 72

Destructors 81

7 Arrays vectors lists and hash-tables 82

Declaring and using arrays 83

Searching Arrays with Linear Search 87

Sorting Arrays with Insertion Sort 90

Multidimensional Arrays 94

Declaring and using vectors 99

stdarray 105

Declaring and using lists 106

72 Hash Tables and Cached Calculations 107

Hash Tables 108

8 Pointers 112

Initialising pointers 113

Pointer Arithmetic and Arrays 115

9 APIs New Delete and Dynamic Memory 124

Using an API 124

Dynamic Memory Management 125

10 More on Functions 125

Multiple arguments overloading and default values 129

Passing Arrays to Functions 132

Passing Two-dimensional Arrays to Functions 135

11 Inheritance and (not presented) Polymorphism 135

111 Inheritance 135

Modelling a student - a first attempt 137

112 Polymorphism 143

12 Appendices 147

Arithmetical Operators 147

Assignment Operators 147

Assignment and Arithmetic examples 148

Relational and Equality Operators 148

Logical Operators 149

Precedence and Associativity Table 150

Escape Sequences 151

Cast Operator 152

Formatted Output 152

Header Files 153

Matrix Libraries 153

Scope 154

Enumerating constants 154

Constants 154

Vector member functions 155

Global functions 155

list member functions 156

cmath functions 156

String class 158

ASCII Character set 161

Handy IDE Settings 169

Exercises

Exercise 1 (Optional) Creating a first and default program 6

Exercise 2 CreatingModifying additional projects 26

Exercise 3 SearchString 29

Puzzled Programmers 29

The Collatz Conjecture 31

Mixing loops 33

PLUSPLUS Recursion 34

PLUSPLUS Base Two and Bits 37

Practising with Logical and Bitwise operators 38

Writing functions 42

Using a struct 43

PLUSPLUS When Things Go Wrong 44

The Monty Hall problem 46

More Functions 48

PLUSPLUS IsLeap in a line 49

Algorithms 49

Pass arguments by reference 52

Returning a value from a function 57

PLUSPLUS Arithmetic Bases 58

Searching for Sequences 61

PLUSPLUS Optimising Searching for Sequences 63

Evolving Searching for Sequences 64

Creating a class 65

Passing parameters 67

Using data members 69

More Objects 70

Using constructors 71

Separating declaration and definition 74

PLUSPLUS Using external libraries and third party header files 78

Creating an array to hold exam results 84

Linear Search 87

PLUSPLUS Debugging Linear Search 89

SortingSearching an array 90

PLUSPLUS Binary Search (Binary Chop) 93

Creating a multidimensional array 95

Creating a vector to hold exam results 100

Using insert() and iterators 103

Computing Fibonacci Numbers 110

Using pointers 114

Pointers and Arrays 116

PLUSPLUS Pointers and Arrays 119

PLUSPLUS Function pointers 122

main() and command-line arguments 126

EncryptDecrypt a file 128

Passing Arrays to functions 132

Base classes 137

PLUSPLUS Polymorphism 144

The PowerPoint slides entitled Exercises show the inclusive fromto exercise numbers which cover the topics discussed in the previous section It is not at all necessary to attempt to work through the entire quoted range variety is the spice of life ndash just choose those that appeal

1

1 Introduction Welcome to C++ A Comprehensive Introduction

These notes accompany the course delivered by Oxfords IT Services IT Learning Programme

If at any time you are not clear about any aspect of the course please make sure you ask your lecturer or demonstrator for some help If you are away from the class you can get help by email from your lecturer or from helpitoxacuk

Please also note that the university subscribes to Lyndacom ndash please check there for other C++ resources

11 What you should already know

The prerequisite for this course says that Either experience in another programming language or attendance on one of the PHP JavaScript or Python Kick-Start courses Is required

The more programming knowledge you have the better That said the documentation and lectures are structured such that those with very little knowledge should still be able to work through the course at their own pace

12 What you will learn

We will cover the following topics

Working with Microsofts Visual Studio Fundamental data types

Control Flow amp Iteration Header Files

Strings Functions

Arrays and Vectors Classes and Objects

Constructors and Destructors Member functions

Pointers And much more

13 Where can I get a copy of the softwaretools used

wwwvisualstudiocom (Microsofts C++ Compiler IDE and tools)

wwwpeetmcomC++introcoursezip (latest course code notes slides etc)

2 Things to understand

21 Compilers new and old

Students on this course often have to work with enhance or bug-fix existing code This sub-section is primarily for their consideration (it assumes some prior C++ knowledge)

2

Not all C++ compilers comply with the latest official ISO C++ standard (C++17) which was finally approved in December 20171

What does this mean It means that the code you write compile and run on one machine may not compile on the next machine if you are using a different compiler (even if it is using the same operating system) In this course you will be using Microsofts C++ Compiler (part of Visual Studio 2019)

Some older header files you may see with inherited C++ code are

include ltiostreamhgt have a h extension The C++ standard for this header file is include ltiostreamgt Your program may run correctly by adding a h but simply adding a h suffix will not work for all included files

include ltstringhgt has been replaced with include ltstringgt The stringh header file does not include C++ strings it includes C strings

include ltmathhgt has been replaced with include ltmathgt

The lesson to be learnt here is that a lot of C++ code you come across will have been created using older compilers Some of the header file and other code will not be recognised and may cause compilation errors when compiled on a machine which is more compliant with the C++ standard

If you are using the Gnu Compiler Collection (gcc g++ etc) you can specify standards compliancy via the ndashstd option eg -std=c++17 (other options are C++98

C++11 C++14)

Visual Studio can also be configured to use LLVM and clang Please see the relevant online documentation of how to install and use these if you wish to use them httpsllvmorgdocsGettingStartedVShtml

22 The C++ Standard Template Library (STL)

enwikipediaorgwikiStandard_Template_Library

The C++ programs you write will consist of the classes and functions that you write or modify (we provide partial solutions to every exercise)

However we will also look at what is still commonly referred to as the STL (now just part of the C++ Standard Library ) which holds a collection of existing classes functions and algorithms that you can use in the programs you will be creating

Some of the classes and template classes we will be looking at are

The string class The vector container template

The sort algorithm The list container template

The find algorithm

In addition you should also look at and be aware of another powerful library called Boost (parts of the STL come directly from the Boost library) wwwboostorg

The Boost library is easy to install (on any platform) as most Boost libraries are what is called header-only ie they consist entirely of header files containing templates and inline

1 A draft of this is included with your course files (n4660pdf) Its worth mentioning that this draft is in effect the published C++17 standard

3

functions and require no separately-compiled library binaries or special treatment when linking

23 Visual Studio 2019

What is Visual Studio (VS) VS is Microsofts freely available integrated development environment (IDE) and comes complete with optional compilerstools for a variety of languages We have only installed the IDE and the C++ compi ler (clexe etc) for this course

So what is a compiler

A compiler is a computer program that allows us to write programs in some specially defined language (unfortunately not English yet) in our case C++ (a so called high- level

language ) As you heard earlier the tex t we write in C++ is called source-code it is just simple text that one could write in Notepadexe for example

Sadly source-code is not directly understood by operat ing systems such as Windows Linux and macOS etc and it is the compilers job to convert our source-code into the terse concise and highly optimised machine-code that computers understand directly

Machine-code is often called executable or object-code and the compiled version of the source code is really just a file that contains numbers ndash a series of 8-bit bytes each holding a value between 0 and 255 The numbers either encode l ow-level instruct ions (code) or data that working together define the program Because these numbers may not encode displayable characters (see the ASCII table in the appendices to see a mapping between the numbers and the displayable characters) opening such a file an exe file in something like Windows notepad application would result in something like this being displayed (just the beginning shown)

However if we open this same executable file in a program that simply displays the files content as numbers and not what characters if any are represented by those numbers as Notepad is doing) we see this (the numbers are shown in base-16 or hexadecimal format)

4

The first two numbers 4D and 5A can be displayed as the text M and Z2 (see the first two characters at the top left in the previous notepad view of this file) 4D in base 10 is 77 and 5A is 90 ie the ASCII values for M amp Z (you can look these up in the ASCII table in the back of your course book)

Also take note of the line sequence starting 55 8B EC Then read on

2 MZ (0x4D5A) at the beginning of a file is an example of whats known as a magic number these are often used to identify a file type ndash in this case an MS-DOS executable file Trivia MZ are the initials of Mark Zbikowski the designer of the MS-DOS executable file format

5

If we have Visual Studio we can open the same file to see how such numbers translate into instructions and data

55 8B EC is the real beginning of our program In the above we see the numbers on the left and on the right what they actually mean Eg the first number 55 means push ebp which is an Intel CPU instruction Likewise 8B and EC together mean mov ebp esp The next line 81 EC C0 00 00 00 combines instructions and data and translate into sub esp 0C0h (subtract from esp the value C0 or 192 in base-10)

This is the entire program really the extra data shown in the previous views are for housekeeping

What does this program actually do then

Well youre about to find out ndash youre optionally now going to recreate it in Exercise 1

6

Creating your first program in Visual Studio 2019

Exercise 1 (Optional) Creating a first and default program

IMPORTANT

This exercise starts with a walk-through of using Visual Studio to create a new solution which you then go on to modify You should have already seen the steps needed to create a new solution in class so if youd rather just get on with the modification part simply open the (exercise solut ion)

f i rs t folder (in the Course folder) and double click the f i rs t s ln file If you choose to do this you can skip over the next few pages to the Explanation section (232) or even jump further on to Task 1 on page 14

Note You will not need to create any completely new programs during the course so even if you didnt fully follow the steps you can still safely move on to the modification part However if you really want to walk it through for yourself

Start the Visual Studio 2019 Integrated Development Environment (IDE) and create a new C++ Console application project You should have a shortcut to Visual Studio on your desktop failing that look for it on the Start menu

If they appear follow the prompts as shown below (if youre asked about keyboard mappings or Develop options select the C++ option)

7

Click Create a new project

Select Console App and click Next

8

Well locate the first project in a folder called first in your C drives Temp folder If the folder doesnt exist it will be created for you Click Create

Something like the above should appear (if you dont see the Solution Explorer panel open it via the View menu)

9

Alter the code adding the lines in bold as show here

include ltiostreamgt using namespace std int main() stdcout ltlt Hello Worldn system(pause)

Build and run the project by pressing the green arrow or by pressing F5

10

Explanation

Disclaimer at this stage you do not need to fully follow all of this just now

include ltiostreamgt

iostream is a standard C++ library file Files of this type are called header files They are text files usually containing C++ declarations definitions and code

Including iostream allows us to use some pre-defined objects to output messages to a console window This file must be included for any program that outputs data to the screen - or inputs data from the keyboard for that matter

The C++ compiler operates in passes through our code In the first pass ndash called the pre-processing pass ndash include directives are processed which are really text-substitution directives To be precise what include ltiostreamgt says is ldquoGo and find the text file called iostream and replace the directive with the contents of that filerdquo

The file name following a include directive can be enclosed in double quotes or chevrons ie include iostream or include ltiostreamgt The meaning of each is defined by the implementation (Microsofts C++ compiler in our case)

However it is common practice that if file name is in quotes it will be looked for locally first - in the same folder as the cpp file containing it and before being sought elsewhere Conversely if it is in chevrons the compiler will usually look for the file in a central include folder that was installed with the compiler ndash this folder is usually reserved for include files that come with the compiler as opposed to those that you might write yourself eg standard includes (like iostream) We therefore usually use quotes when we want to include our own custom project specific include files and chevrons when wanting to use include files that come with the compiler

You may also see that the filename sometimes has a h file extension This typically means that the header file being used is a C language header file and not a C++ one There are other variations (you are welcome to use your own) for example you might also see the occasional hxx file extension or something else entirely

using namespace std

The using namespace std code above doesnt actually appear in the automatically generated code In our project and solution files we will add it just after any include directives

namespaces in summary are very simple Everything within a namespace has a unique name and so theyre often used to help divide larger projects into more manageable chunks and to avoid name clashes

Standard C++ places a lot of its routines and functionality within a namespace call std Wed like to use this functionality and so we say we want to use all of the std namespace In the real world this isnt terribly good practice

11

However by declaring that were using namespace std throughout we can access members of this namespace without having to say exactly where they are (in which namespace) or worry about name clashes - where two objects in different files have been given the same name

The members of std that we will be using throughout are

cin (Console In) and cout (Console Out) and we must use include ltiostreamgt in order to use them

endl - is a stream manipulator that writes a new line to output endl stands for end

of l ine and is pronounced end all

If we dont declare that we were using the std namespace (which is the case in the automatically generated code) we have to prefix any use of cin cout and endl with std eg stdcin stdcout stdendl If youve added the using namespace std directive you may now remove the std in front of the stdcout ltlt Hello Worldn line

int main()

This is the entry point to our program ndash every C++ program must have this same entry point defined main() is a function the body of a function is defined within the opening and closing braces that come after its name The int to the left of main() says that this function returns (or resolves to beevaluates to) an integer value Returning a value requires you to use a return statement However as it is normal practice to simply return the value zero if you omit the return statement a value of zero is returned for you (only where main is concerned) If you want to explicitly return the value yourself you could modify the code to read

int main() stdcout ltlt Hello Worldn system(pause) return 0

So why return a value anyway Our added line return 0 means in this case that our main doing whatever it does as part of its function eventually resolves to the value 0 The value is returned to whatever called our programs entry point in this case and as usually that is the operating system ndash which has been waiting for us to return a value at this point However the operating system will simply ignore whatever value we ultimately return Why do it then

12

Consider the case when one of your programs needs to run another program to perform a part of its entire function Your main program needs to start this other program and wait until it completes successfully before continuing See the description of the system(pause) code line below

stdcout ltlt Hello Worldn

cout is an object declared in iostream ndash think of its name meaning console out Anything sent to cout using the double chevron operator ltlt appears on the console the

The n in the text means that cout should also output a carriage-return linefeed sequence (terms taken from the days of typewriters and telex machines) basically it means start any new output on a newline underneath the current line An alternative to using n is to use endl eg stdcout ltlt Hello World ltlt endl endl does more or less the same thing as n

system(pause)

system() is a standard function that is used to run an external program (here thats a standard Windows program called pauseexe) The system() function waits for the pause program to complete before continuing Going back to the discussion on return 0 earlier this is an example of one program starting another ndash here thats our program starting the pause program The pause program returns a value as part of its completion and we can examine that if we want Programs usually return 0 for success or some other integer value that means something went wrong ndash the value returned indicates what went wrong Ie a returned value of say 42 might mean that we cant answer the ultimate question with this computer3

So what is pause pauseexe is a standard Windows program that simply outputs the message Press any key to continue and then waits for a key to be pressed before exiting We use that facility here so that our program doesnt simply shutdown and disappear as it falls off the end of main()s closing or encounters a return statement If we did allow it to exit we would hardly have time to examine our programs output before it disappeared off the screen Try that and see (comment out the line using a double-slash like this system(pause))

If you run any of the course code on Linux or a Mac youll need to change this line to something like cinget()

3 An unashamed reference to the Hitch Hikers Guide to the Galaxy and the Deep Thought computer

13

Your projects default code template

In the course exercises when it comes to you writing code we will always ask you to open and then modify a partially complete projectsolution so you wont have to fiddle with projects and boilerplate code like this again

Nevertheless should you wish to start from scratch or simply experiment with Visual Studio we recommend using the code below as a starting point

include ltiostreamgt using namespace std int main() Start coding after here system(pause) return 0

14

Task 1

Immediately above system(pause) Replace the stdcout ltlt Hello Worldn line with the code shown here

int anum = 0

cout ltlt Enter a number

cin gtgt anum

cout ltlt The number you entered is

ltlt anum

ltlt endl

Test your modified program Tip remember you may hit the F5 key to build and then run your program

Try entering some text instead of a number Did it work

Alter the spacing (use of spaces and tab characters) in your code ndash does the C++ compiler care about this so called whi tespace

The statement int anum = 0 defines a variable (a memory location) which we will refer to in our code as anum to store a number of type int to hold an in teger (ie 1 -4 27) The memory location is being initialised with a value of 0 here It is good practice to initialise variables when you define them In C++11 a new type of uniform initialisation syntax was introduced and also encouraged eg int anum 0

cout ltlt Enter a number cout is a name that belongs to the namespace std The ltlt is called the stream insert ion operator When the program executes the value to the right of the operator (Enter a number) is inserted in the output stream and ultimately output to console window

cin gtgt anum cin is the input stream object of the namespace std gtgt is called the stream extract ion operator and is used here to read a number from the keyboard

cout ltlt The number you entered is ltlt anum ltlt endl This statement concatenates the output by using multiple stream insertion operators ltlt endl is the stream manipulator that adds a new line

The next Exercise starts on page 26 The pages between here and page 26 contain

code that you may like to try out by further modifying this project if not just read through the textcode until you get to page 26

15

Arithmetic Operators

Most computer programs perform arithmetic calculations Table 1 summarises the standard C++ arithmetic operators When working with integer division where both the numerator and denominator are integer the expression 15 6 evaluates to 2 To get the remainder after integer division you would use the modulus operator Note the modulus operator can only be used with integer operands

To establish the complete result of the following integer division 156 requires two operations

15 6 = 2

15 6 = 3

The result being 2 remainder 3

C++ Operation C++

arithmetic operator

Algebraic expression C++ expression

Addition + y + 6 y + 6

Subtraction - a - b a - b

Multiplication c times d or cd c d

Division xy or y

x or yx x y

Modulus p mod q p q

Table 1 - C++ arithmetic operators

Other fundamental data types Table 2 shows how you would declare and initialise four other data types for use in programs (there are more data types available)

16

Data type Example

Float float aFloat = 1234

Double (the precision of a Float) double aDouble = 123456

Char char aChar = A

Bool bool aBoolean = true

Table 2 - C++ numerical types4

Characters

Characters are normally stored in variables of type char but can also be stored as in t(eger) data types Characters are represented as single byte integers in the computer so it is possible to output a character as an integer or as a character

All characters have a numerical representation in the computer and the ASCII (American Standard Code for Information Interchange) character set shows each character and its decimal equivalent (also note that a combination of characters may be used to form more complex Unicode characters) See appendix 111

Characters can be read in with the following statements

char aChar declares a variable (aChar) of type char

cin gtgt aChar this statement is used to read a character into the variable aChar

Note After entering a character the ltENTERgtkey must be pressed before the character is read by the program

The following four statements correctly declare a variable of type char output a user prompt then read a character and store it in the variable aChar

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar

4 See httpencppreferencecomwcpplanguagetypes for a complete list (or the official ISO standard of course)

17

Header (include) Files

So far weve seen that to use certain functionality we had to include ltiostreamgt We have to do similar to use other functionality which is not part of the code C++ language ie we will need to include anything that comes as part of the standard library

In its current form Visual Studio comes with the following include files (most of which are standard files)

h files (95 C language files)

agentsh agileh ammintrinh amph amprth amprt_exceptionsh amp_graphicsh amp_mathh amp_short_vectorsh armintrh arm_neonh cfguardh collectionh comdefh comdefsph comiph comutilh concrth concrtrmh ConcurrencySalh concurrent_priority_queueh concurrent_queueh concurrent_unordered_maph concurrent_unordered_seth concurrent_vectorh crtdefsh crtversionh delayimph dloadsuph dvech ehh emmintrinh excpth fvech gcrooth immintrinh internal_concurrent_hashh internal_split_ordered_listh intrinh intrin0h invkprxyh iso646h ivech limitsh mm3dnowh mmintrinh nmmintrinh omph pgobootrunh pmmintrinh pplh pplawaith pplcancellation_tokenh pplinterfaceh ppltasksh ppltaskschedulerh pplwinh rtcapih salh setjmph setjmpexh smmintrinh srvh stdargh stdboolh stdexcpth stdinth tmmintrinh typeinfoh use_ansih vadefsh varargsh vcclrh vccorlibh vcruntimeh vcruntime_exceptionh vcruntime_newh vcruntime_new_debugh vcruntime_startuph vcruntime_stringh vcruntime_typeinfoh wmmintrinh xatomich xatomic0h xkeycheckh xlocinfoh xmmintrinh xsmf_controlh xstring_inserth xtgmathh xxamph xxamp_inlh ymathh yvalsh zmmintrinh

115 C++ files

algorithm allocators any array atomic bitset cassert ccomplex cctype cerrno cfenv cfloat chrono cinttypes ciso646 cliext climits clocale cmath CodeAnalysis codecvt complex condition_variable csetjmp csignal cstdalign cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cuchar cvt cwchar cwctype deque exception experimental filesystem forward_list fstream functional future hash_map hash_set initializer_list iomanip ios iosfwd iostream istream iterator limits list locale Manifest

18

map memory msclr mutex new numeric optional ostream queue random ratio regex scoped_allocator set shared_mutex sstream stack stdexcept streambuf string string_view strstream system_error thr thread tuple typeindex typeinfo type_traits unordered_map unordered_set utility valarray variant vector xcomplex xfacet xfunctional xhash xiosbase xlocale xlocbuf xlocinfo xlocmes xlocmon xlocnum xloctime xmemory xmemory0 xstddef xstring xtr1common xtree xutility xxatomic

Strings

Next to numbers strings are the most commonly used data type in programming

A string is both a datatype (string) and also literal character data ie a sequence of characters such as Oxford or StAndrews In C++ string literals are enclosed in quotes The quotes are not part of the string they identify the data type as a string

Actually this isnt quite true the double quoted strings are a sequence of characters and are taken from the C programming language The things declared of the string type are C++ string objects ndash which may be initialised using the C language literal

C++ strings can be declared and initialised in this way

string institution = Oxford

string name = Peet

To use the string type in your programs add the header file include ltstringgt at the top of your program This allows the use of part of the C++ library of classes called the string class (and its member functionsmethods explanations will follow soon)

Of course strings are normally used when requesting an input Consider this code

string aName aDept Two string objects

cout ltlt Enter your full name

cin gtgt aName

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

19

If in answer to the first prompt we were to enter say Fred Brooks 5 the interaction and output of our program would immediately result in this

Enter your full name Fred Brooks

Enter your department Fred is associated with Brooks

Why When reading in a string with a space such as FredltspgtBrooks only the first part Fred is read into aName ndash and the input is said to be space delimited by cin ndash and consists of two separate inputs (so the Brooks parts is read into the aDept string variable)

We could use multiple prompts to read in a name of course but this is inconvenient

To handle this situation we can use the standard getline(cin aName) function to read in a name instead of using cin gtgt aName This reads all key-strokes into aName until the ltENTERgt key is pressed at which point it returns a string containing all of the characters from the input

cout ltlt Enter your full name

getline(cin aName)

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

The string class has many useful functions you can use to manipulate strings An example is the length() member functionmethod

string aName = Fred Brooks

cout ltlt The length of the string aName is ltlt aNamelength() ltlt endl

This statement will output - The length of the str ing aName is 11

See section 12119 for more information on the string class and its member functions

5 Fred Brooks is a real person and a legendary computer scientist httpenwikipediaorgwikiFred_Brooks

20

The LF (Line Feed) Problem and Reading Keys

Continuing on consider the following code

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

string aName

cout ltlt Enter your full name

getline(cin aName)

cout ltlt You entered ltlt aName ltlt endl

system(pause)

The intent here is to first ask for a character and then to use getline() to ask for a name

If only things were that simple

If we were to enter say a Z to satisfy the first prompt the program would immediately output

Enter a character Z

You entered Z

Enter your full name You entered

Press any key to continue

The problem here is that being a keyboard key theltENTERgt key is itself being seen as a valid input so when we enter Z followed by the ltENTERgt key were actually entering two keys ndash Z and the ltENTERgt key The first keys placed into aChar whilst the enter key is left in the keyboards buffer This is quite reasonable if you think about it you entered two keys (Z and ltENTERgt) but provided a home for just one of them in aChar

Ok so whats the problem Well the problem is that we really need to use something like getline() to read text that contains spaces and it just so happens that getline() given this scenario will see the residual ltENTERgt key left in the buffer and it will assume that you didnt enter anything you just hit the enter key

This problem - that of having a mischievous ltENTERgt key waiting to surprise us ndash will occur whenever you read a key from the keyboard using cin Luckily theres an easy fix as we can use another input function to read and then discard the waiting ltENTERgt key Its called cinget() Here is a modified version of the code above that fixes the problem

21

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

cinget() REMOVE THE ENTER KEY discarding the got character

string aName

cout ltlt Enter your full name

getline(cin aName)

Used like this cinget() reads and discards a character from the input stream You can do the same using cinignore() cinget extracts a single character from the stream and returns it cinignore() extracts any number of characters and discards them (the details are specified via passed parameters to the function) or a single character if no arguments to the function are provided

You can easily use cinignore() to ignore a number of characters or until a certain token (character) is met eg the following code reads in a users first and last names and then outputs their initials

22

char first last Two 8-bit characters

cout ltlt Please enter your first name followed by your surname

first = cinget() Get one character

The first parameter is the maximum number of characters to

extract (and ignore) The second parameter is a

delimiting character The function stops extracting characters

as soon as an extracted character matches this one

cinignore(2566 ) Ignore until a space is seen

last = cinget() Get one character

cout ltlt Your initials are ltlt first ltlt last ltlt endl

Casts

On occasions in your programs you may want to store a value in a variable of a different type (when there is a danger of a loss of information the compiler will issue a warning for example when storing a double in an int) If you store a double as an integer you lose information in two ways

any mantissa (fractional part) will be lost

the magnitude of the double being stored may be too large to fit into the integer

Eg it is not possible7 to store 6678 x 10000 as a 16-bit unsigned integer because 667800 is 10000010011011100 in binary (17-bits) and is therefore larger than the maximum storable value of 65535 (1111111111111111) However you can store 1230 as an integer8

When you need to represent a value as a different type you can use the static_cast notation as shown here to change a double to an integer

6 If this is exactly numeric_limitsltstreamsizegtmax() there is no limit As many characters are extracted as needed until delim (or the end-of-file) is found

7 Actually the result of attempting to store 66780 in a 16-bit unsigned integer will be 10011011100 or 1244 Do you see how this value comes about

8 Also see the (demonst rat ion) L imi ts project

23

int anInt

anInt = static_castltintgt(doResult) where dResult is a double

You may also use the following historic classic C-style9 notation to cast to different data types

anInt = (int)dResult

Eg to change an integer to a character

char aChar

aChar = static_castltchargt(bInt) where bInt is an integer

You may also combine this using the

object-constructionfunction-call syntax of C++ eg

double d = 314157

int n = (int)d Convert ds value to an integer

int j = int(d) Ditto

9 C-style casts are usually considered to be too powerful ndash in that they indiscriminately allow unsafe and downright dangerous conversions C++ casts were introduced to solve this problem

24

Other Cast Types

Although outside the scope of this introductory course for reference here is a summary of the cast types in C++ (feel free to skip this for now and come back to it at a later time)

static_castlttypegt(object)

The type parameter must be a data type for which there is a known method for converting object to whether this be a built-in or through a casting function (constructor) All types of conversions that are well-defined and allowed by the compiler are done using static_cast

The static_cast operator may be used for operations such as converting a pointer of a base class to a pointer of a derived class converting numeric data types such as enums to ints or ints to floats However static_cast conversions are not necessarily safe as no run-time type check is done which can cause casting between incompatible data types for example initialised pointers However this is checked at compile time to prevent casting obvious incompatibles Also be aware that a static_cast between pointer of base to pointer of derived may produce an erroneous result (where the actual object pointed to is of type base not derived)

dynamic_castlttypegt(object)

In the C++ programming language the dynamic_cast operator is a part of the run-time type information (RTTI) system that performs a typecast Unlike the static_cast the target of the dynamic_cast must be pointer or reference to class Unlike static_cast and C-style typecast (where a type check is made during compilation) a type safety check is performed at runtime If the types are not compatible an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers)

reinterpret_castlttypegt(object)

Allows any pointer to be converted into any other pointer type Also allows any integral type to be converted into any pointer type and vice versa

The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument (unlike static_cast but like const_cast the reinterpret_cast expression does not compile to any CPU instructions It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type)

You cannot cast away a const or volatile qualification You can explicitly perform the following conversions

const_castlttypegt(object) A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is

25

identical except for the const and volatile qualifiers For pointers and references the result will refer to the original object For pointers to data members the result will refer to the same member as the original (uncast) pointer to data member Depending on the type of the referenced object a write operation through the resulting pointer reference or pointer to data member may produce undefined behaviour

26

Exercise 2 CreatingModifying additional projects

Examine how comments look in a program

Examine the use of some fundamental data types

Using different data types

Using the cast operator

Using the string class

Task 1

Open the skeleton project called EvenI

The project folder is

EvenIEvenI s ln

Modify the projects code in to prompt for two numbers of type double and two numbers of type integer

The program should output the sum the product and the difference of the double numbers Also output the quotient and the fractional part of the two integers10

Youll need something along the lines of hellip

double aDouble double bDouble

etc

To read a number into aDouble you could use

cin gtgt aDouble

Task 2

Modify your EvenI program to read in two characters Enter the characters a and Z

Output the two characters with the character case changed ie a becomes A and Z becomes z

You will need to look online or at in 12120 to establish the ASCII integer values of each character hellip you can alter a characters case by treating it as an integer and

To convert integers (or the results of evaluating integer expressions) to say characters we need to use a cast Eg

int i = 65

cout ltlt static_castltchargt(i + 32)

10 Trivia quotient comes from the Latin quotiens for how many times For example when dividing twenty by three the quotient is six and two thirds You can use a modulus b to get the fractional part

27

then by addingsubtracting tofrom it

Task 3

Open the skeleton project called Address and modify it so that it can be used to collect some user data

Output this collected data to screen as shown in Figure 1

Note that youll have to have include ltstringgt in order to use getline()

Figure 1

Visual Studio builds projects in one of two different modes ndash Debug or Release we will always use the Debug mode (a Release build is normally only used when a product is being beta tested ie late in the cycle)

When using Visual Studio (or most other IDEs for that matter) we normally do not have to concern ourselves with the location of the executable that is built by the program ndash because we normally run it from within Visual Studio itself However and just for your information really the exe for a debug build will always be located in the Debug folder immediately below the projects root folder ie for this project Addressexe is located in the (exercise solut ion) Address Debug folder whilst a version built in Release mode would be in the (exercise solut ion) Address Release folder

Debug builds contain extra diagnostic code that is automatically inserted by the compiler

28

3 Basic Control Flow The programs you have created so far are limited in that they run through a sequence of instructions once and then stop Most computer programs will make decisions and carry out different actions determined by the user input

C++ has three kinds of control structures

Sequence statement - the computer executes the statements one after another All the programs you have written so far use sequence statements

Select ion statements - if ifelse switch

The if selection statement selects an action if a condition is true or skips the action if the condition is false

The ifelse selection statement selects an action if a condition is true or performs a different action if the condition is false

The switch multiple selection statement can be used to perform many different actions based on a character or integer value

Repeti t ion statements - while for do while

The while and for statements perform actions within their bodies zero or more times If the loop condition test is initially false no actions will occur

The dowhile statement will perform the actions in the body at least once (the test ndash as to whether to continue - is at the end)

Selection - ifhellipelse statement

The if selection structure is used to choose among alternative courses of action The structure of the statement is

if(mark gt= 50)

cout ltlt Passed

else

cout ltlt Failed

If the condition (mark gt= 50) is t rue the statement following it is executed cout ltlt Passed

If the condition is false the statement is ignored and control is passed to the else part of the selection and statement following else is then executed cout ltlt Failed

ifelse selection statements can also be nested within other ifelse selection statements

29

Exercise 3 SearchString

Task 4

Open the skeleton project called SearchStr ing

You will need to include ltstringgt at the top of the code to complete this exercise See page 158 for more on the string class functionality

Modify the program to display a string of text to the user

The user should then be prompted to select a word from the sentence and input a replacement word Your program should replace one with the other You will want to See section 12119 on string functionality

The prompting string should be shown both before and after the update

Tips

Given a string s initialised to

string s = C++ at the University of Oxford

string t

int i = sfind(U)

cout ltlt i ltlt endl 11

t = ssubstr(0 i) bit before U in t

t = t + ancient + + ssubstr(i) +

Outputs C++ at the ancient University of Oxford

cout ltlt t ltlt endl

Puzzled Programmers

Using if if else nested ifs switch and the conditional operator -

Task 1

Solving puzzles

Open the I fp project and WITHOUT compilingrunning it determine its output

You will need to consult the operator precedence table in section 1216

You shouldnt compile or run the program to start with ndash the idea here is for you to determine its output on paper11

Tip you might want to consider tidying up the codes layout before attempting to solve it

void out(int n) is a function We havent covered functions yet but it makes sense to use one here and so we have Suffice to say for now that using out(some value) will output the value to the console window

11 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

30

Functions will be explained fully soon

Compile and run the program ndash if your workings from Step 1 differ from the output you should determine where you went wrong

Selection - switch multiple selection statement

The switch multiple selection statement can be used to perform many different actions based only on a single integer value Note however the switch statement can only be applied in narrow circumstances The tests must be constants and be integers Lets compare the two statements

int num switch(num) case 1 cout ltlt num = one

double num switch(num) case 11 cout ltlt num = 11

OK ndash Test is 1 a constant and an integer NOT OK ndash Test is not constant integer

Repetition ndash while dohellipwhile and for loops

The while statement is commonly used to carry out repeated steps perhaps reading in values before doing a calculation on values read in The format of the code is

while(condition)

statement

This can be read as whi le the condition is t rue continue to do the statements until the condition is false

31

The Collatz Conjecture

Win a million dollars

Task 1

Open and complete the project called Col latz (use a while() loop)

Given any positive integer if the number is even divide it by two else treble it and then add one If the result is one stop else repeat the process

The Collatz conjecture says that given any starting value the process above will eventually hal t (goes to one and stops)

Eg setting n to 9 as a starting point successive values would be

28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is not known whether the Collatz conjecture is true Fame and fortune await anyone who can prove it httpenwikipediaorgwikiCollatz_conjecture

A Collatz tree as visualised by Edmund Harriss

32

This image is a sample from the colouring book Visions of the Universe by Alex Bellos and Edmund Harriss

Get your own hi-res version for colouring-in here and see here for an explanation

33

Task 2

Re-implement your code so as to use a for() loop (this will be a lot easier than you might first think)

Not essential for this task but as we mention for loops you might like to look at the for project to see how a for loop can be animated to show how the three sections of it work in order

Mixing loops

Task 1

Open and modify the skeleton project called Factor ial

Modify it to use different repetition statements to calculate and display the factorial of a value entered by the user (they should enter a value between 1 and 10 inclusive)

Example use a while loop to prompt for an input value (between 1 and 10) and a for loop to calculate the factorial result

The output should be like that shown in Figure 2 below

Factorials12

The factorial of 5 (usually written as 5) is

1 x 2 x 3 x 4 x 5 = 120

If factorials are new to you think of them as defining the number of ways to arrange n items

To avoid displaying results in scient i f ic notat ion use

cout ltlt setprecision(0) ltlt fixed

setprecision() requires include ltiomanipgt

12 0 Is defined to be 1

34

Figure 2

PLUSPLUS Recursion

Come back to this after weve covered functions

Note that our solution optionally also uses a function and recursion to find the same factorial If you open it you will see that just after where we perform the output above we have commented out an extra line of code (uncomment and rebuild to see it in action)

We havent covered recursion in this C++ course yet but its basically the process of solving a problem in terms of smaller versions of the same problem Since the problem gets smaller each time the process eventually terminates in a problem (the base case) that can be solved directly When defining a recursive function be sure of three things 1 The problem gets smaller each time 2 Include a solution for the base case And 3 Each case is handled correctly

The recursive function looks like this ndash add then test it in your own solution

Factorial function using recursion

long long int recur_factorial(long long int n)

return n lt 1 1 n recur_factorial(n - 1)

The question mark is the conditional operator and is used with the colon to form the functional equivalent of an if then else

35

If the expression before the is true then the expressionstatement to the left of the is evaluated otherwise the one after the is evaluated Eg these are equivalent

x boo() hoo()

if(x)

boo()

else

hoo()

4 Logical and Bitwise Operators

41 Logical

Quite often we will want to perform some action if two things are true and we can achieve this using nested if statements eg

if(onething == true)

if(secondthing == true)

do something

In C++ we can achieve the same result through the use of the l ogical And operator - ampamp

if(onething == true ampamp secondthing == true)

do something

ampamp is a binary operator ndash meaning that it takes two arguments (nothing to do with base 2) eg Op1 ampamp Op2 The expressions Op1 and Op2 must be capable of evaluating to t rue or false (false in C++ has the value 0 whilst any other value is considered true) and both Op1 and Op2 have to be true in order to have the conditional part execute eg if(x ampamp y) Z = 10 Here both x and y must have non-zero values in order for z to be assigned the value 10 Note again that this is equivalent to

36

if(x)

if(y)

z = 10

The truth table for logical And is as follows ndash note that both Op1 AND Op2 have to be true for the result to be true

Logical And

Op1 Op2 Result

True True True

True False False

False True False

False False False

We also have a Logical Or operator (||) in C++ and its truth table looks like this ndash note that its one OR the other that has to be true in order for the result to be true here

Logical Or

Op1 Op2 Result

True True True

True False True

False True True

False False False

The remaining logical operator we have is the unary Logical Not (the exclamation mark is used for this)

Logical Not

Op1 Result

True False

False True

Logical ampamp and Logical || short-circuit ie for ampamp if the expression on the left-hand side is found to be false then the expression on the right is never evaluated as the whole will evaluate to false (because to be true both sides have to be true and we know that the first one is false at this point)

37

The same is true for logical || in that the right-hand expression is not evaluated if the left is found to be true (the whole will evaluate to true because the left is true so there is no need to evaluate the right-hand expression)

42 Bitwise

PLUSPLUS Base Two and Bits

We also have bitwise versions of the logical operators ndash plus some extra ones Bitwise operators work on a variables individual binary bits ndash rather than the value of all the bits taken as a whole For bitwise And we do not use ampamp but use just a single amp The same is true for bitwise Or we just use a single | and not || Bitwise Not is a little different we use ~ (the tilde) for bitwise Not

The additional bitwise operators we have are for bitwise XOr ndash for which we use the ^ symbol and lastly for left and right bit shifting we use ltlt and gtgt

Bitwise operators work on binary bits (1s and 0s) whereas the logical operators work on values equating to either true or false

For example consider the following code

int w = 10 int x = 42

int y = w amp x

int z = w ampamp x

cout ltlt y ltlt endl

cout ltlt z ltlt endl

The base-2 binary representation of 10 is 001010 and for 42 it is 101010 So w amp x means

001010 101010 amp ------ 001010 ------

Remember And is one and the other

Now let us consider w ampamp x Here were not interested in ws or xs bits just whether when taken together they are zero or something else Here both are non-zero so both are considered to be t rue and if we refer to our truth table from earlier on we will see that the result will be t rue When we assign that to an integer like were doing here the value assigned will be 1

38

Shifts

The shift operators shift the binary bits left or right Bits that do not fit fall off the ends and bits are replaced with zeros when shifting left ie bits do not rotate and come back on the other end again When shifting right the sign-bit may be preserved depending upon whether youre using a signed or unsigned integer

Shifts are useful for all sorts of things but one of the obvious uses is to multiply and divide eg x = 2 x = x ltlt 1 shifts the bits in x one place to the left so given that xs value is 00000010 in binary x = x ltlt 1 turns x into 00000100 which is 4 So x = x ltlt 1 is like saying x = x 2 You can of course divide by right shifting

XOr

The rule for XOr is one or the other but not both ie 1 ^ 0 = 1 (just like 1 | 0) but whereas 1 | 1 = 1 with 1 ^ 1 the answer is 0

Note that we do not have a logical XOr operator in C++ as we can just use = (not equal to) ndash see the (demonstrat ion) Logical XOr project

Practising with Logical and Bitwise operators

You will need to use the Precedence and Associativity table in 1216 to complete these tasks

Task 1

Open the Logical project As earlier DO NOT compilerun this yet

You will need to consult the operator precedence table in section 1216

On paper determine the programs output13

Run the program ndash output as expected

Task 2

Open the Bitwise ndash

unsigned project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Unsigned The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

13 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

39

PLUSPLUS Signs and bits

Task 1

This one is tough as you should really know something about Twos Complement arithmetic to complete this

Open the Bitwise ndash s igned

project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Signed The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

5 Introduction to Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine (which will also be a function) Encapsulat ion is data information or detail hiding If youre mathematically minded you may think of a C++ function as being very similar to one in mathematics ie a mechanism for mapping one thing to another

Once a function is written the detail of how it works is not important It is only necessary to understand what if any inputs the function needs (its parameters) and what output is produced (the functions return value)

The use of functions provides several benefits but the main one is that it makes programs significantly easier to understand and maintain The main program function can consist of a series of function calls rather than hundreds of lines of code A second benefit is that well written functions can be reused across multiple programs

You have to tell the compiler about a function before you use it and this is normally done using a prototype early in the program A function prototype consists of the return type a funct ion name and a parameter l is t - indicating the data the function will receive ndash and is terminated using a semicolon Eg

int someFunc(int int)

This tells the compiler that there is a function (somewhere) called someFunc that takes two integers as its input and returns an integer value for its output

40

Using a prototype is a way of telling the compiler the data types of any return value and of any parameters being passed and enables error checking to be done

The function defini t ion consists of the modified prototype and a function body which is a block of code enclosed in parenthesis which does the work Eg

int someFunc(int a int b)

return a + b

Here we have named the two inputs a and b and we can see that the functions job is to add these two value and to return them As this function returns a value (the sum of a and b) it may be used to expressions like this

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

Arguments can be passed to functions in two ways pass-by-value the default is where a copy of the argument value in the main program is made and then passed to the function The copy in the function only exists in memory as long as the function is active When the code within function has been run to completion the memory is released and the value held there is lost Any changes made to the copy passed to the function do not affect the original variable in any way For example if we altered and used someFunc like this

int someFunc(int a int b)

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 20

41

Note that because we passed a copy of b to the function that the line b = b 2 alters the copy (which then isnt used) and not the original

Arguments can also be passed-by-reference When arguments are passed in this way any changes made to the arguments in the function are reflected by corresponding changes to that data variable in the calling part of the program Pass-by-reference is good for performance reasons because it can eliminate the pass-by-value overhead of copying large amounts of data (In later sections we will examine how pointers can be used to fake pass-by-reference) Eg this will alter b now

int someFunc(int a int amp b) Note the amp

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 40

See section 521 for more on this subject

Creating a function

The format of a function prototype is

return_data_type FunctionName ( argument_l ist )

The function CtoF - void CtoF(int temp) - has no return data type (void) its name is CtoF and it accepts a single input argument called temp of type int (integer)

It is not strictly necessary to give the argument a name (temp) in a function prototype you saw this above in int someFunc(int int) However the argument type must be specified The statement void CtoF(int) is therefore an alternative prototype

The following exercise is an introduction to functions You will learn a lot more about functions in later exercises

42

Writing functions

Task 1

Open the project EvenI you created earlier and change the structure of the program to make use of functions

Solution in (exercise solut ion)

EvenI I

Read two integers in to main() and pass them to a function The prototype is void intCalcs(int int)

intCalcs() function should calculate and display the result of the division and modulus of the two variables passed see Figure 3

Read in two doubles to variables in main() Pass the two doubles and the value of one integer to the second function the prototype is int Calcs(double double int)

Within function Calcs() write statements to produce the output as shown in Figure 3 Most of the code already exists within main()

Return the result of the multiplication of one double and an integer cast this value as an integer

Display the returned value within main() as shown in Figure 3

Figure 3

43

Using a struct

Task 1

Open the project Person

Solution in (exercise solut ion)

Person

As you saw during the presentation we can keep related data together using the struct keyword For example say we define a thing as follows

struct thing

int x

string y

double z

Having done this we can now create as many thing objects as we wish ndash simply by declaring them as we would say an integer

thing a

thing b

Each thing object a and b contains its own x y and z member variables eg

ax = 10 thing as x member set to 10

bx = 20 thing bs x member set to 20

cout ltlt ax ltlt endl outputs 10

cout ltlt bx ltlt endl outputs 20

Complete the exercise by creating and populating a struct Person object Once populated amend the printPerson() function so as to output the persons details

44

PLUSPLUS When Things Go Wrong

Going back to Exercise 8 if you havent tried it already enter zero as your second number What happens

C++ contains mechanisms for catching errors in the form of a trycatch mechanism

cin gtgt y Enter zero

try

intResult = x y

catch(myException amp e)

cout ltlt ewhat() ltlt endl

catch()

cout ltlt Generic oops ltlt endl

Modify your code so as to catch the divide by zero

Hopefully try and catch are fairly self-evident try something and catch any error if something goes wrong

There are two catch blocks here One tries to catch a myException object (we cannot see the definition of this classstruct here) and the other tries to catch anything else that is missed by catch(myException amp e) The amp says that the myException object e is being passed to the catch handler by reference Well learn what this means a little later in section 521

So did you see the Generic oops message appear

Your C++ compiler doesnt have to catch the divide by zero error ndash doing such a thing results in undefined behaviour This is because an arithmetic exception is an OS or processor exception - which is not the same as a C++ exception - hence it cannot be caught by a in a try catch block

To catch errors like this we either need extra support from the compiler14 andor operating system or to write some extra code For example we could do this

14 See also C signal handling httpenwikipediaorgwikiC_signal_handling

45

cin gtgt y Enter zero

if(y gt 0)

intResult = x y

However first we have to realise that this is a possible source of a runtime error and secondly we have to write (correctly) the code to handle the condition

Windows has built-in exception handling ndash called Structured Exception Handl ing (SEH) and we can generate code that uses this in support of the try catch structure used earlier

To enable this we need to tell the compiler to generate code that links into the SEH mechanism

To do this open the Project | ltproject namegt Properties hellip dialog box and in the Code Generation section select Yes wi th SEH Exceptions ( EHa) in the Enable C++

Exceptions line See Figure 4

46

Figure 4

The Monty Hall problem

The Monty Hall problem is a probability puzzle loosely based on the American television game show Lets Make a Deal and named after the shows original host Monty Hall

It goes like this

You are on a game show where you are shown three closed doors You are told that behind one of them is a new car and that behind the other two are goats

Two pieces of essential information at this stage 1 your goal is to win the car 2 the game show host knows what is behind each door

Lets walk through a trial game

The game show hosts asks you to choose a door ndash lets say you choose door number 1 (your door remains closed) The host now opens one of the remaining doors to reveal a goat (as there are two goats they can of course always do this) lets say they open door number 3

47

The situation is now as follows you have chosen door number 1 Only door number 3 is open and it reveals a goat The host now asks you if you would like to switch your door to the only other closed door - door number 2 At this stage you must either stick with door number 1 or switch to door number 2 and at that point the host will open the door youve chosen to reveal your prize

The question is when youre offered the chance should you stick or should you swap - will swapping increase your chance of winning the car or is it just 5050 The claim made here is that by swapping doors you will double your chance of winning the car What does your completed project claim

Task 1

Open and complete the incomplete project MontyHal l

The goal of this project to provide a simulation of problem outlined above

The function

int getRandomDoor(int n = 3)

return rand() n + 1

is used to choose a door number between 1 and 3 (inclusive)

Note that it has a default argument ie if it is called without an argument like this int val = getRandomDoor() the argument n is set to 3 by default and val will be set to a value between 1 and 3 However if it is called like this int val = getRandomDoor(10) then n is set to 10 and val will receive a value in the range of 1 to 10

48

More Functions

Task 1

Open the incomplete project IsLeap

The program asks for a year and determines whether the year is or will be a leap year

You need to complete the function IsLeap(int y) to implement the necessary code

Although the program is incomplete the program contains pseudo code for the algorithm required to compute the answer The pseudo is also show opposite

if year modulo 4 is 0

then

if year modulo 100 is 0

then

if year modulo 400 is 0

then

is_leap_year

else

not_leap_year

else

is_leap_year

else

not_leap_year

Figure 5

49

PLUSPLUS IsLeap in a line

Task 1

Extra points for implementing the IsLeap() function in just a single line of code This could be done using ampamp and || or by using the operator (a short form of if then else)

If you completed this step how readable is your code when compared to the if else version on the right

52 Algorithms

Algorithms

An Aside Big-O notation and Algorithm Complexity feel free to jump over this to Task 1

As programmers we usually implement the various parts of any new program in the simplest and most straight-forward way possible Then later if we find parts of our program are slow (causing what are called hot-spots) we will look again at the code to see if there is a better way to do whatever it is that is taking up the time

As a general rule the most optimal algorithms run in the shortest possible constant t ime ndash such algorithms are often symbolised using O(1) whereas the worst run in quadratic cubic exponential or factorial time (you can think of the O [called Big-Oh] as meaning in the Order of for some input n)

Usually were often happy with those running in O(n) (in the order of n) time ie their running time scales linearly with the number of steps or operations they involve Loops invariably signal O(n) parts of any algorithm

This is best explained using an example

50

Task 1 Understanding Gauss algorithm

Q How would you sum the integers from 1 to n where n is say 100

The obvious way is to use a loop

int tot = 0

for(int i = 1 n = 100 i lt= n ++i)

tot += i

This is fine for small values of n but not so good for very large ones

Interestingly it is said that this self-same problem was once given to a class of children which included one Carl Friedrich Gauss (presumably the teacher wanted to keep his charges occupied for a time) While most of the children started working at the problem (using the loop approach above) Gauss thought about it for a moment and then wrote down the solution 5050

The algorithm Gauss used may be easily demonstrated using the values 1 ndash 10

Gauss realised that if he wrote out the values twice (whether on paper or just in his head) once forward and once in reverse that he could sum each column formed to 11

1 2 3 4 5 6 7 8 9 10

10 9 8 7 6 5 4 3 2 1

1+10 2+9 3+8 4+7 5+6 6+5 7+4 8+3 9+2 10+1

=11 =11 =11 =11 =11 =11 =11 =11 =11 =11

Then sum of 1 ndash 10 is then 11 10 (columns) = 110 2 = 55 (we divided by two because we used each value twice)

Coming back to algorithm runtimes you can see that when using a loop summing 1 ndash 1000 will take ten times longer than summing 1 ndash 100 which will take ten times longer than summing 1 - 10 However by using Gauss approach we can arrive at the answer for any range of values in the same time this is what we mean by a constant time algorithm

51

Task 2

Open the incomplete project SumIntSeries

Complete the project so as to implement Gauss algorithm for any continuous range of integers

The solution project is (exercise solut ion)

SumIntSer ies

The general formula required is

((119948 minus 119947) + 120783)(119947 + 119948)

120784

Or in a more code form

Sum = ((k - j) + 1) (j + k) 2

Where j and k are the starting and ending values in the range respectively (both inclusive)

Functions and Pass by Reference

In the previous section when working with functions all arguments passed to the functions were copies of variable values from main() The arguments were passed by their value

Pass by Value is the default argument passing mechanism for C++ (and the C language)

In pass by value when a function is passed an argument it receives a copy of the value from the calling function (main() in previous examples) This copy remains in scope until the called function has completed and returned at which time the copy is destroyed

Therefore a function that takes value-arguments cannot change a passed variables value because any changes only apply to copies and not to the actual callers variables

An alternate passing scheme is called Pass by Reference

Passing variables to functions by reference is very useful when we need to change or update variable(s) via a function (it is also a faster mechanism than pass by value as no copies have to be made)

Under the covers pass by reference involves passing a memory address and not a copy of the data to the function This is usually more efficient than passing by value because there is no requirement to copy memory However this argument passing mechanism enables a function to modify any argument even if its not supposed to To avoid this we usually declare all read-only parameters as const and pass them by reference

The format of a function prototype when using call by reference is

return-data-type funct ion-name (reference parameter) To indicate a reference parameter an ampersand (amp) is written in the function prototype and header after the parameter type name

The statement void squared(int amp) has no return data type (void) its name is squared and it accepts a reference parameter (amp) of type int (integer)

52

The function definition would be something like this

void squared(int amp inVal)

inVal = inVal inVal inVal

The function call to it would look like this

squared(aValue)

As mentioned above pass by reference is normally used for one of two reasons 1 Because we want to be able to change a passed variable inside a called function 2 Because we want the speed associated with a pass by reference

In 2 we will normally protect our argument by using const in the called function Eg say we want to pass the double argument x to a function f() and take the least possible time about doing it (and given that function f() shouldnt alter x) we would use the following code

void f(const double x)

Use x in some calculation Note that if

x appears on the left hand side of an assignment operator

that it will result in a compilation error

Pass arguments by reference

Task 1

Open the project (demonstrat ion) FunctionRef

Compile and run the program The output should be the same as shown in Figure 6

53

Figure 6

Examine the function prototype

void squared(int amp)

This shows the function squared accepts a reference

parameter of type int The reference parameter is ndash under the covers - the memory address of the argument passed to the function

The function uses this address to both get and set the value stored in variable a (value 21) in main() A reference to this address is passed to the function with the function call squared(a)

Examine the function void squared(int amp x)

Under the covers references to x refer to the address of the variable a in main (that holds the value 21) Ie x and a reference the same piece of memory (the word object was deliberately not used there) So we can think of x and a as two names for the same item

Returning values from functions

In previous programs we have most often produced output (using cout) from within the functions However to be of most use and general utility functions should return resultsinformation rather than output it

Functions may return results in one of two ways 1 via a return value or 2 via arguments ndash either passed as references or via pointer (address)

Non void Functions return a single value ndash if you will they evaluate to this value As such non-void functions may be used in expressions Eg

54

w = x sqrt(y) z

The function sqrt() is replaced with the value of whatever the square root of y happens to be For example if y has the value 4 then to evaluate x sqrt(y) z fully the sqrt() function has to be called ndash where it returns 2 This value is then substituted into the expression for further evaluation ie it becomes w = x 2 z

The second way for functions to return results is via its parameters ndash if they are references or passed via memory addresses Eg

void doubleIt(int amp n)

return n 2 Error The void means doesnt return a value

doubleIt() is a void function ndash so it cannot contain a return statement ndash so it cannot evaluate to anything ndash so it cannot be used in an expression

x = doubleIt(y) error

However the function is still able to return a result (modify something outside of itself is perhaps a better way of putting it)

void doubleIt(int amp n) using amp - a reference

n = n 2

55

doubleIt() cannot (still) be used in an expression but it can change things

int x = 10

doubleIt(x)

cout ltlt x Outputs 20

Why would you use references like this Well references are mainly used for speed (by passing an actual external entity a copy does not have to be made) but they are also useful when multiple values (entities) might best be updated via a single operation (function call)

int x y z

x = y = z = 10

doubleAll(x y z)

void doubleAll(int amp a int amp b int amp c)

a = a 2 b = b 2 c = c 2

Side effects

Going back to w = x sqrt(y) z

Lets replace sqrt() with our own function and cause some havoc

double havoc(double amp d)

++x

d = sqrt(d)

return d

x = 3

w = x havoc(y) z

56

Here the value of y has been changed (yet it is not clear that could happen from the functions call site ndash where it was called from) and so has x Also what value for x will be used in x havoc(y) z Will it be 3 or 4 These sorts of issues are called side-effects

This is one problem (or advantage) with reference arguments ndash and that is that they can cause a change in a variable outside of the function being called

One way to protect against this is to use const references eg

double havoc(const double amp d)

++x

d = sqrt(d) Compilation error here

return d

57

Returning a value from a function

Task 1

Open the TempConver t

project

Run the program The output should be the same as shown in Figure 7

Examine the function prototype

double convert(double temp int mode)

This function prototype has a return type of double When the function is called and calculations are completed a double value is returned to the caller

Examine the function definition The function definition matches the prototype indicating a double and an integer are being passed to the function and a double is being returned

Examine the function body The two statements below convert the temperature input The conversion type required is identified using the user input mode and a switch selection

The statement (temp - 32) 5 9 is used to calculate the temp in Centigrade

The statement 18 temp + 32 is used to calculate the temp in Fahrenheit

Figure 7

58

PLUSPLUS Arithmetic Bases

Task 2

Open compile and run the partially complete Bases project

Note that the project isnt complete

The program uses intrinsic functionality to output values in hexadecimal and octal ndash base 16 and base 8 Both these bases are useful in programming its all to do with binary and the size of a byte

Note that there isnt a bin equivalent to hex and oct and that we have instead written a function called bin1() to convert a value into its binary (base 2) representation

Understanding how bin1() works

bin1 uses the modulus operator () and the right shift operator (gtgt) to work eg 42 in binary is 101010

25 24 23 22 21 20

32 16 8 4 2 1

----------------------

1 0 1 0 1 0

----------------------

1 32 + 0 16 + 1 8 + 0 4 + 1 2 + 0 1 = 42

The function progresses like this

42 2 has remainder zero (false as evaluated in the if) If the if test is true we store a 1 else we store a 0 We then divide 42 by 2 by right shifting it one place ndash but just replace that with n = 42 2 if you prefer We then loop while we have a non-zero value in n to operate on hellip

42 2 = 210 42 2 = 0 if(42 2) = false string value = 0

21 2 = 105 21 2 = 1 if(21 2) = true string value = 1

10 2 = 50 10 2 = 0 if(10 2) = false string value = 0

5 2 = 25 5 2 = 1 if(5 2) = true string value = 1

2 2 = 10 2 2 = 0 if(2 2) = false string value = 0

1 2 = 05 1 2 = 1 if(1 2) = true string value = 1

59

Task 3

The project needs completing specifically it needs the function bin2() writing

We could write such a function as bin1 in a variety of ways and wed like you to write a new function called bin2() that produces the same output as bin1() here

Heres a step by step algorithm for implementing bin2()

Youll use either gtgt or and the bitwise And (amp) operator

Take the functions input (the number to convert) in as a parameter called n To keep it as simple as possible for now you could use plain int types rather than the unsigned long long type we used so the functions signature would look like string bin2(int n)

1 In the function create an integer called i and initialise it to 1

2 Realise that if you left shift the single bit in i (use ltlt or multiply it by 2) it will take on the values 2 4 8 16 32 hellip until it eventually goes to 0 ndash as you shift the bit off of the end

3 Recognise that you could compare your shifting bit with one in the same position in n using bitwise And Ie if((n amp i) == 1) then you know youll need a 1 in your output string for the bit position in n (2 4 8 ) given by is value at this point

4 Build up your result string as you proceed

Change your int n and int i to unsigned long long int and re-run

Try using other integer types ndash signed and unsigned

Lastly examine the solution project in (exercise

solut ion) Bases

60

Figure 8

61

Searching for Sequences

Task 1

Open and modify the incomplete project called called HeadsOrTai ls

When all completed the output should be similar to that shown in

Figure 9

This is the (exercise

solut ion) HeadsOrTai ls project

The programs purpose is to look for a sequence of simulated coin tosses ndash a series consisting of Hs and Ts

The program is complete (as in it runs) but it has some issues At first test it using quite short sequences

The timing information displayed by the application is included simply to demonstrate a timing mechanism that can be used to test the efficiency of the code

The first problem is that the user can currently enter characters other than H or T (h and t are ok as the input is converted to uppercase ndash note the string is passed by reference to toupper() which uses a pointer (which well cover later) to process the string

The second problem is that as it stands the algorithm isnt very optimal if we do not find our pattern we add the result of another coin toss to the current sequence and then re-check the sequence in its entirety

For example if were looking for HHTHH and the generated sequence is currently HTTHHHTTHTHHTTH we will fail to find HHTHH and then proceed to add another coin-toss result at the end ndash HTTHHHTTHTHHTTHH We will then scan this for HHTHH However as we know that we failed to find HHTHH before we added the extra coin-toss re-checking the previously checked sequence is pointless and very time consuming (think how this would (or wouldnt) scale) Your task here is to think of and implement another more optimal approach

62

Figure 9

Task 2

Open the HTTvsHTH project you will find that the project will compile correctly but displays an incorrect result

When completed the program can be used to check how many coin-tosses are required on average to see a particular sequence

Why should that be of interest Because sometimes its rather surprising For example test how many tosses are needed to see say HTH and then HTT

When the program is corrected the output should be as shown in Figure 10

63

Figure 10

PLUSPLUS Optimising Searching for Sequences

Task 1

As it stands the program (yours and ours) encodes a coin toss as a character ndasheither an H or a T Each character is encoded using at least 8-bits and so checking whether a generated sequence is the sequence were looking for means performing a string comparison which is costly in terms of clock-cycles Of course generating and storing the new coin toss also requires the use of these costly string operations

As we have just two tokens as an alternative to generating and storing characters and performing string operations we could encode a sequence as a series of bits For example the sequence HTH could be encoded as 101 in binary (5 in decimal) You can set the corresponding individual bits in an int using the bitwise Or operator | (a vertical bar) eg int n = 0 n = n | i which youd most likely do as a result of scanning the users entered search-sequence string a character at a time In this way you could encode the sequence HTHHTHHTHHTHHTHH in a single sixteen bit unsigned int

Additional operators needed to implement sequence checking and H or T bit manipulation are bitwise And (amp) and the left shift operator (ltlt)

You will find more information on some of these operators just a little below

64

Evolving Searching for Sequences

Task 1

Looking for sequences in stringssequences is an interesting and complex problem in computing and also in genetics where the string being searched could be a DNA sequence and pattern could represent a gene perhaps with a snip (a modificationmutation)

Modify your HeadsOrTai ls program (or our solution) so that instead of Hs and Ts it generates and searches for Gs As Ts and Cs instead

Randomly generate a GCTA sequence and a similar pattern to find within the sequence

How much more time and variation is required in this slightly more complex situation

Conduct a few experiments and using Excel graph your results (copy and paste some data highlight it and then select Excels line graph ndash Excel should then automatically plot your data)

Extrapolate The human genome is how long A gene might contain how many bases How difficult is the task of finding interesting sequences in the human genome How about checking for the odd mutation (insertion transposition deletion) ndash fuzzy matching

A solution for this problem can be found in the (demonstrat ion) GATTACA project

6 Classes and Objects In the previous section we have been working with simple programs that display messages to the user store data input as different data types manipulate the data in some way and output the results to screen

We will now start to look at C++ objects and classes

In the real world there are objects everywhere students staff cars birds houses and many more All objects have at tr ibutes these are similar to the variables created in previous tasks Some attributes of a student may be height weight race course of study etc All objects exhibit behaviours or operations cars accelerate and decelerate students matriculate enrol on courses and leave university

65

Now what is the relationship between a class and an object A good analogy would be from an architects blueprint for a house it would be possible to build many houses Similarly from a class in C++ it would be possible to build many objects

If we had a student class we could create many objects from the student class to represent the many students enrolling Each of these objects would be uniquely identified They would share common attributes and exhibit common behaviours If we wanted an object to perform some task we would call the appropriate member function allowing an operationaction to take place changing the behaviour of that object

Member functions are different from the functions you have created so far Member functions are always associated with objects and are usually called or invoked using a dot notation object member funct ionname() An example is student1getName() The object instance is student1 and the member function is getName()

Member functions contain the detail of how the technical aspects of some operation will be processed When member functions are invoked these technical issues are hidden from the end user When the member function is asked to do some operation a message is sent (a member-function call) telling the member function of that object to perform the operation detailed in the function

Functions are not completely new we have had a brief introduction and you have already created some of your own Note also that main() is a function that is called automatically when you run your program However it is not a member function as there is no object associated with it

Creating your first class

Creating a class

Task 1

Open the project called StudentUG

Compile and run the program It should look like Figure 11

66

Figure 11

Before you can create the object myName it is necessary to define the class from which the object will be created The class definition is shown below

class StudentUG Start of class definition

public

void displayName() Start of member function

cout ltlt My name is Michael Cain ltlt endl

Note a semicolon is required at the end of the class definition

Within main() the statement StudentUG myName creates the object myName of class StudentUG In effect StudentUG is a new type

The statement myNamedisplayName() is used to call the member function displayName() of object myName

As we have seen previously the function main() is called automatically when our programs are executed However member functions (displayname() is one we could have many) must be called in this way objectInstanceNamefunctionName() when dealing with an

67

object directly and like this objectInstanceName-gtfunctionName() if working through a pointer to an object (more on pointers later)

The member function displayName() is preceded by the word void All functions can return values this one does not The word void preceding the function name indicates nothing is being returned If this function returned an integer the definition would be int displayName()

When you use functions it is common to pass data (called parameters) to the function The function then manipulates the data before displaying an output andor returning a value

To pass a parameter to the function in the studentUG class the calling statement in main() would be

myNamedisplayName(name) where name is a string (a series of characters) that contains a value read in from the keyboard

In order for the function displayName() to recognise the parameter being passed the function declaration is changed to include the parameter (name) and type (string) as shown in below

void displayName(string name)

cout ltlt My name is ltlt name ltlt endl

Figure 12

Member functions and Passing parameters

Passing parameters

Task 1

Modify StudentUG to read in a student name The name should be passed to a member function The parameter should be output from within the function to welcome the user to C++ programming

68

Task 2

Modify the program in the above task to read in two more names Each name will be for a different student and you will need to create additional objects (instances) of the class

Data Members

In most of the programs written so far the variables have been declared inside the main() function Variables declared inside a function are local to that function and cannot be accessed from outside that function

You have created a student class and it would be reasonable to assume that a student would be following a particular course So courseName might be one of several attributes of a StudentUG object Attributes are represented as variables in a class defini t ion These variables are called data members and must be declared inside a class definition When you create an object of a StudentUG class each object has a unique memory location for its data members

Figure 13 shows data member name declared in the class definition The access specifier private means that only member functions of the class in which the attribute was declared can use this data member

private string name

Figure 13

When data members are declared as private the data is hidden This is called encapsulat ion and means the attributes of the object are hidden and can only be accessed via member functions

As there is no direct way to change a data member you will also need to create a member

funct ion to set the data member to a value and create a second member funct ion to output the value held there

Data members can also be declared public A data member that is declared public can be accessed from any (non-member) function

A protected data member can only be accessed by member functions of its own class and by member functions of classes derived from this class We will learn more about derived classes and inheritance later

69

Using data members

Task 1

Open the project called StudentCoursesln

Compile and run the program it should look like Figure 14

Figure 14

Task 2

Examine the member function getCourse() shown in Figure 15

string getCourse()

return course

Figure 15

Task 3

Modify the StudentCourse source file to enable the user to add a student name enrolment date and number of years of course Once entered this data should be output to screen You will need to create additional data members and member funct ions to achieve this

70

More Objects

Task 1

So far you have created one StudentCourse object It is about time we had a second student on the course Create a second object of the class StudentCourse You will need to add the second statement shown in Figure 16 to add the new object student2 Call the member functions passing parameters as necessary

Figure 16

Constructors

When you create objects from the StudentCourse class it is necessary to give initial values to all the data members If we were entering data for five people and they were all following the same course of study it would make sense to initialise the course data member (it is possible to initialise some or all of the data members) when each object is created

A constructor is a special kind of function that must have the same name as the class Constructors are normally defined to be publ ic and never have a return type They can be used to automatically initialise data members

In previous programs you have written a defaul t constructor has been provided by the compiler However it is not possible to pass parameters to a default constructor function so the data members in the programs created so far have not been automatically

71

initialised To initialise these data members you created member functions that assigned values to data members

Although a default constructor is provided at compilation time it is a good idea to create your own so that the data members can be initialised

It is worth noting here that functions (constructors are functions) can be over loaded This means it is possible to have more than one function with the same name Note that overloaded functions (functions with the same name) must have different types of or number of arguments

Constructors (functions) can also be overloaded with more than one function with the same name but different types or number of parameters Fortunately for us the compiler automatically calls the correct function whose parameters match the arguments used in the function call

Using constructors

Task 1

Open the project called Constructorss ln

Compile and run the program it should look like Figure 17

Figure 17

72

Task 2

In the constructor shown in Figure 18 what is the purpose behind course = Note that as the string parameter name has the same name as the class variable that we use the hidden this pointer to access the class variable in the assignment If we didnt do this and simply used name = name instead then all we would be doing is assigning the value in the parameter back to the parameter

StudentCourse(string name)

this -gt name = name

course =

Figure 18

Task 3

Create a third constructor that will take an argument enrolment_date

Add a third object call it student3

Write code that will test this additional constructor

Solution in (exercise

solut ion) Constructors

If time allows add other useful properties (data members) access methods (functions) and constructors

Separating use from declaration and definition

C++ is all about objects and any decent project will usually make use of a number of application or domain specific classes

To keeps things maintainable and to promote code reuse C++ projects usually contain a number of cpp and h files where each h files will usually contain a declaration of a class (sometimes called an interface) Note though that the definition of the class (sometimes called the implementation) ndash the code that implements it ndash will be absent from the h file and will instead reside in an accompanying cpp file

Aside from allowing different teams to more easily work on separate parts of the program one of the main reasons for separating definition from declaration is to enforce abstraction which is a programming (and design) technique that relies on the separation of declaration and implementation For example lets say that your team needs a class that acts a bit like a stack (a last-in first-out or LIFO structure) and as this is required

73

urgently you decide to implement it using a simple array You would then only want to give your team what is absolutely necessary to use this class a single h file for your team members to include in their cpp files If they look in the h file they will only see information on how to use the class but how it does what it does is kept elsewhere in the cpp and that youve withheld Consumers shouldnt need to know how a thing works in order to use it

An obvious advantage to this is that there is no danger in you changing how it works Perhaps you later decide to use a vector instead of the array You go ahead and alter the implementation and your team members are none the wiser ndash after all the interface hasnt altered just the implementation

So how does the project get built Of course the implementation of this class will be required at compile time and you can either do that by including the cpp file directly (which will give away the implementation details of course) or by including it as object code ie compiled C++ code (binary machine code) This is how valuable commercial source code is kept in-house while the binary implementation complete with a h file is provided to customers (you will see an example of this just below in Using external

l ibrar ies and thi rd par ty header f i les )

Any discussion on separating use from declaration and definition should include something on namespaces You introduce a namespace by simply using the keyword and braces Anything entered inside these braces is inside the namespace eg

namespace securityModule class Encryptor using namespace std using namespace securityModule int main() Encryptor e Without the using we would have had to use securityModuleEncryptor e securityModuleEncryptor e2

See the (demonstrat ion) Namespaces project for more on this

74

Separating declaration and definition

Using a header and source file to separate class declaration from definition

Task 1

Open and modify the partially complete skeleton project called Precis ionTimers

Like HeadsOrTai ls this project makes use of the Windows operating system to very precisely measure elapsed time However unlike HeadsOrTai ls we have separated the stopWatch class interface from its implementation

As weve previously mentioned Gauss and algorithm efficiency we could test our theory that summing in a loop is O(n) ie that the time taken scales with n

Examine the project files hrTimercpp and hrTimerh noting that the h file contains just enough information for someone to use the declared class stopWatch whilst htTimercpp contains the implementation of the class

Now look in PrecisionTimerscpp You will see that an instance of the stopWatch class is declared Also note that we include hrTimerh but make no reference to hrTimercpp

As it stands the code calls two functions to calculate the sum of a range of integers sumGauss() and sumLoop() The program outputs the clock-ticks used and time taken in seconds

Note that sumLoop() is incomplete

Complete the sumLoop() function and then choosing suitable values for the ranges upper-bound carry out a few experiments to test if the loop is really O(n)

What is this used to do in hrTimerh15

ifndef HRTIMER

define HRTIMER

endif

15 You should also see pragma once as this is rapidly becoming the alternate way to do this ndash whatever this is of course

75

PLUSPLUS Providing object code only

Task 2

We have provided a separate demonstration project that takes the discussion on this one step further (demonstrat ion)

Separat ingThings

In its current form the project wont compile To compile the project in the Solution Explorer add the existing carcpp file to the source files list that just contains SeparatingThingscpp and recompile carcpp is in the same folder as SeparatingThingscpp

Once youve done that right-click on carcpp in the Solution Explorer and select Remove Very importantly when youre prompted for confirmation choose Remove do not choose Delete Now recompile once more youll see that the project fails to compile as the definition of car has been removed

76

But hold on we created carobj - the compiled object-code version of carcpp during our previous compilation so we could tell the linker about that and all should be well (this more or less duplicates the scene whereby you do not provide source code but provide only object code)

The carobj file will be located somewhere like

CUsersDesktopCourse(demonstration) Separating Things(demonstration) Separating Thingsbincarobj

To add this to your project go to Project | Properties | Configuration Properties | Linker | Input

77

In the right-hand window select Additional Dependencies drop down the list and select ltEdit gt

In the dialog that appears add the full path to carobj (see earlier in Step 2) and press Ok

Lastly recompile the code once more It should compile and run At this point you could if you wanted to delete carcpp altogether

One last thing

If you look in the comments in SeparatingThingscpp you will find a discussion that goes into the advanced topic of hiding things even further This includes a brief discussion of the the so called pimpl pattern (pronounced Pimple this stands for Pointer to Implementation16)

16 httpenwikipediaorgwikiOpaque_pointer

78

PLUSPLUS Using external libraries and third party

header files

Task 3

Open and modify the project called Lot to

Examine the projects comments to understand the programs function Run the program ndash does it work

It is supposed to compute the odds of winning the UKs lottery httpwwwnational-lotterycouk (try as we might we couldnt find the odds on their own website)

The program uses the recursive factorial function used earlier in the course (with bigint being typedef ed as unsigned long long int)

Factorial function using recursion

bigint recur_factorial(bigint n)

return n lt 1 1 n recur_factorial(n - 1)

There is a problem here however in that to compute the odds we must compute some significant factorials ie

49 = 608281864034267560872252163321295376887552831379210240000000000

and

6 (49 - 6) = 43498989405629161658895695089330078205230448640000000000

Sadly our bigint (unsigned long long) can hold a maximum value of 2^64 ndash 1 = 18446744073709551615 ie not hardly big enough

Fortunately in C++ we can define new types like an arbitrarily sized integer (outside of the scope of this course but see the (demonstrat ion) newINT project for a small taste) However this is object orientation ndash surely we can just use an existing already defined arbitrarily sized integer class

79

Task 4

The good news is that in this class you can You can use LEDA (The L ibrary of

Eff ic ient Data types and Algor i thms ) a professional class library of advanced numerical functionality

You will need to download the program called

LEDA-63 i386 msc 10 ( NET 2010) 32 bi t

or

LEDA-63 i386 msc 10 ( NET 2010) 64 bi t

Go to wwwalgorithmic-solutionsinfofreeindexphp Accept the licence terms and download the appropriate version (usually the 64 bit version)

The LEDA installation program will install additional numerical libraries and header files from the Algorithmic Solutions company

Once the setup is complete modify the Lotto program

In the Solut ion Explorer right-click on your project (Lot to ) and left-click on Proper t ies A dialog-box appears

Under the CC++ section

1 Click on General Choose Addi t ional include di rec tor ies and enter the directory CAlgor i thmic Solut ions LEDA-63- free-win-msc10-

s td incl

2 Click on Preprocessor and add LEDA_DLL to the end of Preprocessor

Defini t ions Note the semicolon is required

3 Click on Code Generat ion and check that Runtime Library is set to Mult i - threaded Debug DLL ( MDd)

Under the Linker section

4 Click on General

5 Choose Addi t ional l ibrary di rector ies and enter the directory CAlgor i thmic Solut ionsLEDA-63- free-win-msc10-s td

6 Click on Input and add l ibGeoW_mdd_dl l l ib leda_mddl ib to the end of Addi t ional Dependencies Again the semicolon is significant

You may now close Properties dialog-box

7 Modify your code Add the following under include ltiostreamgt

include ltLEDAnumbersintegerhgt using ledainteger using namespace std

80

Then modify the recur_factorial() function so that it accepts and returns a type called simply integer rather than bigint

Save the project and exit Visual Studio

In order to build and execute Lottoexe Windows needs to have l eda_mdddl l in its search path for DLLs Therefore we need to add the path to the folder containing leda_mdddll to the PATH environment variable

8 In Windows Explorer navigate to My Computer then right-click on it and select Propert ies

9 Click on the Advanced tab and then on the Environment Var iables button

10 In the bottom section (System var iables ) of the dialog box highlight Path and then click the Edi t button

At the end of the existing path add -

11 CAlgor i thmic Solut ions LEDA-63- free-win-msc10-s td

Once more note the leading semicolon is significant

81

12 Restart Visual Studio and re-open Lot to Build and run the application as normal

It might seem that this was a lot of work for such an apparently trivial result but the fact is that you now have access to (and have seen how to use) an advanced numerical library of functionality And anyway when all is said and done you must admit that at least you got a return here ndash which is more than you should reasonably expect from the lottery

Figure 19

Task 5

Explore the LEDA samples and documentation ndash if you installed it there should be a shortcut in your start menu to LEDA-63-free-win-msc10-s td

Task 6

Modify the Lotto program to see how the odds change when there are more balls andor when more balls need to be matched (you might also display more of the intermediate results of calculations ndash like 49)

Destructors

Both constructors and destructors are special class methods We have seen how a constructor is called whenever an object is defined

A destructor has the class name prefixed by a tilde ~ Like constructors destructors cannot return values and therefore they have no return type specified but unlike constructors destructors have no arguments and thus cannot be overloaded

An objects destructor is called whenever an object goes out of scope The purpose of the destructor is to clean up eg to free any dynamically allocated memory that the object was using and release other system resources such as files and database connections etc

In the examples used so far no destructor has been provided for any class created In these programs it has been unnecessary If the programmer does not explicitly provide a

82

destructor the compiler will create an empty destructor in the same way that an empty constructor is created if one is not explicitly created

When classes are created any objects instantiated from them that contain dynamically allocated memory will need destructor methods added to implicitly free any dynamically allocated memory when the object goes out of scope

In the class example shown below the destructor function is ~StudentCourse()

~StudentCourse()

cout ltlt Im being destroyed

7 Arrays vectors lists and hash-tables Arrays vectors and lists are all types of data structures Data structures are areas of memory where collections of the same data type are held The main difference between arrays vectors and lists is that arrays stay the same size throughout the program execution whereas vectors and lists can grow automatically

Arrays consist of a series of elements (variables) all of the same type placed consecutively in memory Each of the elements can be individually referenced by adding an index to the arrays name We saw this type of notation earlier when using arrays

Eg

int examMarks[10]

This declares an array of ten scores score 1 is accessed via an index of zero ndash examMarks[0] and score 10 is access through an index of nine ndash examMarks[9] Very important note that indexes start at zero

The advantage of using arrays compared to using discrete variables (the way we have stored values so far) is it is possible to store any number of values of the same type in an array using the same identifier

With arrays it is possible to store 100 student exam marks or 100 student names with using one unique identifier

Vectors and lists are container classes which were originally part of the Standard

Template Library (STL) The STL evolved into C++ Standard Library ndash which includes iostream etc This is the general-purpose C++ library of functions algorithms and data structures that we can use in our programs While some aspects of the library are very complex it can often be applied in a very straightforward way that allows reuse of sophisticated data structures and algorithms

There are many container classes in the library ndash note that C++ now also provides such a class for the more primitive array

ltarraygt

New in C++11 and TR1 (Technical Report One)

83

A container for a fixed sized array

ltbitsetgt

A bit array

ltdequegt

A double-ended queue

ltforward_listgt

New in C++11 and TR1 A singly linked list

ltlistgt

A doubly linked list

ltmapgt

Sorted associative array and multi-map

ltqueuegt

A single-ended queue

ltsetgt

Sorted associative containers or sets

ltstackgt

A stack

ltunordered_mapgt

New in C++11 and TR1 Hash tables

ltunordered_setgt

An unordered_set unordered_multiset

ltvectorgt

A dynamic array

As with an array vector and l is t can hold objects of various types However unlike arrays vectors and lists can resize shrink and grow as elements are added or removed

The standard library provides access via iterators or subscripting Iterators are classes that are abstractions of pointers (more on pointers later) They provide access to container classes using pointer-like syntax and have other useful methods as well

The use of vectors lists and iterators is preferred to arrays and pointers By using containers common problems involving accessing past the bounds of an array are avoided Additionally the C++ standard library includes generic algorithms (an algorithm is a set of instructions on how to perform a task) that can be applied to vectors lists and other container classes

Declaring and using arrays

Arrays are declared indicating the type and number of elements in the following way

type ar rayName[arraySize]

84

Examples are

int inNumbers[20] an array called i nNumbers of 20 in tegers

char inName [20] an array called i nName of 20 characters

float ExamMarks[5] = 0 an array called ExamMarks of 5 floats with all elements explicitly initialised to zero

const int size = 5 declaring a constant variable size

float ExamMarks[size] When the constant variable size is applied to the array declaration the number of elements is set to 5 This cannot be changed during runtime of the program However it is handy when the number of array elements needs to be changed Changing the constant value size changes the number of elements wherever the ExamMarks array is used in the program

int numArray [2][3] is a multidimensional array with 2 rows and 3 columns

Note Arrays have been used in C++ for many years and there will be code you work with that was written before vectors became available Vectors are are usually preferred to using arrays and pointers Common problems involving accessing past the bounds of an array are avoided when using vectors

Creating an array to hold exam results

Task 1

Open the project Array s ln

Compile and run the program

Run the program adding five exam results The output should be similar to Figure 20

Figure 20

85

Examine the following statements

double ExamMarks[5] = 0 This statement declares the array setting its size to 5 elements and explicitly initialising all elements to zero

cout ltlt Enter Exam Mark ltlt i + 1 ltlt This statement prompts the user to enter an Exam mark into the array at element i + 1

Using the notation i + 1 indicates to the user to enter Exam Mark 1 not exam mark 0 which would be less intuitive

Array elements are numbered from 0 to n - 1 So an array that holds 20 integers will be addressed from element 0 to 19

ExamMarks[0] -ExamMarks[19]

The first number will be entered into element [0 ] The last into element [19]

cin gtgt ExamMarks[i]

This statement reads in the user input and stores the values in the array elements of ExamMarks[i] i is incremented within the for loop and starts at 0

Task 2

As it stands the program could be generally improved ndash see the notes in the code and consider how you might make such improvements

Next modify the program to output the highest and lowest marks entered

Task 3

Modify the program so that the number of marks may be easily changed (at compile time)

86

Task 4

Modify the program so as to break out the part that calculates the average and put it into a separate function

Write another function that given an array of this sort returns the mode mean and median values ndash you will need to pass in references as the function will need to return three values

Lastly put your two new functions into a separate cpp (you will also have to create a h file for Arraycpp to use ndash this will contain the new functions prototypes)

87

Searching Arrays with Linear Search

Linear search allows the user to search the array and establish whether the array contains a value that matches a search criteria defined by the user

The search compares each element of the array with the user input The array is not sorted and this method of searching works well for small arrays For large arrays linear searching is inefficient and it is necessary to use other forms of array searching after the array has been sorted

Linear Search

Task 1

Open the project LinearSearch

Compile and run the program - choose a number between 1 and 100 The output should be similar to Figure 21

Figure 21

88

Examine the following statements

myArray[i] = (1 + rand() 100) This statement uses the rand function part of the ltstdlibhgt header file (included via iostream being included) 1 + rand() 100 produces integers in the range 0 to 99

The function l inearSearch takes three arguments The array name the size of the array the third argument is the search value

if(theArray[j] == value)

return j

This selection statement compares each element to the search value If the search value is in the array the element number is returned to main() otherwise -1 is returned

The if selection statement if(containingElement = -1) in main() is used select the output indicating a successful or unsuccessful search

Task 2

Currently the program searches for the first occurrence the search value only

Modify the program so that it outputs al l matching element locations

This function can be used for turning an int value into a string See also the comment below about C++11s to_string() functions

string convertInt(int number)

stringstream ss

ss ltlt number

return ssstr()

Youll need to include ltsstreamgt to use the stringstream class

89

Task 3

Modify the program so that repeated searches may be carried out

See Figure 22

If using C++11 or later you can also use the to_string() helper functions of the string class eg to_string(10) yields 10

Figure 22

PLUSPLUS Debugging Linear Search

Task 1

For debugging purposes modify the program so as to output the contents of the array

Open and run (exercise solution) LinearSearch to see what this might look like You might want to use the modulus operator () to work out when to neatly break a line

You may or may not like to have the program generate varying sets of random numbers To facilitate this youll need to seed the random number generator by inserting a line of code like this

srand((unsigned)time(NULL))

Note the use of the cast

To use srand() include timeh at the top of your program

90

Sorting Arrays with Insertion Sort

When working with large quantities of data in an array you will need to sort the data at some point This makes searching for information quicker and there are many algorithms available that can be used In the following exercise you will learn how to sort numbers stored in an array in ascending order

SortingSearching an array

Task 1

Open the project Sorts

Run the program and examine the code

The program currently uses a class (sorts) which is defined in sortsh to implement one popular sorting algorithm called Inser t ion Sor t

For details on this algorithm see

httpenwikipediaorgwikiInsertion_sort

91

Task 2

Add a new sort to the sorts class

The text file quicksor t txt (in the Sorts folder) contains the C++ code required to implement another popular sorting algorithm called Quicksor t17

For details on this algorithm see

httpenwikipediaorgwikiQuicksort

Add the quicksort code found in quicksor t tx t to the sorts class - considering what parts of it need to be publicprivate

quicksort tx t is in the same folder as the Sortss ln project file

Step 2

Test the quicksort implementation on a range of values

Alter the quicksort implementation so as to have it sort in descending order

Following on from Step 3 parameterise the quickSort() function so as to add an option to have the array sorted in either ascending or descending order

17 Invented by C A R Hoare ndash Sir Tony Hoare with Christopher Strachey the most distinguished computer scientists Oxfords ever produced

92

Figure 23

93

PLUSPLUS Binary Search (Binary Chop)

Task 1

Now that the array is sorted we can implement a very efficient searching algorithm usually called either binary search or binary chop search

See Figure 24

Modify your project to allow the sorted array to be searched for a value using the binary chop algorithm See opposite

The algorithm for binary chop is quite straight forward

1 Look at the value of the middle element of the array If the value = target then youre done

2 If the value is lt than target discard the lower half of the array treating the upper half as though it were the complete array

If the value found is gt than target you obviously want to look in the lower half

3 Repeat step 1 until the item is found or else the index value becomes invalid

Pseudo code for this algorithm is here

first integer = 0

mid integer = 0

last integer = NumberOfItems

while first ltgt last

begin

mid = first + last 2

if List[mid] = target

exit while Found item

If List[mid]gt target

last = mid In the first half

else

first = mid + 1 In the last half

end

found boolean = List[mid] = target

94

Figure 24

Multidimensional Arrays

Multidimensional arrays with two dimensions (arrays can have more than two dimensions) may be thought of as consisting of data arranged in rows and columns see Table 3

Each element in the array is identified by using two subscripts as shown in Table 3 The first subscript identifies the element row and the second identifies the element column a[0] [1] identifies a value in Row 0 Column 1

The array in Table 3 contains two rows and three columns and can be called a 2 by 3 array

Column 0 Column 1 Column 2

Row 0 a[0] [0] a[0] [1] a[0] [2]

Row 1 a[1] [0] a[1] [1] a[1] [2]

Table 3 ndash Array Layout

A multidimensional (2 by 3) array of doubles is shown in Table 4

Column 0 Column 1 Column 2

Row 0 2367 6792 8557

Row 1 1276 9132 2789

Table 4 ndash Array Values

95

Creating a multidimensional array

Task 1

Open the Mult iDimArray

project

Compile and run the program adding 2 exam results for each of the two students The output should be similar to Figure 25

Figure 25

96

Task 2

Examine the code used to write values to and read from a multidimensional array

Examine the following code segments

double ExamMarks[2][2] = 0 This statement creates a two-dimensional array having two rows and two columns and initialises the elements to 0

Every element in the array is identified by an element name in the form a[x] [y] where a is the name of the array and x and y are the subscripts that uniquely identify each element in a Notice that the names of the elements in row 0 all have a first subscript of 0 see Table 5 The names of the elements in column 1 all have a second subscript of 1

Note multidimensional arrays can have two or more dimensions (subscripts) Three-dimensional arrays are uncommon

Column 0 Column 1

Row 0

a[0] [0] a[0] [1]

Row 1

a[1] [0] a[1] [1]

Table 5 ndash Array Indexing

97

Examine the following code segment used to read values in to the array

for(int row = 0 row lt 2 ++row)

for(int col = 0 col lt 2 ++col)

cout ltlt Enter Exam Mark No

ltlt col + 1

ltlt for student No

ltlt row + 1 ltlt

cin gtgt ExamMarks[row][col]

cout ltlt endl

The two for loops work taking one row at a time (the outer for loop) and looping through the columns in that row (the inner for loop) When the marks have been entered for all the columns in row 0 row 1 is selected and values entered for each column cell in row 1

Table 6 shows how four results would be allocated in a 2 x 2 multidimensional array

Exam mark 1 Exam mark 2

Student 1 67 71

Student 2 61 58

Table 6 ndash Populated Array

98

Examine the following code segment used to calculate the total of each students marks

if(row == 0)

r1total += ExamMarks[row][col]

else

r2total += ExamMarks[row][col]

r1total is a variable to hold the sum of values in column 0 and 1 for row 0 (Stud1) r2total sums the values in the columns for row 1 (Stud 2)

Selection for each row is made with if(row == 0) this is Stud1 If row is not 0 then row must be 1 and the mark can be added to r2total If three exam marks were input per student the code for selecting the marks would need to change

Task 3

Modify the program to read in four exam marks for f ive students

Establish the highest and average mark for each student Output the results

One way to do this is to keep a separate array to record the students statistics An alternative would be to extend the existing arrays row so that it may hold the necessary student data

99

Declaring and using vectors

Vectors are declared indicating the type and number of elements in the following way

vectorlttypegtvectorName

vectorlttypegtvectorName(initialSize)

vectorlttypegtvectorName(initialSize elementValues)

Examples

A vector called i nNumbers with no initial size to hold doubles

vectorltdoublegt inNumbers

A vector called Name with an initial size 20 to hold characters

vectorltchargt Name(20)

A vector called ExamMarks holding integers with initial size of 4 elements each with the value 6

vectorltintgt ExamMarks(46)

Note In previous exercises you have created your own member functions In the following exercises you will use some of the vector class member functions Some of these are begin() end() erase() and size() See section 12115 for more detail

The standard library also includes a large collection of algor i thms that manipulate the data stored in containers (vectors are one of several types of container)

You can sort the order of elements in a vector (vec) for example by using the sort algorithm

sort(vecbegin() vecend()) C++11 sort(begin(vec) end(vec))

You can find a value (69) in a vector by using the find algorithm

ptr = find(vecbegin() vecend() 69) See C++ note above

100

ptr is an iterator to store the memory location of the element found

You can reverse the order of elements in a vector for example by using the reverse algorithm

reverse(vecbegin() vecend()) See C++ note above

There are two important points to notice about the call to reverse First it is a global

function (as are find and sort) not a member function Second it takes two arguments rather than one and operates on a range of elements rather than on the container (vector container in this case)

With the above examples the range is the entire container from begin() to end() (vecbegin() to vecend()) reverse like the other standard algorithms is decoupled from the libraries container classes The reverse algorithm can be used to reverse elements in vectors in lists (another container) and even elements in C arrays

int myArray[] = 1 6 20 4

reverse(myArray myArray + 4)

for(int i = 0 i lt 4 ++i) Lets see the reversed array

cout ltlt Array[ ltlt i ltlt ] = ltlt myArray[i]

In the above example the first argument to reverse is a pointer (pointers are covered in Section 8 but for now we can say the first argument points to the address in memory that is the start of the vector ) to the beginning of the range and the second argument points one element past the end of the range This range is denoted (myArray myArray + 4)

Arguments to reverse are i terators which are a generalization of pointers which is why it is possible to reverse the elements of a C array using the array address and pointer notation

Creating a vector to hold exam results

Task 1

Open the Vector project

Compile and run the program adding five exam results The output should be similar to Figure 26

101

Figure 26

Examine the following statements

include ltvectorgt This statement includes the header file vector enabling the program to use the class template vector (templates allow the use of generic functions that admit any data type as parameters and return a value more on this later)

vectorltdoublegt ExamMarks(5) This statement declares the vector to hold doubles and sets the initial size to 5 elements

Note Although vectors can grow to any size it is good practice and more efficient to specify the size when this is known When no size is given and the contiguous memory spaces have been exhausted the elements must be copied to a larger memory space to increase the size of the vector

cin gtgt ExamMarks[i] This statement reads in the user input and stores the values in the vector slot i of ExamMarks[i] i is incremented within the for loop Note that we the same indexingsubscripting syntax as we used previously with arrays ie[ ]

102

Task 2

Modify the code so as to accommodate the adding of an extra exam mark

Note this should not be done (simply) as part of the loop but as a separate action later and you should use the vectors push_back() method to facilitate this

push_back() is a member function of the vector class that adds an additional vector element at the end

After adding the extra mark you will need to generate a new set of statistics ie the average will have changed now To do this separate out the statistical code and place it in a separate function so that you may re-use later (after the new data has been entered)

size() is a member function (method) of the vector class It can be used to establish the size of a vector

The statement for(int i = 0 i lt ExamMarkssize() i++) uses the vector member function size() available to the vector ExamMarks to obtain the size (number of elements) in the vector The size of the vector is used to identify a terminating value that ends iteration of the for loop

Task 3

Open VectorSor t

You will see three TODO sections in the code which need completing

1 Populate a vector with 100 randomly generated numbers

2 Sort the vector

3 Reverse the vector

For sortingreversing you will can use the algorithms sort() and reverse()

Heres a useful link hellip

httpwwwcpluspluscomreferencealgorithm

103

Using insert() and iterators

Task 1

Open and modify the skeleton project called Inser t

Important areas of the program are explained in the steps opposite

Examine the code

vectorltintgtiterator it

This statement creates an iterator that is used to access members of the vector

Iterators are used to access members of the container classes (the container type vector in this case) and can be used in a similar manner to pointers

In the example iterator it is used with the insert() function to place the value (200) at the beginning of the vector nums

it = numsbegin()

This statement uses the vector member function begin() to initialise the iterator it with the address of the start of the vector

it = numsinsert(it 200)

This statement uses the member function insert() and iterator it to insert 200 at the beginning of the vector (it)

Note that an iterator is returned by the function insert() that points to the newly inserted element

104

numsinsert(it + 1 numsTwobegin()

numsTwoend())

This version of the insert() function takes 3 arguments and is used for copying in part or full another collection This may be a vector a plain C++ array or some other collection that is accessed using pointersiterators

This statement inserts a second vector (numsTwo) into nums The three parameters are (copy to nums+1 from star t of numsTwo to end of numsTwo)

it = numsinsert(it + 2 696 )

This version of the insert() function takes 2 arguments The iterator it + 2 points to element number three it points to the beginning of the vector and the 2 moves two elements in The value 696 is inserted at that element

void display(vectorltintgt amp vec)

cout ltlt Vector contains

for(

unsigned int i = 0

i lt vecsize()

++i

)

cout ltlt vecat(i) ltlt

Function display() is passed a reference to a vector and outputs the vector contents used throughout program

105

Task 2

Add the code shown in Figure 27 to the program and using the insert() member function add the array to the nums vector at position two (in the vector) Output the contents of the nums vector to screen

int myArray[] = 5 6 3 4

Figure 27

stdarray

C++11 Introduced a new template array type called stdarray

stdvector is a template class that encapsulates a dynamic array that is stored on the heap and that grows and shrinks automatically if elements are added or removed It provides all the hooks (begin() end() i terators etc) that make it work fine with the rest of the STL It also has several useful methods that let you perform operations that on a normal array would be cumbersome like inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes) Since it stores the elements in memory allocated on the heap it has some overhead in respect to static arrays

stdarray is a template class that encapsulates a static array that is stored inside the object itself which means that if you instantiate the class on the stack the static array will be on the stack Its size has to be known at compile time (it is passed as a template parameter) and it cannot grow or shrink

It is more limited than stdvector but it is often more efficient especially for small sizes because in practice it is mostly a lightweight wrapper around a C-style array However it is more secure since the implicit conversion to a pointer is disabled and it provides much of the STL-related functionality of stdvector and of the other containers so you can use it easily with STL algor i thms

Here is a small example demonstrating the template and some other C++11 extras such as auto and a ranged-based for loop

106

include ltstringgt include ltiteratorgt include ltiostreamgt include ltarraygt using namespace std template ltsize_t N class Tgt arrayltT Ngt make_array(const T amp v) arrayltT Ngt ret retfill(v) return ret int main() The char here can be inferred and so is optional auto a = make_arraylt10 chargt(1) for (const auto amp s a) stdcout ltlt s ltlt system(pause) return 0

1 1 1 1 1 1 1 1 1 1 Press any key to continue

Declaring and using lists

Lists are a kind of sequence container similar to vectors The elements of a list are ordered following a linear sequence with storage handled automatically by the class

List containers are implemented as doubly-linked lists and it is worth noting that elements may be in different and unrelated storage locations

Ordering of a list is kept by a relationship to each element of a link to the element preceding it and a link to the element following it

Because linking information is associated with each element (possibly to different and unrelated storage locations) extra memory may be used to keep the linking This may be important when using a large list

l is ts tend to perform better than vectors at inserting extracting and moving elements in any position within the container but lack direct access to the elements by their position and because of this have a slower access time than vectors Access to an element has to be via a known position (the beginning or the end) and there is a time cost in linking between the known position and the element to be accessed

107

lists are declared indicating the type and number of elements in the following way

listlttypegt listName

listlttypegt listName(initialSize)

listlttypegt listName(initialSize elementValues)

Examples

A list called inNumbers with no initial size to hold doubles

listltdoublegt inNumbers

A list called Name with an initial size 20 to hold characters

listltchargt Name(20)

A list called ExamMarks holding integers with initial size of 4 elements each with the value 6

listltintgt ExamMarks(46)

72 Hash Tables and Cached Calculations

This section has ultimately really been about introducing you to templates and algorithms and well mix both now in a final example

From the binary chop exercise earlier we have seen that sorted arrays provide a very efficient means of storing data for later look-up However we have to bear in mind the algorithmic cost of sorting the array in the first place ie if we have a million unsorted items in our list and we want to find a single item (only) is it better to sort the entire list first and then find the item or is it better to simply walk through the array from the beginning ndash after all we could safely assume that weve a 5050 chance of finding it in the first half of the array Of course as were sorting we could keep an eye open for our item ie we could combine a (partial) sort with look-up operation ndash over time if we repeat this procedure looking for other items we will ultimately sort our array as a side -effect of the look-up operations

But lets move on a little and just consider the fastest look-up method we know so far that carried out on a sorted array using binary chop and think about our programs overall performance when we need to insert additional items into the array When considering problems like this we always think of the worst case hellip despite their often being fans of

108

Monty Python Computer Scientists rarely look on the bright side of life The worst case here is that we need to insert an item into array position zero

Eg say we have this sorted array (look-up operations average O log2 N = fast)

15 24 25 31 78 250 255 262 277

We now have to insert the value 5 into this array Using normal array indexing methods how many operations will this take

5 15 24 25 31 78 250 255 262 277

Each item needs to be shuffled up one position to the right and if weve millions of items that is rather costly especially if the next thing were likely to do is to insert another item

So weve seen that accessing sorted data is very useful and weve also seen that sorting and especially inserting items can be costly The big question is then is there a way we can make both just as efficient - finding andor inserting an item in Olog2N or O(1) (constant time)

Hash Tables

A hash-table is a data structure designed to allow for both rapid insertion and look-up

Although any specific hash-table is implementation specific (there are very many different types of hash-table) well quickly go through the basics

The storage medium well use for our hash-table is an array of strings and we will say that this array has just 10 elements It looks like this

string myhash[10]

Well use this hash-table to store words and well determine the array index for any specific word using a hash- funct ion ndash something that will take a word as its input and return an array index as its output

109

unsigned hashfunc(string s)

unsigned result = 0

for(unsigned i = 0 i lt slength() ++i)

result = result + s[i]

return result 10

hashfunc() iterates through s keeping a running total of the sum of the ASCII codes for each of the characters eg hashfunc(hash-table) computes

h + a + s + h + - + t + a + b + l + e

where the characters ASCII values are

104 + 97 + 115 + 104 + 45 + 116 + 97 + 98 + 108 + 101

The total = 985 and 985 modulus 10 = 5

The final computed value will be used as an index into the array The modulus value used is the size of the hash-table and we use it so as to ensure that resultant computed index value cannot be greater than 9 (remember our arrays indexes are 0 ndash 9)

We can now store words in the myhash array like this

string myhash[10]

string s = hash-table

index = hashfunc(s)

if(myhash[index] = )

myhash[index] = s

else

The complex part is what to do if we have what is called a collision ndash when we find that myhash[index] is already occupied Youll probably have already thought of what value hashfunc(elbat-hsah) will have

One way to help avoid collisions to use a better hash-function and a larger array However in real life collisions are practically impossible to avoid and the only other option to deal with them is to allow more than one string to inhabit an array slot in some way ndash perhaps by having each of the original array slots contain an array ndash rather than an individual string Of course in this case we would also need some way to determine which of the n colliding entries is the one were interested in ndash is it elbat-hsah or hash-table

110

Well briefly leave our examination of hash-tables at this point and instead look at Fibonacci numbers Do not worry we will return to hash-tables very soon

Fibonacci numbers are the numbers in the following integer sequence

0 1 1 2 3 5 8 13 21 34 55 89

By definition the first two numbers in the Fibonacci sequence are 0 and 1 and each subsequent number is the sum of the previous two More formally that is

119865119899 ∶= 119865(119899) ∶=

0 119894119891 119899 = 0 1 119894119891 119899 = 1

119865(119899 minus 1) + 119865 (119899 minus 2) 119894119891 119899 gt 1

Computing Fibonacci Numbers

Task 1

Open Cached_fibonacci

Compile and run the program as is

Examine main() and the calcfib() functions

bigint calcfib(bigint n)

if(n == 1 || n == 0)

return n

else

return calcfib(n - 1) + calcfib(n - 2)

bigint is defined as a unsigned long long int and we have used typedef to save some typing

NOTE The method used to calculate Fibonacci numbers here has been selected because it is perhaps the most obvious way to turn the formal definition into code If you are interested please see the separate Fibonacci project for two other examples of how to calculate Fibonacci numbers

111

Modify the beginning of the calcfib() code

bigint calcfib(bigint n) cout ltlt calcfib was passed ltlt n ltlt endl

Modify main() to set max = 5 and re-run the program

calcfib was passed 0 Fibonacci number 0 is 0 calcfib was passed 1 Fibonacci number 1 is 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 2 is 1 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 Fibonacci number 3 is 2 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 4 is 3 calcfib was passed 5 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1

Fibonacci number 5 is 5

112

Note that to calculate Fibonacci number 5 we calculate Fibonacci number 4 and Fibonacci number 3 - even though weve previously calculated Fibonacci number 3 in order to calculate Fibonacci number 4

To fully appreciate the growth of this process re-run the program adding 10 to max for each subsequent run You maymay not like to comment out the line you inserted in Step 2

Task 2

Getting back to Hash Tables Using a hash-table to store previously computed Fibonacci numbers

As it stands the incomplete solution declares a template hash-table called fibs of the type unordered_map

Read the comments in the function fibCache() and modify the code to as to use the fibs hash-table to store previously computed Fibonacci numbers

fibs[n] = f stores f the n-th Fibonacci number in the n-th slot of fibs (which as you can see you may treat as an array for indexing into)

8 Pointers In C++ programming data (variables) can be referenced via the memory address of the variable This is done using a pointer var iable

A pointer var iable contains the address (location in memory) of a data variable

There are also functional pointers ie those that point to code rather than data and these are briefly explored later

Pointers can be particularly useful when interacting with the operating system andor when working with arrays - as the elements in an array will always occupy consecutive memory places Incrementing the pointer variable by one addresses the next array element

Lastly pointers are also used to fake pass by reference

Declarat ions

int n This is a standard variable declaration n that contains a value as yet unknown of type int

int p This is a pointer p that can hold (point to) an address that contains a variable of type int The type of p is int

Each variable declared as a pointer must be preceded by an asterisk () This modifies the type of the object being declared from thing of type to pointer to thing of type Eg int n means n is an int whereas int n says that n is a pointer to an int

113

int age height age is a pointer to an int height is an int value

double far cent are both pointers to doubles

Pointers can be initialised when they are declared or set using an assignment It is common to initialise pointers to a memory address but they can also be initialised to the predefined constant NULL ndash meaning that they do not (as yet) hold (point to) a valid memory location NULL is defined in the standard library such a pointer is called a nul l pointer

When is used in a variable declaration it indicates the variable being declared is a pointer and not a value

But do beware as is used elsewhere with pointers when the appears before a previously declared pointer variable elsewhere in the program it is said to dereference the pointer and so is used to access data stored at the address which is stored in the pointer A dereferenced pointer is essentially the variable to which the pointer was originally set to point

To complicate matters further using the pointer name without the dereference operator references whatever is stored in the pointer variable itself ndash this is the address of the object it references in memory (which maybe NULL of course)

As we have seen using can mean two things that something is being declared as a pointer or that a previously declared pointer is being dereferenced Experienced programmers sometimes enter the two usages differently ndash a notation we would highly recommend ie

int n n is an object that can hold the address of an int

int k = 0 k is an int holding the value zero

n = ampk n is set to hold ks address amp is explained below

n = 1 k (yes k) is set to hold the value 1

Note the space used in the different usages - int n vs no space in n

Initialising pointers

Pointers can be initialised in two ways

int x = 16 y = 69 variable declaration and initialisation int x_ptr = ampx pointer declaration and initialisation x_ptr holds the address of x int y_ptr pointer declaration yptr is a pointer

y_ptr = ampy pointer assignment yptr holds the address of y

Once declared a pointer variable can be assigned the address of another variable using the amp the addressof operator

114

Note the variable name should not be prefixed by the in the assignment statement unless the pointer is initialised immediately in the variable declaration

We also use pointers when creating objects on the Heap for example we can create and initialise a string object like this string pstring = new string(Hi there) Such objects are not normally tidied away as are the objects created on the stack - objects simply declared in a functionmethod and so they should explicitly be tidied away using delete eg delete pstring For more on this subject see section 9

Using pointers

Task 1

Open the project Pointers

Compile and run the program The output should be as shown in Figure 28

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int x_ptr = ampx This is x_ptr pointer declaration and initialisation

int y_ptr Declaring another pointer y_ptr

y_ptr = ampy Initialising y_ptr

y_ptr = x_ptr Assigning x_ptr contents to y_ptr Both pointers are pointing to variable x (16)

y_ptr = ampy Assigning the address of y back to pointer y_ptr

y_ptr = 170 Assign 170 to the variable at memory location of y_ptr y_ptr points to variable y so 170 has been assigned to y

115

Figure 28

Pointer Arithmetic and Arrays

We have seen that once a pointer is initialised it has a memory address and this address can be reassigned another address It is also possible to change an address using standard arithmetic

The ++ and -- increment and decrement operators can be used to move the pointer along to the next or back to the previous memory address To jump more than one memory address you would have to use the assignment operators += and -=

When using arrays and pointers the array name is the address of the first element in the array

int intArray[] = 1 2 3 4 5

int int_ptr = intArray Same as int int_ptr = ampintArray[0]

The pointer has been declared and initialised with the statement int int_ptr =

intArray Note there is no need to use the address of operator amp when initialising arrays as the array name is the address of the beginning of the array

When working with arrays each element of the array will be the type and size at declaration When an array is declared to hold integers each element will usually be 4 bytes in size An array of doubles will have element sizes of 8 bytes Note ndash these sizes are actually down to the compiler being used and are usually in turn dependent upon the operating system being used

It is not important to know how many bytes make up each element Moving the pointer through the array with the assignment operator x_ptr += 2 will move two elements further through the memory allocated for the array or 16 bytes for an array of doubles

116

Pointers and Arrays

Task 1

Open the project PointerAr i thmetic

Compile and run the program The output should be the same as Figure 29

Examine the program carefully

You may not fully follow the program at first glance as it employees a few potentially new constructs (it depends how far weve got through the lectures)

One slightly truncated new construct is

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

A struct in C++ is just like a class except that the default public and private sections are reversed By default everything in a struct is public

typedef in C++ allows the definition of our own types based on other existing data types

typedef exist ing_type new_type_name

where exist ing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining For example

117

typedef unsigned int WORD

typedef char pChar

You may also remember initialiser lists from earlier eg

s_thing(int a) a(a) b(sqrt((double)a))

If we re-write this

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

We quickly see that a(a) and b() are initialising the a and b struct members const int a and const double b

118

Remember that as these are const we cannot use assignment

typedef struct s_thing

const int a

const double b

s_thing(int a)

Error ndash a and b are const

this -gt a = a

this -gt b = sqrt(a)

thing

Lastly when dealing with pointers to compound types one may access the members of the type via dereferencing or via the so called crows foot operator

(t) dereferences t giving us a thing which was pointed to by t Then we use the dot operator to access the member (t)a

We have to parenthesiset otherwise the would bind to t first ie it would be as though we had done this (ta) which would be an error

The crows foot saves us the dereference t-gta is just like (t)a

119

Figure 29

PLUSPLUS Pointers and Arrays

Task 1

Open and modify the skeleton project called ReverseArray

In main() create an array of 10 integers Fill the array with random numbers between 0 ndash 100

Write a helper function called to output the contents of the array to the console A suitable prototype for this would be void dumpArray(int array[] int size)

Write a helper function to reverse the contents of the array Use a temporary variable as an aid A suitable prototype for this function would be void reverseArray(int array[] int size)

Reverse the values in the array using only pointers

120

Reverse the array without using a temporary variable You should use the XOR operator ^ to achieve this

Pseudo code for an XOR swap is

X = X XOR Y

Y = X XOR Y

X = X XOR Y

The completed program should look like Figure 30

Figure 30

Task 2

Reverse the array using a vector and the standard function template stdreverse()

We can also have pointers to functions in C++ (and C)

The name of a function resolves to be its address in memory (somewhat similar to the case where we use the name of an array) When we call a function we use this name to retrieve the functions address and then use the function invocation operator to execute it The function invocation operator is the set of brackets you use eg

Lets take an example

121

include ltiostreamgt

using namespace std

int lue() life the universe and everything

return 42

int main()

cout ltlt The address of the function lue is

ltlt lue

ltlt invoking it yields

ltlt lue()

ltlt endl

system(pause)

return 0

Typical output is shown in Figure 31

Figure 31

122

We can also store addresses of functions in variables (theyre just numbers) and the type system allows for us to describe and declare scalar variable types for function pointers eg this modified code fragment would produce the same output as that show above

fp is a pointer to a function taking

no arguments and returning an int

int (fp)()

fp = lue

cout ltlt The address of the function lue is

ltlt fp

ltlt invoking it yields

ltlt fp()

ltlt endl

fp is a funct ion pointer var iable so it may be used to point to any other function having the correct signature at runtime

PLUSPLUS Function pointers

Task 1

Open the project Calculator

Compile and run the program The output should be as shown in Figure 32

123

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int (fp)(int int) This is the function pointer declaration It may point to functions that take two integers and return an integer

Like all automatic storage class variables fp will currently be pointing at a random location What happens if you run the program without setting fp to point to an actual function Comment out the switch to find out

switch (Operator)

case 0 fp = Add break

case 1 fp = Subtract break

case 2 fp = Multiply break

The code could do with improving

Modify it to allow for multiple trials eg add the necessary logic to loop and perform multiple calculations ndash youll need to add some way to end the program too therefore

Modify it so that the operator may be inputted as an operator character eg + - etc Allow X x and for multiplication and add for division

All three pieces of information could be entered on a single line eg 6 x 7ltentergt Using cin to read that data just requires you to use three cin statements

cin gtgt X

cin gtgt Operator

cin gtgt Y

Lastly modify the program to that it uses floating point arithmetic

124

Figure 32

9 APIs New Delete and Dynamic Memory As has been stated earlier pointers are useful in a variety of situations However because they are easy to get wrong ndash and when they go wrong everything goes very wrong indeed ndash languages like C++ have tried to make their use the exception rather than the norm For example without reference arguments (eg void someFunc(int amp)) we would have to use pointers to achieve the same functionality and performance

On the whole the underlying philosophy when it comes to pointers is to try to avoid using them whenever possible You can get a real feel for this subject by Googling for smart pointers c++ and from Wikipedia httpenwikipediaorgwikiSmart_pointer

Two areas where we absolutely need pointers are when calling into an external API (Appl icat ion Programming Interface ) and when allocating memory for our own purposes ndash the latter case is also eased by advances in the library support in C++

Using an API

An Appl icat ion Programming Inter face is functionality provided by some third party The most obvious API whether it is Windows Linux or OSX is that exposed by an operating system

If your application needs to interact with the user in any non-portable way you will need to call into your OSs API For example if you want to display a dialog box you will need to access the OSs functionality to do so (perhaps indirectly through a framework like Nokias Qt - httpsenwikipediaorgwikiQt_(framework)) In summary if you ever want to go outside of the standard libraries andor writing consoleterminal applications you will need to call into your operating systems API

When it comes to calling into operating systems pointers are used extensively As an example 1 Google for Linux API 2 Find any website that lists the API functions and then 3 click-through to any function The odds are that the function prototype you see will contain asterisks (pointers)

125

Dynamic Memory Management

The second area where you simply must know something about pointers is when it comes to using the heap

The heap is an area of memory available to your programs You may allocate and use the heap as you wish

Why would you want to do this Normally its to create variable length arrays or to model and use an advanced data structure of some sort a self-balancing red black tree perhaps (httpenwikipediaorgwikiRedAndblack_tree) Of course the more esoteric the data structure and less likely it is that it will be incorporated into the C++ standard library (although the library does contain most of the generally useful and popular ones like doubly l inked l is ts )

To allocate memory from the heap in C++ you use the new keyword and to return it you use the delete eg

int nSize = 12

note nSize does not need to be constant

int pArray = new int[nSize]

pArray[4] = 7

delete [] pArray

10 More on Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine Encapsulation is data information or detail hiding

Once a function is written the detail of how it works is not important to the end user The user needs to understand what data to input and what output will be produced

One of the most important aspects of writing programs using functions is that the functions can be reused from one project to the next Think about the standard functions youve seen already eg the square root function sqrt() Libraries contain atomic generally useful functionality that is likely to be of use at some future time It is useful to bear this thought in mind whenever we build new programs ie we should be on the lookout for generally useful functionality (given our domain) that we should consider coding as functions for later reuse The same goes for classes of course

Probably the most important function in your program in main() ndash without it you do not have a program at all

main() is your programs entry point and as such it may be used in such a way as to inform the rest of your program as to the actions required

126

main() and command-line arguments

Task 1

Open a Command Prompt or PowerShell Prompt and enter the following

dirltreturngt

di r Odltreturngt

t ree ltreturngt

t ree altreturngt

dir and t ree etc are like mini-programs They have default functionality which may be altered by providing additional command-line arguments eg for the dir command dir L N 4 TC

Command-line arguments are passed to your programs by optional parameters eg

int main(int argc char argv[])

Where argc is a count of the number of arguments and argv is an array of pointers to arrays of character (C strings) for each argument being passed Note that argc is always at least 1 and so argv always contains at least one entry ndash this is the name of the program being run

Task 2

Open (demonstrat ion)

CommandLineArgs and Build and run the program

Examine the code

The programs configuration is Debug

In the projects Project | Debugging | Command

Arguments you will see where the programs default command-line arguments are set for debugging purposes

Using the command prompt you opened earlier navigate to your where CommandLineArgsexe is located

CommandLineArgs debug

Run the program by entering its name followed by a variety of arguments eg

gtCommandLineAgs one two threelte ntergt

127

Task 3

Open the project UserPrompter project

Run the program and then examine its code

We will modify this program to use a command-line argument However before doing that its worth pointing out that the primary purpose of this program is to demonstrate the separation of a class declarat ion with its implementat ion (the mechanismfunctionality of class prompter is defined in promptercpp but its capabilities are declared in prompter h )

Its also interesting to note that the optimal strategy is to use an algorithm called binary search or binary chop (we saw this earlier in the course) with each guess you reduce the number of possible solutions by a half This sort of algorithms Big Oh is Log n (where log is base-two logs)

httpenwikipediaorgwikiBig_O_notation

Task 4

Modify the program so that the upper range for the max value is given as a command-line argument

The UserPrompter cpp is the file youll need to modify

Test your program via the setting the projects Command Arguments as detailed above -or- by running the application standalone in a command prompt after building (also as detailed above)

See Figure 33

To convert a string into a number (weve seen one other way of doing this earlier) we can use

include ltcstdlibgt

and the function atoi() eg

atoi(argv[1])

128

Figure 33

EncryptDecrypt a file

Task 1

Open compile and run the EncodeDecode project

Complete the program so that it may be run outside of the IDE and process a file for encryptiondecryption

This is actually quite a simple task as youll only need to add a couple of lines of code However the project also demonstrates how to use the Debug and Release modes to influence the way a program runs ie that in its Debug configuration the program automatically runs through a test

Other things to note include using bitwise XOr to perform the encoding and the use of the C standard library functions putchar() and printf() to perform some of the output eg putchar() is used to output a CR to the console window (CR = char 13)

129

Figure 34

Multiple arguments overloading and default values

In C++ we can over load functions ndash meaning that we can provide different versions of the same function (the different versions must differ by the number andor type of the parameters they take) For example

130

void foo(double d) 1

cout ltlt In void foo(double d)nn

void foo(long int n) 2

cout ltlt In void foo(long int n)nn

void foo(int n) 3

cout ltlt In void foo(int n)nn

double dtest = 0

long int ltest = 0

int ntest = 0

foo(dtest) Calls 1

foo(ltest) Calls 2

foo(ntest) Calls 3

In the above the compiler works out which version of the foo() to call based upon the argument type it is given

We can also overload functions if the number of arguments differ eg

131

void bar(double d)

void bar(double d double t)

We would use a feature like this if sometimes we needed to use extra information ndash in the shape of passing in t in the above eg we would most likely implement void bar(double d) as

void bar(double d)

bar(d 25) Call bar(double d double t)

What were really saying above is that in most cases the implicit double second parameters value is normally 25 ndash perhaps its a standard discount percentage ndash and only occasionally we will need to change that value in which case wed call bar(double d double t) directly and not by going through bar(double d)

Lastly C++ has one extra feature that can make this simpler ndash defaul t arguments

Rewriting bar using this feature we get

void bar(double d double t = 25)

Note that we now only have one bar function now and that we may call it like this

bar(x)

Or like this

132

bar(x y)

In the case of bar(x) the second parameter is omitted and so will receive the default value of 25 in the second example t will receive ys value

Although outside the scope of this class for more on overloading see the (demonstrat ion) Operator Over loading project This shows how to overload the ++ pre and post increment operators overload and provide your own ltlt stream insertion operator (and one use of a friend function) and using an enum with a typedef

Passing Arrays to Functions

To pass an array to a function it is only necessary to pass the array name and the number of elements in the array

The array name is the position (address) in memory of the first element The number of elements is passed to enable the function to establish the array size

An array declared as double somearray[10] would require a function call somefunction(somearray 10)

Passing Arrays to functions

Task 1

Open and modify the skeleton project called the project called ArrayReturnValue

Pass an array to a function to read in five numbers

Pass the array to another function to calculate the average value in the array return this to main() and output to screen

Lastly at the end of the program output the values in the array from within main() The finished program should look something that that in Figure 35

Create two function prototypes

void enterMarks(double ExamMarks[] int num)

double calcAverage(double ExamMarks[] int num)

ExamMarks[] is the array to be passed As with passing variables it is not strictly necessary to give the argument a name in the prototype just its type This could have been written as calcAverage(double [] int) However it is sometimes useful to include this information as it might help explain the functions operation

It is also necessary to pass the size of the array num is the number of elements in the array its size

Within main() declare the array and initialise the elements to zero with the following statement double ExamMarks[5] = 0

This declaration explicitly initialises the first element to zero and implicitly initialises the remaining four to zero

133

Create both functions

enterMarks to read in the values and calcAverage to calculate the average (you will need a for loop in each function)

Return the average value from calcAverage to main() and output the value using cout

Call the functions from within main() with the following statements

enterMarks(ExamMarks 5)

average = calcAverage(ExamMarks 5)

You may output the average directly of course ie without first storing the value in average

At the end of main() add the statements

for(int i = 0 i lt 5 ++i)

cout ltlt Exam Mark Number

ltlt i + 1

ltlt is

ltlt ExamMarks[i]

ltlt endl

ltlt endl

134

Explain how it is possible at the end of the program to output from within main() all the values in the array entered within the function

Modify the program so that the number of exam marks (5) appears only once

In previous exercises when parameters (variables) were passed to functions the function received a value When a value is used in a function a copy is stored in a part of memory that only exists from the time the function is called to when it ends After this the memory and any value in it are lost

However the array in this exercise was initialised in main() with zeros and then passed to the function Data was then added to the array and calculations done At the end of main() the values in the array elements are output The array contains values input from within the function

The name of the array is the address of the first element of the array in the machines memory As the starting address is passed (the name of the array) the called function knows where the array is stored in memory

Because we are working with memory addresses (references ) any changes made to array elements in the function affect the memory location set up in main() for the array

C++ passes arrays to functions by reference (to the memory location of the first element) In previous exercises functions were passed values copies of the variables in main()

135

Figure 35

Passing Two-dimensional Arrays to Functions

It is common to want to store numbers in a two dimensional layout of rows and columns as shown in Table 7

187645 783473 298372

871223 629399 561201

Table 7

This arrangement is known as a two-dimensional array or matrix

C++ uses an array with two subscripts to store a two dimensional array

double Balance[2][3]

When we specify a one-dimensional array the number of elements must be given

When a two-dimensional array is specified it is necessary to specify the array elements in both dimensions We therefore specify the number of rows and columns

The Balance array in the statement above has two rows and three columns

11 Inheritance and (not presented) Polymorphism

111 Inheritance

In Object Oriented languages like C++ inheritance describes a relationship between classes of objects and which usually implies some sort of a sub-division of labour

For example lets say that we want to build an IT system that has something to do with the members of the university

136

In an OO world the first question usually is how would we categorise our significant entities and that always means naming things what names would we use to categorise university members When modelling (for that is what were going to be doing) real-world objects its sensible to use proper names So heres an attempt ndash to broadly categorise university membership

Members are members of the sets

Students

Staff

Other

What is other though

The Bodleian and the card-office issue Readers cards ndash so is a Reader a university members or are they something else And if they are something else does our system really want to concern itself them Or more broadly does our system really want to concern itself with holders of cards issued by the card-office

Are all students really the same

What sort of students do we have at Oxford (and do we want a system ndash either now or in the future ndash that might be interested in recording the differences) Lets see we have undergraduates and graduates We also have Rhodes scholars ndash but are these sorts of student that are distinct (or should be in our system) from our underpost-graduates categories And how about graduates would we want to have some sort of sub-groups Masters students MScMBAMPhil or Doctoral students DPhilDScDLitt etc Perhaps wed like to know something about how theyre being funded ndash and we might want that piece of functionality shared by our undergraduates

We can of course go through the same process when thinking about members of staff (university staff departmental staff members of congregation academic staff fulltimepart-time staff casual staff ndash and how about staff that are sometimes (or also) students) We can go on thinking about this sort of thing for a very long time and we should as its important and when its important it has a name ndash Object Oriented Design or OOD

One of the things wed hope to see appear as part of the OOD phase is the relationship between entities For example if we were to say that a common property of all university members is that they have a date-of-birth we wouldnt want to have our Student and Staff C++ objects contain this information directly by way of some datastate class member (which might seem a little odd at first) But think about it If we performed some validation on the members DoB (perhaps when its being set) we would need to include this in both Student and Staff classes Or as an alternative we would capture the validation in some external function ndash which we would call from the separate classes (if we remember) No its messy and it would be much better if we thought of things this way that all university members are people and that people all have dates of birth

To put it another way we would say that studentsstaffother are just specialisations of people ndash they are people but with a bit of extra something tagged on to them ndash like a bod card number

Now if we also had some way of capturing people stuff in say a basic Person class and could somehow use that automatically ndash perhaps by deriving a Member class from it and then doing the same from Member to both Staff and Student classes from Member One thing though ndash we wouldnt want someone to be able to instantiate a Member object

137

perhaps ie in our system Member is an abstract class Imagine a generic Car vs a Renault Clio ndash it makes no sense to create a Car object ndash there are no generic cars on the road they are all specific cars Similarly we wouldnt want a generic Member wandering around our system (if you remain unconvinced well see why later)

Modelling a student - a first attempt

Please note that in this Introduction to C++ we do not expect you to complete an exercise that requires coding from now on Please just look through the code and follow along with the discussion

Base classes

Task 1

Open the project UnivMember1

Examine the program carefully

The project contains three classes Person Member Student In main() we create a Student and then attempt to output the students name ndash which fails

name is in the protected section of Person ndash which means only Person methods or methods in derived-from-Person classes can access it

Add a public section to the Person class and relocate the name there

Eg

public

string name

Any better now

The problem now is that Student only by default inherits the private side of Person

Change class Student so that we also inherit the public members of Person hellip

class Student public Person

138

Before we tackle further problems with name lets bring in the Member class (left doing nothing until now)

We really want Student to inherit from Member and not Person Change the code to reflect this

People have dates-of-birth and Members have bod cards Add a string member dateOfBirth to Person and move the bodCardNumber member out of Student and into Member ndash make them both strings

Change the code in main() to set these extra pieces of data

If you havent done it already Persons dateOfBirth and Members bodCardNumber should be set via constructors

139

Task 2

Open and examine the project called UnivMember2

UnivMember2 is a copy of the (exercise solut ion)

UnivMember1 solution

One of the problems we have in UnivMember1 is that too much of it is public eg given Student object s we can change name to simply by using assignment eg sname =

We should protect data members at each level using the maximum level of protection we can ie private

However if we do that then cout ltlt sname will no longer work and so well need to provide access methods to the data members Eg heres a modified Member class showing the basic scheme

class Member public Person

public

Member(string bodCardNumber)

this-gtbodCardNumber = bodCardNumber

string getBodCardNumber() For access

return bodCardNumber

private

string bodCardNumber

140

Another problem is that wed really like to not use assignment at all Eg in the above ctor snippet

this -gt bodCardNumber = bodCardNumber

is using assignment

Change string bodCardNumber to const string bodCardNumber Youll see now that assignment wont now work (you have to initialise constants)

What wed really like (most likely) is to use in i t ial isat ion

We can do this via initialiser lists Ie we could change the above to the following

class Member public Person

public

Member(string bodCardNumber)

bodCardNumber(bodCardNumber)

const string getBodCardNumber()

return bodCardNumber

private

const string bodCardNumber

The initialiser list is read thus

bodCardNumber(bodCardNumber)

^^member^^ ^^parameter^^

Note that weve also modified getBodCardNumber() to show that it returns a const string

141

Modify all three classes to use initialiser lists private const data members and use access functions (getBlah() etc)

Task 3

Open and examine the project called UnivMember3

UnivMember3 is a copy of the (exercise solut ion)

UnivMember2 solution

We will now finish this project to the level of an introductory course

Things to note

The main problem with the solution as it stands is that one may create a Member object

Remember that this is analogous to being able to create a generic Car object ndash we should not be allowed to create one

Going right back to UnivMember1 you may remember a comment in there about a protected constructor

protected Protected ctor Person()

At that point in your project we were thinking two things 1) we wont want to create a generic person and 2) a protected constructor will facilitate this

And we were wrong to think both thoughts

1) A properly thought through Person class would be perfectly good to model generic people But although this is true one question here ndash would we ever want just a generic person

2) A protected constructor in a (more) base class doesnt prevent a derived class from creating a base object So what about the Member class ndash would it be ok to instantiate that

The proper means to prevent a Member being created would be to use what is called a pure v i r tual funct ion as part of its definition (such a function is one that must be overridden in a derived class) But what function

142

If you look at the classes derived from Member ndash you can take it from us that one might want to interrogate at runtime ndash to ask them what they are

So a suitable member function to declare in Member would be something like string getRole() A function that does return Student for a student and return Staff for a Staff object

If its pure virtual in in Member wed best define it in our derived classes

class Member public Person

public

virtual const string getRole() = 0

class Student public Member

public

const string getRole() return Student

143

1 Why did we want duplicate (named) functions in Member Student and Staff 2 And what does virtual really mean

We require both 1 and 2 so that we can provide specific responses when being asked the same question and all when being treated in a rather basic way

Being asked the same question means having a method invoked eg getRole() and in a rather basic way means treating us all Students and Staff (etc) as Persons and Members

112 Polymorphism

Polymorphism comes in a few forms

Ad-hoc Polymorphism via function overloading

Parametric Polymorphism or Compile-Time Polymorphism via templates

Subtype Polymorphism or Runtime Polymorphism via virtual functions and

Coercion Polymorphism via casting

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class (after all a derived from base must have or contain all that a base has) Polymorphism is the art of taking advantage of this simple but powerful and versatile feature

One way Subtype Polymorphism is applied is to use a base reference to access a collection of instances of different types that are derived from a common base ndash one way to paraphrase that is to say that related (derived from a common class) objects respond according to their type rather than according to the type of the reference one uses to access them (a base class pointer type) That is the dynamic type of the object is used instead of its static type

All of this is best demonstrated via an example of course

144

PLUSPLUS Polymorphism

Task 1

Open and examine the project called (exercise

solut ion) UnivMember3

Run the program the output should be the same as shown in Figure 36

The crucial code here is as follows

Member arr[6]

Student studs1()

Student studs2()

Staff staff1()

Student studs3()

Staff staff2()

Student studs4()

arr[0] = ampstuds1

arr[1] = ampstaff1

arr[2] = ampstuds2

arr[3] = ampstaff2

arr[4] = ampstuds3

arr[5] = ampstuds4

for(int i = 0 i lt ++i)

cout ltlt arr[i]

ltlt i ltlt s name is

ltlt arr[i]-gtgetName()

ltlt t Their role is

ltlt arr[i]-gtgetRole()

ltlt endl

Weve created an array of Members (it isnt important that weve used pointers) and note that we have set some of the members of this to be pointers to Student and Staff objects We are allowed to do this as both Student and Staff are derived from Member

However when and if we invoke member functions on these objects wed really like it if they responded as what they really are ndash Student and Staff objects

145

From the output below you can see that they indeed do respond accordingly

Figure 36

The mechanism behind allowing this is the virtualisation of the getRole() member function Remember that this was declared and made virtual in the Member class

Play about with the code eg change

Member arr[6] to Person arr[6] Everything still ok How about not using pointers here ndash easy to do

146

Lastly weve implemented (for no good reason but to show you how its done) some instance counting in all three classes Have a look for the static members and the inserted lines immediately below the class definitions that look like this int PersonCount = 0

The End Thank you for coming and we hope that you enjoyed the class

Oh and please Please PLEASE fill out the feedback form email when it arrives

147

12 Appendices

Arithmetical Operators

Operator Operation

+ Addition

- Subtraction

Multiplication

Division

Modulus

++ Increment

-- Decrement

Table 8 ndash Arithmetical Operators

Assignment Operators

Operator Example Equivalent

= a = b a = b

+= a += b a = a + b

-= a -= b a = a - b

= a = b a = a b

= a = b a = a b

= a = b a = a b

Table 9 ndash Assignment Operators

148

Assignment and Arithmetic examples

The assignment operator in C++ is =

The format is var iable = expression this can be read as assign to the var iable the value of the expression

An example to calculate the number of pence in a value in pounds would be

pence = pounds 100

Note it is easy to confuse the assignment operator = with the equals notation used in mathematics The equals notation in C++ is ==

Incrementing a var iable

month = month + 1 adds the value one to the variable month This can be written as

month++

Decrementing a var iable

month = month - 1 deducts the value one from the variable month This can be written as month--

Note that ++ and ndash can be used before or after the thing being modified eg ++x x++ --y y-- However there are some subtle differences which will be explained in the lectures

In C++ it is also possible to combine arithmetic and assignment operations

To add 2 to a variable total

total = total + 2 or total +=2

To subtract 2 from to tal

total = total - 2 or total -=2

To multiply total by 2

total = total 2 or total =2

Relational and Equality Operators

The equality operator is used to compare two operands (a == b) and returns 1 (t rue) if both are equal otherwise 0 (false ) is returned

The inequality operator (=) returns 1 (t rue) if both are NOT equal otherwise 0 (false) is returned

Both the above operators are commonly used to test the state of two variables to perform conditional branching

The relational operators also return either true or false (a gt= b) returns 1 (t rue ) if a is greater than or equal to b otherwise 0 (false ) is returned

149

Standard algebraic equality or relational

operator

C++ equality or relational operator

Sample C++ condition

Meaning of C++ condition

Relational operators

gt gt a gt b a is greater than b

lt lt a lt b a is less than b

gt= a gt= b a is greater than or equal to b

lt= a lt= b a is less than or equal to b

Equality operators

= == a == b a is equal to b

= a = b a is not equal to b

Table 10 ndash Relational Operators

Logical Operators

When using i f selection statements it is common to use the relational operators as part of the test if(num gt 5) if(size lt= 14) if(Char == A) These are fine for testing one condition

To test multiple conditions it is possible to nest i f statements but this can be a bit cumbersome

Logical Operators can be used to form more complex conditions by combining simple conditions

Logical AND (ampamp) Operator allows a test to see if two conditions are true

if(leaveBooked gt LeaveLeft ampamp staffCover == false)

cout ltlt Take your holidays sometime else

Logical OR (||) Operator allows a test to see if either or both of the conditions are true

if(Temperature lt 16 || windspeed gt 15)

cout ltlt Too cold or windy to sunbath today then

Logical Negation ( ) Operator reverses the meaning of a condition

if((windspeed == 20))

150

cout ltlt The wind speed is not 20 its ltlt windspeed

This could be written equally as well with the equality operator

if(windspeed = 20)

cout ltlt The wind speed is not 20 its ltlt windspeed

Precedence and Associativity Table

Precedence Operator Description Associativity

1 Scope resolution Left-to-right

2

++ -- Suffixpostfix increment and decrement

() Function call

[] Array subscripting

Element selection by reference

-gt Element selection through pointer

typeid() Run-time type information (see typeid)

const_cast Type cast (see const_cast)

dynamic_cast Type cast (see dynamic_cast)

reinterpret_cast Type cast (see reinterpret_cast)

static_cast Type cast (see static_cast)

3

++ -- Prefix increment and decrement Right-to-left

+ - Unary plus and minus

~ Logical NOT and bitwise NOT

(type) Type cast

Indirection (dereference)

amp Address-of

sizeof Size-of

new new[] Dynamic memory allocation

delete delete[] Dynamic memory deallocation

151

4 -gt Pointer to member Left-to-right

5 Multiplication division and remainder

6 + - Addition and subtraction

7 ltlt gtgt Bitwise left shift and right shift

8 lt lt= For relational operators lt and le respectively

gt gt= For relational operators gt and ge respectively

9 == = For relational = and ne respectively

10 amp Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 ampamp Logical AND

14 || Logical OR

15 Ternary conditional Right-to-Left

16

= Direct assignment (provided by default for C++ classes)

+= -= Assignment by sum and difference

= = = Assignment by product quotient and remainder

ltlt= gtgt= Assignment by bitwise left shift and right shift

amp= ^= |= Assignment by bitwise AND XOR and OR

17 throw Throw operator (exceptions throwing)

18 Comma Left-to-right

Table 11 ndash Precedence and Associativity Table

Escape Sequences

Escape Sequence

Description

n Newline Position the screen cursor at the beginning of the next line

152

t Horizontal tab Move the cursor to the next tab stop

r Carriage return Position the cursor at the beginning of the current line

a Alert Sound the system bell

Backslash used to print a backslash

Single quote Use to print a single quote character

Double quote Used to print a double quote character

Table 12 ndash Escape Sequences

Cast Operator

Is where the programmer explicitly asks for a change in data type It may be that the result of a calculation is a double and the user wants it to be of type integer

A double can be cast to an integer in the following way

double aNum = 237

int anInt = 0

anInt = static_castltintgt(aNum)

A C style cast may also be used eg

anInt = (int)aNum OR anInt = int(aNum)

Formatted Output

When several numbers are displayed each is printed with the minimum number of digits needed to show the value This can yield some unexpected output

The width of an output field can be set using a stream manipulator To set the next number to be printed to a width of 5 digits use cout ltlt setw(5) This command does not produce any output it manipulates the stream to change the output format of the next value Note setw() must be specified for every item output

To use any stream manipulators you must include the header include ltiomanipgt

setprecision is another manipulator and is used to set the precision of the next floating point number Note setprecis ion only has to be set once as the stream remembers the formatting directive and does not affect integer fields The format is cout ltlt

setprecision(3)

To set precision for trailing zeros (0100 will appear as 01) it is necessary to use the fixed format The notation is cout ltlt fixed Note f ixed only has to be set once

The three manipulators can be combined to achieve the required precision and field width when used in this way

153

cout ltlt fixed ltlt setprecision(3) ltlt setw(5) ltlt myDouble

Alternatively as fixed and setprecision only have to be set once this statement could be written as

cout ltlt fixed ltlt setprecision(3)

cout ltlt setw(5) ltlt myDouble

Header Files

Every program that you create will have at least one header file If you use input or output you will have to include the iostream header

If you use mathematical functions you will need cmath It can be difficult to know which header files to use for each function Some of the common header files used together with some of the older ones you may find with inherited code are shown below It is a good idea to use the help if you are unsure which header files are associated with particular functions

Standard C++ header Old header

iostream iostreamh

iomanip iomaniph

fstream fstreamh

cmath mathh

cstdlib stdlibh

string No equivalent

vector vectorh

Table 13 ndash Header Files Old and New

Matrix Libraries

The STL does not contain a Matrix type and so we must look elsewhere for a suitable implementation that suits the individuals needs

The table below lists the third party libraries that we are aware of

Some Linear AlgebraMatrix Libraries

Armadillo Blitz++ Boost

CPPLapack CPPScaLapack CVM Class Library

Eigen Elemental FLENS

Gmm++ GNU Scientific Library (GSL) HSL

154

IML++ IT++ LA library

Lapack++ LinBox Matrix Template Library (MTL)

MV++ Newmat PETSc

RNM Seldon SimuNova

SL++ (Scientific Library)

SparseLib++ SuiteSparse

TCBI (Temporary Base Class Idiom)

Template Numerical Toolkit (TNT)

Trilinos

uBlas ViennaCL

Table 14 ndash Matrix Libraries

Scope

The portion of a program where an identifier can be used is known as its scope

An identifier declared outside any function or class has f i le scope This type of identifier is known by all functions Global variables and function prototypes all have file scope

Identifiers declared inside a block of code have block scope This type of scope begins at the identifiers declaration and ends at the termination right brace ( ) of the block in which the identifier is declared

Any block can contain local variable declarations If blocks are nested it is possible to declare variables with the same name in each nested block The variable in the outer block is hidden while the inner block is being executed

Enumerating constants

The enum keyword provides a handy way to create a sequence of integer constants An example of enumeration is shown below

enum Months JAN = 1 FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC

Each of the constants will have a default value 1 greater than the constants that it follows in the list The first value in the enumeration above is explicitly set to 1 and the remaining values increment by 1 The values assigned from JAN to DEC will be 1 to 12

The statement cout ltlt DECEMBER is month number ltlt DEC ltlt endl would be output as DECEMBER is month number 12

Constants

Data that will not change during the execution of a program should be stored in a constant container rather than a variable If the program attempts to change the value stored in a constant the compiler will report an error and compilation will fail

Constant can be created for any data type by prefixing the declaration with const keyword followed by a space Note Constants must always be initialised at declaration

The following declaration declares a constant for the speed of sound at sea level ms

155

const double SpeedOfSound = 34029

Vector member functions

Some commonly used member functions of the vector class are

Vector member Functions Effect

at(element number) Gets the value contained in the specified element

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

push_back(value) Adds an element to the end of the vector containing the specified value

size() Gets the number of elements

Table 15 ndash Vector Member Functions

Global functions

Global functions are not member functions They take more than one argument and operate on a range of elements rather than on the vector container ie they can be used on other types of containers

Vector global Functions Effect

find()

ptr = find(vbegin() vend() 67)

Finds the element in the vector containing number 67 Needs iterator (ptr) to store location of element

reverse()

reverse(vbegin() vend()) Reverses the values in a vector (v)

sort()

sort(vbegin() vend()) Sorts the vector (v)

Table 16 ndash Vector Global Functions

156

list member functions

Some commonly used member functions of the list class are

List member Functions Effect

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

pop_front Removes the first element

push_back(value) Adds an element to the end of the vector containing the specified value

sort() Sorts the elements in the container from lower to higher

size() Gets the number of elements

swap() Exchanges the content of the list

Table 17 ndash List class Member Functions

cmath functions

Function Argument Result Returned Value Example Result

ceil(x) double double Smallest integer ge x

ceil(21) 30

cos(x) double double Cosine of x radians cos(10) 054

fabs(x) double double Absolute value of x

fabs(-15) 15

floor(x) double double Largest integer le 29

floor(29) 20

157

pow(x y) double double x to the yth power pow(24) 160

sin(x) double double Sine of x radians sin(10) 084

sqrt(x) double double Square root of x sqrt(4) 20

tan(x) double double Tangent of x radians

tan(10) 156

Table 18 ndash cmath Functions

158

String class

The string class defines many member funct ions A few of the basic ones are described below

Initialisation - constructors form

A string expression string str2 = str1

A character string literal string Intro = Programming with C++

A substring of another string object

string Intro = Capetown

string Mytown = Boars

string MyTown(Intro 4 5)

starts at character 4 (t)

with a length of 5 (or the rest of the string if shorter)

cout ltlt myTown ltlt endl

will produce an output town

Member Functions

length()

string myName = Sebastion

myNamelength()

will produce an output of 9

insert ()

Inserts a string into the current string starting at the specified position

string myName = Sebastion

string nameAdd = rjio

myNameinsert (2nameAdd)

cout ltlt myName ltlt endl

will produce an output Serjiobastion

erase()

Delete a substring from the current string

string myName = Sebastion

myNameerase (02)

cout ltlt myName ltlt endl

will produce an output bastion

replace()

Delete a substring from the current string and replace it with another string

string myName = Sebastion

string aName = renna

159

Member Functions

myNamereplace(3 6 aName)

cout ltlt myName ltlt endl

will produce an output Sebrenna

find()

Search for the first occurrence of the substring in the current string If the word is found return the position of the first character If not return -1

string sName

string findWord

position = sNamefind(findWord)

substr()

Returns a substring of the current string

string myName = Sebastion

string aName = myNamesubstr(0 3)

cout ltlt aName ltlt endl

will produce an output Seb

Non-member functions

getline()

string name

getline(cin name)

Table 19 ndash String Class Member Functions

160

A number of C++ operators also work with str ing objects

Operator

=

string fString = Hello

string lString

lString = fString

Assign a character (char ) to a str ing object

string aStringC

aStringC = Z

+

Concatenate two str ing objects

string str1 = C++

string str2 = Programming

string str3 = str1 + str2

+

Concatenate a string object and a character string literal

string str = Hello

string str1 = str + there

The same concatenation can be done in this way

str += there

+

Concatenate a string object and a single character

string str = Bye Bye

string strBye = str +

161

ASCII Character set

Decimal Octal Hexadecimal Binary Value Meaning

0 0 0 0 NUL (Null char)

1 1 1 1 SOH (Start of Header)

2 2 2 10 STX (Start of Text)

3 3 3 11 ETX (End of Text)

4 4 4 100 EOT (End of Transmission)

5 5 5 101 ENQ (Enquiry)

6 6 6 110 ACK (Acknowledgment)

7 7 7 111 BEL (Bell)

8 10 8 1000 BS (Backspace)

9 11 9 1001 HT (Horizontal Tab)

10 12 00A 1010 LF (Line Feed)

11 13 00B 1011 VT (Vertical Tab)

12 14 00C 1100 FF (Form Feed)

13 15 00D 1101 CR (Carriage Return)

14 16 00E 1110 SO (Shift Out)

15 17 00F 1111 SI (Shift In)

16 20 10 10000 DLE (Data Link Escape)

162

Decimal Octal Hexadecimal Binary Value Meaning

17 21 11 10001 DC1 (X ON) (Device Control 1)

18 22 12 10010 DC2 (Device Control 2)

19 23 13 10011 DC3 (X OFF)(Device Control 3)

20 24 14 10100 DC4 (Device Control 4)

21 25 15 10101 NAK (Negative Acknowledgement)

22 26 16 10110 SYN (Synchronous Idle)

23 27 17 10111 ETB (End of Trans Block)

24 30 18 11000 CAN (Cancel)

25 31 19 11001 EM (End of Medium)

26 32 01A 11010 SUB (Substitute)

27 33 01B 11011 ESC (Escape)

28 34 01C 11100 FS (File Separator)

29 35 01D 11101 GS (Group Separator)

30 36 01E 11110 RS (Request to Send)(Record Separator)

31 37 01F 11111 US (Unit Separator)

32 40 20 100000 SP (Space)

33 41 21 100001 (exclamation mark)

34 42 22 100010 (double quote)

163

Decimal Octal Hexadecimal Binary Value Meaning

35 43 23 100011 (number sign)

36 44 24 100100 $ (dollar sign)

37 45 25 100101 (percent)

38 46 26 100110 amp (ampersand)

39 47 27 100111 (single quote)

40 50 28 101000 ( (leftopening parenthesis)

41 51 29 101001 ) (rightclosing parenthesis)

42 52 02A 101010 (asterisk)

43 53 02B 101011 + (plus)

44 54 02C 101100 (comma)

45 55 02D 101101 - (minus or dash)

46 56 02E 101110 (dot)

47 57 02F 101111 (forward slash)

48 60 30 110000 0

49 61 31 110001 1

50 62 32 110010 2

51 63 33 110011 3

52 64 34 110100 4

164

Decimal Octal Hexadecimal Binary Value Meaning

53 65 35 110101 5

54 66 36 110110 6

55 67 37 110111 7

56 70 38 111000 8

57 71 39 111001 9

58 72 03A 111010 (colon)

59 73 03B 111011 (semi-colon)

60 74 03C 111100 lt (less than)

61 75 03D 111101 = (equal sign)

62 76 03E 111110 gt (greater than)

63 77 03F 111111 (question mark)

64 100 40 1000000 (AT symbol)

65 101 41 1000001 A

66 102 42 1000010 B

67 103 43 1000011 C

68 104 44 1000100 D

69 105 45 1000101 E

70 106 46 1000110 F

165

Decimal Octal Hexadecimal Binary Value Meaning

71 107 47 1000111 G

72 110 48 1001000 H

73 111 49 1001001 I

74 112 04A 1001010 J

75 113 04B 1001011 K

76 114 04C 1001100 L

77 115 04D 1001101 M

78 116 04E 1001110 N

79 117 04F 1001111 O

80 120 50 1010000 P

81 121 51 1010001 Q

82 122 52 1010010 R

83 123 53 1010011 S

84 124 54 1010100 T

85 125 55 1010101 U

86 126 56 1010110 V

87 127 57 1010111 W

88 130 58 1011000 X

166

Decimal Octal Hexadecimal Binary Value Meaning

89 131 59 1011001 Y

90 132 05A 1011010 Z

91 133 05B 1011011 [ (leftopening bracket)

92 134 05C 1011100 (back slash)

93 135 05D 1011101 ] (rightclosing bracket)

94 136 05E 1011110 ^ (caretcirumflex)

95 137 05F 1011111 _ (underscore)

96 140 60 1100000 `

97 141 61 1100001 a

98 142 62 1100010 b

99 143 63 1100011 c

100 144 64 1100100 d

101 145 65 1100101 e

102 146 66 1100110 f

103 147 67 1100111 g

104 150 68 1101000 h

105 151 69 1101001 i

106 152 06A 1101010 j

167

Decimal Octal Hexadecimal Binary Value Meaning

107 153 06B 1101011 k

108 154 06C 1101100 l

109 155 06D 1101101 m

110 156 06E 1101110 n

111 157 06F 1101111 o

112 160 70 1110000 p

113 161 71 1110001 q

114 162 72 1110010 r

115 163 73 1110011 s

116 164 74 1110100 t

117 165 75 1110101 u

118 166 76 1110110 v

119 167 77 1110111 w

120 170 78 1111000 x

121 171 79 1111001 y

122 172 07A 1111010 z

123 173 07B 1111011 (leftopening brace)

124 174 07C 1111100 | (vertical bar)

168

Decimal Octal Hexadecimal Binary Value Meaning

125 175 07D 1111101 (rightclosing brace)

126 176 07E 1111110 ~ (tilde)

127 177 07F 1111111 DEL (delete)

Table 20 ndash Full ASCII Table

169

Handy IDE Settings

Line Numbers onoff Tools | Options | Text Editor | CC++ | Line Numbers

Auto closing the console Tools | Options | Debugging | Automatically close the console window when debugging stops

Saves having to use system(pause)

170

REMAINING PAGES LEFT BLANK FOR NOTE TAKING

171

172

173

Peet Morris

peetmorrisgmailcom

C++ A Comprehensive Introduction

Arrangements

bull We Startfinish at 915am 500pm

bull Format two lectures per day (ask questions) hands-on at all other times

bull You should have Course book (copy of the slides at the back)

bull The course software is pre-installed on the machines

And also separately available from

The compilerIDE wwwvisualstudiocom

Notesslidesexercise files wwwpeetmcomC++introcoursezip

Your safety is important

Where is the fire exit

Beware of hazards

Tripping over bags and coats

Please tell us if anything does not work

Let us know if you have any other concerns

Your comfort is important

The toilets are along the corridor just outside the teaching rooms

The rest area is where you registered it has vending machines and

a water cooler

The seats are adjustable

You can adjust the monitors for brightness

What we assumehellip

What we assume

Experience of using another programming

language

Comprehensive Lots to get through

C++ and OOP

bull Created in 1985 by Bjarne Stroustrup C++ is a highly efficient

multiplatform low level Object Oriented Programming language

bull Latest version is C++17

stroustrupcom

Standard C++ Library

bull Written in the core language it is a collection of classes

(object definitions) functions and algorithms

See wwwcpluspluscomreference

IDEs amp Compilers

Visual Studio 2017

First Program

First application

include ltiostreamgt

using namespace std

int main()

int aNum = 0 aNum(0) or aNum0

cout ltlt Enter a number-

cin gtgt aNum

cout ltlt You entered ltlt aNum

return 0

hellip hellip

First Program

bull include ltiostreamgt

Adds the contents of the iostream header file into the program (for cout and cin)

bull using namespace std

So we donrsquot have to write stdcout ltlt and stdcin gtgt all of the time

bull cin is the standard input stream object that allows input from the keyboard

bull cout is the standard output stream object that allows output to the screen

bull int main() The programs entry point

Mandatory main function in every C++ program ndash always returns an integer value

First Program

bull int aNum = 0

Variable to hold a value of type integer (piece of machine memory referred to via the name aNum)

bull ltlt stream insertion operator ndash outputs to console

cout ltlt Enter a number-

bull gtgt stream extraction operator ndash waits for keyboard input

cin gtgt aNum

Other Types

Microsoft data types summary httpsdocsmicrosoftcomen-gbcppcppfundamental-types-cpp

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststack

Lots

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

x 1

y 2

x 3

y 4

p1

p2

x

y

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 copies the bit pattern from p1 to p2

x 1

y 2

x 1

y 2

p1

p2

Compound Types

Cannot define operators other than assignment

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 p2 compilation error

x 1

y 2

x 3

y 4

p1

p2

Compound Types

We can arbitrarily further compound things

struct point

int xint y

struct rectangle

point tlpoint br

struct line

point startpoint end

startxy

endxy tlxy

brxy

Compound Types

We can also group things using struct to create compound

types

struct point

int xint y

struct rectangle

point tlpoint br

int main()

rectangle r

rtlx = 1rtly = 2

rbrx = 3rbry = 4

int diff_x = abs(rtopLeftx - rbottomRightx)int diff_y = abs(rtopLefty - rbottomRighty)

cout ltlt area ltlt diff_x diff_y ltlt endl

r

tl

br

x 1

y 2

x 3

y 4

Using a Library Type

include ltstringgt

string s

cout ltlt What is your name

getline(cin s)

cout ltlt s ltlt

ltlt is

ltlt slength() ltlt

ltlt characters long ltlt endl

s

Other Types

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststackcomplex

Lots

8 bit Binary signed unsigned

00000001 1 1

00000010 2 2

00000011 3 3

01111111 127 127

10000000 -128 128

10000001 -127 129

10000010 -126 130

11111101 -3 253

11111110 -2 254

11111111 -1 255

00000000 0 0

00000001 1 1

00000010 2 2

signed vs unsigned ndash its all just 1s and 0s and adding

Adding rules

0 + 0 = 0

1 + 0 = 1

0 + 1 = 1

1 + 1 = 0 (carry 1)

1 + 1 + 1 = 1 (carry 1)

-126 + +3 =

10000010

00000011 +

10000101 = -123

-126 + -3

10000010

11111101 +

01111111 = 127 (why not -129)

Arithmetic Operators

+ Addition

- Subtraction and unary minus

Multiplication

Division

Remainder after division (moduloclock arithmetic)

int j k l = 10

j = l 3 js value will be three

k = l 3 ks value will be 1

Relational Operators

Evaluate to either true or false represented by integer values 1 and 0

== Equal to

= Not equal to

gt Greater than

lt Less than

gt= Greater than or equal to

lt= Less than or equal to

Increment and Decrement Operators

++ Increment

-- Decrement

Can be prefix or postfix

b = 3

a = b++ + 6 Add 6 to b then increment b a is 9 b is 4

b = 3

a = ++b + 6 Increment b then add 6 to b a is 10 b is 4

Assignment Operators

Symbol Operation Long Short

= Assign a = 2 a = 2

+= Assign with add a = a + 2 a += 2

-= Assign with subtract a = a ndash 2 a -= 2

= Assign with multiply a = a 2 a = 2

= Assign with divide a = a 2 a = 2

= Assign with remainder a = a 2 a = 2

Basic Control Flow - if

Sequence

What we have been doing already

Selection

if statement if this then that

if (boolean expression) if (score gt= 50)

statement cout ltlt Passed

Logical Operators

Boolean expressions may be combined using

ampamp And

|| Or

Not

Operands and result resolves being either true or false

if (x ampamp (y || z))

else

Precedence and Associativity table in course book

Logical Operators

a b =

true true true

true false false

false true false

false false false

a b =

true true true

true false true

false true true

false false false

a =

true false

false true

a ampamp b a || b a

Logical Operators

if (x ampamp (y || z))

else

The value 0 (zero) is evaluated to mean false any other value is true

x ampamp (y || z) result

false ampamp (false || false) falsefalse ampamp (false || true ) falsefalse ampamp (true || false) falsefalse ampamp (true || true ) falsetrue ampamp (false || true ) falsetrue ampamp (false || false) truetrue ampamp (true || false) truetrue ampamp (true || true ) true

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp (y | ~z))

else

Bitwise Operators

unsigned int x = 11

unsigned int y = 7

unsigned int z = 25

if (x amp (y | ~z))

else

11 (x) = 000010117 (y) = 0000011125 (z) = 00011001

~z = 11100110 (230 or -26)

y | ~z = 11100111 (231 or -25)

x amp (y | ~z) = 00000011 = 3

Operands and the result resolve to a values

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp 1) x is odd

if (x gt y)

x = x ^ y

y = y ^ x XOr swap

x = x ^ y

Control Flow - if else

Selection

ifelse statements

if (boolean exp) if (score gt= 50)

statement cout ltlt Passed

else else

statement cout ltlt Failed

Control Flow -

Selection

Conditional (or Ternary) Operator

boolean exp true result false result

cout ltlt score gt= 50 Passed Failed

Control Flow

if (x gt= y)

if (y 2)

else

if (x gt= y)

if (y 2)

else

Control Flow ndash else if

if (exp)

else if (exp)

else if (exp)

else catch all remaining

if (aNum == 0)

else if (aNum == 1 || aNum == 2)

else if (aNum == 3)

else catch all remaining

aNum not 0123

Control Flow - switch

Selection

switch multiple selection statements

bull test must be an integral value 1 10 A x eg not 1056

bull case values must be constants

switch (aNum)

case 0

break

case 1 Fall through

case 2

break

default catch all

break

Repetition - while

while (exp)

statements

while (n lt k)

cout ltlt Enter mark

cin gtgt mark

t += mark

n++

Repetition - for

for (init exp inc)

statements

for (t = 0 n lt k n++)

cout ltlt Enter mark

cin gtgt mark

t += mark

Preferable to while if the range is known

Repetition - for

for (init exp inc)

statements

for () infinite loop

break causes loop to exit

Preferable to while if the range is known

Repetition - do

do

statements

while (exp)

do

cout ltlt Continue yn

cin gtgt yn

yn = tolower(yn)

while (yn = y ampamp yn = n)

There are a huge number of exercises and we donrsquot expect you to attempt

them all during this course

bull If yoursquore completely new to programming itrsquos probably best to tackle

them in sequence

bull If yoursquove some programming experience you should read through the

exercise summaries and then start wherever you feel comfortable

Exercises

Exercises

Topics covered in ex1 ndash ex6

Functions = mini programs

bull Used to combine data with operations and through functional

decomposition to promote code re-use

bull Simplifies coding

bull Functions for discrete tasks

bull Not hundreds of lines of code

bull Consumer only needs to know

bull What goes in and what comes out

Functions

Like everything else the compiler needs to have seen a prototype or a

definition of a function before we can use it

Prototypes lets the compiler generate the correct code

int min(int int)

int min(int int int)

void drawLine(point to point from = 00)

int square(int)

int main()

void beep()

string getNextPacket(void)

Return type Function name (Parameter list)

min

int min(int int) min prototypes (forward declarations)int min(int int int)

int main()

Having seen the prototypes the compilerc = min(x y) can generate the required code

int min (int a int b) min function definition 1

return a lt b a b

int min (int a int b int c) min function definition 2

return min(min(a b) c)

inline min

int main()

c = min(x y)

inline int min (int a int b)

return a lt b a b

int main()

c = x lt y x y

inline int min (int a int b)

return a lt b a b

Function Parameters

bull Pass by Value

bull A Copy of the parameter is passed to the called function

bull Pass by Reference

bull The actual parameter is passed to the called function

bull Pass by Memory Address (pointer)

bull Same effect as Pass by Reference (tomorrow)

Pass by value

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

return n_copy n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 10

n_copy 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp x)

x just another name for real_n

return x x

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

x 10

Pass by value (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

n_copy = n_copy n_copy

return n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 100

n_copy 100

Pass by reference (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

real_n = real_n real_n

return real_n

100

100

Mem Addr Contents

0x2786 100

real_n 100

Mem Addr Contents

0x2786 100

real_n 100

const Parameters

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Recursion

unsigned long long int fibonacci(int n)

switch(n)

case 0 Fall through - [[fallthrough]]

case 1

return n

break

default

return fibonacci(n - 1) + fibonacci(n - 2) Very inefficient

Arrays (Part 1)

Data structure containing same type of data (int double string char object)

bull Built in to C++

bull Series of elements each containing one item of data (contiguous memory locations)

Size (number of elements) set at compile time

Arrays (1)

int numbers[10] an array of 10 integers Each box sizeof(int) bytes wide

numbers

index values - 0 to 9

0 1 2 3 4 5 6 7 8 9

Arrays (1)

int numbers[10] an array of 10 integers

int n = 0

cout ltlt numbers ltlt endl address of the first element

cout ltlt numbers[n] ltlt endl contents of the nth element

cout ltlt ampnumbers[n] ltlt endl address of the nth element

cout ltlt numbers + n ltlt endl address of the nth element

0 1 2 3 4 5 6 7 8 9

42 hellip hellip hellip hellip hellip hellip hellip hellip hellip

0x1526

Arrays

char name[5] name - an array of five characters

thing t[5] t - an array of five things

examMarks ndash an array of three doubles initialised to 12 39 95double examMarks[] = 12 39 95 C++11 - double examMarks[] 12 39 95

header ndash an array of fifty unsigned chars (bytes) first three elements set to 0 1 255 and the rest to zerotypedef unsigned char bytebyte header[50] = 0 1 -1

Arrays

Accessing array data

define MARKS 5 or const int MARKS = 5

double examMarks[MARKS]

for(int i = 0 i lt MARKS i++)

cout ltlt Enter Exam Mark

ltlt i + 1 ltlt

cin gtgt examMarks[i]

for(i = 0 i lt MARKS i++)

cout ltlt examMarks[i]

Multidimensional Arrays

Two dimensional array Two subscripts First identifies row second identifies column

const int students = 6 const int marks = 3

double examMarks[students][marks] = 0 set to zero

for (int s = 0 s lt students ++s)

for (int m = 0 m lt marks ++m)

cout ltlt Enter mark ltlt m + 1 ltlt for student ltlt s + 1 ltlt endl

cin gtgt examMarks[s][m]

00 01 02

10 11 12

20 21 22

30 31 32

40 41 42

50 51 52

Memory laid out in row column order (more later)

00 01 02 10 11 12 20 21 22 30 31 32 40 41 42 50 51 52

Matrices

Provider Link

Armadillo armasourceforgenet

Blitz blitzsourceforgenet

Boost boostorg

Eigen eigentuxfamilyorg

Elemental libelementalorg

FLENS apfelmathematikuni-ulmde

HSL hslrlacuk

LEDA algorithmic-solutionscom

PETSc mcsanlgov

SimuNova simunovacom

SuiteSparse facultycsetamuedu

TNT mathnistgov

Trilinos trilinosorg

ViennaCL viennaclsourceforgenet

Exercises

Topics covered in ex7 ndash ex16

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people and dice

Recap Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

1 61 61 61 61 6

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

3 11 24 56 12 3

C++ and OOP

Encapsulation Keeping related stuff together

Member functionsmethods

an objectrsquos capabilities functionality and performable actions

int Throw()

Member variablesproperties

an objectrsquos current state values its dumb data

int sides

Dice throwing 3

struct dice

int sides State

dice(int n) Constructor

sides = n

int Throw() Member function (method)

return (rand() sides) + 1

int main()

Could also use dice d1 = 6 or d16 syntaxdice d1(6) d2(6)

d1sides = 6 d2sides = 10 Allow this

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

struct diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

class diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing ndash professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

diceh my-appcpp

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

dicecpp

Compiler

diceobj my-appobj

Linker

my-appexe

other librarycode objectfiles

Dice throwing - professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Compiler

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

diceobj my-appobj

diceh dicecpp my-appcpp

Linker

my-appexe

other librarycode objectfiles

Only items provided to the end-usercustomer

Classes and Objects

the includeltstringgt header file from the standard library

class string

your cpp source code files

include ltstringgt include information about class string

string Name a class string instance

string Address a class string instance

Classes and Objects

the include carh header file

class car

your cpp source code files

include carh include information about class car

car c a class car instance

Classes and Objects

the include househpp header file

class house

your cpp source code files

include househpp include information about class house

house no1 a class house instance

house no2 a class house instance

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do with it

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

cstart()

cenginestart() Or should cstart() internally use enginestart()

OOD

Time for a break

class student

What properties and methods do we need

class student

public

string name

string DoB

string college

string bodCardNumber

float age()

int main()

student s

sname =

sDoB =

How to guarantee an objectrsquos integrity

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s

sname = Compilation errors

sDoB =

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s( )

cout ltlt sage()

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB Error ndash cant assign to a constant

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_name(name) m_DoB(DoB)

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_namename m_DoBDoB

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Exceptions

class student

int main()

try

student s( )

catch(const char msg)

cout ltlt msg ltlt endl

student initialisation failed

Exceptions

try

catch(const char msg)

cout ltlt msg ltlt endl

catch (const invalid_argument amp e)

cout ltlt ewhat() ltlt endl

catch (exception amp e)

cout ltlt ewhat() ltlt endl

catch ()

cout ltlt Something went wrong ltlt endl

student invalid arg 2

if using C++11 see stdcurrent_exception

Reuse and inheritance

Say we now want to add a new type to our system ndash class academic With what we have seen so far we would proceed something like this

class academic

private

string m_name string m_DoB

Duplicating everything we had in class student

class person (generalisation)

OOP is sometimes called Programming by Describing the differences

student and academic are all specialisations of a more generalised and abstract class ndash person

class student public personpublic

student(string name) person(name)

class academic public personpublic

academic(string name) person(name)

class personprotected

person(string name) m_name(name)

private

string m_name

public

base class derived class

derived class

Specialised State

class student public person

private

const string m_bodCard

public

student(string name string DoB string bc ) person(name DoB) m_bodCard(bc)

Multiple inheritance

class student public person public oxMember

public

student(string name int age string bc) person(name age) oxMember(bc)

class academic public person public oxMember

public

academic(string name int age string bc) person(name age) oxMember(bc)

Destructors

class foo

private

int m_x int m_y

public

foo() foo(0 0)

foo(int x) foo(x 0)

foo(int x int y) m_x(x) m_y(y) only ctor that accesses private state

~foo() any necessary tidy up code

Dice throwing 5

class diceprivate

int sides

public

dice(int n) sides(n)

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

srand((unsigned)time(0)) Happy with this

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 6

class diceprivate

int sides

public

dice(int n) sides(n)

classshared state static bool seeded = false

if (seeded)srand((unsigned)time(0))seeded = true

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

3 65 21 44 22 6

Dice throwing 7

class dice private

int sides

public

dice(int n) sides(n)

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

Dice throwing 7

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyesDouble 14 33 5

Dice throwing 8

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6) int t

for(int n = 0 n lt 5 ++n)

cout ltlt (t = d1Throw()) ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp t = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Dice throwing 9

class dice private

int sidesint _lastThrow

public

const int amp lastThrow read-only stateproperty

dice(int n) _lastThrow(-1) lastThrow(_lastThrow) sides(n)

int Throw()

return _lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp d1lastThrow = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Exercises

Topics covered in ex17 ndash ex22

Vectors

Like an array a data structure containing same type of data (int double object)

bull A container class part of the standard library a wrapper similar to arrays

Need to includeltvectorgt

bull Can resize grow shrink as elements are added or removed from the end

bull Algorithms to manipulate data

bull Iterators to cycle through all the elements

Vectors

vectorltchargt name(5) vector of five characters

vectorltthinggt t(5) vector of five things

vectorltdoublegt examMarks 12 39 95 initialised vector of three doubles

typedef unsigned char byte

a vector of fifty bytes first three elements set to 0 1 255 and the rest to zerobyte char b[50] = 0 1 255 fully populate array

calc itemCountint itemCount = sizeof(b) sizeof(b[0])

vectorltbytegt bytes (b ampb[0] + itemCount) then init with vector 50 items

Vectors (iteration 1)

include ltvectorgt

vectorltintgt vec(20) 20 ints

for(int i = 0 i lt vecsize() i++) input values into vec

cin gtgt vec[i]

for(i = 0 i lt vecsize() i++) output vec

cout ltlt vec[i] ltlt

Vectors (iteration 2) (C++11 and later)

for(type identifier container)

statements

vectorltintgt vec(20)

for (int amp i vec)

Vectors

Adding an extra element

cout ltlt Enter an Extra Value

cin gtgt aNum

vecpush_back(aNum)

for (int i = 0 i lt vecsize() i++)

cout ltlt vec[i] ltlt endl

cout ltlt vecat(i) ltlt endl same as above but range checked (ie slowsafe)

Vectors (most of the methods)

docsmicrosoftcomen-uscppstandard-libraryvector-classFull list

Method Purpose

assign Erases a vector and copies the specified elements to the empty vector

at Returns a reference to the element at a specified location in the vector

back Returns a reference to the last element of the vector

begin Returns a random-access iterator to the first element in the vector

capacity Returns the number of elements that the vector could contain without allocating more storage

clear Erases the elements of the vector

C++11 data Returns a pointer to the first element in the vector

C++11 emplace Inserts an element constructed in place into the vector at a specified position

C++11 emplace_back Adds an element constructed in place to the end of the vector

empty Tests if the vector container is empty

end Returns a random-access iterator that points to the end of the vector

erase Removes an element or a range of elements in a vector from specified positions

front Returns a reference to the first element in a vector

insert Inserts an element or a number of elements into the vector at a specified position

max_size Returns the maximum length of the vector

pop_back Deletes the element at the end of the vector

push_back Add an element to the end of the vector

rbegin Returns an iterator to the first element in a reversed vector

rend Returns an iterator to the end of a reversed vector

reserve Reserves a minimum length of storage for a vector object

resize Specifies a new size for a vector

C++11 shrink_to_fit Discards excess capacity

size Returns the number of elements in the vector

swap Exchanges the elements of two vectors

Vectors (iteration 3)

include ltalgorithmgt

vectorltintgt vec

for(int i = 1 i lt= 5 ++i)vecpush_back(i)

1 2 3 4 5

5 4 3 2 1

vectorltintgtiterator it

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Reverse the vectorreverse(vecbegin() vecend())

cout ltlt endl

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Arrays (2) (C++11 and later)

arrayltint 5gt arr Thin veneer over an array ndash so requires fixed size

arrfill(0) int j = 0

for (int amp i arr)

supports latest iteration style

reverse(arrbegin() arrend()) and iterators for use with algorithms

C++11 - Uniform initialisers

C++98

complexltdoublegt c( 271828 314159 )

int a[] = 1 2 3 4

vectorltintgt v

for( int i = 1 i lt= 4 ++i )

vpush_back(i)

C++11

complexltdoublegt c 271828 314159

int a[] 1 2 3 4

vectorltintgt v 1 2 3 4

Pointers ndash What

A pointer is a scalar variable that is used to hold the memory-address of

another variable or function the stored address is said to point to the thing

it holds ndash thus the name

Pointers have a type ndash the type of the thing they point to

int n = 10I (p) am a pointer to an integer and I point to n over thereint p = ampn

Pointers ndash Why

In no particular order

bull Because external libraries and APIs (like the operating system (all of them)) are written using them

bull Create custom data structures like linked-lists trees graphs etc

bull Create tables of functions or single functions for handling events callback or signals

bull Access data on to the heap (allocate memory dynamically)

bull Writecall functions that change their input parameters

1 2

3

4 5 6 nilhead

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

Recap - Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference using Pointers

int main()

int real_n = 10

cout ltlt square(ampreal_n)

cout ltlt real_n

return 0

int square(const int real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x5110 0x2786

real_n 0x2786

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt pcout ltlt pcout ltlt ampxcout ltlt xcout ltlt ampp

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

15438

11

15438

11

17216

Pointers

int main(int argc char argv)

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )(argv + n) ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv + 0 C

argv + 1

argv + 2

argv + 3

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

int main(int argc char argv[])

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )argv[n] ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv[0] C

argv[1]

argv[2]

argv[3]

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

Memory Stack vs Heap

Stack (last in first out - LIFO)

Space automatically allocated

The place where arguments of a function call are stored

The place where local function data is allocated (eg variables)

The place where a function leaves its result (if any)

Heap

Space must be explicitly allocated

A place for allocating memory that is not part of last-in first-out approach

ie dynamically allocated data structures that survive function calls

Stack vs Heap

int stackArray[100] Allocate 100 ints on the stack

stackArray[n] = 0 Do something with it

int heapArray = new int[100] 100 ints on the heap C++

int heapArray = malloc(100 sizeof(int)) 100 ints on the heap C

heapArray[n] = 0 Or (heapArray + n) = 0 Do something with it C++ and C

delete [] heapArray When youre done C++

free(heapArray) When youre done C

Exercises

Topics covered in ex22 onwards

If time allows look through the remaining

exercises and attempt those that fit best

with your requirements

  • C++ Notes TPLO 12-11-2019 Blackbox
  • C++ Slides TPLO 12-11-2019 - Copy

How to Use this User Guide

This handbook accompanies the taught sessions for the course Each section contains a brief overview of a topic for your reference and then one or more exercises

Exercises are arranged as follows

A title and usually a brief overview of the tasks to be carried out

A set of tasks together with a brief description of each

A set of steps that will achieve each task

Additionally there may be extra instructional notes for example some of the incomplete solutions contain notes in the form of code comments

PLUSPLUS As we get a broad mix of attendees on our courses we have occasionally added advanced or more technically in-depth asides labelled PLUSPLUS (all of which lie outside the scope of this introductory class) These are intended to challenge and inform just those students who already possess a more solid programming background

Exercises particularly those within the same section often assume that you have completed earlier exercises If you have any problems with the text or the exercises please ask the lecturer or one of the demonstrators (if any) for help

Note well

1 This course is mainly an introduction to the C++ that in the main attendees are most likely working with ie legacy or some might call it classic C++ With the introduction of C++11C++14C++17 modern up-to-date C++ can sometimes present itself as an almost new language (indeed this is extended further with the upcoming release of C++20) Therefore as this course is mainly aimed at those using existing C++ code we will only cover some of the changes made with the introduction of C++11 and later versions To find out more about C++11 and other versions eg C++17 please watch the relevant presentations found here channel9msdncomEventsGoingNative

2 The slides used by your lecturer do not necessary cover all the material required to complete the exercises ie there is extra information and sometimes a more detailed explanation in the notes or within the comments in code examples Also some slides may NOT be presented ndash in which case they are there for reference only

3 Additionally we do not expect attendees to complete very many of the large number of exercises provided during the course itself From their descriptions and subject matter select those that you feel able to complete Also you should feel free to work on your own project or problem if you would rather

Files and Folders

All of the files and folders you need to interact with should be located in the course folder on your machines desktop

Solutions to the exercises are located in folders named

(exercise solut ion) ProjectName

Where ProjectName will have previously been stated in the course notebook For example the folder called

(exercise solut ion) Sorts

contains the s ln file (Visual Studio solution file) which is the file you would open to see the solution to the Sorts exercise To open the solution you can either double-cl ick on the s ln file or open it via the File menu in Visual Studio NOTE if the file extension s ln is not visible just double-click on the file whose descr ipt ion reads Microsoft Visual

Studio Solut ion

The course folder also contains other C++ solutions in separate folders that again are usually referenced from the text In the main these are demonstrations andor contain code that might be useful to you after this course (but considered beyond the scope of this introduction to C++)

A quick note about Solutions and Projects in Visual Studio

In the real commercial world a full solution to a given problem may involve the creation of many constituent projects (possibly involving a variety of programming languages) A Visual Studio Solution (s ln file) mimics this approach and is really a container for separate constituent Visual Studio Projects files (vcxproj files)

All of our solutions contain single projects ndash and these may be opened in preference to opening the solution files For example in the (demonstrat ion) Ackermann

folder you will find a (demonstration) Ackermanns ln and a (demonstration) Ackermannvcxproj file you may open either file to work on the cpp code in the project

Copyright

This document is Copyright copy 2019 by Dr P Morris All rights are reserved No part of this publication may be reproduced transmitted transcribed stored in a retrieval system or translated into any language or computer language in any form or by any means without the prior written permission of the author

Version Date Author Comments

19 15 October 2019 Peet Morris

Please let us know if you find typos or errors in our course book and code

Contents

1 Introduction 1

11 What you should already know 1

12 What you will learn 1

13 Where can I get a copy of the softwaretools used 1

2 Things to understand 1

21 Compilers new and old 1

22 The C++ Standard Template Library (STL) 2

23 Visual Studio 2019 3

Creating your first program in Visual Studio 2019 6

Explanation 10

Your projects default code template 13

Arithmetic Operators 15

Characters 16

Header (include) Files 17

Strings 18

The LF (Line Feed) Problem and Reading Keys 20

Casts 22

Other Cast Types 24

3 Basic Control Flow 28

Selection - ifhellipelse statement 28

Selection - switch multiple selection statement 30

Repetition ndash while dohellipwhile and for loops 30

4 Logical and Bitwise Operators 35

41 Logical 35

42 Bitwise 37

Shifts 38

XOr 38

5 Introduction to Functions 39

Creating a function 41

52 Algorithms 49

Functions and Pass by Reference 51

Returning values from functions 53

Side effects 55

6 Classes and Objects 64

Creating your first class 65

Member functions and Passing parameters 67

Data Members 68

Constructors 70

Separating use from declaration and definition 72

Destructors 81

7 Arrays vectors lists and hash-tables 82

Declaring and using arrays 83

Searching Arrays with Linear Search 87

Sorting Arrays with Insertion Sort 90

Multidimensional Arrays 94

Declaring and using vectors 99

stdarray 105

Declaring and using lists 106

72 Hash Tables and Cached Calculations 107

Hash Tables 108

8 Pointers 112

Initialising pointers 113

Pointer Arithmetic and Arrays 115

9 APIs New Delete and Dynamic Memory 124

Using an API 124

Dynamic Memory Management 125

10 More on Functions 125

Multiple arguments overloading and default values 129

Passing Arrays to Functions 132

Passing Two-dimensional Arrays to Functions 135

11 Inheritance and (not presented) Polymorphism 135

111 Inheritance 135

Modelling a student - a first attempt 137

112 Polymorphism 143

12 Appendices 147

Arithmetical Operators 147

Assignment Operators 147

Assignment and Arithmetic examples 148

Relational and Equality Operators 148

Logical Operators 149

Precedence and Associativity Table 150

Escape Sequences 151

Cast Operator 152

Formatted Output 152

Header Files 153

Matrix Libraries 153

Scope 154

Enumerating constants 154

Constants 154

Vector member functions 155

Global functions 155

list member functions 156

cmath functions 156

String class 158

ASCII Character set 161

Handy IDE Settings 169

Exercises

Exercise 1 (Optional) Creating a first and default program 6

Exercise 2 CreatingModifying additional projects 26

Exercise 3 SearchString 29

Puzzled Programmers 29

The Collatz Conjecture 31

Mixing loops 33

PLUSPLUS Recursion 34

PLUSPLUS Base Two and Bits 37

Practising with Logical and Bitwise operators 38

Writing functions 42

Using a struct 43

PLUSPLUS When Things Go Wrong 44

The Monty Hall problem 46

More Functions 48

PLUSPLUS IsLeap in a line 49

Algorithms 49

Pass arguments by reference 52

Returning a value from a function 57

PLUSPLUS Arithmetic Bases 58

Searching for Sequences 61

PLUSPLUS Optimising Searching for Sequences 63

Evolving Searching for Sequences 64

Creating a class 65

Passing parameters 67

Using data members 69

More Objects 70

Using constructors 71

Separating declaration and definition 74

PLUSPLUS Using external libraries and third party header files 78

Creating an array to hold exam results 84

Linear Search 87

PLUSPLUS Debugging Linear Search 89

SortingSearching an array 90

PLUSPLUS Binary Search (Binary Chop) 93

Creating a multidimensional array 95

Creating a vector to hold exam results 100

Using insert() and iterators 103

Computing Fibonacci Numbers 110

Using pointers 114

Pointers and Arrays 116

PLUSPLUS Pointers and Arrays 119

PLUSPLUS Function pointers 122

main() and command-line arguments 126

EncryptDecrypt a file 128

Passing Arrays to functions 132

Base classes 137

PLUSPLUS Polymorphism 144

The PowerPoint slides entitled Exercises show the inclusive fromto exercise numbers which cover the topics discussed in the previous section It is not at all necessary to attempt to work through the entire quoted range variety is the spice of life ndash just choose those that appeal

1

1 Introduction Welcome to C++ A Comprehensive Introduction

These notes accompany the course delivered by Oxfords IT Services IT Learning Programme

If at any time you are not clear about any aspect of the course please make sure you ask your lecturer or demonstrator for some help If you are away from the class you can get help by email from your lecturer or from helpitoxacuk

Please also note that the university subscribes to Lyndacom ndash please check there for other C++ resources

11 What you should already know

The prerequisite for this course says that Either experience in another programming language or attendance on one of the PHP JavaScript or Python Kick-Start courses Is required

The more programming knowledge you have the better That said the documentation and lectures are structured such that those with very little knowledge should still be able to work through the course at their own pace

12 What you will learn

We will cover the following topics

Working with Microsofts Visual Studio Fundamental data types

Control Flow amp Iteration Header Files

Strings Functions

Arrays and Vectors Classes and Objects

Constructors and Destructors Member functions

Pointers And much more

13 Where can I get a copy of the softwaretools used

wwwvisualstudiocom (Microsofts C++ Compiler IDE and tools)

wwwpeetmcomC++introcoursezip (latest course code notes slides etc)

2 Things to understand

21 Compilers new and old

Students on this course often have to work with enhance or bug-fix existing code This sub-section is primarily for their consideration (it assumes some prior C++ knowledge)

2

Not all C++ compilers comply with the latest official ISO C++ standard (C++17) which was finally approved in December 20171

What does this mean It means that the code you write compile and run on one machine may not compile on the next machine if you are using a different compiler (even if it is using the same operating system) In this course you will be using Microsofts C++ Compiler (part of Visual Studio 2019)

Some older header files you may see with inherited C++ code are

include ltiostreamhgt have a h extension The C++ standard for this header file is include ltiostreamgt Your program may run correctly by adding a h but simply adding a h suffix will not work for all included files

include ltstringhgt has been replaced with include ltstringgt The stringh header file does not include C++ strings it includes C strings

include ltmathhgt has been replaced with include ltmathgt

The lesson to be learnt here is that a lot of C++ code you come across will have been created using older compilers Some of the header file and other code will not be recognised and may cause compilation errors when compiled on a machine which is more compliant with the C++ standard

If you are using the Gnu Compiler Collection (gcc g++ etc) you can specify standards compliancy via the ndashstd option eg -std=c++17 (other options are C++98

C++11 C++14)

Visual Studio can also be configured to use LLVM and clang Please see the relevant online documentation of how to install and use these if you wish to use them httpsllvmorgdocsGettingStartedVShtml

22 The C++ Standard Template Library (STL)

enwikipediaorgwikiStandard_Template_Library

The C++ programs you write will consist of the classes and functions that you write or modify (we provide partial solutions to every exercise)

However we will also look at what is still commonly referred to as the STL (now just part of the C++ Standard Library ) which holds a collection of existing classes functions and algorithms that you can use in the programs you will be creating

Some of the classes and template classes we will be looking at are

The string class The vector container template

The sort algorithm The list container template

The find algorithm

In addition you should also look at and be aware of another powerful library called Boost (parts of the STL come directly from the Boost library) wwwboostorg

The Boost library is easy to install (on any platform) as most Boost libraries are what is called header-only ie they consist entirely of header files containing templates and inline

1 A draft of this is included with your course files (n4660pdf) Its worth mentioning that this draft is in effect the published C++17 standard

3

functions and require no separately-compiled library binaries or special treatment when linking

23 Visual Studio 2019

What is Visual Studio (VS) VS is Microsofts freely available integrated development environment (IDE) and comes complete with optional compilerstools for a variety of languages We have only installed the IDE and the C++ compi ler (clexe etc) for this course

So what is a compiler

A compiler is a computer program that allows us to write programs in some specially defined language (unfortunately not English yet) in our case C++ (a so called high- level

language ) As you heard earlier the tex t we write in C++ is called source-code it is just simple text that one could write in Notepadexe for example

Sadly source-code is not directly understood by operat ing systems such as Windows Linux and macOS etc and it is the compilers job to convert our source-code into the terse concise and highly optimised machine-code that computers understand directly

Machine-code is often called executable or object-code and the compiled version of the source code is really just a file that contains numbers ndash a series of 8-bit bytes each holding a value between 0 and 255 The numbers either encode l ow-level instruct ions (code) or data that working together define the program Because these numbers may not encode displayable characters (see the ASCII table in the appendices to see a mapping between the numbers and the displayable characters) opening such a file an exe file in something like Windows notepad application would result in something like this being displayed (just the beginning shown)

However if we open this same executable file in a program that simply displays the files content as numbers and not what characters if any are represented by those numbers as Notepad is doing) we see this (the numbers are shown in base-16 or hexadecimal format)

4

The first two numbers 4D and 5A can be displayed as the text M and Z2 (see the first two characters at the top left in the previous notepad view of this file) 4D in base 10 is 77 and 5A is 90 ie the ASCII values for M amp Z (you can look these up in the ASCII table in the back of your course book)

Also take note of the line sequence starting 55 8B EC Then read on

2 MZ (0x4D5A) at the beginning of a file is an example of whats known as a magic number these are often used to identify a file type ndash in this case an MS-DOS executable file Trivia MZ are the initials of Mark Zbikowski the designer of the MS-DOS executable file format

5

If we have Visual Studio we can open the same file to see how such numbers translate into instructions and data

55 8B EC is the real beginning of our program In the above we see the numbers on the left and on the right what they actually mean Eg the first number 55 means push ebp which is an Intel CPU instruction Likewise 8B and EC together mean mov ebp esp The next line 81 EC C0 00 00 00 combines instructions and data and translate into sub esp 0C0h (subtract from esp the value C0 or 192 in base-10)

This is the entire program really the extra data shown in the previous views are for housekeeping

What does this program actually do then

Well youre about to find out ndash youre optionally now going to recreate it in Exercise 1

6

Creating your first program in Visual Studio 2019

Exercise 1 (Optional) Creating a first and default program

IMPORTANT

This exercise starts with a walk-through of using Visual Studio to create a new solution which you then go on to modify You should have already seen the steps needed to create a new solution in class so if youd rather just get on with the modification part simply open the (exercise solut ion)

f i rs t folder (in the Course folder) and double click the f i rs t s ln file If you choose to do this you can skip over the next few pages to the Explanation section (232) or even jump further on to Task 1 on page 14

Note You will not need to create any completely new programs during the course so even if you didnt fully follow the steps you can still safely move on to the modification part However if you really want to walk it through for yourself

Start the Visual Studio 2019 Integrated Development Environment (IDE) and create a new C++ Console application project You should have a shortcut to Visual Studio on your desktop failing that look for it on the Start menu

If they appear follow the prompts as shown below (if youre asked about keyboard mappings or Develop options select the C++ option)

7

Click Create a new project

Select Console App and click Next

8

Well locate the first project in a folder called first in your C drives Temp folder If the folder doesnt exist it will be created for you Click Create

Something like the above should appear (if you dont see the Solution Explorer panel open it via the View menu)

9

Alter the code adding the lines in bold as show here

include ltiostreamgt using namespace std int main() stdcout ltlt Hello Worldn system(pause)

Build and run the project by pressing the green arrow or by pressing F5

10

Explanation

Disclaimer at this stage you do not need to fully follow all of this just now

include ltiostreamgt

iostream is a standard C++ library file Files of this type are called header files They are text files usually containing C++ declarations definitions and code

Including iostream allows us to use some pre-defined objects to output messages to a console window This file must be included for any program that outputs data to the screen - or inputs data from the keyboard for that matter

The C++ compiler operates in passes through our code In the first pass ndash called the pre-processing pass ndash include directives are processed which are really text-substitution directives To be precise what include ltiostreamgt says is ldquoGo and find the text file called iostream and replace the directive with the contents of that filerdquo

The file name following a include directive can be enclosed in double quotes or chevrons ie include iostream or include ltiostreamgt The meaning of each is defined by the implementation (Microsofts C++ compiler in our case)

However it is common practice that if file name is in quotes it will be looked for locally first - in the same folder as the cpp file containing it and before being sought elsewhere Conversely if it is in chevrons the compiler will usually look for the file in a central include folder that was installed with the compiler ndash this folder is usually reserved for include files that come with the compiler as opposed to those that you might write yourself eg standard includes (like iostream) We therefore usually use quotes when we want to include our own custom project specific include files and chevrons when wanting to use include files that come with the compiler

You may also see that the filename sometimes has a h file extension This typically means that the header file being used is a C language header file and not a C++ one There are other variations (you are welcome to use your own) for example you might also see the occasional hxx file extension or something else entirely

using namespace std

The using namespace std code above doesnt actually appear in the automatically generated code In our project and solution files we will add it just after any include directives

namespaces in summary are very simple Everything within a namespace has a unique name and so theyre often used to help divide larger projects into more manageable chunks and to avoid name clashes

Standard C++ places a lot of its routines and functionality within a namespace call std Wed like to use this functionality and so we say we want to use all of the std namespace In the real world this isnt terribly good practice

11

However by declaring that were using namespace std throughout we can access members of this namespace without having to say exactly where they are (in which namespace) or worry about name clashes - where two objects in different files have been given the same name

The members of std that we will be using throughout are

cin (Console In) and cout (Console Out) and we must use include ltiostreamgt in order to use them

endl - is a stream manipulator that writes a new line to output endl stands for end

of l ine and is pronounced end all

If we dont declare that we were using the std namespace (which is the case in the automatically generated code) we have to prefix any use of cin cout and endl with std eg stdcin stdcout stdendl If youve added the using namespace std directive you may now remove the std in front of the stdcout ltlt Hello Worldn line

int main()

This is the entry point to our program ndash every C++ program must have this same entry point defined main() is a function the body of a function is defined within the opening and closing braces that come after its name The int to the left of main() says that this function returns (or resolves to beevaluates to) an integer value Returning a value requires you to use a return statement However as it is normal practice to simply return the value zero if you omit the return statement a value of zero is returned for you (only where main is concerned) If you want to explicitly return the value yourself you could modify the code to read

int main() stdcout ltlt Hello Worldn system(pause) return 0

So why return a value anyway Our added line return 0 means in this case that our main doing whatever it does as part of its function eventually resolves to the value 0 The value is returned to whatever called our programs entry point in this case and as usually that is the operating system ndash which has been waiting for us to return a value at this point However the operating system will simply ignore whatever value we ultimately return Why do it then

12

Consider the case when one of your programs needs to run another program to perform a part of its entire function Your main program needs to start this other program and wait until it completes successfully before continuing See the description of the system(pause) code line below

stdcout ltlt Hello Worldn

cout is an object declared in iostream ndash think of its name meaning console out Anything sent to cout using the double chevron operator ltlt appears on the console the

The n in the text means that cout should also output a carriage-return linefeed sequence (terms taken from the days of typewriters and telex machines) basically it means start any new output on a newline underneath the current line An alternative to using n is to use endl eg stdcout ltlt Hello World ltlt endl endl does more or less the same thing as n

system(pause)

system() is a standard function that is used to run an external program (here thats a standard Windows program called pauseexe) The system() function waits for the pause program to complete before continuing Going back to the discussion on return 0 earlier this is an example of one program starting another ndash here thats our program starting the pause program The pause program returns a value as part of its completion and we can examine that if we want Programs usually return 0 for success or some other integer value that means something went wrong ndash the value returned indicates what went wrong Ie a returned value of say 42 might mean that we cant answer the ultimate question with this computer3

So what is pause pauseexe is a standard Windows program that simply outputs the message Press any key to continue and then waits for a key to be pressed before exiting We use that facility here so that our program doesnt simply shutdown and disappear as it falls off the end of main()s closing or encounters a return statement If we did allow it to exit we would hardly have time to examine our programs output before it disappeared off the screen Try that and see (comment out the line using a double-slash like this system(pause))

If you run any of the course code on Linux or a Mac youll need to change this line to something like cinget()

3 An unashamed reference to the Hitch Hikers Guide to the Galaxy and the Deep Thought computer

13

Your projects default code template

In the course exercises when it comes to you writing code we will always ask you to open and then modify a partially complete projectsolution so you wont have to fiddle with projects and boilerplate code like this again

Nevertheless should you wish to start from scratch or simply experiment with Visual Studio we recommend using the code below as a starting point

include ltiostreamgt using namespace std int main() Start coding after here system(pause) return 0

14

Task 1

Immediately above system(pause) Replace the stdcout ltlt Hello Worldn line with the code shown here

int anum = 0

cout ltlt Enter a number

cin gtgt anum

cout ltlt The number you entered is

ltlt anum

ltlt endl

Test your modified program Tip remember you may hit the F5 key to build and then run your program

Try entering some text instead of a number Did it work

Alter the spacing (use of spaces and tab characters) in your code ndash does the C++ compiler care about this so called whi tespace

The statement int anum = 0 defines a variable (a memory location) which we will refer to in our code as anum to store a number of type int to hold an in teger (ie 1 -4 27) The memory location is being initialised with a value of 0 here It is good practice to initialise variables when you define them In C++11 a new type of uniform initialisation syntax was introduced and also encouraged eg int anum 0

cout ltlt Enter a number cout is a name that belongs to the namespace std The ltlt is called the stream insert ion operator When the program executes the value to the right of the operator (Enter a number) is inserted in the output stream and ultimately output to console window

cin gtgt anum cin is the input stream object of the namespace std gtgt is called the stream extract ion operator and is used here to read a number from the keyboard

cout ltlt The number you entered is ltlt anum ltlt endl This statement concatenates the output by using multiple stream insertion operators ltlt endl is the stream manipulator that adds a new line

The next Exercise starts on page 26 The pages between here and page 26 contain

code that you may like to try out by further modifying this project if not just read through the textcode until you get to page 26

15

Arithmetic Operators

Most computer programs perform arithmetic calculations Table 1 summarises the standard C++ arithmetic operators When working with integer division where both the numerator and denominator are integer the expression 15 6 evaluates to 2 To get the remainder after integer division you would use the modulus operator Note the modulus operator can only be used with integer operands

To establish the complete result of the following integer division 156 requires two operations

15 6 = 2

15 6 = 3

The result being 2 remainder 3

C++ Operation C++

arithmetic operator

Algebraic expression C++ expression

Addition + y + 6 y + 6

Subtraction - a - b a - b

Multiplication c times d or cd c d

Division xy or y

x or yx x y

Modulus p mod q p q

Table 1 - C++ arithmetic operators

Other fundamental data types Table 2 shows how you would declare and initialise four other data types for use in programs (there are more data types available)

16

Data type Example

Float float aFloat = 1234

Double (the precision of a Float) double aDouble = 123456

Char char aChar = A

Bool bool aBoolean = true

Table 2 - C++ numerical types4

Characters

Characters are normally stored in variables of type char but can also be stored as in t(eger) data types Characters are represented as single byte integers in the computer so it is possible to output a character as an integer or as a character

All characters have a numerical representation in the computer and the ASCII (American Standard Code for Information Interchange) character set shows each character and its decimal equivalent (also note that a combination of characters may be used to form more complex Unicode characters) See appendix 111

Characters can be read in with the following statements

char aChar declares a variable (aChar) of type char

cin gtgt aChar this statement is used to read a character into the variable aChar

Note After entering a character the ltENTERgtkey must be pressed before the character is read by the program

The following four statements correctly declare a variable of type char output a user prompt then read a character and store it in the variable aChar

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar

4 See httpencppreferencecomwcpplanguagetypes for a complete list (or the official ISO standard of course)

17

Header (include) Files

So far weve seen that to use certain functionality we had to include ltiostreamgt We have to do similar to use other functionality which is not part of the code C++ language ie we will need to include anything that comes as part of the standard library

In its current form Visual Studio comes with the following include files (most of which are standard files)

h files (95 C language files)

agentsh agileh ammintrinh amph amprth amprt_exceptionsh amp_graphicsh amp_mathh amp_short_vectorsh armintrh arm_neonh cfguardh collectionh comdefh comdefsph comiph comutilh concrth concrtrmh ConcurrencySalh concurrent_priority_queueh concurrent_queueh concurrent_unordered_maph concurrent_unordered_seth concurrent_vectorh crtdefsh crtversionh delayimph dloadsuph dvech ehh emmintrinh excpth fvech gcrooth immintrinh internal_concurrent_hashh internal_split_ordered_listh intrinh intrin0h invkprxyh iso646h ivech limitsh mm3dnowh mmintrinh nmmintrinh omph pgobootrunh pmmintrinh pplh pplawaith pplcancellation_tokenh pplinterfaceh ppltasksh ppltaskschedulerh pplwinh rtcapih salh setjmph setjmpexh smmintrinh srvh stdargh stdboolh stdexcpth stdinth tmmintrinh typeinfoh use_ansih vadefsh varargsh vcclrh vccorlibh vcruntimeh vcruntime_exceptionh vcruntime_newh vcruntime_new_debugh vcruntime_startuph vcruntime_stringh vcruntime_typeinfoh wmmintrinh xatomich xatomic0h xkeycheckh xlocinfoh xmmintrinh xsmf_controlh xstring_inserth xtgmathh xxamph xxamp_inlh ymathh yvalsh zmmintrinh

115 C++ files

algorithm allocators any array atomic bitset cassert ccomplex cctype cerrno cfenv cfloat chrono cinttypes ciso646 cliext climits clocale cmath CodeAnalysis codecvt complex condition_variable csetjmp csignal cstdalign cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cuchar cvt cwchar cwctype deque exception experimental filesystem forward_list fstream functional future hash_map hash_set initializer_list iomanip ios iosfwd iostream istream iterator limits list locale Manifest

18

map memory msclr mutex new numeric optional ostream queue random ratio regex scoped_allocator set shared_mutex sstream stack stdexcept streambuf string string_view strstream system_error thr thread tuple typeindex typeinfo type_traits unordered_map unordered_set utility valarray variant vector xcomplex xfacet xfunctional xhash xiosbase xlocale xlocbuf xlocinfo xlocmes xlocmon xlocnum xloctime xmemory xmemory0 xstddef xstring xtr1common xtree xutility xxatomic

Strings

Next to numbers strings are the most commonly used data type in programming

A string is both a datatype (string) and also literal character data ie a sequence of characters such as Oxford or StAndrews In C++ string literals are enclosed in quotes The quotes are not part of the string they identify the data type as a string

Actually this isnt quite true the double quoted strings are a sequence of characters and are taken from the C programming language The things declared of the string type are C++ string objects ndash which may be initialised using the C language literal

C++ strings can be declared and initialised in this way

string institution = Oxford

string name = Peet

To use the string type in your programs add the header file include ltstringgt at the top of your program This allows the use of part of the C++ library of classes called the string class (and its member functionsmethods explanations will follow soon)

Of course strings are normally used when requesting an input Consider this code

string aName aDept Two string objects

cout ltlt Enter your full name

cin gtgt aName

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

19

If in answer to the first prompt we were to enter say Fred Brooks 5 the interaction and output of our program would immediately result in this

Enter your full name Fred Brooks

Enter your department Fred is associated with Brooks

Why When reading in a string with a space such as FredltspgtBrooks only the first part Fred is read into aName ndash and the input is said to be space delimited by cin ndash and consists of two separate inputs (so the Brooks parts is read into the aDept string variable)

We could use multiple prompts to read in a name of course but this is inconvenient

To handle this situation we can use the standard getline(cin aName) function to read in a name instead of using cin gtgt aName This reads all key-strokes into aName until the ltENTERgt key is pressed at which point it returns a string containing all of the characters from the input

cout ltlt Enter your full name

getline(cin aName)

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

The string class has many useful functions you can use to manipulate strings An example is the length() member functionmethod

string aName = Fred Brooks

cout ltlt The length of the string aName is ltlt aNamelength() ltlt endl

This statement will output - The length of the str ing aName is 11

See section 12119 for more information on the string class and its member functions

5 Fred Brooks is a real person and a legendary computer scientist httpenwikipediaorgwikiFred_Brooks

20

The LF (Line Feed) Problem and Reading Keys

Continuing on consider the following code

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

string aName

cout ltlt Enter your full name

getline(cin aName)

cout ltlt You entered ltlt aName ltlt endl

system(pause)

The intent here is to first ask for a character and then to use getline() to ask for a name

If only things were that simple

If we were to enter say a Z to satisfy the first prompt the program would immediately output

Enter a character Z

You entered Z

Enter your full name You entered

Press any key to continue

The problem here is that being a keyboard key theltENTERgt key is itself being seen as a valid input so when we enter Z followed by the ltENTERgt key were actually entering two keys ndash Z and the ltENTERgt key The first keys placed into aChar whilst the enter key is left in the keyboards buffer This is quite reasonable if you think about it you entered two keys (Z and ltENTERgt) but provided a home for just one of them in aChar

Ok so whats the problem Well the problem is that we really need to use something like getline() to read text that contains spaces and it just so happens that getline() given this scenario will see the residual ltENTERgt key left in the buffer and it will assume that you didnt enter anything you just hit the enter key

This problem - that of having a mischievous ltENTERgt key waiting to surprise us ndash will occur whenever you read a key from the keyboard using cin Luckily theres an easy fix as we can use another input function to read and then discard the waiting ltENTERgt key Its called cinget() Here is a modified version of the code above that fixes the problem

21

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

cinget() REMOVE THE ENTER KEY discarding the got character

string aName

cout ltlt Enter your full name

getline(cin aName)

Used like this cinget() reads and discards a character from the input stream You can do the same using cinignore() cinget extracts a single character from the stream and returns it cinignore() extracts any number of characters and discards them (the details are specified via passed parameters to the function) or a single character if no arguments to the function are provided

You can easily use cinignore() to ignore a number of characters or until a certain token (character) is met eg the following code reads in a users first and last names and then outputs their initials

22

char first last Two 8-bit characters

cout ltlt Please enter your first name followed by your surname

first = cinget() Get one character

The first parameter is the maximum number of characters to

extract (and ignore) The second parameter is a

delimiting character The function stops extracting characters

as soon as an extracted character matches this one

cinignore(2566 ) Ignore until a space is seen

last = cinget() Get one character

cout ltlt Your initials are ltlt first ltlt last ltlt endl

Casts

On occasions in your programs you may want to store a value in a variable of a different type (when there is a danger of a loss of information the compiler will issue a warning for example when storing a double in an int) If you store a double as an integer you lose information in two ways

any mantissa (fractional part) will be lost

the magnitude of the double being stored may be too large to fit into the integer

Eg it is not possible7 to store 6678 x 10000 as a 16-bit unsigned integer because 667800 is 10000010011011100 in binary (17-bits) and is therefore larger than the maximum storable value of 65535 (1111111111111111) However you can store 1230 as an integer8

When you need to represent a value as a different type you can use the static_cast notation as shown here to change a double to an integer

6 If this is exactly numeric_limitsltstreamsizegtmax() there is no limit As many characters are extracted as needed until delim (or the end-of-file) is found

7 Actually the result of attempting to store 66780 in a 16-bit unsigned integer will be 10011011100 or 1244 Do you see how this value comes about

8 Also see the (demonst rat ion) L imi ts project

23

int anInt

anInt = static_castltintgt(doResult) where dResult is a double

You may also use the following historic classic C-style9 notation to cast to different data types

anInt = (int)dResult

Eg to change an integer to a character

char aChar

aChar = static_castltchargt(bInt) where bInt is an integer

You may also combine this using the

object-constructionfunction-call syntax of C++ eg

double d = 314157

int n = (int)d Convert ds value to an integer

int j = int(d) Ditto

9 C-style casts are usually considered to be too powerful ndash in that they indiscriminately allow unsafe and downright dangerous conversions C++ casts were introduced to solve this problem

24

Other Cast Types

Although outside the scope of this introductory course for reference here is a summary of the cast types in C++ (feel free to skip this for now and come back to it at a later time)

static_castlttypegt(object)

The type parameter must be a data type for which there is a known method for converting object to whether this be a built-in or through a casting function (constructor) All types of conversions that are well-defined and allowed by the compiler are done using static_cast

The static_cast operator may be used for operations such as converting a pointer of a base class to a pointer of a derived class converting numeric data types such as enums to ints or ints to floats However static_cast conversions are not necessarily safe as no run-time type check is done which can cause casting between incompatible data types for example initialised pointers However this is checked at compile time to prevent casting obvious incompatibles Also be aware that a static_cast between pointer of base to pointer of derived may produce an erroneous result (where the actual object pointed to is of type base not derived)

dynamic_castlttypegt(object)

In the C++ programming language the dynamic_cast operator is a part of the run-time type information (RTTI) system that performs a typecast Unlike the static_cast the target of the dynamic_cast must be pointer or reference to class Unlike static_cast and C-style typecast (where a type check is made during compilation) a type safety check is performed at runtime If the types are not compatible an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers)

reinterpret_castlttypegt(object)

Allows any pointer to be converted into any other pointer type Also allows any integral type to be converted into any pointer type and vice versa

The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument (unlike static_cast but like const_cast the reinterpret_cast expression does not compile to any CPU instructions It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type)

You cannot cast away a const or volatile qualification You can explicitly perform the following conversions

const_castlttypegt(object) A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is

25

identical except for the const and volatile qualifiers For pointers and references the result will refer to the original object For pointers to data members the result will refer to the same member as the original (uncast) pointer to data member Depending on the type of the referenced object a write operation through the resulting pointer reference or pointer to data member may produce undefined behaviour

26

Exercise 2 CreatingModifying additional projects

Examine how comments look in a program

Examine the use of some fundamental data types

Using different data types

Using the cast operator

Using the string class

Task 1

Open the skeleton project called EvenI

The project folder is

EvenIEvenI s ln

Modify the projects code in to prompt for two numbers of type double and two numbers of type integer

The program should output the sum the product and the difference of the double numbers Also output the quotient and the fractional part of the two integers10

Youll need something along the lines of hellip

double aDouble double bDouble

etc

To read a number into aDouble you could use

cin gtgt aDouble

Task 2

Modify your EvenI program to read in two characters Enter the characters a and Z

Output the two characters with the character case changed ie a becomes A and Z becomes z

You will need to look online or at in 12120 to establish the ASCII integer values of each character hellip you can alter a characters case by treating it as an integer and

To convert integers (or the results of evaluating integer expressions) to say characters we need to use a cast Eg

int i = 65

cout ltlt static_castltchargt(i + 32)

10 Trivia quotient comes from the Latin quotiens for how many times For example when dividing twenty by three the quotient is six and two thirds You can use a modulus b to get the fractional part

27

then by addingsubtracting tofrom it

Task 3

Open the skeleton project called Address and modify it so that it can be used to collect some user data

Output this collected data to screen as shown in Figure 1

Note that youll have to have include ltstringgt in order to use getline()

Figure 1

Visual Studio builds projects in one of two different modes ndash Debug or Release we will always use the Debug mode (a Release build is normally only used when a product is being beta tested ie late in the cycle)

When using Visual Studio (or most other IDEs for that matter) we normally do not have to concern ourselves with the location of the executable that is built by the program ndash because we normally run it from within Visual Studio itself However and just for your information really the exe for a debug build will always be located in the Debug folder immediately below the projects root folder ie for this project Addressexe is located in the (exercise solut ion) Address Debug folder whilst a version built in Release mode would be in the (exercise solut ion) Address Release folder

Debug builds contain extra diagnostic code that is automatically inserted by the compiler

28

3 Basic Control Flow The programs you have created so far are limited in that they run through a sequence of instructions once and then stop Most computer programs will make decisions and carry out different actions determined by the user input

C++ has three kinds of control structures

Sequence statement - the computer executes the statements one after another All the programs you have written so far use sequence statements

Select ion statements - if ifelse switch

The if selection statement selects an action if a condition is true or skips the action if the condition is false

The ifelse selection statement selects an action if a condition is true or performs a different action if the condition is false

The switch multiple selection statement can be used to perform many different actions based on a character or integer value

Repeti t ion statements - while for do while

The while and for statements perform actions within their bodies zero or more times If the loop condition test is initially false no actions will occur

The dowhile statement will perform the actions in the body at least once (the test ndash as to whether to continue - is at the end)

Selection - ifhellipelse statement

The if selection structure is used to choose among alternative courses of action The structure of the statement is

if(mark gt= 50)

cout ltlt Passed

else

cout ltlt Failed

If the condition (mark gt= 50) is t rue the statement following it is executed cout ltlt Passed

If the condition is false the statement is ignored and control is passed to the else part of the selection and statement following else is then executed cout ltlt Failed

ifelse selection statements can also be nested within other ifelse selection statements

29

Exercise 3 SearchString

Task 4

Open the skeleton project called SearchStr ing

You will need to include ltstringgt at the top of the code to complete this exercise See page 158 for more on the string class functionality

Modify the program to display a string of text to the user

The user should then be prompted to select a word from the sentence and input a replacement word Your program should replace one with the other You will want to See section 12119 on string functionality

The prompting string should be shown both before and after the update

Tips

Given a string s initialised to

string s = C++ at the University of Oxford

string t

int i = sfind(U)

cout ltlt i ltlt endl 11

t = ssubstr(0 i) bit before U in t

t = t + ancient + + ssubstr(i) +

Outputs C++ at the ancient University of Oxford

cout ltlt t ltlt endl

Puzzled Programmers

Using if if else nested ifs switch and the conditional operator -

Task 1

Solving puzzles

Open the I fp project and WITHOUT compilingrunning it determine its output

You will need to consult the operator precedence table in section 1216

You shouldnt compile or run the program to start with ndash the idea here is for you to determine its output on paper11

Tip you might want to consider tidying up the codes layout before attempting to solve it

void out(int n) is a function We havent covered functions yet but it makes sense to use one here and so we have Suffice to say for now that using out(some value) will output the value to the console window

11 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

30

Functions will be explained fully soon

Compile and run the program ndash if your workings from Step 1 differ from the output you should determine where you went wrong

Selection - switch multiple selection statement

The switch multiple selection statement can be used to perform many different actions based only on a single integer value Note however the switch statement can only be applied in narrow circumstances The tests must be constants and be integers Lets compare the two statements

int num switch(num) case 1 cout ltlt num = one

double num switch(num) case 11 cout ltlt num = 11

OK ndash Test is 1 a constant and an integer NOT OK ndash Test is not constant integer

Repetition ndash while dohellipwhile and for loops

The while statement is commonly used to carry out repeated steps perhaps reading in values before doing a calculation on values read in The format of the code is

while(condition)

statement

This can be read as whi le the condition is t rue continue to do the statements until the condition is false

31

The Collatz Conjecture

Win a million dollars

Task 1

Open and complete the project called Col latz (use a while() loop)

Given any positive integer if the number is even divide it by two else treble it and then add one If the result is one stop else repeat the process

The Collatz conjecture says that given any starting value the process above will eventually hal t (goes to one and stops)

Eg setting n to 9 as a starting point successive values would be

28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is not known whether the Collatz conjecture is true Fame and fortune await anyone who can prove it httpenwikipediaorgwikiCollatz_conjecture

A Collatz tree as visualised by Edmund Harriss

32

This image is a sample from the colouring book Visions of the Universe by Alex Bellos and Edmund Harriss

Get your own hi-res version for colouring-in here and see here for an explanation

33

Task 2

Re-implement your code so as to use a for() loop (this will be a lot easier than you might first think)

Not essential for this task but as we mention for loops you might like to look at the for project to see how a for loop can be animated to show how the three sections of it work in order

Mixing loops

Task 1

Open and modify the skeleton project called Factor ial

Modify it to use different repetition statements to calculate and display the factorial of a value entered by the user (they should enter a value between 1 and 10 inclusive)

Example use a while loop to prompt for an input value (between 1 and 10) and a for loop to calculate the factorial result

The output should be like that shown in Figure 2 below

Factorials12

The factorial of 5 (usually written as 5) is

1 x 2 x 3 x 4 x 5 = 120

If factorials are new to you think of them as defining the number of ways to arrange n items

To avoid displaying results in scient i f ic notat ion use

cout ltlt setprecision(0) ltlt fixed

setprecision() requires include ltiomanipgt

12 0 Is defined to be 1

34

Figure 2

PLUSPLUS Recursion

Come back to this after weve covered functions

Note that our solution optionally also uses a function and recursion to find the same factorial If you open it you will see that just after where we perform the output above we have commented out an extra line of code (uncomment and rebuild to see it in action)

We havent covered recursion in this C++ course yet but its basically the process of solving a problem in terms of smaller versions of the same problem Since the problem gets smaller each time the process eventually terminates in a problem (the base case) that can be solved directly When defining a recursive function be sure of three things 1 The problem gets smaller each time 2 Include a solution for the base case And 3 Each case is handled correctly

The recursive function looks like this ndash add then test it in your own solution

Factorial function using recursion

long long int recur_factorial(long long int n)

return n lt 1 1 n recur_factorial(n - 1)

The question mark is the conditional operator and is used with the colon to form the functional equivalent of an if then else

35

If the expression before the is true then the expressionstatement to the left of the is evaluated otherwise the one after the is evaluated Eg these are equivalent

x boo() hoo()

if(x)

boo()

else

hoo()

4 Logical and Bitwise Operators

41 Logical

Quite often we will want to perform some action if two things are true and we can achieve this using nested if statements eg

if(onething == true)

if(secondthing == true)

do something

In C++ we can achieve the same result through the use of the l ogical And operator - ampamp

if(onething == true ampamp secondthing == true)

do something

ampamp is a binary operator ndash meaning that it takes two arguments (nothing to do with base 2) eg Op1 ampamp Op2 The expressions Op1 and Op2 must be capable of evaluating to t rue or false (false in C++ has the value 0 whilst any other value is considered true) and both Op1 and Op2 have to be true in order to have the conditional part execute eg if(x ampamp y) Z = 10 Here both x and y must have non-zero values in order for z to be assigned the value 10 Note again that this is equivalent to

36

if(x)

if(y)

z = 10

The truth table for logical And is as follows ndash note that both Op1 AND Op2 have to be true for the result to be true

Logical And

Op1 Op2 Result

True True True

True False False

False True False

False False False

We also have a Logical Or operator (||) in C++ and its truth table looks like this ndash note that its one OR the other that has to be true in order for the result to be true here

Logical Or

Op1 Op2 Result

True True True

True False True

False True True

False False False

The remaining logical operator we have is the unary Logical Not (the exclamation mark is used for this)

Logical Not

Op1 Result

True False

False True

Logical ampamp and Logical || short-circuit ie for ampamp if the expression on the left-hand side is found to be false then the expression on the right is never evaluated as the whole will evaluate to false (because to be true both sides have to be true and we know that the first one is false at this point)

37

The same is true for logical || in that the right-hand expression is not evaluated if the left is found to be true (the whole will evaluate to true because the left is true so there is no need to evaluate the right-hand expression)

42 Bitwise

PLUSPLUS Base Two and Bits

We also have bitwise versions of the logical operators ndash plus some extra ones Bitwise operators work on a variables individual binary bits ndash rather than the value of all the bits taken as a whole For bitwise And we do not use ampamp but use just a single amp The same is true for bitwise Or we just use a single | and not || Bitwise Not is a little different we use ~ (the tilde) for bitwise Not

The additional bitwise operators we have are for bitwise XOr ndash for which we use the ^ symbol and lastly for left and right bit shifting we use ltlt and gtgt

Bitwise operators work on binary bits (1s and 0s) whereas the logical operators work on values equating to either true or false

For example consider the following code

int w = 10 int x = 42

int y = w amp x

int z = w ampamp x

cout ltlt y ltlt endl

cout ltlt z ltlt endl

The base-2 binary representation of 10 is 001010 and for 42 it is 101010 So w amp x means

001010 101010 amp ------ 001010 ------

Remember And is one and the other

Now let us consider w ampamp x Here were not interested in ws or xs bits just whether when taken together they are zero or something else Here both are non-zero so both are considered to be t rue and if we refer to our truth table from earlier on we will see that the result will be t rue When we assign that to an integer like were doing here the value assigned will be 1

38

Shifts

The shift operators shift the binary bits left or right Bits that do not fit fall off the ends and bits are replaced with zeros when shifting left ie bits do not rotate and come back on the other end again When shifting right the sign-bit may be preserved depending upon whether youre using a signed or unsigned integer

Shifts are useful for all sorts of things but one of the obvious uses is to multiply and divide eg x = 2 x = x ltlt 1 shifts the bits in x one place to the left so given that xs value is 00000010 in binary x = x ltlt 1 turns x into 00000100 which is 4 So x = x ltlt 1 is like saying x = x 2 You can of course divide by right shifting

XOr

The rule for XOr is one or the other but not both ie 1 ^ 0 = 1 (just like 1 | 0) but whereas 1 | 1 = 1 with 1 ^ 1 the answer is 0

Note that we do not have a logical XOr operator in C++ as we can just use = (not equal to) ndash see the (demonstrat ion) Logical XOr project

Practising with Logical and Bitwise operators

You will need to use the Precedence and Associativity table in 1216 to complete these tasks

Task 1

Open the Logical project As earlier DO NOT compilerun this yet

You will need to consult the operator precedence table in section 1216

On paper determine the programs output13

Run the program ndash output as expected

Task 2

Open the Bitwise ndash

unsigned project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Unsigned The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

13 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

39

PLUSPLUS Signs and bits

Task 1

This one is tough as you should really know something about Twos Complement arithmetic to complete this

Open the Bitwise ndash s igned

project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Signed The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

5 Introduction to Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine (which will also be a function) Encapsulat ion is data information or detail hiding If youre mathematically minded you may think of a C++ function as being very similar to one in mathematics ie a mechanism for mapping one thing to another

Once a function is written the detail of how it works is not important It is only necessary to understand what if any inputs the function needs (its parameters) and what output is produced (the functions return value)

The use of functions provides several benefits but the main one is that it makes programs significantly easier to understand and maintain The main program function can consist of a series of function calls rather than hundreds of lines of code A second benefit is that well written functions can be reused across multiple programs

You have to tell the compiler about a function before you use it and this is normally done using a prototype early in the program A function prototype consists of the return type a funct ion name and a parameter l is t - indicating the data the function will receive ndash and is terminated using a semicolon Eg

int someFunc(int int)

This tells the compiler that there is a function (somewhere) called someFunc that takes two integers as its input and returns an integer value for its output

40

Using a prototype is a way of telling the compiler the data types of any return value and of any parameters being passed and enables error checking to be done

The function defini t ion consists of the modified prototype and a function body which is a block of code enclosed in parenthesis which does the work Eg

int someFunc(int a int b)

return a + b

Here we have named the two inputs a and b and we can see that the functions job is to add these two value and to return them As this function returns a value (the sum of a and b) it may be used to expressions like this

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

Arguments can be passed to functions in two ways pass-by-value the default is where a copy of the argument value in the main program is made and then passed to the function The copy in the function only exists in memory as long as the function is active When the code within function has been run to completion the memory is released and the value held there is lost Any changes made to the copy passed to the function do not affect the original variable in any way For example if we altered and used someFunc like this

int someFunc(int a int b)

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 20

41

Note that because we passed a copy of b to the function that the line b = b 2 alters the copy (which then isnt used) and not the original

Arguments can also be passed-by-reference When arguments are passed in this way any changes made to the arguments in the function are reflected by corresponding changes to that data variable in the calling part of the program Pass-by-reference is good for performance reasons because it can eliminate the pass-by-value overhead of copying large amounts of data (In later sections we will examine how pointers can be used to fake pass-by-reference) Eg this will alter b now

int someFunc(int a int amp b) Note the amp

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 40

See section 521 for more on this subject

Creating a function

The format of a function prototype is

return_data_type FunctionName ( argument_l ist )

The function CtoF - void CtoF(int temp) - has no return data type (void) its name is CtoF and it accepts a single input argument called temp of type int (integer)

It is not strictly necessary to give the argument a name (temp) in a function prototype you saw this above in int someFunc(int int) However the argument type must be specified The statement void CtoF(int) is therefore an alternative prototype

The following exercise is an introduction to functions You will learn a lot more about functions in later exercises

42

Writing functions

Task 1

Open the project EvenI you created earlier and change the structure of the program to make use of functions

Solution in (exercise solut ion)

EvenI I

Read two integers in to main() and pass them to a function The prototype is void intCalcs(int int)

intCalcs() function should calculate and display the result of the division and modulus of the two variables passed see Figure 3

Read in two doubles to variables in main() Pass the two doubles and the value of one integer to the second function the prototype is int Calcs(double double int)

Within function Calcs() write statements to produce the output as shown in Figure 3 Most of the code already exists within main()

Return the result of the multiplication of one double and an integer cast this value as an integer

Display the returned value within main() as shown in Figure 3

Figure 3

43

Using a struct

Task 1

Open the project Person

Solution in (exercise solut ion)

Person

As you saw during the presentation we can keep related data together using the struct keyword For example say we define a thing as follows

struct thing

int x

string y

double z

Having done this we can now create as many thing objects as we wish ndash simply by declaring them as we would say an integer

thing a

thing b

Each thing object a and b contains its own x y and z member variables eg

ax = 10 thing as x member set to 10

bx = 20 thing bs x member set to 20

cout ltlt ax ltlt endl outputs 10

cout ltlt bx ltlt endl outputs 20

Complete the exercise by creating and populating a struct Person object Once populated amend the printPerson() function so as to output the persons details

44

PLUSPLUS When Things Go Wrong

Going back to Exercise 8 if you havent tried it already enter zero as your second number What happens

C++ contains mechanisms for catching errors in the form of a trycatch mechanism

cin gtgt y Enter zero

try

intResult = x y

catch(myException amp e)

cout ltlt ewhat() ltlt endl

catch()

cout ltlt Generic oops ltlt endl

Modify your code so as to catch the divide by zero

Hopefully try and catch are fairly self-evident try something and catch any error if something goes wrong

There are two catch blocks here One tries to catch a myException object (we cannot see the definition of this classstruct here) and the other tries to catch anything else that is missed by catch(myException amp e) The amp says that the myException object e is being passed to the catch handler by reference Well learn what this means a little later in section 521

So did you see the Generic oops message appear

Your C++ compiler doesnt have to catch the divide by zero error ndash doing such a thing results in undefined behaviour This is because an arithmetic exception is an OS or processor exception - which is not the same as a C++ exception - hence it cannot be caught by a in a try catch block

To catch errors like this we either need extra support from the compiler14 andor operating system or to write some extra code For example we could do this

14 See also C signal handling httpenwikipediaorgwikiC_signal_handling

45

cin gtgt y Enter zero

if(y gt 0)

intResult = x y

However first we have to realise that this is a possible source of a runtime error and secondly we have to write (correctly) the code to handle the condition

Windows has built-in exception handling ndash called Structured Exception Handl ing (SEH) and we can generate code that uses this in support of the try catch structure used earlier

To enable this we need to tell the compiler to generate code that links into the SEH mechanism

To do this open the Project | ltproject namegt Properties hellip dialog box and in the Code Generation section select Yes wi th SEH Exceptions ( EHa) in the Enable C++

Exceptions line See Figure 4

46

Figure 4

The Monty Hall problem

The Monty Hall problem is a probability puzzle loosely based on the American television game show Lets Make a Deal and named after the shows original host Monty Hall

It goes like this

You are on a game show where you are shown three closed doors You are told that behind one of them is a new car and that behind the other two are goats

Two pieces of essential information at this stage 1 your goal is to win the car 2 the game show host knows what is behind each door

Lets walk through a trial game

The game show hosts asks you to choose a door ndash lets say you choose door number 1 (your door remains closed) The host now opens one of the remaining doors to reveal a goat (as there are two goats they can of course always do this) lets say they open door number 3

47

The situation is now as follows you have chosen door number 1 Only door number 3 is open and it reveals a goat The host now asks you if you would like to switch your door to the only other closed door - door number 2 At this stage you must either stick with door number 1 or switch to door number 2 and at that point the host will open the door youve chosen to reveal your prize

The question is when youre offered the chance should you stick or should you swap - will swapping increase your chance of winning the car or is it just 5050 The claim made here is that by swapping doors you will double your chance of winning the car What does your completed project claim

Task 1

Open and complete the incomplete project MontyHal l

The goal of this project to provide a simulation of problem outlined above

The function

int getRandomDoor(int n = 3)

return rand() n + 1

is used to choose a door number between 1 and 3 (inclusive)

Note that it has a default argument ie if it is called without an argument like this int val = getRandomDoor() the argument n is set to 3 by default and val will be set to a value between 1 and 3 However if it is called like this int val = getRandomDoor(10) then n is set to 10 and val will receive a value in the range of 1 to 10

48

More Functions

Task 1

Open the incomplete project IsLeap

The program asks for a year and determines whether the year is or will be a leap year

You need to complete the function IsLeap(int y) to implement the necessary code

Although the program is incomplete the program contains pseudo code for the algorithm required to compute the answer The pseudo is also show opposite

if year modulo 4 is 0

then

if year modulo 100 is 0

then

if year modulo 400 is 0

then

is_leap_year

else

not_leap_year

else

is_leap_year

else

not_leap_year

Figure 5

49

PLUSPLUS IsLeap in a line

Task 1

Extra points for implementing the IsLeap() function in just a single line of code This could be done using ampamp and || or by using the operator (a short form of if then else)

If you completed this step how readable is your code when compared to the if else version on the right

52 Algorithms

Algorithms

An Aside Big-O notation and Algorithm Complexity feel free to jump over this to Task 1

As programmers we usually implement the various parts of any new program in the simplest and most straight-forward way possible Then later if we find parts of our program are slow (causing what are called hot-spots) we will look again at the code to see if there is a better way to do whatever it is that is taking up the time

As a general rule the most optimal algorithms run in the shortest possible constant t ime ndash such algorithms are often symbolised using O(1) whereas the worst run in quadratic cubic exponential or factorial time (you can think of the O [called Big-Oh] as meaning in the Order of for some input n)

Usually were often happy with those running in O(n) (in the order of n) time ie their running time scales linearly with the number of steps or operations they involve Loops invariably signal O(n) parts of any algorithm

This is best explained using an example

50

Task 1 Understanding Gauss algorithm

Q How would you sum the integers from 1 to n where n is say 100

The obvious way is to use a loop

int tot = 0

for(int i = 1 n = 100 i lt= n ++i)

tot += i

This is fine for small values of n but not so good for very large ones

Interestingly it is said that this self-same problem was once given to a class of children which included one Carl Friedrich Gauss (presumably the teacher wanted to keep his charges occupied for a time) While most of the children started working at the problem (using the loop approach above) Gauss thought about it for a moment and then wrote down the solution 5050

The algorithm Gauss used may be easily demonstrated using the values 1 ndash 10

Gauss realised that if he wrote out the values twice (whether on paper or just in his head) once forward and once in reverse that he could sum each column formed to 11

1 2 3 4 5 6 7 8 9 10

10 9 8 7 6 5 4 3 2 1

1+10 2+9 3+8 4+7 5+6 6+5 7+4 8+3 9+2 10+1

=11 =11 =11 =11 =11 =11 =11 =11 =11 =11

Then sum of 1 ndash 10 is then 11 10 (columns) = 110 2 = 55 (we divided by two because we used each value twice)

Coming back to algorithm runtimes you can see that when using a loop summing 1 ndash 1000 will take ten times longer than summing 1 ndash 100 which will take ten times longer than summing 1 - 10 However by using Gauss approach we can arrive at the answer for any range of values in the same time this is what we mean by a constant time algorithm

51

Task 2

Open the incomplete project SumIntSeries

Complete the project so as to implement Gauss algorithm for any continuous range of integers

The solution project is (exercise solut ion)

SumIntSer ies

The general formula required is

((119948 minus 119947) + 120783)(119947 + 119948)

120784

Or in a more code form

Sum = ((k - j) + 1) (j + k) 2

Where j and k are the starting and ending values in the range respectively (both inclusive)

Functions and Pass by Reference

In the previous section when working with functions all arguments passed to the functions were copies of variable values from main() The arguments were passed by their value

Pass by Value is the default argument passing mechanism for C++ (and the C language)

In pass by value when a function is passed an argument it receives a copy of the value from the calling function (main() in previous examples) This copy remains in scope until the called function has completed and returned at which time the copy is destroyed

Therefore a function that takes value-arguments cannot change a passed variables value because any changes only apply to copies and not to the actual callers variables

An alternate passing scheme is called Pass by Reference

Passing variables to functions by reference is very useful when we need to change or update variable(s) via a function (it is also a faster mechanism than pass by value as no copies have to be made)

Under the covers pass by reference involves passing a memory address and not a copy of the data to the function This is usually more efficient than passing by value because there is no requirement to copy memory However this argument passing mechanism enables a function to modify any argument even if its not supposed to To avoid this we usually declare all read-only parameters as const and pass them by reference

The format of a function prototype when using call by reference is

return-data-type funct ion-name (reference parameter) To indicate a reference parameter an ampersand (amp) is written in the function prototype and header after the parameter type name

The statement void squared(int amp) has no return data type (void) its name is squared and it accepts a reference parameter (amp) of type int (integer)

52

The function definition would be something like this

void squared(int amp inVal)

inVal = inVal inVal inVal

The function call to it would look like this

squared(aValue)

As mentioned above pass by reference is normally used for one of two reasons 1 Because we want to be able to change a passed variable inside a called function 2 Because we want the speed associated with a pass by reference

In 2 we will normally protect our argument by using const in the called function Eg say we want to pass the double argument x to a function f() and take the least possible time about doing it (and given that function f() shouldnt alter x) we would use the following code

void f(const double x)

Use x in some calculation Note that if

x appears on the left hand side of an assignment operator

that it will result in a compilation error

Pass arguments by reference

Task 1

Open the project (demonstrat ion) FunctionRef

Compile and run the program The output should be the same as shown in Figure 6

53

Figure 6

Examine the function prototype

void squared(int amp)

This shows the function squared accepts a reference

parameter of type int The reference parameter is ndash under the covers - the memory address of the argument passed to the function

The function uses this address to both get and set the value stored in variable a (value 21) in main() A reference to this address is passed to the function with the function call squared(a)

Examine the function void squared(int amp x)

Under the covers references to x refer to the address of the variable a in main (that holds the value 21) Ie x and a reference the same piece of memory (the word object was deliberately not used there) So we can think of x and a as two names for the same item

Returning values from functions

In previous programs we have most often produced output (using cout) from within the functions However to be of most use and general utility functions should return resultsinformation rather than output it

Functions may return results in one of two ways 1 via a return value or 2 via arguments ndash either passed as references or via pointer (address)

Non void Functions return a single value ndash if you will they evaluate to this value As such non-void functions may be used in expressions Eg

54

w = x sqrt(y) z

The function sqrt() is replaced with the value of whatever the square root of y happens to be For example if y has the value 4 then to evaluate x sqrt(y) z fully the sqrt() function has to be called ndash where it returns 2 This value is then substituted into the expression for further evaluation ie it becomes w = x 2 z

The second way for functions to return results is via its parameters ndash if they are references or passed via memory addresses Eg

void doubleIt(int amp n)

return n 2 Error The void means doesnt return a value

doubleIt() is a void function ndash so it cannot contain a return statement ndash so it cannot evaluate to anything ndash so it cannot be used in an expression

x = doubleIt(y) error

However the function is still able to return a result (modify something outside of itself is perhaps a better way of putting it)

void doubleIt(int amp n) using amp - a reference

n = n 2

55

doubleIt() cannot (still) be used in an expression but it can change things

int x = 10

doubleIt(x)

cout ltlt x Outputs 20

Why would you use references like this Well references are mainly used for speed (by passing an actual external entity a copy does not have to be made) but they are also useful when multiple values (entities) might best be updated via a single operation (function call)

int x y z

x = y = z = 10

doubleAll(x y z)

void doubleAll(int amp a int amp b int amp c)

a = a 2 b = b 2 c = c 2

Side effects

Going back to w = x sqrt(y) z

Lets replace sqrt() with our own function and cause some havoc

double havoc(double amp d)

++x

d = sqrt(d)

return d

x = 3

w = x havoc(y) z

56

Here the value of y has been changed (yet it is not clear that could happen from the functions call site ndash where it was called from) and so has x Also what value for x will be used in x havoc(y) z Will it be 3 or 4 These sorts of issues are called side-effects

This is one problem (or advantage) with reference arguments ndash and that is that they can cause a change in a variable outside of the function being called

One way to protect against this is to use const references eg

double havoc(const double amp d)

++x

d = sqrt(d) Compilation error here

return d

57

Returning a value from a function

Task 1

Open the TempConver t

project

Run the program The output should be the same as shown in Figure 7

Examine the function prototype

double convert(double temp int mode)

This function prototype has a return type of double When the function is called and calculations are completed a double value is returned to the caller

Examine the function definition The function definition matches the prototype indicating a double and an integer are being passed to the function and a double is being returned

Examine the function body The two statements below convert the temperature input The conversion type required is identified using the user input mode and a switch selection

The statement (temp - 32) 5 9 is used to calculate the temp in Centigrade

The statement 18 temp + 32 is used to calculate the temp in Fahrenheit

Figure 7

58

PLUSPLUS Arithmetic Bases

Task 2

Open compile and run the partially complete Bases project

Note that the project isnt complete

The program uses intrinsic functionality to output values in hexadecimal and octal ndash base 16 and base 8 Both these bases are useful in programming its all to do with binary and the size of a byte

Note that there isnt a bin equivalent to hex and oct and that we have instead written a function called bin1() to convert a value into its binary (base 2) representation

Understanding how bin1() works

bin1 uses the modulus operator () and the right shift operator (gtgt) to work eg 42 in binary is 101010

25 24 23 22 21 20

32 16 8 4 2 1

----------------------

1 0 1 0 1 0

----------------------

1 32 + 0 16 + 1 8 + 0 4 + 1 2 + 0 1 = 42

The function progresses like this

42 2 has remainder zero (false as evaluated in the if) If the if test is true we store a 1 else we store a 0 We then divide 42 by 2 by right shifting it one place ndash but just replace that with n = 42 2 if you prefer We then loop while we have a non-zero value in n to operate on hellip

42 2 = 210 42 2 = 0 if(42 2) = false string value = 0

21 2 = 105 21 2 = 1 if(21 2) = true string value = 1

10 2 = 50 10 2 = 0 if(10 2) = false string value = 0

5 2 = 25 5 2 = 1 if(5 2) = true string value = 1

2 2 = 10 2 2 = 0 if(2 2) = false string value = 0

1 2 = 05 1 2 = 1 if(1 2) = true string value = 1

59

Task 3

The project needs completing specifically it needs the function bin2() writing

We could write such a function as bin1 in a variety of ways and wed like you to write a new function called bin2() that produces the same output as bin1() here

Heres a step by step algorithm for implementing bin2()

Youll use either gtgt or and the bitwise And (amp) operator

Take the functions input (the number to convert) in as a parameter called n To keep it as simple as possible for now you could use plain int types rather than the unsigned long long type we used so the functions signature would look like string bin2(int n)

1 In the function create an integer called i and initialise it to 1

2 Realise that if you left shift the single bit in i (use ltlt or multiply it by 2) it will take on the values 2 4 8 16 32 hellip until it eventually goes to 0 ndash as you shift the bit off of the end

3 Recognise that you could compare your shifting bit with one in the same position in n using bitwise And Ie if((n amp i) == 1) then you know youll need a 1 in your output string for the bit position in n (2 4 8 ) given by is value at this point

4 Build up your result string as you proceed

Change your int n and int i to unsigned long long int and re-run

Try using other integer types ndash signed and unsigned

Lastly examine the solution project in (exercise

solut ion) Bases

60

Figure 8

61

Searching for Sequences

Task 1

Open and modify the incomplete project called called HeadsOrTai ls

When all completed the output should be similar to that shown in

Figure 9

This is the (exercise

solut ion) HeadsOrTai ls project

The programs purpose is to look for a sequence of simulated coin tosses ndash a series consisting of Hs and Ts

The program is complete (as in it runs) but it has some issues At first test it using quite short sequences

The timing information displayed by the application is included simply to demonstrate a timing mechanism that can be used to test the efficiency of the code

The first problem is that the user can currently enter characters other than H or T (h and t are ok as the input is converted to uppercase ndash note the string is passed by reference to toupper() which uses a pointer (which well cover later) to process the string

The second problem is that as it stands the algorithm isnt very optimal if we do not find our pattern we add the result of another coin toss to the current sequence and then re-check the sequence in its entirety

For example if were looking for HHTHH and the generated sequence is currently HTTHHHTTHTHHTTH we will fail to find HHTHH and then proceed to add another coin-toss result at the end ndash HTTHHHTTHTHHTTHH We will then scan this for HHTHH However as we know that we failed to find HHTHH before we added the extra coin-toss re-checking the previously checked sequence is pointless and very time consuming (think how this would (or wouldnt) scale) Your task here is to think of and implement another more optimal approach

62

Figure 9

Task 2

Open the HTTvsHTH project you will find that the project will compile correctly but displays an incorrect result

When completed the program can be used to check how many coin-tosses are required on average to see a particular sequence

Why should that be of interest Because sometimes its rather surprising For example test how many tosses are needed to see say HTH and then HTT

When the program is corrected the output should be as shown in Figure 10

63

Figure 10

PLUSPLUS Optimising Searching for Sequences

Task 1

As it stands the program (yours and ours) encodes a coin toss as a character ndasheither an H or a T Each character is encoded using at least 8-bits and so checking whether a generated sequence is the sequence were looking for means performing a string comparison which is costly in terms of clock-cycles Of course generating and storing the new coin toss also requires the use of these costly string operations

As we have just two tokens as an alternative to generating and storing characters and performing string operations we could encode a sequence as a series of bits For example the sequence HTH could be encoded as 101 in binary (5 in decimal) You can set the corresponding individual bits in an int using the bitwise Or operator | (a vertical bar) eg int n = 0 n = n | i which youd most likely do as a result of scanning the users entered search-sequence string a character at a time In this way you could encode the sequence HTHHTHHTHHTHHTHH in a single sixteen bit unsigned int

Additional operators needed to implement sequence checking and H or T bit manipulation are bitwise And (amp) and the left shift operator (ltlt)

You will find more information on some of these operators just a little below

64

Evolving Searching for Sequences

Task 1

Looking for sequences in stringssequences is an interesting and complex problem in computing and also in genetics where the string being searched could be a DNA sequence and pattern could represent a gene perhaps with a snip (a modificationmutation)

Modify your HeadsOrTai ls program (or our solution) so that instead of Hs and Ts it generates and searches for Gs As Ts and Cs instead

Randomly generate a GCTA sequence and a similar pattern to find within the sequence

How much more time and variation is required in this slightly more complex situation

Conduct a few experiments and using Excel graph your results (copy and paste some data highlight it and then select Excels line graph ndash Excel should then automatically plot your data)

Extrapolate The human genome is how long A gene might contain how many bases How difficult is the task of finding interesting sequences in the human genome How about checking for the odd mutation (insertion transposition deletion) ndash fuzzy matching

A solution for this problem can be found in the (demonstrat ion) GATTACA project

6 Classes and Objects In the previous section we have been working with simple programs that display messages to the user store data input as different data types manipulate the data in some way and output the results to screen

We will now start to look at C++ objects and classes

In the real world there are objects everywhere students staff cars birds houses and many more All objects have at tr ibutes these are similar to the variables created in previous tasks Some attributes of a student may be height weight race course of study etc All objects exhibit behaviours or operations cars accelerate and decelerate students matriculate enrol on courses and leave university

65

Now what is the relationship between a class and an object A good analogy would be from an architects blueprint for a house it would be possible to build many houses Similarly from a class in C++ it would be possible to build many objects

If we had a student class we could create many objects from the student class to represent the many students enrolling Each of these objects would be uniquely identified They would share common attributes and exhibit common behaviours If we wanted an object to perform some task we would call the appropriate member function allowing an operationaction to take place changing the behaviour of that object

Member functions are different from the functions you have created so far Member functions are always associated with objects and are usually called or invoked using a dot notation object member funct ionname() An example is student1getName() The object instance is student1 and the member function is getName()

Member functions contain the detail of how the technical aspects of some operation will be processed When member functions are invoked these technical issues are hidden from the end user When the member function is asked to do some operation a message is sent (a member-function call) telling the member function of that object to perform the operation detailed in the function

Functions are not completely new we have had a brief introduction and you have already created some of your own Note also that main() is a function that is called automatically when you run your program However it is not a member function as there is no object associated with it

Creating your first class

Creating a class

Task 1

Open the project called StudentUG

Compile and run the program It should look like Figure 11

66

Figure 11

Before you can create the object myName it is necessary to define the class from which the object will be created The class definition is shown below

class StudentUG Start of class definition

public

void displayName() Start of member function

cout ltlt My name is Michael Cain ltlt endl

Note a semicolon is required at the end of the class definition

Within main() the statement StudentUG myName creates the object myName of class StudentUG In effect StudentUG is a new type

The statement myNamedisplayName() is used to call the member function displayName() of object myName

As we have seen previously the function main() is called automatically when our programs are executed However member functions (displayname() is one we could have many) must be called in this way objectInstanceNamefunctionName() when dealing with an

67

object directly and like this objectInstanceName-gtfunctionName() if working through a pointer to an object (more on pointers later)

The member function displayName() is preceded by the word void All functions can return values this one does not The word void preceding the function name indicates nothing is being returned If this function returned an integer the definition would be int displayName()

When you use functions it is common to pass data (called parameters) to the function The function then manipulates the data before displaying an output andor returning a value

To pass a parameter to the function in the studentUG class the calling statement in main() would be

myNamedisplayName(name) where name is a string (a series of characters) that contains a value read in from the keyboard

In order for the function displayName() to recognise the parameter being passed the function declaration is changed to include the parameter (name) and type (string) as shown in below

void displayName(string name)

cout ltlt My name is ltlt name ltlt endl

Figure 12

Member functions and Passing parameters

Passing parameters

Task 1

Modify StudentUG to read in a student name The name should be passed to a member function The parameter should be output from within the function to welcome the user to C++ programming

68

Task 2

Modify the program in the above task to read in two more names Each name will be for a different student and you will need to create additional objects (instances) of the class

Data Members

In most of the programs written so far the variables have been declared inside the main() function Variables declared inside a function are local to that function and cannot be accessed from outside that function

You have created a student class and it would be reasonable to assume that a student would be following a particular course So courseName might be one of several attributes of a StudentUG object Attributes are represented as variables in a class defini t ion These variables are called data members and must be declared inside a class definition When you create an object of a StudentUG class each object has a unique memory location for its data members

Figure 13 shows data member name declared in the class definition The access specifier private means that only member functions of the class in which the attribute was declared can use this data member

private string name

Figure 13

When data members are declared as private the data is hidden This is called encapsulat ion and means the attributes of the object are hidden and can only be accessed via member functions

As there is no direct way to change a data member you will also need to create a member

funct ion to set the data member to a value and create a second member funct ion to output the value held there

Data members can also be declared public A data member that is declared public can be accessed from any (non-member) function

A protected data member can only be accessed by member functions of its own class and by member functions of classes derived from this class We will learn more about derived classes and inheritance later

69

Using data members

Task 1

Open the project called StudentCoursesln

Compile and run the program it should look like Figure 14

Figure 14

Task 2

Examine the member function getCourse() shown in Figure 15

string getCourse()

return course

Figure 15

Task 3

Modify the StudentCourse source file to enable the user to add a student name enrolment date and number of years of course Once entered this data should be output to screen You will need to create additional data members and member funct ions to achieve this

70

More Objects

Task 1

So far you have created one StudentCourse object It is about time we had a second student on the course Create a second object of the class StudentCourse You will need to add the second statement shown in Figure 16 to add the new object student2 Call the member functions passing parameters as necessary

Figure 16

Constructors

When you create objects from the StudentCourse class it is necessary to give initial values to all the data members If we were entering data for five people and they were all following the same course of study it would make sense to initialise the course data member (it is possible to initialise some or all of the data members) when each object is created

A constructor is a special kind of function that must have the same name as the class Constructors are normally defined to be publ ic and never have a return type They can be used to automatically initialise data members

In previous programs you have written a defaul t constructor has been provided by the compiler However it is not possible to pass parameters to a default constructor function so the data members in the programs created so far have not been automatically

71

initialised To initialise these data members you created member functions that assigned values to data members

Although a default constructor is provided at compilation time it is a good idea to create your own so that the data members can be initialised

It is worth noting here that functions (constructors are functions) can be over loaded This means it is possible to have more than one function with the same name Note that overloaded functions (functions with the same name) must have different types of or number of arguments

Constructors (functions) can also be overloaded with more than one function with the same name but different types or number of parameters Fortunately for us the compiler automatically calls the correct function whose parameters match the arguments used in the function call

Using constructors

Task 1

Open the project called Constructorss ln

Compile and run the program it should look like Figure 17

Figure 17

72

Task 2

In the constructor shown in Figure 18 what is the purpose behind course = Note that as the string parameter name has the same name as the class variable that we use the hidden this pointer to access the class variable in the assignment If we didnt do this and simply used name = name instead then all we would be doing is assigning the value in the parameter back to the parameter

StudentCourse(string name)

this -gt name = name

course =

Figure 18

Task 3

Create a third constructor that will take an argument enrolment_date

Add a third object call it student3

Write code that will test this additional constructor

Solution in (exercise

solut ion) Constructors

If time allows add other useful properties (data members) access methods (functions) and constructors

Separating use from declaration and definition

C++ is all about objects and any decent project will usually make use of a number of application or domain specific classes

To keeps things maintainable and to promote code reuse C++ projects usually contain a number of cpp and h files where each h files will usually contain a declaration of a class (sometimes called an interface) Note though that the definition of the class (sometimes called the implementation) ndash the code that implements it ndash will be absent from the h file and will instead reside in an accompanying cpp file

Aside from allowing different teams to more easily work on separate parts of the program one of the main reasons for separating definition from declaration is to enforce abstraction which is a programming (and design) technique that relies on the separation of declaration and implementation For example lets say that your team needs a class that acts a bit like a stack (a last-in first-out or LIFO structure) and as this is required

73

urgently you decide to implement it using a simple array You would then only want to give your team what is absolutely necessary to use this class a single h file for your team members to include in their cpp files If they look in the h file they will only see information on how to use the class but how it does what it does is kept elsewhere in the cpp and that youve withheld Consumers shouldnt need to know how a thing works in order to use it

An obvious advantage to this is that there is no danger in you changing how it works Perhaps you later decide to use a vector instead of the array You go ahead and alter the implementation and your team members are none the wiser ndash after all the interface hasnt altered just the implementation

So how does the project get built Of course the implementation of this class will be required at compile time and you can either do that by including the cpp file directly (which will give away the implementation details of course) or by including it as object code ie compiled C++ code (binary machine code) This is how valuable commercial source code is kept in-house while the binary implementation complete with a h file is provided to customers (you will see an example of this just below in Using external

l ibrar ies and thi rd par ty header f i les )

Any discussion on separating use from declaration and definition should include something on namespaces You introduce a namespace by simply using the keyword and braces Anything entered inside these braces is inside the namespace eg

namespace securityModule class Encryptor using namespace std using namespace securityModule int main() Encryptor e Without the using we would have had to use securityModuleEncryptor e securityModuleEncryptor e2

See the (demonstrat ion) Namespaces project for more on this

74

Separating declaration and definition

Using a header and source file to separate class declaration from definition

Task 1

Open and modify the partially complete skeleton project called Precis ionTimers

Like HeadsOrTai ls this project makes use of the Windows operating system to very precisely measure elapsed time However unlike HeadsOrTai ls we have separated the stopWatch class interface from its implementation

As weve previously mentioned Gauss and algorithm efficiency we could test our theory that summing in a loop is O(n) ie that the time taken scales with n

Examine the project files hrTimercpp and hrTimerh noting that the h file contains just enough information for someone to use the declared class stopWatch whilst htTimercpp contains the implementation of the class

Now look in PrecisionTimerscpp You will see that an instance of the stopWatch class is declared Also note that we include hrTimerh but make no reference to hrTimercpp

As it stands the code calls two functions to calculate the sum of a range of integers sumGauss() and sumLoop() The program outputs the clock-ticks used and time taken in seconds

Note that sumLoop() is incomplete

Complete the sumLoop() function and then choosing suitable values for the ranges upper-bound carry out a few experiments to test if the loop is really O(n)

What is this used to do in hrTimerh15

ifndef HRTIMER

define HRTIMER

endif

15 You should also see pragma once as this is rapidly becoming the alternate way to do this ndash whatever this is of course

75

PLUSPLUS Providing object code only

Task 2

We have provided a separate demonstration project that takes the discussion on this one step further (demonstrat ion)

Separat ingThings

In its current form the project wont compile To compile the project in the Solution Explorer add the existing carcpp file to the source files list that just contains SeparatingThingscpp and recompile carcpp is in the same folder as SeparatingThingscpp

Once youve done that right-click on carcpp in the Solution Explorer and select Remove Very importantly when youre prompted for confirmation choose Remove do not choose Delete Now recompile once more youll see that the project fails to compile as the definition of car has been removed

76

But hold on we created carobj - the compiled object-code version of carcpp during our previous compilation so we could tell the linker about that and all should be well (this more or less duplicates the scene whereby you do not provide source code but provide only object code)

The carobj file will be located somewhere like

CUsersDesktopCourse(demonstration) Separating Things(demonstration) Separating Thingsbincarobj

To add this to your project go to Project | Properties | Configuration Properties | Linker | Input

77

In the right-hand window select Additional Dependencies drop down the list and select ltEdit gt

In the dialog that appears add the full path to carobj (see earlier in Step 2) and press Ok

Lastly recompile the code once more It should compile and run At this point you could if you wanted to delete carcpp altogether

One last thing

If you look in the comments in SeparatingThingscpp you will find a discussion that goes into the advanced topic of hiding things even further This includes a brief discussion of the the so called pimpl pattern (pronounced Pimple this stands for Pointer to Implementation16)

16 httpenwikipediaorgwikiOpaque_pointer

78

PLUSPLUS Using external libraries and third party

header files

Task 3

Open and modify the project called Lot to

Examine the projects comments to understand the programs function Run the program ndash does it work

It is supposed to compute the odds of winning the UKs lottery httpwwwnational-lotterycouk (try as we might we couldnt find the odds on their own website)

The program uses the recursive factorial function used earlier in the course (with bigint being typedef ed as unsigned long long int)

Factorial function using recursion

bigint recur_factorial(bigint n)

return n lt 1 1 n recur_factorial(n - 1)

There is a problem here however in that to compute the odds we must compute some significant factorials ie

49 = 608281864034267560872252163321295376887552831379210240000000000

and

6 (49 - 6) = 43498989405629161658895695089330078205230448640000000000

Sadly our bigint (unsigned long long) can hold a maximum value of 2^64 ndash 1 = 18446744073709551615 ie not hardly big enough

Fortunately in C++ we can define new types like an arbitrarily sized integer (outside of the scope of this course but see the (demonstrat ion) newINT project for a small taste) However this is object orientation ndash surely we can just use an existing already defined arbitrarily sized integer class

79

Task 4

The good news is that in this class you can You can use LEDA (The L ibrary of

Eff ic ient Data types and Algor i thms ) a professional class library of advanced numerical functionality

You will need to download the program called

LEDA-63 i386 msc 10 ( NET 2010) 32 bi t

or

LEDA-63 i386 msc 10 ( NET 2010) 64 bi t

Go to wwwalgorithmic-solutionsinfofreeindexphp Accept the licence terms and download the appropriate version (usually the 64 bit version)

The LEDA installation program will install additional numerical libraries and header files from the Algorithmic Solutions company

Once the setup is complete modify the Lotto program

In the Solut ion Explorer right-click on your project (Lot to ) and left-click on Proper t ies A dialog-box appears

Under the CC++ section

1 Click on General Choose Addi t ional include di rec tor ies and enter the directory CAlgor i thmic Solut ions LEDA-63- free-win-msc10-

s td incl

2 Click on Preprocessor and add LEDA_DLL to the end of Preprocessor

Defini t ions Note the semicolon is required

3 Click on Code Generat ion and check that Runtime Library is set to Mult i - threaded Debug DLL ( MDd)

Under the Linker section

4 Click on General

5 Choose Addi t ional l ibrary di rector ies and enter the directory CAlgor i thmic Solut ionsLEDA-63- free-win-msc10-s td

6 Click on Input and add l ibGeoW_mdd_dl l l ib leda_mddl ib to the end of Addi t ional Dependencies Again the semicolon is significant

You may now close Properties dialog-box

7 Modify your code Add the following under include ltiostreamgt

include ltLEDAnumbersintegerhgt using ledainteger using namespace std

80

Then modify the recur_factorial() function so that it accepts and returns a type called simply integer rather than bigint

Save the project and exit Visual Studio

In order to build and execute Lottoexe Windows needs to have l eda_mdddl l in its search path for DLLs Therefore we need to add the path to the folder containing leda_mdddll to the PATH environment variable

8 In Windows Explorer navigate to My Computer then right-click on it and select Propert ies

9 Click on the Advanced tab and then on the Environment Var iables button

10 In the bottom section (System var iables ) of the dialog box highlight Path and then click the Edi t button

At the end of the existing path add -

11 CAlgor i thmic Solut ions LEDA-63- free-win-msc10-s td

Once more note the leading semicolon is significant

81

12 Restart Visual Studio and re-open Lot to Build and run the application as normal

It might seem that this was a lot of work for such an apparently trivial result but the fact is that you now have access to (and have seen how to use) an advanced numerical library of functionality And anyway when all is said and done you must admit that at least you got a return here ndash which is more than you should reasonably expect from the lottery

Figure 19

Task 5

Explore the LEDA samples and documentation ndash if you installed it there should be a shortcut in your start menu to LEDA-63-free-win-msc10-s td

Task 6

Modify the Lotto program to see how the odds change when there are more balls andor when more balls need to be matched (you might also display more of the intermediate results of calculations ndash like 49)

Destructors

Both constructors and destructors are special class methods We have seen how a constructor is called whenever an object is defined

A destructor has the class name prefixed by a tilde ~ Like constructors destructors cannot return values and therefore they have no return type specified but unlike constructors destructors have no arguments and thus cannot be overloaded

An objects destructor is called whenever an object goes out of scope The purpose of the destructor is to clean up eg to free any dynamically allocated memory that the object was using and release other system resources such as files and database connections etc

In the examples used so far no destructor has been provided for any class created In these programs it has been unnecessary If the programmer does not explicitly provide a

82

destructor the compiler will create an empty destructor in the same way that an empty constructor is created if one is not explicitly created

When classes are created any objects instantiated from them that contain dynamically allocated memory will need destructor methods added to implicitly free any dynamically allocated memory when the object goes out of scope

In the class example shown below the destructor function is ~StudentCourse()

~StudentCourse()

cout ltlt Im being destroyed

7 Arrays vectors lists and hash-tables Arrays vectors and lists are all types of data structures Data structures are areas of memory where collections of the same data type are held The main difference between arrays vectors and lists is that arrays stay the same size throughout the program execution whereas vectors and lists can grow automatically

Arrays consist of a series of elements (variables) all of the same type placed consecutively in memory Each of the elements can be individually referenced by adding an index to the arrays name We saw this type of notation earlier when using arrays

Eg

int examMarks[10]

This declares an array of ten scores score 1 is accessed via an index of zero ndash examMarks[0] and score 10 is access through an index of nine ndash examMarks[9] Very important note that indexes start at zero

The advantage of using arrays compared to using discrete variables (the way we have stored values so far) is it is possible to store any number of values of the same type in an array using the same identifier

With arrays it is possible to store 100 student exam marks or 100 student names with using one unique identifier

Vectors and lists are container classes which were originally part of the Standard

Template Library (STL) The STL evolved into C++ Standard Library ndash which includes iostream etc This is the general-purpose C++ library of functions algorithms and data structures that we can use in our programs While some aspects of the library are very complex it can often be applied in a very straightforward way that allows reuse of sophisticated data structures and algorithms

There are many container classes in the library ndash note that C++ now also provides such a class for the more primitive array

ltarraygt

New in C++11 and TR1 (Technical Report One)

83

A container for a fixed sized array

ltbitsetgt

A bit array

ltdequegt

A double-ended queue

ltforward_listgt

New in C++11 and TR1 A singly linked list

ltlistgt

A doubly linked list

ltmapgt

Sorted associative array and multi-map

ltqueuegt

A single-ended queue

ltsetgt

Sorted associative containers or sets

ltstackgt

A stack

ltunordered_mapgt

New in C++11 and TR1 Hash tables

ltunordered_setgt

An unordered_set unordered_multiset

ltvectorgt

A dynamic array

As with an array vector and l is t can hold objects of various types However unlike arrays vectors and lists can resize shrink and grow as elements are added or removed

The standard library provides access via iterators or subscripting Iterators are classes that are abstractions of pointers (more on pointers later) They provide access to container classes using pointer-like syntax and have other useful methods as well

The use of vectors lists and iterators is preferred to arrays and pointers By using containers common problems involving accessing past the bounds of an array are avoided Additionally the C++ standard library includes generic algorithms (an algorithm is a set of instructions on how to perform a task) that can be applied to vectors lists and other container classes

Declaring and using arrays

Arrays are declared indicating the type and number of elements in the following way

type ar rayName[arraySize]

84

Examples are

int inNumbers[20] an array called i nNumbers of 20 in tegers

char inName [20] an array called i nName of 20 characters

float ExamMarks[5] = 0 an array called ExamMarks of 5 floats with all elements explicitly initialised to zero

const int size = 5 declaring a constant variable size

float ExamMarks[size] When the constant variable size is applied to the array declaration the number of elements is set to 5 This cannot be changed during runtime of the program However it is handy when the number of array elements needs to be changed Changing the constant value size changes the number of elements wherever the ExamMarks array is used in the program

int numArray [2][3] is a multidimensional array with 2 rows and 3 columns

Note Arrays have been used in C++ for many years and there will be code you work with that was written before vectors became available Vectors are are usually preferred to using arrays and pointers Common problems involving accessing past the bounds of an array are avoided when using vectors

Creating an array to hold exam results

Task 1

Open the project Array s ln

Compile and run the program

Run the program adding five exam results The output should be similar to Figure 20

Figure 20

85

Examine the following statements

double ExamMarks[5] = 0 This statement declares the array setting its size to 5 elements and explicitly initialising all elements to zero

cout ltlt Enter Exam Mark ltlt i + 1 ltlt This statement prompts the user to enter an Exam mark into the array at element i + 1

Using the notation i + 1 indicates to the user to enter Exam Mark 1 not exam mark 0 which would be less intuitive

Array elements are numbered from 0 to n - 1 So an array that holds 20 integers will be addressed from element 0 to 19

ExamMarks[0] -ExamMarks[19]

The first number will be entered into element [0 ] The last into element [19]

cin gtgt ExamMarks[i]

This statement reads in the user input and stores the values in the array elements of ExamMarks[i] i is incremented within the for loop and starts at 0

Task 2

As it stands the program could be generally improved ndash see the notes in the code and consider how you might make such improvements

Next modify the program to output the highest and lowest marks entered

Task 3

Modify the program so that the number of marks may be easily changed (at compile time)

86

Task 4

Modify the program so as to break out the part that calculates the average and put it into a separate function

Write another function that given an array of this sort returns the mode mean and median values ndash you will need to pass in references as the function will need to return three values

Lastly put your two new functions into a separate cpp (you will also have to create a h file for Arraycpp to use ndash this will contain the new functions prototypes)

87

Searching Arrays with Linear Search

Linear search allows the user to search the array and establish whether the array contains a value that matches a search criteria defined by the user

The search compares each element of the array with the user input The array is not sorted and this method of searching works well for small arrays For large arrays linear searching is inefficient and it is necessary to use other forms of array searching after the array has been sorted

Linear Search

Task 1

Open the project LinearSearch

Compile and run the program - choose a number between 1 and 100 The output should be similar to Figure 21

Figure 21

88

Examine the following statements

myArray[i] = (1 + rand() 100) This statement uses the rand function part of the ltstdlibhgt header file (included via iostream being included) 1 + rand() 100 produces integers in the range 0 to 99

The function l inearSearch takes three arguments The array name the size of the array the third argument is the search value

if(theArray[j] == value)

return j

This selection statement compares each element to the search value If the search value is in the array the element number is returned to main() otherwise -1 is returned

The if selection statement if(containingElement = -1) in main() is used select the output indicating a successful or unsuccessful search

Task 2

Currently the program searches for the first occurrence the search value only

Modify the program so that it outputs al l matching element locations

This function can be used for turning an int value into a string See also the comment below about C++11s to_string() functions

string convertInt(int number)

stringstream ss

ss ltlt number

return ssstr()

Youll need to include ltsstreamgt to use the stringstream class

89

Task 3

Modify the program so that repeated searches may be carried out

See Figure 22

If using C++11 or later you can also use the to_string() helper functions of the string class eg to_string(10) yields 10

Figure 22

PLUSPLUS Debugging Linear Search

Task 1

For debugging purposes modify the program so as to output the contents of the array

Open and run (exercise solution) LinearSearch to see what this might look like You might want to use the modulus operator () to work out when to neatly break a line

You may or may not like to have the program generate varying sets of random numbers To facilitate this youll need to seed the random number generator by inserting a line of code like this

srand((unsigned)time(NULL))

Note the use of the cast

To use srand() include timeh at the top of your program

90

Sorting Arrays with Insertion Sort

When working with large quantities of data in an array you will need to sort the data at some point This makes searching for information quicker and there are many algorithms available that can be used In the following exercise you will learn how to sort numbers stored in an array in ascending order

SortingSearching an array

Task 1

Open the project Sorts

Run the program and examine the code

The program currently uses a class (sorts) which is defined in sortsh to implement one popular sorting algorithm called Inser t ion Sor t

For details on this algorithm see

httpenwikipediaorgwikiInsertion_sort

91

Task 2

Add a new sort to the sorts class

The text file quicksor t txt (in the Sorts folder) contains the C++ code required to implement another popular sorting algorithm called Quicksor t17

For details on this algorithm see

httpenwikipediaorgwikiQuicksort

Add the quicksort code found in quicksor t tx t to the sorts class - considering what parts of it need to be publicprivate

quicksort tx t is in the same folder as the Sortss ln project file

Step 2

Test the quicksort implementation on a range of values

Alter the quicksort implementation so as to have it sort in descending order

Following on from Step 3 parameterise the quickSort() function so as to add an option to have the array sorted in either ascending or descending order

17 Invented by C A R Hoare ndash Sir Tony Hoare with Christopher Strachey the most distinguished computer scientists Oxfords ever produced

92

Figure 23

93

PLUSPLUS Binary Search (Binary Chop)

Task 1

Now that the array is sorted we can implement a very efficient searching algorithm usually called either binary search or binary chop search

See Figure 24

Modify your project to allow the sorted array to be searched for a value using the binary chop algorithm See opposite

The algorithm for binary chop is quite straight forward

1 Look at the value of the middle element of the array If the value = target then youre done

2 If the value is lt than target discard the lower half of the array treating the upper half as though it were the complete array

If the value found is gt than target you obviously want to look in the lower half

3 Repeat step 1 until the item is found or else the index value becomes invalid

Pseudo code for this algorithm is here

first integer = 0

mid integer = 0

last integer = NumberOfItems

while first ltgt last

begin

mid = first + last 2

if List[mid] = target

exit while Found item

If List[mid]gt target

last = mid In the first half

else

first = mid + 1 In the last half

end

found boolean = List[mid] = target

94

Figure 24

Multidimensional Arrays

Multidimensional arrays with two dimensions (arrays can have more than two dimensions) may be thought of as consisting of data arranged in rows and columns see Table 3

Each element in the array is identified by using two subscripts as shown in Table 3 The first subscript identifies the element row and the second identifies the element column a[0] [1] identifies a value in Row 0 Column 1

The array in Table 3 contains two rows and three columns and can be called a 2 by 3 array

Column 0 Column 1 Column 2

Row 0 a[0] [0] a[0] [1] a[0] [2]

Row 1 a[1] [0] a[1] [1] a[1] [2]

Table 3 ndash Array Layout

A multidimensional (2 by 3) array of doubles is shown in Table 4

Column 0 Column 1 Column 2

Row 0 2367 6792 8557

Row 1 1276 9132 2789

Table 4 ndash Array Values

95

Creating a multidimensional array

Task 1

Open the Mult iDimArray

project

Compile and run the program adding 2 exam results for each of the two students The output should be similar to Figure 25

Figure 25

96

Task 2

Examine the code used to write values to and read from a multidimensional array

Examine the following code segments

double ExamMarks[2][2] = 0 This statement creates a two-dimensional array having two rows and two columns and initialises the elements to 0

Every element in the array is identified by an element name in the form a[x] [y] where a is the name of the array and x and y are the subscripts that uniquely identify each element in a Notice that the names of the elements in row 0 all have a first subscript of 0 see Table 5 The names of the elements in column 1 all have a second subscript of 1

Note multidimensional arrays can have two or more dimensions (subscripts) Three-dimensional arrays are uncommon

Column 0 Column 1

Row 0

a[0] [0] a[0] [1]

Row 1

a[1] [0] a[1] [1]

Table 5 ndash Array Indexing

97

Examine the following code segment used to read values in to the array

for(int row = 0 row lt 2 ++row)

for(int col = 0 col lt 2 ++col)

cout ltlt Enter Exam Mark No

ltlt col + 1

ltlt for student No

ltlt row + 1 ltlt

cin gtgt ExamMarks[row][col]

cout ltlt endl

The two for loops work taking one row at a time (the outer for loop) and looping through the columns in that row (the inner for loop) When the marks have been entered for all the columns in row 0 row 1 is selected and values entered for each column cell in row 1

Table 6 shows how four results would be allocated in a 2 x 2 multidimensional array

Exam mark 1 Exam mark 2

Student 1 67 71

Student 2 61 58

Table 6 ndash Populated Array

98

Examine the following code segment used to calculate the total of each students marks

if(row == 0)

r1total += ExamMarks[row][col]

else

r2total += ExamMarks[row][col]

r1total is a variable to hold the sum of values in column 0 and 1 for row 0 (Stud1) r2total sums the values in the columns for row 1 (Stud 2)

Selection for each row is made with if(row == 0) this is Stud1 If row is not 0 then row must be 1 and the mark can be added to r2total If three exam marks were input per student the code for selecting the marks would need to change

Task 3

Modify the program to read in four exam marks for f ive students

Establish the highest and average mark for each student Output the results

One way to do this is to keep a separate array to record the students statistics An alternative would be to extend the existing arrays row so that it may hold the necessary student data

99

Declaring and using vectors

Vectors are declared indicating the type and number of elements in the following way

vectorlttypegtvectorName

vectorlttypegtvectorName(initialSize)

vectorlttypegtvectorName(initialSize elementValues)

Examples

A vector called i nNumbers with no initial size to hold doubles

vectorltdoublegt inNumbers

A vector called Name with an initial size 20 to hold characters

vectorltchargt Name(20)

A vector called ExamMarks holding integers with initial size of 4 elements each with the value 6

vectorltintgt ExamMarks(46)

Note In previous exercises you have created your own member functions In the following exercises you will use some of the vector class member functions Some of these are begin() end() erase() and size() See section 12115 for more detail

The standard library also includes a large collection of algor i thms that manipulate the data stored in containers (vectors are one of several types of container)

You can sort the order of elements in a vector (vec) for example by using the sort algorithm

sort(vecbegin() vecend()) C++11 sort(begin(vec) end(vec))

You can find a value (69) in a vector by using the find algorithm

ptr = find(vecbegin() vecend() 69) See C++ note above

100

ptr is an iterator to store the memory location of the element found

You can reverse the order of elements in a vector for example by using the reverse algorithm

reverse(vecbegin() vecend()) See C++ note above

There are two important points to notice about the call to reverse First it is a global

function (as are find and sort) not a member function Second it takes two arguments rather than one and operates on a range of elements rather than on the container (vector container in this case)

With the above examples the range is the entire container from begin() to end() (vecbegin() to vecend()) reverse like the other standard algorithms is decoupled from the libraries container classes The reverse algorithm can be used to reverse elements in vectors in lists (another container) and even elements in C arrays

int myArray[] = 1 6 20 4

reverse(myArray myArray + 4)

for(int i = 0 i lt 4 ++i) Lets see the reversed array

cout ltlt Array[ ltlt i ltlt ] = ltlt myArray[i]

In the above example the first argument to reverse is a pointer (pointers are covered in Section 8 but for now we can say the first argument points to the address in memory that is the start of the vector ) to the beginning of the range and the second argument points one element past the end of the range This range is denoted (myArray myArray + 4)

Arguments to reverse are i terators which are a generalization of pointers which is why it is possible to reverse the elements of a C array using the array address and pointer notation

Creating a vector to hold exam results

Task 1

Open the Vector project

Compile and run the program adding five exam results The output should be similar to Figure 26

101

Figure 26

Examine the following statements

include ltvectorgt This statement includes the header file vector enabling the program to use the class template vector (templates allow the use of generic functions that admit any data type as parameters and return a value more on this later)

vectorltdoublegt ExamMarks(5) This statement declares the vector to hold doubles and sets the initial size to 5 elements

Note Although vectors can grow to any size it is good practice and more efficient to specify the size when this is known When no size is given and the contiguous memory spaces have been exhausted the elements must be copied to a larger memory space to increase the size of the vector

cin gtgt ExamMarks[i] This statement reads in the user input and stores the values in the vector slot i of ExamMarks[i] i is incremented within the for loop Note that we the same indexingsubscripting syntax as we used previously with arrays ie[ ]

102

Task 2

Modify the code so as to accommodate the adding of an extra exam mark

Note this should not be done (simply) as part of the loop but as a separate action later and you should use the vectors push_back() method to facilitate this

push_back() is a member function of the vector class that adds an additional vector element at the end

After adding the extra mark you will need to generate a new set of statistics ie the average will have changed now To do this separate out the statistical code and place it in a separate function so that you may re-use later (after the new data has been entered)

size() is a member function (method) of the vector class It can be used to establish the size of a vector

The statement for(int i = 0 i lt ExamMarkssize() i++) uses the vector member function size() available to the vector ExamMarks to obtain the size (number of elements) in the vector The size of the vector is used to identify a terminating value that ends iteration of the for loop

Task 3

Open VectorSor t

You will see three TODO sections in the code which need completing

1 Populate a vector with 100 randomly generated numbers

2 Sort the vector

3 Reverse the vector

For sortingreversing you will can use the algorithms sort() and reverse()

Heres a useful link hellip

httpwwwcpluspluscomreferencealgorithm

103

Using insert() and iterators

Task 1

Open and modify the skeleton project called Inser t

Important areas of the program are explained in the steps opposite

Examine the code

vectorltintgtiterator it

This statement creates an iterator that is used to access members of the vector

Iterators are used to access members of the container classes (the container type vector in this case) and can be used in a similar manner to pointers

In the example iterator it is used with the insert() function to place the value (200) at the beginning of the vector nums

it = numsbegin()

This statement uses the vector member function begin() to initialise the iterator it with the address of the start of the vector

it = numsinsert(it 200)

This statement uses the member function insert() and iterator it to insert 200 at the beginning of the vector (it)

Note that an iterator is returned by the function insert() that points to the newly inserted element

104

numsinsert(it + 1 numsTwobegin()

numsTwoend())

This version of the insert() function takes 3 arguments and is used for copying in part or full another collection This may be a vector a plain C++ array or some other collection that is accessed using pointersiterators

This statement inserts a second vector (numsTwo) into nums The three parameters are (copy to nums+1 from star t of numsTwo to end of numsTwo)

it = numsinsert(it + 2 696 )

This version of the insert() function takes 2 arguments The iterator it + 2 points to element number three it points to the beginning of the vector and the 2 moves two elements in The value 696 is inserted at that element

void display(vectorltintgt amp vec)

cout ltlt Vector contains

for(

unsigned int i = 0

i lt vecsize()

++i

)

cout ltlt vecat(i) ltlt

Function display() is passed a reference to a vector and outputs the vector contents used throughout program

105

Task 2

Add the code shown in Figure 27 to the program and using the insert() member function add the array to the nums vector at position two (in the vector) Output the contents of the nums vector to screen

int myArray[] = 5 6 3 4

Figure 27

stdarray

C++11 Introduced a new template array type called stdarray

stdvector is a template class that encapsulates a dynamic array that is stored on the heap and that grows and shrinks automatically if elements are added or removed It provides all the hooks (begin() end() i terators etc) that make it work fine with the rest of the STL It also has several useful methods that let you perform operations that on a normal array would be cumbersome like inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes) Since it stores the elements in memory allocated on the heap it has some overhead in respect to static arrays

stdarray is a template class that encapsulates a static array that is stored inside the object itself which means that if you instantiate the class on the stack the static array will be on the stack Its size has to be known at compile time (it is passed as a template parameter) and it cannot grow or shrink

It is more limited than stdvector but it is often more efficient especially for small sizes because in practice it is mostly a lightweight wrapper around a C-style array However it is more secure since the implicit conversion to a pointer is disabled and it provides much of the STL-related functionality of stdvector and of the other containers so you can use it easily with STL algor i thms

Here is a small example demonstrating the template and some other C++11 extras such as auto and a ranged-based for loop

106

include ltstringgt include ltiteratorgt include ltiostreamgt include ltarraygt using namespace std template ltsize_t N class Tgt arrayltT Ngt make_array(const T amp v) arrayltT Ngt ret retfill(v) return ret int main() The char here can be inferred and so is optional auto a = make_arraylt10 chargt(1) for (const auto amp s a) stdcout ltlt s ltlt system(pause) return 0

1 1 1 1 1 1 1 1 1 1 Press any key to continue

Declaring and using lists

Lists are a kind of sequence container similar to vectors The elements of a list are ordered following a linear sequence with storage handled automatically by the class

List containers are implemented as doubly-linked lists and it is worth noting that elements may be in different and unrelated storage locations

Ordering of a list is kept by a relationship to each element of a link to the element preceding it and a link to the element following it

Because linking information is associated with each element (possibly to different and unrelated storage locations) extra memory may be used to keep the linking This may be important when using a large list

l is ts tend to perform better than vectors at inserting extracting and moving elements in any position within the container but lack direct access to the elements by their position and because of this have a slower access time than vectors Access to an element has to be via a known position (the beginning or the end) and there is a time cost in linking between the known position and the element to be accessed

107

lists are declared indicating the type and number of elements in the following way

listlttypegt listName

listlttypegt listName(initialSize)

listlttypegt listName(initialSize elementValues)

Examples

A list called inNumbers with no initial size to hold doubles

listltdoublegt inNumbers

A list called Name with an initial size 20 to hold characters

listltchargt Name(20)

A list called ExamMarks holding integers with initial size of 4 elements each with the value 6

listltintgt ExamMarks(46)

72 Hash Tables and Cached Calculations

This section has ultimately really been about introducing you to templates and algorithms and well mix both now in a final example

From the binary chop exercise earlier we have seen that sorted arrays provide a very efficient means of storing data for later look-up However we have to bear in mind the algorithmic cost of sorting the array in the first place ie if we have a million unsorted items in our list and we want to find a single item (only) is it better to sort the entire list first and then find the item or is it better to simply walk through the array from the beginning ndash after all we could safely assume that weve a 5050 chance of finding it in the first half of the array Of course as were sorting we could keep an eye open for our item ie we could combine a (partial) sort with look-up operation ndash over time if we repeat this procedure looking for other items we will ultimately sort our array as a side -effect of the look-up operations

But lets move on a little and just consider the fastest look-up method we know so far that carried out on a sorted array using binary chop and think about our programs overall performance when we need to insert additional items into the array When considering problems like this we always think of the worst case hellip despite their often being fans of

108

Monty Python Computer Scientists rarely look on the bright side of life The worst case here is that we need to insert an item into array position zero

Eg say we have this sorted array (look-up operations average O log2 N = fast)

15 24 25 31 78 250 255 262 277

We now have to insert the value 5 into this array Using normal array indexing methods how many operations will this take

5 15 24 25 31 78 250 255 262 277

Each item needs to be shuffled up one position to the right and if weve millions of items that is rather costly especially if the next thing were likely to do is to insert another item

So weve seen that accessing sorted data is very useful and weve also seen that sorting and especially inserting items can be costly The big question is then is there a way we can make both just as efficient - finding andor inserting an item in Olog2N or O(1) (constant time)

Hash Tables

A hash-table is a data structure designed to allow for both rapid insertion and look-up

Although any specific hash-table is implementation specific (there are very many different types of hash-table) well quickly go through the basics

The storage medium well use for our hash-table is an array of strings and we will say that this array has just 10 elements It looks like this

string myhash[10]

Well use this hash-table to store words and well determine the array index for any specific word using a hash- funct ion ndash something that will take a word as its input and return an array index as its output

109

unsigned hashfunc(string s)

unsigned result = 0

for(unsigned i = 0 i lt slength() ++i)

result = result + s[i]

return result 10

hashfunc() iterates through s keeping a running total of the sum of the ASCII codes for each of the characters eg hashfunc(hash-table) computes

h + a + s + h + - + t + a + b + l + e

where the characters ASCII values are

104 + 97 + 115 + 104 + 45 + 116 + 97 + 98 + 108 + 101

The total = 985 and 985 modulus 10 = 5

The final computed value will be used as an index into the array The modulus value used is the size of the hash-table and we use it so as to ensure that resultant computed index value cannot be greater than 9 (remember our arrays indexes are 0 ndash 9)

We can now store words in the myhash array like this

string myhash[10]

string s = hash-table

index = hashfunc(s)

if(myhash[index] = )

myhash[index] = s

else

The complex part is what to do if we have what is called a collision ndash when we find that myhash[index] is already occupied Youll probably have already thought of what value hashfunc(elbat-hsah) will have

One way to help avoid collisions to use a better hash-function and a larger array However in real life collisions are practically impossible to avoid and the only other option to deal with them is to allow more than one string to inhabit an array slot in some way ndash perhaps by having each of the original array slots contain an array ndash rather than an individual string Of course in this case we would also need some way to determine which of the n colliding entries is the one were interested in ndash is it elbat-hsah or hash-table

110

Well briefly leave our examination of hash-tables at this point and instead look at Fibonacci numbers Do not worry we will return to hash-tables very soon

Fibonacci numbers are the numbers in the following integer sequence

0 1 1 2 3 5 8 13 21 34 55 89

By definition the first two numbers in the Fibonacci sequence are 0 and 1 and each subsequent number is the sum of the previous two More formally that is

119865119899 ∶= 119865(119899) ∶=

0 119894119891 119899 = 0 1 119894119891 119899 = 1

119865(119899 minus 1) + 119865 (119899 minus 2) 119894119891 119899 gt 1

Computing Fibonacci Numbers

Task 1

Open Cached_fibonacci

Compile and run the program as is

Examine main() and the calcfib() functions

bigint calcfib(bigint n)

if(n == 1 || n == 0)

return n

else

return calcfib(n - 1) + calcfib(n - 2)

bigint is defined as a unsigned long long int and we have used typedef to save some typing

NOTE The method used to calculate Fibonacci numbers here has been selected because it is perhaps the most obvious way to turn the formal definition into code If you are interested please see the separate Fibonacci project for two other examples of how to calculate Fibonacci numbers

111

Modify the beginning of the calcfib() code

bigint calcfib(bigint n) cout ltlt calcfib was passed ltlt n ltlt endl

Modify main() to set max = 5 and re-run the program

calcfib was passed 0 Fibonacci number 0 is 0 calcfib was passed 1 Fibonacci number 1 is 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 2 is 1 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 Fibonacci number 3 is 2 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 4 is 3 calcfib was passed 5 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1

Fibonacci number 5 is 5

112

Note that to calculate Fibonacci number 5 we calculate Fibonacci number 4 and Fibonacci number 3 - even though weve previously calculated Fibonacci number 3 in order to calculate Fibonacci number 4

To fully appreciate the growth of this process re-run the program adding 10 to max for each subsequent run You maymay not like to comment out the line you inserted in Step 2

Task 2

Getting back to Hash Tables Using a hash-table to store previously computed Fibonacci numbers

As it stands the incomplete solution declares a template hash-table called fibs of the type unordered_map

Read the comments in the function fibCache() and modify the code to as to use the fibs hash-table to store previously computed Fibonacci numbers

fibs[n] = f stores f the n-th Fibonacci number in the n-th slot of fibs (which as you can see you may treat as an array for indexing into)

8 Pointers In C++ programming data (variables) can be referenced via the memory address of the variable This is done using a pointer var iable

A pointer var iable contains the address (location in memory) of a data variable

There are also functional pointers ie those that point to code rather than data and these are briefly explored later

Pointers can be particularly useful when interacting with the operating system andor when working with arrays - as the elements in an array will always occupy consecutive memory places Incrementing the pointer variable by one addresses the next array element

Lastly pointers are also used to fake pass by reference

Declarat ions

int n This is a standard variable declaration n that contains a value as yet unknown of type int

int p This is a pointer p that can hold (point to) an address that contains a variable of type int The type of p is int

Each variable declared as a pointer must be preceded by an asterisk () This modifies the type of the object being declared from thing of type to pointer to thing of type Eg int n means n is an int whereas int n says that n is a pointer to an int

113

int age height age is a pointer to an int height is an int value

double far cent are both pointers to doubles

Pointers can be initialised when they are declared or set using an assignment It is common to initialise pointers to a memory address but they can also be initialised to the predefined constant NULL ndash meaning that they do not (as yet) hold (point to) a valid memory location NULL is defined in the standard library such a pointer is called a nul l pointer

When is used in a variable declaration it indicates the variable being declared is a pointer and not a value

But do beware as is used elsewhere with pointers when the appears before a previously declared pointer variable elsewhere in the program it is said to dereference the pointer and so is used to access data stored at the address which is stored in the pointer A dereferenced pointer is essentially the variable to which the pointer was originally set to point

To complicate matters further using the pointer name without the dereference operator references whatever is stored in the pointer variable itself ndash this is the address of the object it references in memory (which maybe NULL of course)

As we have seen using can mean two things that something is being declared as a pointer or that a previously declared pointer is being dereferenced Experienced programmers sometimes enter the two usages differently ndash a notation we would highly recommend ie

int n n is an object that can hold the address of an int

int k = 0 k is an int holding the value zero

n = ampk n is set to hold ks address amp is explained below

n = 1 k (yes k) is set to hold the value 1

Note the space used in the different usages - int n vs no space in n

Initialising pointers

Pointers can be initialised in two ways

int x = 16 y = 69 variable declaration and initialisation int x_ptr = ampx pointer declaration and initialisation x_ptr holds the address of x int y_ptr pointer declaration yptr is a pointer

y_ptr = ampy pointer assignment yptr holds the address of y

Once declared a pointer variable can be assigned the address of another variable using the amp the addressof operator

114

Note the variable name should not be prefixed by the in the assignment statement unless the pointer is initialised immediately in the variable declaration

We also use pointers when creating objects on the Heap for example we can create and initialise a string object like this string pstring = new string(Hi there) Such objects are not normally tidied away as are the objects created on the stack - objects simply declared in a functionmethod and so they should explicitly be tidied away using delete eg delete pstring For more on this subject see section 9

Using pointers

Task 1

Open the project Pointers

Compile and run the program The output should be as shown in Figure 28

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int x_ptr = ampx This is x_ptr pointer declaration and initialisation

int y_ptr Declaring another pointer y_ptr

y_ptr = ampy Initialising y_ptr

y_ptr = x_ptr Assigning x_ptr contents to y_ptr Both pointers are pointing to variable x (16)

y_ptr = ampy Assigning the address of y back to pointer y_ptr

y_ptr = 170 Assign 170 to the variable at memory location of y_ptr y_ptr points to variable y so 170 has been assigned to y

115

Figure 28

Pointer Arithmetic and Arrays

We have seen that once a pointer is initialised it has a memory address and this address can be reassigned another address It is also possible to change an address using standard arithmetic

The ++ and -- increment and decrement operators can be used to move the pointer along to the next or back to the previous memory address To jump more than one memory address you would have to use the assignment operators += and -=

When using arrays and pointers the array name is the address of the first element in the array

int intArray[] = 1 2 3 4 5

int int_ptr = intArray Same as int int_ptr = ampintArray[0]

The pointer has been declared and initialised with the statement int int_ptr =

intArray Note there is no need to use the address of operator amp when initialising arrays as the array name is the address of the beginning of the array

When working with arrays each element of the array will be the type and size at declaration When an array is declared to hold integers each element will usually be 4 bytes in size An array of doubles will have element sizes of 8 bytes Note ndash these sizes are actually down to the compiler being used and are usually in turn dependent upon the operating system being used

It is not important to know how many bytes make up each element Moving the pointer through the array with the assignment operator x_ptr += 2 will move two elements further through the memory allocated for the array or 16 bytes for an array of doubles

116

Pointers and Arrays

Task 1

Open the project PointerAr i thmetic

Compile and run the program The output should be the same as Figure 29

Examine the program carefully

You may not fully follow the program at first glance as it employees a few potentially new constructs (it depends how far weve got through the lectures)

One slightly truncated new construct is

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

A struct in C++ is just like a class except that the default public and private sections are reversed By default everything in a struct is public

typedef in C++ allows the definition of our own types based on other existing data types

typedef exist ing_type new_type_name

where exist ing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining For example

117

typedef unsigned int WORD

typedef char pChar

You may also remember initialiser lists from earlier eg

s_thing(int a) a(a) b(sqrt((double)a))

If we re-write this

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

We quickly see that a(a) and b() are initialising the a and b struct members const int a and const double b

118

Remember that as these are const we cannot use assignment

typedef struct s_thing

const int a

const double b

s_thing(int a)

Error ndash a and b are const

this -gt a = a

this -gt b = sqrt(a)

thing

Lastly when dealing with pointers to compound types one may access the members of the type via dereferencing or via the so called crows foot operator

(t) dereferences t giving us a thing which was pointed to by t Then we use the dot operator to access the member (t)a

We have to parenthesiset otherwise the would bind to t first ie it would be as though we had done this (ta) which would be an error

The crows foot saves us the dereference t-gta is just like (t)a

119

Figure 29

PLUSPLUS Pointers and Arrays

Task 1

Open and modify the skeleton project called ReverseArray

In main() create an array of 10 integers Fill the array with random numbers between 0 ndash 100

Write a helper function called to output the contents of the array to the console A suitable prototype for this would be void dumpArray(int array[] int size)

Write a helper function to reverse the contents of the array Use a temporary variable as an aid A suitable prototype for this function would be void reverseArray(int array[] int size)

Reverse the values in the array using only pointers

120

Reverse the array without using a temporary variable You should use the XOR operator ^ to achieve this

Pseudo code for an XOR swap is

X = X XOR Y

Y = X XOR Y

X = X XOR Y

The completed program should look like Figure 30

Figure 30

Task 2

Reverse the array using a vector and the standard function template stdreverse()

We can also have pointers to functions in C++ (and C)

The name of a function resolves to be its address in memory (somewhat similar to the case where we use the name of an array) When we call a function we use this name to retrieve the functions address and then use the function invocation operator to execute it The function invocation operator is the set of brackets you use eg

Lets take an example

121

include ltiostreamgt

using namespace std

int lue() life the universe and everything

return 42

int main()

cout ltlt The address of the function lue is

ltlt lue

ltlt invoking it yields

ltlt lue()

ltlt endl

system(pause)

return 0

Typical output is shown in Figure 31

Figure 31

122

We can also store addresses of functions in variables (theyre just numbers) and the type system allows for us to describe and declare scalar variable types for function pointers eg this modified code fragment would produce the same output as that show above

fp is a pointer to a function taking

no arguments and returning an int

int (fp)()

fp = lue

cout ltlt The address of the function lue is

ltlt fp

ltlt invoking it yields

ltlt fp()

ltlt endl

fp is a funct ion pointer var iable so it may be used to point to any other function having the correct signature at runtime

PLUSPLUS Function pointers

Task 1

Open the project Calculator

Compile and run the program The output should be as shown in Figure 32

123

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int (fp)(int int) This is the function pointer declaration It may point to functions that take two integers and return an integer

Like all automatic storage class variables fp will currently be pointing at a random location What happens if you run the program without setting fp to point to an actual function Comment out the switch to find out

switch (Operator)

case 0 fp = Add break

case 1 fp = Subtract break

case 2 fp = Multiply break

The code could do with improving

Modify it to allow for multiple trials eg add the necessary logic to loop and perform multiple calculations ndash youll need to add some way to end the program too therefore

Modify it so that the operator may be inputted as an operator character eg + - etc Allow X x and for multiplication and add for division

All three pieces of information could be entered on a single line eg 6 x 7ltentergt Using cin to read that data just requires you to use three cin statements

cin gtgt X

cin gtgt Operator

cin gtgt Y

Lastly modify the program to that it uses floating point arithmetic

124

Figure 32

9 APIs New Delete and Dynamic Memory As has been stated earlier pointers are useful in a variety of situations However because they are easy to get wrong ndash and when they go wrong everything goes very wrong indeed ndash languages like C++ have tried to make their use the exception rather than the norm For example without reference arguments (eg void someFunc(int amp)) we would have to use pointers to achieve the same functionality and performance

On the whole the underlying philosophy when it comes to pointers is to try to avoid using them whenever possible You can get a real feel for this subject by Googling for smart pointers c++ and from Wikipedia httpenwikipediaorgwikiSmart_pointer

Two areas where we absolutely need pointers are when calling into an external API (Appl icat ion Programming Interface ) and when allocating memory for our own purposes ndash the latter case is also eased by advances in the library support in C++

Using an API

An Appl icat ion Programming Inter face is functionality provided by some third party The most obvious API whether it is Windows Linux or OSX is that exposed by an operating system

If your application needs to interact with the user in any non-portable way you will need to call into your OSs API For example if you want to display a dialog box you will need to access the OSs functionality to do so (perhaps indirectly through a framework like Nokias Qt - httpsenwikipediaorgwikiQt_(framework)) In summary if you ever want to go outside of the standard libraries andor writing consoleterminal applications you will need to call into your operating systems API

When it comes to calling into operating systems pointers are used extensively As an example 1 Google for Linux API 2 Find any website that lists the API functions and then 3 click-through to any function The odds are that the function prototype you see will contain asterisks (pointers)

125

Dynamic Memory Management

The second area where you simply must know something about pointers is when it comes to using the heap

The heap is an area of memory available to your programs You may allocate and use the heap as you wish

Why would you want to do this Normally its to create variable length arrays or to model and use an advanced data structure of some sort a self-balancing red black tree perhaps (httpenwikipediaorgwikiRedAndblack_tree) Of course the more esoteric the data structure and less likely it is that it will be incorporated into the C++ standard library (although the library does contain most of the generally useful and popular ones like doubly l inked l is ts )

To allocate memory from the heap in C++ you use the new keyword and to return it you use the delete eg

int nSize = 12

note nSize does not need to be constant

int pArray = new int[nSize]

pArray[4] = 7

delete [] pArray

10 More on Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine Encapsulation is data information or detail hiding

Once a function is written the detail of how it works is not important to the end user The user needs to understand what data to input and what output will be produced

One of the most important aspects of writing programs using functions is that the functions can be reused from one project to the next Think about the standard functions youve seen already eg the square root function sqrt() Libraries contain atomic generally useful functionality that is likely to be of use at some future time It is useful to bear this thought in mind whenever we build new programs ie we should be on the lookout for generally useful functionality (given our domain) that we should consider coding as functions for later reuse The same goes for classes of course

Probably the most important function in your program in main() ndash without it you do not have a program at all

main() is your programs entry point and as such it may be used in such a way as to inform the rest of your program as to the actions required

126

main() and command-line arguments

Task 1

Open a Command Prompt or PowerShell Prompt and enter the following

dirltreturngt

di r Odltreturngt

t ree ltreturngt

t ree altreturngt

dir and t ree etc are like mini-programs They have default functionality which may be altered by providing additional command-line arguments eg for the dir command dir L N 4 TC

Command-line arguments are passed to your programs by optional parameters eg

int main(int argc char argv[])

Where argc is a count of the number of arguments and argv is an array of pointers to arrays of character (C strings) for each argument being passed Note that argc is always at least 1 and so argv always contains at least one entry ndash this is the name of the program being run

Task 2

Open (demonstrat ion)

CommandLineArgs and Build and run the program

Examine the code

The programs configuration is Debug

In the projects Project | Debugging | Command

Arguments you will see where the programs default command-line arguments are set for debugging purposes

Using the command prompt you opened earlier navigate to your where CommandLineArgsexe is located

CommandLineArgs debug

Run the program by entering its name followed by a variety of arguments eg

gtCommandLineAgs one two threelte ntergt

127

Task 3

Open the project UserPrompter project

Run the program and then examine its code

We will modify this program to use a command-line argument However before doing that its worth pointing out that the primary purpose of this program is to demonstrate the separation of a class declarat ion with its implementat ion (the mechanismfunctionality of class prompter is defined in promptercpp but its capabilities are declared in prompter h )

Its also interesting to note that the optimal strategy is to use an algorithm called binary search or binary chop (we saw this earlier in the course) with each guess you reduce the number of possible solutions by a half This sort of algorithms Big Oh is Log n (where log is base-two logs)

httpenwikipediaorgwikiBig_O_notation

Task 4

Modify the program so that the upper range for the max value is given as a command-line argument

The UserPrompter cpp is the file youll need to modify

Test your program via the setting the projects Command Arguments as detailed above -or- by running the application standalone in a command prompt after building (also as detailed above)

See Figure 33

To convert a string into a number (weve seen one other way of doing this earlier) we can use

include ltcstdlibgt

and the function atoi() eg

atoi(argv[1])

128

Figure 33

EncryptDecrypt a file

Task 1

Open compile and run the EncodeDecode project

Complete the program so that it may be run outside of the IDE and process a file for encryptiondecryption

This is actually quite a simple task as youll only need to add a couple of lines of code However the project also demonstrates how to use the Debug and Release modes to influence the way a program runs ie that in its Debug configuration the program automatically runs through a test

Other things to note include using bitwise XOr to perform the encoding and the use of the C standard library functions putchar() and printf() to perform some of the output eg putchar() is used to output a CR to the console window (CR = char 13)

129

Figure 34

Multiple arguments overloading and default values

In C++ we can over load functions ndash meaning that we can provide different versions of the same function (the different versions must differ by the number andor type of the parameters they take) For example

130

void foo(double d) 1

cout ltlt In void foo(double d)nn

void foo(long int n) 2

cout ltlt In void foo(long int n)nn

void foo(int n) 3

cout ltlt In void foo(int n)nn

double dtest = 0

long int ltest = 0

int ntest = 0

foo(dtest) Calls 1

foo(ltest) Calls 2

foo(ntest) Calls 3

In the above the compiler works out which version of the foo() to call based upon the argument type it is given

We can also overload functions if the number of arguments differ eg

131

void bar(double d)

void bar(double d double t)

We would use a feature like this if sometimes we needed to use extra information ndash in the shape of passing in t in the above eg we would most likely implement void bar(double d) as

void bar(double d)

bar(d 25) Call bar(double d double t)

What were really saying above is that in most cases the implicit double second parameters value is normally 25 ndash perhaps its a standard discount percentage ndash and only occasionally we will need to change that value in which case wed call bar(double d double t) directly and not by going through bar(double d)

Lastly C++ has one extra feature that can make this simpler ndash defaul t arguments

Rewriting bar using this feature we get

void bar(double d double t = 25)

Note that we now only have one bar function now and that we may call it like this

bar(x)

Or like this

132

bar(x y)

In the case of bar(x) the second parameter is omitted and so will receive the default value of 25 in the second example t will receive ys value

Although outside the scope of this class for more on overloading see the (demonstrat ion) Operator Over loading project This shows how to overload the ++ pre and post increment operators overload and provide your own ltlt stream insertion operator (and one use of a friend function) and using an enum with a typedef

Passing Arrays to Functions

To pass an array to a function it is only necessary to pass the array name and the number of elements in the array

The array name is the position (address) in memory of the first element The number of elements is passed to enable the function to establish the array size

An array declared as double somearray[10] would require a function call somefunction(somearray 10)

Passing Arrays to functions

Task 1

Open and modify the skeleton project called the project called ArrayReturnValue

Pass an array to a function to read in five numbers

Pass the array to another function to calculate the average value in the array return this to main() and output to screen

Lastly at the end of the program output the values in the array from within main() The finished program should look something that that in Figure 35

Create two function prototypes

void enterMarks(double ExamMarks[] int num)

double calcAverage(double ExamMarks[] int num)

ExamMarks[] is the array to be passed As with passing variables it is not strictly necessary to give the argument a name in the prototype just its type This could have been written as calcAverage(double [] int) However it is sometimes useful to include this information as it might help explain the functions operation

It is also necessary to pass the size of the array num is the number of elements in the array its size

Within main() declare the array and initialise the elements to zero with the following statement double ExamMarks[5] = 0

This declaration explicitly initialises the first element to zero and implicitly initialises the remaining four to zero

133

Create both functions

enterMarks to read in the values and calcAverage to calculate the average (you will need a for loop in each function)

Return the average value from calcAverage to main() and output the value using cout

Call the functions from within main() with the following statements

enterMarks(ExamMarks 5)

average = calcAverage(ExamMarks 5)

You may output the average directly of course ie without first storing the value in average

At the end of main() add the statements

for(int i = 0 i lt 5 ++i)

cout ltlt Exam Mark Number

ltlt i + 1

ltlt is

ltlt ExamMarks[i]

ltlt endl

ltlt endl

134

Explain how it is possible at the end of the program to output from within main() all the values in the array entered within the function

Modify the program so that the number of exam marks (5) appears only once

In previous exercises when parameters (variables) were passed to functions the function received a value When a value is used in a function a copy is stored in a part of memory that only exists from the time the function is called to when it ends After this the memory and any value in it are lost

However the array in this exercise was initialised in main() with zeros and then passed to the function Data was then added to the array and calculations done At the end of main() the values in the array elements are output The array contains values input from within the function

The name of the array is the address of the first element of the array in the machines memory As the starting address is passed (the name of the array) the called function knows where the array is stored in memory

Because we are working with memory addresses (references ) any changes made to array elements in the function affect the memory location set up in main() for the array

C++ passes arrays to functions by reference (to the memory location of the first element) In previous exercises functions were passed values copies of the variables in main()

135

Figure 35

Passing Two-dimensional Arrays to Functions

It is common to want to store numbers in a two dimensional layout of rows and columns as shown in Table 7

187645 783473 298372

871223 629399 561201

Table 7

This arrangement is known as a two-dimensional array or matrix

C++ uses an array with two subscripts to store a two dimensional array

double Balance[2][3]

When we specify a one-dimensional array the number of elements must be given

When a two-dimensional array is specified it is necessary to specify the array elements in both dimensions We therefore specify the number of rows and columns

The Balance array in the statement above has two rows and three columns

11 Inheritance and (not presented) Polymorphism

111 Inheritance

In Object Oriented languages like C++ inheritance describes a relationship between classes of objects and which usually implies some sort of a sub-division of labour

For example lets say that we want to build an IT system that has something to do with the members of the university

136

In an OO world the first question usually is how would we categorise our significant entities and that always means naming things what names would we use to categorise university members When modelling (for that is what were going to be doing) real-world objects its sensible to use proper names So heres an attempt ndash to broadly categorise university membership

Members are members of the sets

Students

Staff

Other

What is other though

The Bodleian and the card-office issue Readers cards ndash so is a Reader a university members or are they something else And if they are something else does our system really want to concern itself them Or more broadly does our system really want to concern itself with holders of cards issued by the card-office

Are all students really the same

What sort of students do we have at Oxford (and do we want a system ndash either now or in the future ndash that might be interested in recording the differences) Lets see we have undergraduates and graduates We also have Rhodes scholars ndash but are these sorts of student that are distinct (or should be in our system) from our underpost-graduates categories And how about graduates would we want to have some sort of sub-groups Masters students MScMBAMPhil or Doctoral students DPhilDScDLitt etc Perhaps wed like to know something about how theyre being funded ndash and we might want that piece of functionality shared by our undergraduates

We can of course go through the same process when thinking about members of staff (university staff departmental staff members of congregation academic staff fulltimepart-time staff casual staff ndash and how about staff that are sometimes (or also) students) We can go on thinking about this sort of thing for a very long time and we should as its important and when its important it has a name ndash Object Oriented Design or OOD

One of the things wed hope to see appear as part of the OOD phase is the relationship between entities For example if we were to say that a common property of all university members is that they have a date-of-birth we wouldnt want to have our Student and Staff C++ objects contain this information directly by way of some datastate class member (which might seem a little odd at first) But think about it If we performed some validation on the members DoB (perhaps when its being set) we would need to include this in both Student and Staff classes Or as an alternative we would capture the validation in some external function ndash which we would call from the separate classes (if we remember) No its messy and it would be much better if we thought of things this way that all university members are people and that people all have dates of birth

To put it another way we would say that studentsstaffother are just specialisations of people ndash they are people but with a bit of extra something tagged on to them ndash like a bod card number

Now if we also had some way of capturing people stuff in say a basic Person class and could somehow use that automatically ndash perhaps by deriving a Member class from it and then doing the same from Member to both Staff and Student classes from Member One thing though ndash we wouldnt want someone to be able to instantiate a Member object

137

perhaps ie in our system Member is an abstract class Imagine a generic Car vs a Renault Clio ndash it makes no sense to create a Car object ndash there are no generic cars on the road they are all specific cars Similarly we wouldnt want a generic Member wandering around our system (if you remain unconvinced well see why later)

Modelling a student - a first attempt

Please note that in this Introduction to C++ we do not expect you to complete an exercise that requires coding from now on Please just look through the code and follow along with the discussion

Base classes

Task 1

Open the project UnivMember1

Examine the program carefully

The project contains three classes Person Member Student In main() we create a Student and then attempt to output the students name ndash which fails

name is in the protected section of Person ndash which means only Person methods or methods in derived-from-Person classes can access it

Add a public section to the Person class and relocate the name there

Eg

public

string name

Any better now

The problem now is that Student only by default inherits the private side of Person

Change class Student so that we also inherit the public members of Person hellip

class Student public Person

138

Before we tackle further problems with name lets bring in the Member class (left doing nothing until now)

We really want Student to inherit from Member and not Person Change the code to reflect this

People have dates-of-birth and Members have bod cards Add a string member dateOfBirth to Person and move the bodCardNumber member out of Student and into Member ndash make them both strings

Change the code in main() to set these extra pieces of data

If you havent done it already Persons dateOfBirth and Members bodCardNumber should be set via constructors

139

Task 2

Open and examine the project called UnivMember2

UnivMember2 is a copy of the (exercise solut ion)

UnivMember1 solution

One of the problems we have in UnivMember1 is that too much of it is public eg given Student object s we can change name to simply by using assignment eg sname =

We should protect data members at each level using the maximum level of protection we can ie private

However if we do that then cout ltlt sname will no longer work and so well need to provide access methods to the data members Eg heres a modified Member class showing the basic scheme

class Member public Person

public

Member(string bodCardNumber)

this-gtbodCardNumber = bodCardNumber

string getBodCardNumber() For access

return bodCardNumber

private

string bodCardNumber

140

Another problem is that wed really like to not use assignment at all Eg in the above ctor snippet

this -gt bodCardNumber = bodCardNumber

is using assignment

Change string bodCardNumber to const string bodCardNumber Youll see now that assignment wont now work (you have to initialise constants)

What wed really like (most likely) is to use in i t ial isat ion

We can do this via initialiser lists Ie we could change the above to the following

class Member public Person

public

Member(string bodCardNumber)

bodCardNumber(bodCardNumber)

const string getBodCardNumber()

return bodCardNumber

private

const string bodCardNumber

The initialiser list is read thus

bodCardNumber(bodCardNumber)

^^member^^ ^^parameter^^

Note that weve also modified getBodCardNumber() to show that it returns a const string

141

Modify all three classes to use initialiser lists private const data members and use access functions (getBlah() etc)

Task 3

Open and examine the project called UnivMember3

UnivMember3 is a copy of the (exercise solut ion)

UnivMember2 solution

We will now finish this project to the level of an introductory course

Things to note

The main problem with the solution as it stands is that one may create a Member object

Remember that this is analogous to being able to create a generic Car object ndash we should not be allowed to create one

Going right back to UnivMember1 you may remember a comment in there about a protected constructor

protected Protected ctor Person()

At that point in your project we were thinking two things 1) we wont want to create a generic person and 2) a protected constructor will facilitate this

And we were wrong to think both thoughts

1) A properly thought through Person class would be perfectly good to model generic people But although this is true one question here ndash would we ever want just a generic person

2) A protected constructor in a (more) base class doesnt prevent a derived class from creating a base object So what about the Member class ndash would it be ok to instantiate that

The proper means to prevent a Member being created would be to use what is called a pure v i r tual funct ion as part of its definition (such a function is one that must be overridden in a derived class) But what function

142

If you look at the classes derived from Member ndash you can take it from us that one might want to interrogate at runtime ndash to ask them what they are

So a suitable member function to declare in Member would be something like string getRole() A function that does return Student for a student and return Staff for a Staff object

If its pure virtual in in Member wed best define it in our derived classes

class Member public Person

public

virtual const string getRole() = 0

class Student public Member

public

const string getRole() return Student

143

1 Why did we want duplicate (named) functions in Member Student and Staff 2 And what does virtual really mean

We require both 1 and 2 so that we can provide specific responses when being asked the same question and all when being treated in a rather basic way

Being asked the same question means having a method invoked eg getRole() and in a rather basic way means treating us all Students and Staff (etc) as Persons and Members

112 Polymorphism

Polymorphism comes in a few forms

Ad-hoc Polymorphism via function overloading

Parametric Polymorphism or Compile-Time Polymorphism via templates

Subtype Polymorphism or Runtime Polymorphism via virtual functions and

Coercion Polymorphism via casting

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class (after all a derived from base must have or contain all that a base has) Polymorphism is the art of taking advantage of this simple but powerful and versatile feature

One way Subtype Polymorphism is applied is to use a base reference to access a collection of instances of different types that are derived from a common base ndash one way to paraphrase that is to say that related (derived from a common class) objects respond according to their type rather than according to the type of the reference one uses to access them (a base class pointer type) That is the dynamic type of the object is used instead of its static type

All of this is best demonstrated via an example of course

144

PLUSPLUS Polymorphism

Task 1

Open and examine the project called (exercise

solut ion) UnivMember3

Run the program the output should be the same as shown in Figure 36

The crucial code here is as follows

Member arr[6]

Student studs1()

Student studs2()

Staff staff1()

Student studs3()

Staff staff2()

Student studs4()

arr[0] = ampstuds1

arr[1] = ampstaff1

arr[2] = ampstuds2

arr[3] = ampstaff2

arr[4] = ampstuds3

arr[5] = ampstuds4

for(int i = 0 i lt ++i)

cout ltlt arr[i]

ltlt i ltlt s name is

ltlt arr[i]-gtgetName()

ltlt t Their role is

ltlt arr[i]-gtgetRole()

ltlt endl

Weve created an array of Members (it isnt important that weve used pointers) and note that we have set some of the members of this to be pointers to Student and Staff objects We are allowed to do this as both Student and Staff are derived from Member

However when and if we invoke member functions on these objects wed really like it if they responded as what they really are ndash Student and Staff objects

145

From the output below you can see that they indeed do respond accordingly

Figure 36

The mechanism behind allowing this is the virtualisation of the getRole() member function Remember that this was declared and made virtual in the Member class

Play about with the code eg change

Member arr[6] to Person arr[6] Everything still ok How about not using pointers here ndash easy to do

146

Lastly weve implemented (for no good reason but to show you how its done) some instance counting in all three classes Have a look for the static members and the inserted lines immediately below the class definitions that look like this int PersonCount = 0

The End Thank you for coming and we hope that you enjoyed the class

Oh and please Please PLEASE fill out the feedback form email when it arrives

147

12 Appendices

Arithmetical Operators

Operator Operation

+ Addition

- Subtraction

Multiplication

Division

Modulus

++ Increment

-- Decrement

Table 8 ndash Arithmetical Operators

Assignment Operators

Operator Example Equivalent

= a = b a = b

+= a += b a = a + b

-= a -= b a = a - b

= a = b a = a b

= a = b a = a b

= a = b a = a b

Table 9 ndash Assignment Operators

148

Assignment and Arithmetic examples

The assignment operator in C++ is =

The format is var iable = expression this can be read as assign to the var iable the value of the expression

An example to calculate the number of pence in a value in pounds would be

pence = pounds 100

Note it is easy to confuse the assignment operator = with the equals notation used in mathematics The equals notation in C++ is ==

Incrementing a var iable

month = month + 1 adds the value one to the variable month This can be written as

month++

Decrementing a var iable

month = month - 1 deducts the value one from the variable month This can be written as month--

Note that ++ and ndash can be used before or after the thing being modified eg ++x x++ --y y-- However there are some subtle differences which will be explained in the lectures

In C++ it is also possible to combine arithmetic and assignment operations

To add 2 to a variable total

total = total + 2 or total +=2

To subtract 2 from to tal

total = total - 2 or total -=2

To multiply total by 2

total = total 2 or total =2

Relational and Equality Operators

The equality operator is used to compare two operands (a == b) and returns 1 (t rue) if both are equal otherwise 0 (false ) is returned

The inequality operator (=) returns 1 (t rue) if both are NOT equal otherwise 0 (false) is returned

Both the above operators are commonly used to test the state of two variables to perform conditional branching

The relational operators also return either true or false (a gt= b) returns 1 (t rue ) if a is greater than or equal to b otherwise 0 (false ) is returned

149

Standard algebraic equality or relational

operator

C++ equality or relational operator

Sample C++ condition

Meaning of C++ condition

Relational operators

gt gt a gt b a is greater than b

lt lt a lt b a is less than b

gt= a gt= b a is greater than or equal to b

lt= a lt= b a is less than or equal to b

Equality operators

= == a == b a is equal to b

= a = b a is not equal to b

Table 10 ndash Relational Operators

Logical Operators

When using i f selection statements it is common to use the relational operators as part of the test if(num gt 5) if(size lt= 14) if(Char == A) These are fine for testing one condition

To test multiple conditions it is possible to nest i f statements but this can be a bit cumbersome

Logical Operators can be used to form more complex conditions by combining simple conditions

Logical AND (ampamp) Operator allows a test to see if two conditions are true

if(leaveBooked gt LeaveLeft ampamp staffCover == false)

cout ltlt Take your holidays sometime else

Logical OR (||) Operator allows a test to see if either or both of the conditions are true

if(Temperature lt 16 || windspeed gt 15)

cout ltlt Too cold or windy to sunbath today then

Logical Negation ( ) Operator reverses the meaning of a condition

if((windspeed == 20))

150

cout ltlt The wind speed is not 20 its ltlt windspeed

This could be written equally as well with the equality operator

if(windspeed = 20)

cout ltlt The wind speed is not 20 its ltlt windspeed

Precedence and Associativity Table

Precedence Operator Description Associativity

1 Scope resolution Left-to-right

2

++ -- Suffixpostfix increment and decrement

() Function call

[] Array subscripting

Element selection by reference

-gt Element selection through pointer

typeid() Run-time type information (see typeid)

const_cast Type cast (see const_cast)

dynamic_cast Type cast (see dynamic_cast)

reinterpret_cast Type cast (see reinterpret_cast)

static_cast Type cast (see static_cast)

3

++ -- Prefix increment and decrement Right-to-left

+ - Unary plus and minus

~ Logical NOT and bitwise NOT

(type) Type cast

Indirection (dereference)

amp Address-of

sizeof Size-of

new new[] Dynamic memory allocation

delete delete[] Dynamic memory deallocation

151

4 -gt Pointer to member Left-to-right

5 Multiplication division and remainder

6 + - Addition and subtraction

7 ltlt gtgt Bitwise left shift and right shift

8 lt lt= For relational operators lt and le respectively

gt gt= For relational operators gt and ge respectively

9 == = For relational = and ne respectively

10 amp Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 ampamp Logical AND

14 || Logical OR

15 Ternary conditional Right-to-Left

16

= Direct assignment (provided by default for C++ classes)

+= -= Assignment by sum and difference

= = = Assignment by product quotient and remainder

ltlt= gtgt= Assignment by bitwise left shift and right shift

amp= ^= |= Assignment by bitwise AND XOR and OR

17 throw Throw operator (exceptions throwing)

18 Comma Left-to-right

Table 11 ndash Precedence and Associativity Table

Escape Sequences

Escape Sequence

Description

n Newline Position the screen cursor at the beginning of the next line

152

t Horizontal tab Move the cursor to the next tab stop

r Carriage return Position the cursor at the beginning of the current line

a Alert Sound the system bell

Backslash used to print a backslash

Single quote Use to print a single quote character

Double quote Used to print a double quote character

Table 12 ndash Escape Sequences

Cast Operator

Is where the programmer explicitly asks for a change in data type It may be that the result of a calculation is a double and the user wants it to be of type integer

A double can be cast to an integer in the following way

double aNum = 237

int anInt = 0

anInt = static_castltintgt(aNum)

A C style cast may also be used eg

anInt = (int)aNum OR anInt = int(aNum)

Formatted Output

When several numbers are displayed each is printed with the minimum number of digits needed to show the value This can yield some unexpected output

The width of an output field can be set using a stream manipulator To set the next number to be printed to a width of 5 digits use cout ltlt setw(5) This command does not produce any output it manipulates the stream to change the output format of the next value Note setw() must be specified for every item output

To use any stream manipulators you must include the header include ltiomanipgt

setprecision is another manipulator and is used to set the precision of the next floating point number Note setprecis ion only has to be set once as the stream remembers the formatting directive and does not affect integer fields The format is cout ltlt

setprecision(3)

To set precision for trailing zeros (0100 will appear as 01) it is necessary to use the fixed format The notation is cout ltlt fixed Note f ixed only has to be set once

The three manipulators can be combined to achieve the required precision and field width when used in this way

153

cout ltlt fixed ltlt setprecision(3) ltlt setw(5) ltlt myDouble

Alternatively as fixed and setprecision only have to be set once this statement could be written as

cout ltlt fixed ltlt setprecision(3)

cout ltlt setw(5) ltlt myDouble

Header Files

Every program that you create will have at least one header file If you use input or output you will have to include the iostream header

If you use mathematical functions you will need cmath It can be difficult to know which header files to use for each function Some of the common header files used together with some of the older ones you may find with inherited code are shown below It is a good idea to use the help if you are unsure which header files are associated with particular functions

Standard C++ header Old header

iostream iostreamh

iomanip iomaniph

fstream fstreamh

cmath mathh

cstdlib stdlibh

string No equivalent

vector vectorh

Table 13 ndash Header Files Old and New

Matrix Libraries

The STL does not contain a Matrix type and so we must look elsewhere for a suitable implementation that suits the individuals needs

The table below lists the third party libraries that we are aware of

Some Linear AlgebraMatrix Libraries

Armadillo Blitz++ Boost

CPPLapack CPPScaLapack CVM Class Library

Eigen Elemental FLENS

Gmm++ GNU Scientific Library (GSL) HSL

154

IML++ IT++ LA library

Lapack++ LinBox Matrix Template Library (MTL)

MV++ Newmat PETSc

RNM Seldon SimuNova

SL++ (Scientific Library)

SparseLib++ SuiteSparse

TCBI (Temporary Base Class Idiom)

Template Numerical Toolkit (TNT)

Trilinos

uBlas ViennaCL

Table 14 ndash Matrix Libraries

Scope

The portion of a program where an identifier can be used is known as its scope

An identifier declared outside any function or class has f i le scope This type of identifier is known by all functions Global variables and function prototypes all have file scope

Identifiers declared inside a block of code have block scope This type of scope begins at the identifiers declaration and ends at the termination right brace ( ) of the block in which the identifier is declared

Any block can contain local variable declarations If blocks are nested it is possible to declare variables with the same name in each nested block The variable in the outer block is hidden while the inner block is being executed

Enumerating constants

The enum keyword provides a handy way to create a sequence of integer constants An example of enumeration is shown below

enum Months JAN = 1 FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC

Each of the constants will have a default value 1 greater than the constants that it follows in the list The first value in the enumeration above is explicitly set to 1 and the remaining values increment by 1 The values assigned from JAN to DEC will be 1 to 12

The statement cout ltlt DECEMBER is month number ltlt DEC ltlt endl would be output as DECEMBER is month number 12

Constants

Data that will not change during the execution of a program should be stored in a constant container rather than a variable If the program attempts to change the value stored in a constant the compiler will report an error and compilation will fail

Constant can be created for any data type by prefixing the declaration with const keyword followed by a space Note Constants must always be initialised at declaration

The following declaration declares a constant for the speed of sound at sea level ms

155

const double SpeedOfSound = 34029

Vector member functions

Some commonly used member functions of the vector class are

Vector member Functions Effect

at(element number) Gets the value contained in the specified element

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

push_back(value) Adds an element to the end of the vector containing the specified value

size() Gets the number of elements

Table 15 ndash Vector Member Functions

Global functions

Global functions are not member functions They take more than one argument and operate on a range of elements rather than on the vector container ie they can be used on other types of containers

Vector global Functions Effect

find()

ptr = find(vbegin() vend() 67)

Finds the element in the vector containing number 67 Needs iterator (ptr) to store location of element

reverse()

reverse(vbegin() vend()) Reverses the values in a vector (v)

sort()

sort(vbegin() vend()) Sorts the vector (v)

Table 16 ndash Vector Global Functions

156

list member functions

Some commonly used member functions of the list class are

List member Functions Effect

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

pop_front Removes the first element

push_back(value) Adds an element to the end of the vector containing the specified value

sort() Sorts the elements in the container from lower to higher

size() Gets the number of elements

swap() Exchanges the content of the list

Table 17 ndash List class Member Functions

cmath functions

Function Argument Result Returned Value Example Result

ceil(x) double double Smallest integer ge x

ceil(21) 30

cos(x) double double Cosine of x radians cos(10) 054

fabs(x) double double Absolute value of x

fabs(-15) 15

floor(x) double double Largest integer le 29

floor(29) 20

157

pow(x y) double double x to the yth power pow(24) 160

sin(x) double double Sine of x radians sin(10) 084

sqrt(x) double double Square root of x sqrt(4) 20

tan(x) double double Tangent of x radians

tan(10) 156

Table 18 ndash cmath Functions

158

String class

The string class defines many member funct ions A few of the basic ones are described below

Initialisation - constructors form

A string expression string str2 = str1

A character string literal string Intro = Programming with C++

A substring of another string object

string Intro = Capetown

string Mytown = Boars

string MyTown(Intro 4 5)

starts at character 4 (t)

with a length of 5 (or the rest of the string if shorter)

cout ltlt myTown ltlt endl

will produce an output town

Member Functions

length()

string myName = Sebastion

myNamelength()

will produce an output of 9

insert ()

Inserts a string into the current string starting at the specified position

string myName = Sebastion

string nameAdd = rjio

myNameinsert (2nameAdd)

cout ltlt myName ltlt endl

will produce an output Serjiobastion

erase()

Delete a substring from the current string

string myName = Sebastion

myNameerase (02)

cout ltlt myName ltlt endl

will produce an output bastion

replace()

Delete a substring from the current string and replace it with another string

string myName = Sebastion

string aName = renna

159

Member Functions

myNamereplace(3 6 aName)

cout ltlt myName ltlt endl

will produce an output Sebrenna

find()

Search for the first occurrence of the substring in the current string If the word is found return the position of the first character If not return -1

string sName

string findWord

position = sNamefind(findWord)

substr()

Returns a substring of the current string

string myName = Sebastion

string aName = myNamesubstr(0 3)

cout ltlt aName ltlt endl

will produce an output Seb

Non-member functions

getline()

string name

getline(cin name)

Table 19 ndash String Class Member Functions

160

A number of C++ operators also work with str ing objects

Operator

=

string fString = Hello

string lString

lString = fString

Assign a character (char ) to a str ing object

string aStringC

aStringC = Z

+

Concatenate two str ing objects

string str1 = C++

string str2 = Programming

string str3 = str1 + str2

+

Concatenate a string object and a character string literal

string str = Hello

string str1 = str + there

The same concatenation can be done in this way

str += there

+

Concatenate a string object and a single character

string str = Bye Bye

string strBye = str +

161

ASCII Character set

Decimal Octal Hexadecimal Binary Value Meaning

0 0 0 0 NUL (Null char)

1 1 1 1 SOH (Start of Header)

2 2 2 10 STX (Start of Text)

3 3 3 11 ETX (End of Text)

4 4 4 100 EOT (End of Transmission)

5 5 5 101 ENQ (Enquiry)

6 6 6 110 ACK (Acknowledgment)

7 7 7 111 BEL (Bell)

8 10 8 1000 BS (Backspace)

9 11 9 1001 HT (Horizontal Tab)

10 12 00A 1010 LF (Line Feed)

11 13 00B 1011 VT (Vertical Tab)

12 14 00C 1100 FF (Form Feed)

13 15 00D 1101 CR (Carriage Return)

14 16 00E 1110 SO (Shift Out)

15 17 00F 1111 SI (Shift In)

16 20 10 10000 DLE (Data Link Escape)

162

Decimal Octal Hexadecimal Binary Value Meaning

17 21 11 10001 DC1 (X ON) (Device Control 1)

18 22 12 10010 DC2 (Device Control 2)

19 23 13 10011 DC3 (X OFF)(Device Control 3)

20 24 14 10100 DC4 (Device Control 4)

21 25 15 10101 NAK (Negative Acknowledgement)

22 26 16 10110 SYN (Synchronous Idle)

23 27 17 10111 ETB (End of Trans Block)

24 30 18 11000 CAN (Cancel)

25 31 19 11001 EM (End of Medium)

26 32 01A 11010 SUB (Substitute)

27 33 01B 11011 ESC (Escape)

28 34 01C 11100 FS (File Separator)

29 35 01D 11101 GS (Group Separator)

30 36 01E 11110 RS (Request to Send)(Record Separator)

31 37 01F 11111 US (Unit Separator)

32 40 20 100000 SP (Space)

33 41 21 100001 (exclamation mark)

34 42 22 100010 (double quote)

163

Decimal Octal Hexadecimal Binary Value Meaning

35 43 23 100011 (number sign)

36 44 24 100100 $ (dollar sign)

37 45 25 100101 (percent)

38 46 26 100110 amp (ampersand)

39 47 27 100111 (single quote)

40 50 28 101000 ( (leftopening parenthesis)

41 51 29 101001 ) (rightclosing parenthesis)

42 52 02A 101010 (asterisk)

43 53 02B 101011 + (plus)

44 54 02C 101100 (comma)

45 55 02D 101101 - (minus or dash)

46 56 02E 101110 (dot)

47 57 02F 101111 (forward slash)

48 60 30 110000 0

49 61 31 110001 1

50 62 32 110010 2

51 63 33 110011 3

52 64 34 110100 4

164

Decimal Octal Hexadecimal Binary Value Meaning

53 65 35 110101 5

54 66 36 110110 6

55 67 37 110111 7

56 70 38 111000 8

57 71 39 111001 9

58 72 03A 111010 (colon)

59 73 03B 111011 (semi-colon)

60 74 03C 111100 lt (less than)

61 75 03D 111101 = (equal sign)

62 76 03E 111110 gt (greater than)

63 77 03F 111111 (question mark)

64 100 40 1000000 (AT symbol)

65 101 41 1000001 A

66 102 42 1000010 B

67 103 43 1000011 C

68 104 44 1000100 D

69 105 45 1000101 E

70 106 46 1000110 F

165

Decimal Octal Hexadecimal Binary Value Meaning

71 107 47 1000111 G

72 110 48 1001000 H

73 111 49 1001001 I

74 112 04A 1001010 J

75 113 04B 1001011 K

76 114 04C 1001100 L

77 115 04D 1001101 M

78 116 04E 1001110 N

79 117 04F 1001111 O

80 120 50 1010000 P

81 121 51 1010001 Q

82 122 52 1010010 R

83 123 53 1010011 S

84 124 54 1010100 T

85 125 55 1010101 U

86 126 56 1010110 V

87 127 57 1010111 W

88 130 58 1011000 X

166

Decimal Octal Hexadecimal Binary Value Meaning

89 131 59 1011001 Y

90 132 05A 1011010 Z

91 133 05B 1011011 [ (leftopening bracket)

92 134 05C 1011100 (back slash)

93 135 05D 1011101 ] (rightclosing bracket)

94 136 05E 1011110 ^ (caretcirumflex)

95 137 05F 1011111 _ (underscore)

96 140 60 1100000 `

97 141 61 1100001 a

98 142 62 1100010 b

99 143 63 1100011 c

100 144 64 1100100 d

101 145 65 1100101 e

102 146 66 1100110 f

103 147 67 1100111 g

104 150 68 1101000 h

105 151 69 1101001 i

106 152 06A 1101010 j

167

Decimal Octal Hexadecimal Binary Value Meaning

107 153 06B 1101011 k

108 154 06C 1101100 l

109 155 06D 1101101 m

110 156 06E 1101110 n

111 157 06F 1101111 o

112 160 70 1110000 p

113 161 71 1110001 q

114 162 72 1110010 r

115 163 73 1110011 s

116 164 74 1110100 t

117 165 75 1110101 u

118 166 76 1110110 v

119 167 77 1110111 w

120 170 78 1111000 x

121 171 79 1111001 y

122 172 07A 1111010 z

123 173 07B 1111011 (leftopening brace)

124 174 07C 1111100 | (vertical bar)

168

Decimal Octal Hexadecimal Binary Value Meaning

125 175 07D 1111101 (rightclosing brace)

126 176 07E 1111110 ~ (tilde)

127 177 07F 1111111 DEL (delete)

Table 20 ndash Full ASCII Table

169

Handy IDE Settings

Line Numbers onoff Tools | Options | Text Editor | CC++ | Line Numbers

Auto closing the console Tools | Options | Debugging | Automatically close the console window when debugging stops

Saves having to use system(pause)

170

REMAINING PAGES LEFT BLANK FOR NOTE TAKING

171

172

173

Peet Morris

peetmorrisgmailcom

C++ A Comprehensive Introduction

Arrangements

bull We Startfinish at 915am 500pm

bull Format two lectures per day (ask questions) hands-on at all other times

bull You should have Course book (copy of the slides at the back)

bull The course software is pre-installed on the machines

And also separately available from

The compilerIDE wwwvisualstudiocom

Notesslidesexercise files wwwpeetmcomC++introcoursezip

Your safety is important

Where is the fire exit

Beware of hazards

Tripping over bags and coats

Please tell us if anything does not work

Let us know if you have any other concerns

Your comfort is important

The toilets are along the corridor just outside the teaching rooms

The rest area is where you registered it has vending machines and

a water cooler

The seats are adjustable

You can adjust the monitors for brightness

What we assumehellip

What we assume

Experience of using another programming

language

Comprehensive Lots to get through

C++ and OOP

bull Created in 1985 by Bjarne Stroustrup C++ is a highly efficient

multiplatform low level Object Oriented Programming language

bull Latest version is C++17

stroustrupcom

Standard C++ Library

bull Written in the core language it is a collection of classes

(object definitions) functions and algorithms

See wwwcpluspluscomreference

IDEs amp Compilers

Visual Studio 2017

First Program

First application

include ltiostreamgt

using namespace std

int main()

int aNum = 0 aNum(0) or aNum0

cout ltlt Enter a number-

cin gtgt aNum

cout ltlt You entered ltlt aNum

return 0

hellip hellip

First Program

bull include ltiostreamgt

Adds the contents of the iostream header file into the program (for cout and cin)

bull using namespace std

So we donrsquot have to write stdcout ltlt and stdcin gtgt all of the time

bull cin is the standard input stream object that allows input from the keyboard

bull cout is the standard output stream object that allows output to the screen

bull int main() The programs entry point

Mandatory main function in every C++ program ndash always returns an integer value

First Program

bull int aNum = 0

Variable to hold a value of type integer (piece of machine memory referred to via the name aNum)

bull ltlt stream insertion operator ndash outputs to console

cout ltlt Enter a number-

bull gtgt stream extraction operator ndash waits for keyboard input

cin gtgt aNum

Other Types

Microsoft data types summary httpsdocsmicrosoftcomen-gbcppcppfundamental-types-cpp

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststack

Lots

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

x 1

y 2

x 3

y 4

p1

p2

x

y

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 copies the bit pattern from p1 to p2

x 1

y 2

x 1

y 2

p1

p2

Compound Types

Cannot define operators other than assignment

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 p2 compilation error

x 1

y 2

x 3

y 4

p1

p2

Compound Types

We can arbitrarily further compound things

struct point

int xint y

struct rectangle

point tlpoint br

struct line

point startpoint end

startxy

endxy tlxy

brxy

Compound Types

We can also group things using struct to create compound

types

struct point

int xint y

struct rectangle

point tlpoint br

int main()

rectangle r

rtlx = 1rtly = 2

rbrx = 3rbry = 4

int diff_x = abs(rtopLeftx - rbottomRightx)int diff_y = abs(rtopLefty - rbottomRighty)

cout ltlt area ltlt diff_x diff_y ltlt endl

r

tl

br

x 1

y 2

x 3

y 4

Using a Library Type

include ltstringgt

string s

cout ltlt What is your name

getline(cin s)

cout ltlt s ltlt

ltlt is

ltlt slength() ltlt

ltlt characters long ltlt endl

s

Other Types

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststackcomplex

Lots

8 bit Binary signed unsigned

00000001 1 1

00000010 2 2

00000011 3 3

01111111 127 127

10000000 -128 128

10000001 -127 129

10000010 -126 130

11111101 -3 253

11111110 -2 254

11111111 -1 255

00000000 0 0

00000001 1 1

00000010 2 2

signed vs unsigned ndash its all just 1s and 0s and adding

Adding rules

0 + 0 = 0

1 + 0 = 1

0 + 1 = 1

1 + 1 = 0 (carry 1)

1 + 1 + 1 = 1 (carry 1)

-126 + +3 =

10000010

00000011 +

10000101 = -123

-126 + -3

10000010

11111101 +

01111111 = 127 (why not -129)

Arithmetic Operators

+ Addition

- Subtraction and unary minus

Multiplication

Division

Remainder after division (moduloclock arithmetic)

int j k l = 10

j = l 3 js value will be three

k = l 3 ks value will be 1

Relational Operators

Evaluate to either true or false represented by integer values 1 and 0

== Equal to

= Not equal to

gt Greater than

lt Less than

gt= Greater than or equal to

lt= Less than or equal to

Increment and Decrement Operators

++ Increment

-- Decrement

Can be prefix or postfix

b = 3

a = b++ + 6 Add 6 to b then increment b a is 9 b is 4

b = 3

a = ++b + 6 Increment b then add 6 to b a is 10 b is 4

Assignment Operators

Symbol Operation Long Short

= Assign a = 2 a = 2

+= Assign with add a = a + 2 a += 2

-= Assign with subtract a = a ndash 2 a -= 2

= Assign with multiply a = a 2 a = 2

= Assign with divide a = a 2 a = 2

= Assign with remainder a = a 2 a = 2

Basic Control Flow - if

Sequence

What we have been doing already

Selection

if statement if this then that

if (boolean expression) if (score gt= 50)

statement cout ltlt Passed

Logical Operators

Boolean expressions may be combined using

ampamp And

|| Or

Not

Operands and result resolves being either true or false

if (x ampamp (y || z))

else

Precedence and Associativity table in course book

Logical Operators

a b =

true true true

true false false

false true false

false false false

a b =

true true true

true false true

false true true

false false false

a =

true false

false true

a ampamp b a || b a

Logical Operators

if (x ampamp (y || z))

else

The value 0 (zero) is evaluated to mean false any other value is true

x ampamp (y || z) result

false ampamp (false || false) falsefalse ampamp (false || true ) falsefalse ampamp (true || false) falsefalse ampamp (true || true ) falsetrue ampamp (false || true ) falsetrue ampamp (false || false) truetrue ampamp (true || false) truetrue ampamp (true || true ) true

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp (y | ~z))

else

Bitwise Operators

unsigned int x = 11

unsigned int y = 7

unsigned int z = 25

if (x amp (y | ~z))

else

11 (x) = 000010117 (y) = 0000011125 (z) = 00011001

~z = 11100110 (230 or -26)

y | ~z = 11100111 (231 or -25)

x amp (y | ~z) = 00000011 = 3

Operands and the result resolve to a values

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp 1) x is odd

if (x gt y)

x = x ^ y

y = y ^ x XOr swap

x = x ^ y

Control Flow - if else

Selection

ifelse statements

if (boolean exp) if (score gt= 50)

statement cout ltlt Passed

else else

statement cout ltlt Failed

Control Flow -

Selection

Conditional (or Ternary) Operator

boolean exp true result false result

cout ltlt score gt= 50 Passed Failed

Control Flow

if (x gt= y)

if (y 2)

else

if (x gt= y)

if (y 2)

else

Control Flow ndash else if

if (exp)

else if (exp)

else if (exp)

else catch all remaining

if (aNum == 0)

else if (aNum == 1 || aNum == 2)

else if (aNum == 3)

else catch all remaining

aNum not 0123

Control Flow - switch

Selection

switch multiple selection statements

bull test must be an integral value 1 10 A x eg not 1056

bull case values must be constants

switch (aNum)

case 0

break

case 1 Fall through

case 2

break

default catch all

break

Repetition - while

while (exp)

statements

while (n lt k)

cout ltlt Enter mark

cin gtgt mark

t += mark

n++

Repetition - for

for (init exp inc)

statements

for (t = 0 n lt k n++)

cout ltlt Enter mark

cin gtgt mark

t += mark

Preferable to while if the range is known

Repetition - for

for (init exp inc)

statements

for () infinite loop

break causes loop to exit

Preferable to while if the range is known

Repetition - do

do

statements

while (exp)

do

cout ltlt Continue yn

cin gtgt yn

yn = tolower(yn)

while (yn = y ampamp yn = n)

There are a huge number of exercises and we donrsquot expect you to attempt

them all during this course

bull If yoursquore completely new to programming itrsquos probably best to tackle

them in sequence

bull If yoursquove some programming experience you should read through the

exercise summaries and then start wherever you feel comfortable

Exercises

Exercises

Topics covered in ex1 ndash ex6

Functions = mini programs

bull Used to combine data with operations and through functional

decomposition to promote code re-use

bull Simplifies coding

bull Functions for discrete tasks

bull Not hundreds of lines of code

bull Consumer only needs to know

bull What goes in and what comes out

Functions

Like everything else the compiler needs to have seen a prototype or a

definition of a function before we can use it

Prototypes lets the compiler generate the correct code

int min(int int)

int min(int int int)

void drawLine(point to point from = 00)

int square(int)

int main()

void beep()

string getNextPacket(void)

Return type Function name (Parameter list)

min

int min(int int) min prototypes (forward declarations)int min(int int int)

int main()

Having seen the prototypes the compilerc = min(x y) can generate the required code

int min (int a int b) min function definition 1

return a lt b a b

int min (int a int b int c) min function definition 2

return min(min(a b) c)

inline min

int main()

c = min(x y)

inline int min (int a int b)

return a lt b a b

int main()

c = x lt y x y

inline int min (int a int b)

return a lt b a b

Function Parameters

bull Pass by Value

bull A Copy of the parameter is passed to the called function

bull Pass by Reference

bull The actual parameter is passed to the called function

bull Pass by Memory Address (pointer)

bull Same effect as Pass by Reference (tomorrow)

Pass by value

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

return n_copy n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 10

n_copy 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp x)

x just another name for real_n

return x x

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

x 10

Pass by value (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

n_copy = n_copy n_copy

return n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 100

n_copy 100

Pass by reference (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

real_n = real_n real_n

return real_n

100

100

Mem Addr Contents

0x2786 100

real_n 100

Mem Addr Contents

0x2786 100

real_n 100

const Parameters

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Recursion

unsigned long long int fibonacci(int n)

switch(n)

case 0 Fall through - [[fallthrough]]

case 1

return n

break

default

return fibonacci(n - 1) + fibonacci(n - 2) Very inefficient

Arrays (Part 1)

Data structure containing same type of data (int double string char object)

bull Built in to C++

bull Series of elements each containing one item of data (contiguous memory locations)

Size (number of elements) set at compile time

Arrays (1)

int numbers[10] an array of 10 integers Each box sizeof(int) bytes wide

numbers

index values - 0 to 9

0 1 2 3 4 5 6 7 8 9

Arrays (1)

int numbers[10] an array of 10 integers

int n = 0

cout ltlt numbers ltlt endl address of the first element

cout ltlt numbers[n] ltlt endl contents of the nth element

cout ltlt ampnumbers[n] ltlt endl address of the nth element

cout ltlt numbers + n ltlt endl address of the nth element

0 1 2 3 4 5 6 7 8 9

42 hellip hellip hellip hellip hellip hellip hellip hellip hellip

0x1526

Arrays

char name[5] name - an array of five characters

thing t[5] t - an array of five things

examMarks ndash an array of three doubles initialised to 12 39 95double examMarks[] = 12 39 95 C++11 - double examMarks[] 12 39 95

header ndash an array of fifty unsigned chars (bytes) first three elements set to 0 1 255 and the rest to zerotypedef unsigned char bytebyte header[50] = 0 1 -1

Arrays

Accessing array data

define MARKS 5 or const int MARKS = 5

double examMarks[MARKS]

for(int i = 0 i lt MARKS i++)

cout ltlt Enter Exam Mark

ltlt i + 1 ltlt

cin gtgt examMarks[i]

for(i = 0 i lt MARKS i++)

cout ltlt examMarks[i]

Multidimensional Arrays

Two dimensional array Two subscripts First identifies row second identifies column

const int students = 6 const int marks = 3

double examMarks[students][marks] = 0 set to zero

for (int s = 0 s lt students ++s)

for (int m = 0 m lt marks ++m)

cout ltlt Enter mark ltlt m + 1 ltlt for student ltlt s + 1 ltlt endl

cin gtgt examMarks[s][m]

00 01 02

10 11 12

20 21 22

30 31 32

40 41 42

50 51 52

Memory laid out in row column order (more later)

00 01 02 10 11 12 20 21 22 30 31 32 40 41 42 50 51 52

Matrices

Provider Link

Armadillo armasourceforgenet

Blitz blitzsourceforgenet

Boost boostorg

Eigen eigentuxfamilyorg

Elemental libelementalorg

FLENS apfelmathematikuni-ulmde

HSL hslrlacuk

LEDA algorithmic-solutionscom

PETSc mcsanlgov

SimuNova simunovacom

SuiteSparse facultycsetamuedu

TNT mathnistgov

Trilinos trilinosorg

ViennaCL viennaclsourceforgenet

Exercises

Topics covered in ex7 ndash ex16

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people and dice

Recap Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

1 61 61 61 61 6

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

3 11 24 56 12 3

C++ and OOP

Encapsulation Keeping related stuff together

Member functionsmethods

an objectrsquos capabilities functionality and performable actions

int Throw()

Member variablesproperties

an objectrsquos current state values its dumb data

int sides

Dice throwing 3

struct dice

int sides State

dice(int n) Constructor

sides = n

int Throw() Member function (method)

return (rand() sides) + 1

int main()

Could also use dice d1 = 6 or d16 syntaxdice d1(6) d2(6)

d1sides = 6 d2sides = 10 Allow this

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

struct diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

class diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing ndash professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

diceh my-appcpp

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

dicecpp

Compiler

diceobj my-appobj

Linker

my-appexe

other librarycode objectfiles

Dice throwing - professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Compiler

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

diceobj my-appobj

diceh dicecpp my-appcpp

Linker

my-appexe

other librarycode objectfiles

Only items provided to the end-usercustomer

Classes and Objects

the includeltstringgt header file from the standard library

class string

your cpp source code files

include ltstringgt include information about class string

string Name a class string instance

string Address a class string instance

Classes and Objects

the include carh header file

class car

your cpp source code files

include carh include information about class car

car c a class car instance

Classes and Objects

the include househpp header file

class house

your cpp source code files

include househpp include information about class house

house no1 a class house instance

house no2 a class house instance

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do with it

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

cstart()

cenginestart() Or should cstart() internally use enginestart()

OOD

Time for a break

class student

What properties and methods do we need

class student

public

string name

string DoB

string college

string bodCardNumber

float age()

int main()

student s

sname =

sDoB =

How to guarantee an objectrsquos integrity

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s

sname = Compilation errors

sDoB =

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s( )

cout ltlt sage()

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB Error ndash cant assign to a constant

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_name(name) m_DoB(DoB)

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_namename m_DoBDoB

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Exceptions

class student

int main()

try

student s( )

catch(const char msg)

cout ltlt msg ltlt endl

student initialisation failed

Exceptions

try

catch(const char msg)

cout ltlt msg ltlt endl

catch (const invalid_argument amp e)

cout ltlt ewhat() ltlt endl

catch (exception amp e)

cout ltlt ewhat() ltlt endl

catch ()

cout ltlt Something went wrong ltlt endl

student invalid arg 2

if using C++11 see stdcurrent_exception

Reuse and inheritance

Say we now want to add a new type to our system ndash class academic With what we have seen so far we would proceed something like this

class academic

private

string m_name string m_DoB

Duplicating everything we had in class student

class person (generalisation)

OOP is sometimes called Programming by Describing the differences

student and academic are all specialisations of a more generalised and abstract class ndash person

class student public personpublic

student(string name) person(name)

class academic public personpublic

academic(string name) person(name)

class personprotected

person(string name) m_name(name)

private

string m_name

public

base class derived class

derived class

Specialised State

class student public person

private

const string m_bodCard

public

student(string name string DoB string bc ) person(name DoB) m_bodCard(bc)

Multiple inheritance

class student public person public oxMember

public

student(string name int age string bc) person(name age) oxMember(bc)

class academic public person public oxMember

public

academic(string name int age string bc) person(name age) oxMember(bc)

Destructors

class foo

private

int m_x int m_y

public

foo() foo(0 0)

foo(int x) foo(x 0)

foo(int x int y) m_x(x) m_y(y) only ctor that accesses private state

~foo() any necessary tidy up code

Dice throwing 5

class diceprivate

int sides

public

dice(int n) sides(n)

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

srand((unsigned)time(0)) Happy with this

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 6

class diceprivate

int sides

public

dice(int n) sides(n)

classshared state static bool seeded = false

if (seeded)srand((unsigned)time(0))seeded = true

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

3 65 21 44 22 6

Dice throwing 7

class dice private

int sides

public

dice(int n) sides(n)

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

Dice throwing 7

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyesDouble 14 33 5

Dice throwing 8

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6) int t

for(int n = 0 n lt 5 ++n)

cout ltlt (t = d1Throw()) ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp t = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Dice throwing 9

class dice private

int sidesint _lastThrow

public

const int amp lastThrow read-only stateproperty

dice(int n) _lastThrow(-1) lastThrow(_lastThrow) sides(n)

int Throw()

return _lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp d1lastThrow = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Exercises

Topics covered in ex17 ndash ex22

Vectors

Like an array a data structure containing same type of data (int double object)

bull A container class part of the standard library a wrapper similar to arrays

Need to includeltvectorgt

bull Can resize grow shrink as elements are added or removed from the end

bull Algorithms to manipulate data

bull Iterators to cycle through all the elements

Vectors

vectorltchargt name(5) vector of five characters

vectorltthinggt t(5) vector of five things

vectorltdoublegt examMarks 12 39 95 initialised vector of three doubles

typedef unsigned char byte

a vector of fifty bytes first three elements set to 0 1 255 and the rest to zerobyte char b[50] = 0 1 255 fully populate array

calc itemCountint itemCount = sizeof(b) sizeof(b[0])

vectorltbytegt bytes (b ampb[0] + itemCount) then init with vector 50 items

Vectors (iteration 1)

include ltvectorgt

vectorltintgt vec(20) 20 ints

for(int i = 0 i lt vecsize() i++) input values into vec

cin gtgt vec[i]

for(i = 0 i lt vecsize() i++) output vec

cout ltlt vec[i] ltlt

Vectors (iteration 2) (C++11 and later)

for(type identifier container)

statements

vectorltintgt vec(20)

for (int amp i vec)

Vectors

Adding an extra element

cout ltlt Enter an Extra Value

cin gtgt aNum

vecpush_back(aNum)

for (int i = 0 i lt vecsize() i++)

cout ltlt vec[i] ltlt endl

cout ltlt vecat(i) ltlt endl same as above but range checked (ie slowsafe)

Vectors (most of the methods)

docsmicrosoftcomen-uscppstandard-libraryvector-classFull list

Method Purpose

assign Erases a vector and copies the specified elements to the empty vector

at Returns a reference to the element at a specified location in the vector

back Returns a reference to the last element of the vector

begin Returns a random-access iterator to the first element in the vector

capacity Returns the number of elements that the vector could contain without allocating more storage

clear Erases the elements of the vector

C++11 data Returns a pointer to the first element in the vector

C++11 emplace Inserts an element constructed in place into the vector at a specified position

C++11 emplace_back Adds an element constructed in place to the end of the vector

empty Tests if the vector container is empty

end Returns a random-access iterator that points to the end of the vector

erase Removes an element or a range of elements in a vector from specified positions

front Returns a reference to the first element in a vector

insert Inserts an element or a number of elements into the vector at a specified position

max_size Returns the maximum length of the vector

pop_back Deletes the element at the end of the vector

push_back Add an element to the end of the vector

rbegin Returns an iterator to the first element in a reversed vector

rend Returns an iterator to the end of a reversed vector

reserve Reserves a minimum length of storage for a vector object

resize Specifies a new size for a vector

C++11 shrink_to_fit Discards excess capacity

size Returns the number of elements in the vector

swap Exchanges the elements of two vectors

Vectors (iteration 3)

include ltalgorithmgt

vectorltintgt vec

for(int i = 1 i lt= 5 ++i)vecpush_back(i)

1 2 3 4 5

5 4 3 2 1

vectorltintgtiterator it

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Reverse the vectorreverse(vecbegin() vecend())

cout ltlt endl

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Arrays (2) (C++11 and later)

arrayltint 5gt arr Thin veneer over an array ndash so requires fixed size

arrfill(0) int j = 0

for (int amp i arr)

supports latest iteration style

reverse(arrbegin() arrend()) and iterators for use with algorithms

C++11 - Uniform initialisers

C++98

complexltdoublegt c( 271828 314159 )

int a[] = 1 2 3 4

vectorltintgt v

for( int i = 1 i lt= 4 ++i )

vpush_back(i)

C++11

complexltdoublegt c 271828 314159

int a[] 1 2 3 4

vectorltintgt v 1 2 3 4

Pointers ndash What

A pointer is a scalar variable that is used to hold the memory-address of

another variable or function the stored address is said to point to the thing

it holds ndash thus the name

Pointers have a type ndash the type of the thing they point to

int n = 10I (p) am a pointer to an integer and I point to n over thereint p = ampn

Pointers ndash Why

In no particular order

bull Because external libraries and APIs (like the operating system (all of them)) are written using them

bull Create custom data structures like linked-lists trees graphs etc

bull Create tables of functions or single functions for handling events callback or signals

bull Access data on to the heap (allocate memory dynamically)

bull Writecall functions that change their input parameters

1 2

3

4 5 6 nilhead

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

Recap - Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference using Pointers

int main()

int real_n = 10

cout ltlt square(ampreal_n)

cout ltlt real_n

return 0

int square(const int real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x5110 0x2786

real_n 0x2786

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt pcout ltlt pcout ltlt ampxcout ltlt xcout ltlt ampp

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

15438

11

15438

11

17216

Pointers

int main(int argc char argv)

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )(argv + n) ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv + 0 C

argv + 1

argv + 2

argv + 3

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

int main(int argc char argv[])

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )argv[n] ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv[0] C

argv[1]

argv[2]

argv[3]

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

Memory Stack vs Heap

Stack (last in first out - LIFO)

Space automatically allocated

The place where arguments of a function call are stored

The place where local function data is allocated (eg variables)

The place where a function leaves its result (if any)

Heap

Space must be explicitly allocated

A place for allocating memory that is not part of last-in first-out approach

ie dynamically allocated data structures that survive function calls

Stack vs Heap

int stackArray[100] Allocate 100 ints on the stack

stackArray[n] = 0 Do something with it

int heapArray = new int[100] 100 ints on the heap C++

int heapArray = malloc(100 sizeof(int)) 100 ints on the heap C

heapArray[n] = 0 Or (heapArray + n) = 0 Do something with it C++ and C

delete [] heapArray When youre done C++

free(heapArray) When youre done C

Exercises

Topics covered in ex22 onwards

If time allows look through the remaining

exercises and attempt those that fit best

with your requirements

  • C++ Notes TPLO 12-11-2019 Blackbox
  • C++ Slides TPLO 12-11-2019 - Copy

Files and Folders

All of the files and folders you need to interact with should be located in the course folder on your machines desktop

Solutions to the exercises are located in folders named

(exercise solut ion) ProjectName

Where ProjectName will have previously been stated in the course notebook For example the folder called

(exercise solut ion) Sorts

contains the s ln file (Visual Studio solution file) which is the file you would open to see the solution to the Sorts exercise To open the solution you can either double-cl ick on the s ln file or open it via the File menu in Visual Studio NOTE if the file extension s ln is not visible just double-click on the file whose descr ipt ion reads Microsoft Visual

Studio Solut ion

The course folder also contains other C++ solutions in separate folders that again are usually referenced from the text In the main these are demonstrations andor contain code that might be useful to you after this course (but considered beyond the scope of this introduction to C++)

A quick note about Solutions and Projects in Visual Studio

In the real commercial world a full solution to a given problem may involve the creation of many constituent projects (possibly involving a variety of programming languages) A Visual Studio Solution (s ln file) mimics this approach and is really a container for separate constituent Visual Studio Projects files (vcxproj files)

All of our solutions contain single projects ndash and these may be opened in preference to opening the solution files For example in the (demonstrat ion) Ackermann

folder you will find a (demonstration) Ackermanns ln and a (demonstration) Ackermannvcxproj file you may open either file to work on the cpp code in the project

Copyright

This document is Copyright copy 2019 by Dr P Morris All rights are reserved No part of this publication may be reproduced transmitted transcribed stored in a retrieval system or translated into any language or computer language in any form or by any means without the prior written permission of the author

Version Date Author Comments

19 15 October 2019 Peet Morris

Please let us know if you find typos or errors in our course book and code

Contents

1 Introduction 1

11 What you should already know 1

12 What you will learn 1

13 Where can I get a copy of the softwaretools used 1

2 Things to understand 1

21 Compilers new and old 1

22 The C++ Standard Template Library (STL) 2

23 Visual Studio 2019 3

Creating your first program in Visual Studio 2019 6

Explanation 10

Your projects default code template 13

Arithmetic Operators 15

Characters 16

Header (include) Files 17

Strings 18

The LF (Line Feed) Problem and Reading Keys 20

Casts 22

Other Cast Types 24

3 Basic Control Flow 28

Selection - ifhellipelse statement 28

Selection - switch multiple selection statement 30

Repetition ndash while dohellipwhile and for loops 30

4 Logical and Bitwise Operators 35

41 Logical 35

42 Bitwise 37

Shifts 38

XOr 38

5 Introduction to Functions 39

Creating a function 41

52 Algorithms 49

Functions and Pass by Reference 51

Returning values from functions 53

Side effects 55

6 Classes and Objects 64

Creating your first class 65

Member functions and Passing parameters 67

Data Members 68

Constructors 70

Separating use from declaration and definition 72

Destructors 81

7 Arrays vectors lists and hash-tables 82

Declaring and using arrays 83

Searching Arrays with Linear Search 87

Sorting Arrays with Insertion Sort 90

Multidimensional Arrays 94

Declaring and using vectors 99

stdarray 105

Declaring and using lists 106

72 Hash Tables and Cached Calculations 107

Hash Tables 108

8 Pointers 112

Initialising pointers 113

Pointer Arithmetic and Arrays 115

9 APIs New Delete and Dynamic Memory 124

Using an API 124

Dynamic Memory Management 125

10 More on Functions 125

Multiple arguments overloading and default values 129

Passing Arrays to Functions 132

Passing Two-dimensional Arrays to Functions 135

11 Inheritance and (not presented) Polymorphism 135

111 Inheritance 135

Modelling a student - a first attempt 137

112 Polymorphism 143

12 Appendices 147

Arithmetical Operators 147

Assignment Operators 147

Assignment and Arithmetic examples 148

Relational and Equality Operators 148

Logical Operators 149

Precedence and Associativity Table 150

Escape Sequences 151

Cast Operator 152

Formatted Output 152

Header Files 153

Matrix Libraries 153

Scope 154

Enumerating constants 154

Constants 154

Vector member functions 155

Global functions 155

list member functions 156

cmath functions 156

String class 158

ASCII Character set 161

Handy IDE Settings 169

Exercises

Exercise 1 (Optional) Creating a first and default program 6

Exercise 2 CreatingModifying additional projects 26

Exercise 3 SearchString 29

Puzzled Programmers 29

The Collatz Conjecture 31

Mixing loops 33

PLUSPLUS Recursion 34

PLUSPLUS Base Two and Bits 37

Practising with Logical and Bitwise operators 38

Writing functions 42

Using a struct 43

PLUSPLUS When Things Go Wrong 44

The Monty Hall problem 46

More Functions 48

PLUSPLUS IsLeap in a line 49

Algorithms 49

Pass arguments by reference 52

Returning a value from a function 57

PLUSPLUS Arithmetic Bases 58

Searching for Sequences 61

PLUSPLUS Optimising Searching for Sequences 63

Evolving Searching for Sequences 64

Creating a class 65

Passing parameters 67

Using data members 69

More Objects 70

Using constructors 71

Separating declaration and definition 74

PLUSPLUS Using external libraries and third party header files 78

Creating an array to hold exam results 84

Linear Search 87

PLUSPLUS Debugging Linear Search 89

SortingSearching an array 90

PLUSPLUS Binary Search (Binary Chop) 93

Creating a multidimensional array 95

Creating a vector to hold exam results 100

Using insert() and iterators 103

Computing Fibonacci Numbers 110

Using pointers 114

Pointers and Arrays 116

PLUSPLUS Pointers and Arrays 119

PLUSPLUS Function pointers 122

main() and command-line arguments 126

EncryptDecrypt a file 128

Passing Arrays to functions 132

Base classes 137

PLUSPLUS Polymorphism 144

The PowerPoint slides entitled Exercises show the inclusive fromto exercise numbers which cover the topics discussed in the previous section It is not at all necessary to attempt to work through the entire quoted range variety is the spice of life ndash just choose those that appeal

1

1 Introduction Welcome to C++ A Comprehensive Introduction

These notes accompany the course delivered by Oxfords IT Services IT Learning Programme

If at any time you are not clear about any aspect of the course please make sure you ask your lecturer or demonstrator for some help If you are away from the class you can get help by email from your lecturer or from helpitoxacuk

Please also note that the university subscribes to Lyndacom ndash please check there for other C++ resources

11 What you should already know

The prerequisite for this course says that Either experience in another programming language or attendance on one of the PHP JavaScript or Python Kick-Start courses Is required

The more programming knowledge you have the better That said the documentation and lectures are structured such that those with very little knowledge should still be able to work through the course at their own pace

12 What you will learn

We will cover the following topics

Working with Microsofts Visual Studio Fundamental data types

Control Flow amp Iteration Header Files

Strings Functions

Arrays and Vectors Classes and Objects

Constructors and Destructors Member functions

Pointers And much more

13 Where can I get a copy of the softwaretools used

wwwvisualstudiocom (Microsofts C++ Compiler IDE and tools)

wwwpeetmcomC++introcoursezip (latest course code notes slides etc)

2 Things to understand

21 Compilers new and old

Students on this course often have to work with enhance or bug-fix existing code This sub-section is primarily for their consideration (it assumes some prior C++ knowledge)

2

Not all C++ compilers comply with the latest official ISO C++ standard (C++17) which was finally approved in December 20171

What does this mean It means that the code you write compile and run on one machine may not compile on the next machine if you are using a different compiler (even if it is using the same operating system) In this course you will be using Microsofts C++ Compiler (part of Visual Studio 2019)

Some older header files you may see with inherited C++ code are

include ltiostreamhgt have a h extension The C++ standard for this header file is include ltiostreamgt Your program may run correctly by adding a h but simply adding a h suffix will not work for all included files

include ltstringhgt has been replaced with include ltstringgt The stringh header file does not include C++ strings it includes C strings

include ltmathhgt has been replaced with include ltmathgt

The lesson to be learnt here is that a lot of C++ code you come across will have been created using older compilers Some of the header file and other code will not be recognised and may cause compilation errors when compiled on a machine which is more compliant with the C++ standard

If you are using the Gnu Compiler Collection (gcc g++ etc) you can specify standards compliancy via the ndashstd option eg -std=c++17 (other options are C++98

C++11 C++14)

Visual Studio can also be configured to use LLVM and clang Please see the relevant online documentation of how to install and use these if you wish to use them httpsllvmorgdocsGettingStartedVShtml

22 The C++ Standard Template Library (STL)

enwikipediaorgwikiStandard_Template_Library

The C++ programs you write will consist of the classes and functions that you write or modify (we provide partial solutions to every exercise)

However we will also look at what is still commonly referred to as the STL (now just part of the C++ Standard Library ) which holds a collection of existing classes functions and algorithms that you can use in the programs you will be creating

Some of the classes and template classes we will be looking at are

The string class The vector container template

The sort algorithm The list container template

The find algorithm

In addition you should also look at and be aware of another powerful library called Boost (parts of the STL come directly from the Boost library) wwwboostorg

The Boost library is easy to install (on any platform) as most Boost libraries are what is called header-only ie they consist entirely of header files containing templates and inline

1 A draft of this is included with your course files (n4660pdf) Its worth mentioning that this draft is in effect the published C++17 standard

3

functions and require no separately-compiled library binaries or special treatment when linking

23 Visual Studio 2019

What is Visual Studio (VS) VS is Microsofts freely available integrated development environment (IDE) and comes complete with optional compilerstools for a variety of languages We have only installed the IDE and the C++ compi ler (clexe etc) for this course

So what is a compiler

A compiler is a computer program that allows us to write programs in some specially defined language (unfortunately not English yet) in our case C++ (a so called high- level

language ) As you heard earlier the tex t we write in C++ is called source-code it is just simple text that one could write in Notepadexe for example

Sadly source-code is not directly understood by operat ing systems such as Windows Linux and macOS etc and it is the compilers job to convert our source-code into the terse concise and highly optimised machine-code that computers understand directly

Machine-code is often called executable or object-code and the compiled version of the source code is really just a file that contains numbers ndash a series of 8-bit bytes each holding a value between 0 and 255 The numbers either encode l ow-level instruct ions (code) or data that working together define the program Because these numbers may not encode displayable characters (see the ASCII table in the appendices to see a mapping between the numbers and the displayable characters) opening such a file an exe file in something like Windows notepad application would result in something like this being displayed (just the beginning shown)

However if we open this same executable file in a program that simply displays the files content as numbers and not what characters if any are represented by those numbers as Notepad is doing) we see this (the numbers are shown in base-16 or hexadecimal format)

4

The first two numbers 4D and 5A can be displayed as the text M and Z2 (see the first two characters at the top left in the previous notepad view of this file) 4D in base 10 is 77 and 5A is 90 ie the ASCII values for M amp Z (you can look these up in the ASCII table in the back of your course book)

Also take note of the line sequence starting 55 8B EC Then read on

2 MZ (0x4D5A) at the beginning of a file is an example of whats known as a magic number these are often used to identify a file type ndash in this case an MS-DOS executable file Trivia MZ are the initials of Mark Zbikowski the designer of the MS-DOS executable file format

5

If we have Visual Studio we can open the same file to see how such numbers translate into instructions and data

55 8B EC is the real beginning of our program In the above we see the numbers on the left and on the right what they actually mean Eg the first number 55 means push ebp which is an Intel CPU instruction Likewise 8B and EC together mean mov ebp esp The next line 81 EC C0 00 00 00 combines instructions and data and translate into sub esp 0C0h (subtract from esp the value C0 or 192 in base-10)

This is the entire program really the extra data shown in the previous views are for housekeeping

What does this program actually do then

Well youre about to find out ndash youre optionally now going to recreate it in Exercise 1

6

Creating your first program in Visual Studio 2019

Exercise 1 (Optional) Creating a first and default program

IMPORTANT

This exercise starts with a walk-through of using Visual Studio to create a new solution which you then go on to modify You should have already seen the steps needed to create a new solution in class so if youd rather just get on with the modification part simply open the (exercise solut ion)

f i rs t folder (in the Course folder) and double click the f i rs t s ln file If you choose to do this you can skip over the next few pages to the Explanation section (232) or even jump further on to Task 1 on page 14

Note You will not need to create any completely new programs during the course so even if you didnt fully follow the steps you can still safely move on to the modification part However if you really want to walk it through for yourself

Start the Visual Studio 2019 Integrated Development Environment (IDE) and create a new C++ Console application project You should have a shortcut to Visual Studio on your desktop failing that look for it on the Start menu

If they appear follow the prompts as shown below (if youre asked about keyboard mappings or Develop options select the C++ option)

7

Click Create a new project

Select Console App and click Next

8

Well locate the first project in a folder called first in your C drives Temp folder If the folder doesnt exist it will be created for you Click Create

Something like the above should appear (if you dont see the Solution Explorer panel open it via the View menu)

9

Alter the code adding the lines in bold as show here

include ltiostreamgt using namespace std int main() stdcout ltlt Hello Worldn system(pause)

Build and run the project by pressing the green arrow or by pressing F5

10

Explanation

Disclaimer at this stage you do not need to fully follow all of this just now

include ltiostreamgt

iostream is a standard C++ library file Files of this type are called header files They are text files usually containing C++ declarations definitions and code

Including iostream allows us to use some pre-defined objects to output messages to a console window This file must be included for any program that outputs data to the screen - or inputs data from the keyboard for that matter

The C++ compiler operates in passes through our code In the first pass ndash called the pre-processing pass ndash include directives are processed which are really text-substitution directives To be precise what include ltiostreamgt says is ldquoGo and find the text file called iostream and replace the directive with the contents of that filerdquo

The file name following a include directive can be enclosed in double quotes or chevrons ie include iostream or include ltiostreamgt The meaning of each is defined by the implementation (Microsofts C++ compiler in our case)

However it is common practice that if file name is in quotes it will be looked for locally first - in the same folder as the cpp file containing it and before being sought elsewhere Conversely if it is in chevrons the compiler will usually look for the file in a central include folder that was installed with the compiler ndash this folder is usually reserved for include files that come with the compiler as opposed to those that you might write yourself eg standard includes (like iostream) We therefore usually use quotes when we want to include our own custom project specific include files and chevrons when wanting to use include files that come with the compiler

You may also see that the filename sometimes has a h file extension This typically means that the header file being used is a C language header file and not a C++ one There are other variations (you are welcome to use your own) for example you might also see the occasional hxx file extension or something else entirely

using namespace std

The using namespace std code above doesnt actually appear in the automatically generated code In our project and solution files we will add it just after any include directives

namespaces in summary are very simple Everything within a namespace has a unique name and so theyre often used to help divide larger projects into more manageable chunks and to avoid name clashes

Standard C++ places a lot of its routines and functionality within a namespace call std Wed like to use this functionality and so we say we want to use all of the std namespace In the real world this isnt terribly good practice

11

However by declaring that were using namespace std throughout we can access members of this namespace without having to say exactly where they are (in which namespace) or worry about name clashes - where two objects in different files have been given the same name

The members of std that we will be using throughout are

cin (Console In) and cout (Console Out) and we must use include ltiostreamgt in order to use them

endl - is a stream manipulator that writes a new line to output endl stands for end

of l ine and is pronounced end all

If we dont declare that we were using the std namespace (which is the case in the automatically generated code) we have to prefix any use of cin cout and endl with std eg stdcin stdcout stdendl If youve added the using namespace std directive you may now remove the std in front of the stdcout ltlt Hello Worldn line

int main()

This is the entry point to our program ndash every C++ program must have this same entry point defined main() is a function the body of a function is defined within the opening and closing braces that come after its name The int to the left of main() says that this function returns (or resolves to beevaluates to) an integer value Returning a value requires you to use a return statement However as it is normal practice to simply return the value zero if you omit the return statement a value of zero is returned for you (only where main is concerned) If you want to explicitly return the value yourself you could modify the code to read

int main() stdcout ltlt Hello Worldn system(pause) return 0

So why return a value anyway Our added line return 0 means in this case that our main doing whatever it does as part of its function eventually resolves to the value 0 The value is returned to whatever called our programs entry point in this case and as usually that is the operating system ndash which has been waiting for us to return a value at this point However the operating system will simply ignore whatever value we ultimately return Why do it then

12

Consider the case when one of your programs needs to run another program to perform a part of its entire function Your main program needs to start this other program and wait until it completes successfully before continuing See the description of the system(pause) code line below

stdcout ltlt Hello Worldn

cout is an object declared in iostream ndash think of its name meaning console out Anything sent to cout using the double chevron operator ltlt appears on the console the

The n in the text means that cout should also output a carriage-return linefeed sequence (terms taken from the days of typewriters and telex machines) basically it means start any new output on a newline underneath the current line An alternative to using n is to use endl eg stdcout ltlt Hello World ltlt endl endl does more or less the same thing as n

system(pause)

system() is a standard function that is used to run an external program (here thats a standard Windows program called pauseexe) The system() function waits for the pause program to complete before continuing Going back to the discussion on return 0 earlier this is an example of one program starting another ndash here thats our program starting the pause program The pause program returns a value as part of its completion and we can examine that if we want Programs usually return 0 for success or some other integer value that means something went wrong ndash the value returned indicates what went wrong Ie a returned value of say 42 might mean that we cant answer the ultimate question with this computer3

So what is pause pauseexe is a standard Windows program that simply outputs the message Press any key to continue and then waits for a key to be pressed before exiting We use that facility here so that our program doesnt simply shutdown and disappear as it falls off the end of main()s closing or encounters a return statement If we did allow it to exit we would hardly have time to examine our programs output before it disappeared off the screen Try that and see (comment out the line using a double-slash like this system(pause))

If you run any of the course code on Linux or a Mac youll need to change this line to something like cinget()

3 An unashamed reference to the Hitch Hikers Guide to the Galaxy and the Deep Thought computer

13

Your projects default code template

In the course exercises when it comes to you writing code we will always ask you to open and then modify a partially complete projectsolution so you wont have to fiddle with projects and boilerplate code like this again

Nevertheless should you wish to start from scratch or simply experiment with Visual Studio we recommend using the code below as a starting point

include ltiostreamgt using namespace std int main() Start coding after here system(pause) return 0

14

Task 1

Immediately above system(pause) Replace the stdcout ltlt Hello Worldn line with the code shown here

int anum = 0

cout ltlt Enter a number

cin gtgt anum

cout ltlt The number you entered is

ltlt anum

ltlt endl

Test your modified program Tip remember you may hit the F5 key to build and then run your program

Try entering some text instead of a number Did it work

Alter the spacing (use of spaces and tab characters) in your code ndash does the C++ compiler care about this so called whi tespace

The statement int anum = 0 defines a variable (a memory location) which we will refer to in our code as anum to store a number of type int to hold an in teger (ie 1 -4 27) The memory location is being initialised with a value of 0 here It is good practice to initialise variables when you define them In C++11 a new type of uniform initialisation syntax was introduced and also encouraged eg int anum 0

cout ltlt Enter a number cout is a name that belongs to the namespace std The ltlt is called the stream insert ion operator When the program executes the value to the right of the operator (Enter a number) is inserted in the output stream and ultimately output to console window

cin gtgt anum cin is the input stream object of the namespace std gtgt is called the stream extract ion operator and is used here to read a number from the keyboard

cout ltlt The number you entered is ltlt anum ltlt endl This statement concatenates the output by using multiple stream insertion operators ltlt endl is the stream manipulator that adds a new line

The next Exercise starts on page 26 The pages between here and page 26 contain

code that you may like to try out by further modifying this project if not just read through the textcode until you get to page 26

15

Arithmetic Operators

Most computer programs perform arithmetic calculations Table 1 summarises the standard C++ arithmetic operators When working with integer division where both the numerator and denominator are integer the expression 15 6 evaluates to 2 To get the remainder after integer division you would use the modulus operator Note the modulus operator can only be used with integer operands

To establish the complete result of the following integer division 156 requires two operations

15 6 = 2

15 6 = 3

The result being 2 remainder 3

C++ Operation C++

arithmetic operator

Algebraic expression C++ expression

Addition + y + 6 y + 6

Subtraction - a - b a - b

Multiplication c times d or cd c d

Division xy or y

x or yx x y

Modulus p mod q p q

Table 1 - C++ arithmetic operators

Other fundamental data types Table 2 shows how you would declare and initialise four other data types for use in programs (there are more data types available)

16

Data type Example

Float float aFloat = 1234

Double (the precision of a Float) double aDouble = 123456

Char char aChar = A

Bool bool aBoolean = true

Table 2 - C++ numerical types4

Characters

Characters are normally stored in variables of type char but can also be stored as in t(eger) data types Characters are represented as single byte integers in the computer so it is possible to output a character as an integer or as a character

All characters have a numerical representation in the computer and the ASCII (American Standard Code for Information Interchange) character set shows each character and its decimal equivalent (also note that a combination of characters may be used to form more complex Unicode characters) See appendix 111

Characters can be read in with the following statements

char aChar declares a variable (aChar) of type char

cin gtgt aChar this statement is used to read a character into the variable aChar

Note After entering a character the ltENTERgtkey must be pressed before the character is read by the program

The following four statements correctly declare a variable of type char output a user prompt then read a character and store it in the variable aChar

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar

4 See httpencppreferencecomwcpplanguagetypes for a complete list (or the official ISO standard of course)

17

Header (include) Files

So far weve seen that to use certain functionality we had to include ltiostreamgt We have to do similar to use other functionality which is not part of the code C++ language ie we will need to include anything that comes as part of the standard library

In its current form Visual Studio comes with the following include files (most of which are standard files)

h files (95 C language files)

agentsh agileh ammintrinh amph amprth amprt_exceptionsh amp_graphicsh amp_mathh amp_short_vectorsh armintrh arm_neonh cfguardh collectionh comdefh comdefsph comiph comutilh concrth concrtrmh ConcurrencySalh concurrent_priority_queueh concurrent_queueh concurrent_unordered_maph concurrent_unordered_seth concurrent_vectorh crtdefsh crtversionh delayimph dloadsuph dvech ehh emmintrinh excpth fvech gcrooth immintrinh internal_concurrent_hashh internal_split_ordered_listh intrinh intrin0h invkprxyh iso646h ivech limitsh mm3dnowh mmintrinh nmmintrinh omph pgobootrunh pmmintrinh pplh pplawaith pplcancellation_tokenh pplinterfaceh ppltasksh ppltaskschedulerh pplwinh rtcapih salh setjmph setjmpexh smmintrinh srvh stdargh stdboolh stdexcpth stdinth tmmintrinh typeinfoh use_ansih vadefsh varargsh vcclrh vccorlibh vcruntimeh vcruntime_exceptionh vcruntime_newh vcruntime_new_debugh vcruntime_startuph vcruntime_stringh vcruntime_typeinfoh wmmintrinh xatomich xatomic0h xkeycheckh xlocinfoh xmmintrinh xsmf_controlh xstring_inserth xtgmathh xxamph xxamp_inlh ymathh yvalsh zmmintrinh

115 C++ files

algorithm allocators any array atomic bitset cassert ccomplex cctype cerrno cfenv cfloat chrono cinttypes ciso646 cliext climits clocale cmath CodeAnalysis codecvt complex condition_variable csetjmp csignal cstdalign cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cuchar cvt cwchar cwctype deque exception experimental filesystem forward_list fstream functional future hash_map hash_set initializer_list iomanip ios iosfwd iostream istream iterator limits list locale Manifest

18

map memory msclr mutex new numeric optional ostream queue random ratio regex scoped_allocator set shared_mutex sstream stack stdexcept streambuf string string_view strstream system_error thr thread tuple typeindex typeinfo type_traits unordered_map unordered_set utility valarray variant vector xcomplex xfacet xfunctional xhash xiosbase xlocale xlocbuf xlocinfo xlocmes xlocmon xlocnum xloctime xmemory xmemory0 xstddef xstring xtr1common xtree xutility xxatomic

Strings

Next to numbers strings are the most commonly used data type in programming

A string is both a datatype (string) and also literal character data ie a sequence of characters such as Oxford or StAndrews In C++ string literals are enclosed in quotes The quotes are not part of the string they identify the data type as a string

Actually this isnt quite true the double quoted strings are a sequence of characters and are taken from the C programming language The things declared of the string type are C++ string objects ndash which may be initialised using the C language literal

C++ strings can be declared and initialised in this way

string institution = Oxford

string name = Peet

To use the string type in your programs add the header file include ltstringgt at the top of your program This allows the use of part of the C++ library of classes called the string class (and its member functionsmethods explanations will follow soon)

Of course strings are normally used when requesting an input Consider this code

string aName aDept Two string objects

cout ltlt Enter your full name

cin gtgt aName

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

19

If in answer to the first prompt we were to enter say Fred Brooks 5 the interaction and output of our program would immediately result in this

Enter your full name Fred Brooks

Enter your department Fred is associated with Brooks

Why When reading in a string with a space such as FredltspgtBrooks only the first part Fred is read into aName ndash and the input is said to be space delimited by cin ndash and consists of two separate inputs (so the Brooks parts is read into the aDept string variable)

We could use multiple prompts to read in a name of course but this is inconvenient

To handle this situation we can use the standard getline(cin aName) function to read in a name instead of using cin gtgt aName This reads all key-strokes into aName until the ltENTERgt key is pressed at which point it returns a string containing all of the characters from the input

cout ltlt Enter your full name

getline(cin aName)

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

The string class has many useful functions you can use to manipulate strings An example is the length() member functionmethod

string aName = Fred Brooks

cout ltlt The length of the string aName is ltlt aNamelength() ltlt endl

This statement will output - The length of the str ing aName is 11

See section 12119 for more information on the string class and its member functions

5 Fred Brooks is a real person and a legendary computer scientist httpenwikipediaorgwikiFred_Brooks

20

The LF (Line Feed) Problem and Reading Keys

Continuing on consider the following code

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

string aName

cout ltlt Enter your full name

getline(cin aName)

cout ltlt You entered ltlt aName ltlt endl

system(pause)

The intent here is to first ask for a character and then to use getline() to ask for a name

If only things were that simple

If we were to enter say a Z to satisfy the first prompt the program would immediately output

Enter a character Z

You entered Z

Enter your full name You entered

Press any key to continue

The problem here is that being a keyboard key theltENTERgt key is itself being seen as a valid input so when we enter Z followed by the ltENTERgt key were actually entering two keys ndash Z and the ltENTERgt key The first keys placed into aChar whilst the enter key is left in the keyboards buffer This is quite reasonable if you think about it you entered two keys (Z and ltENTERgt) but provided a home for just one of them in aChar

Ok so whats the problem Well the problem is that we really need to use something like getline() to read text that contains spaces and it just so happens that getline() given this scenario will see the residual ltENTERgt key left in the buffer and it will assume that you didnt enter anything you just hit the enter key

This problem - that of having a mischievous ltENTERgt key waiting to surprise us ndash will occur whenever you read a key from the keyboard using cin Luckily theres an easy fix as we can use another input function to read and then discard the waiting ltENTERgt key Its called cinget() Here is a modified version of the code above that fixes the problem

21

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

cinget() REMOVE THE ENTER KEY discarding the got character

string aName

cout ltlt Enter your full name

getline(cin aName)

Used like this cinget() reads and discards a character from the input stream You can do the same using cinignore() cinget extracts a single character from the stream and returns it cinignore() extracts any number of characters and discards them (the details are specified via passed parameters to the function) or a single character if no arguments to the function are provided

You can easily use cinignore() to ignore a number of characters or until a certain token (character) is met eg the following code reads in a users first and last names and then outputs their initials

22

char first last Two 8-bit characters

cout ltlt Please enter your first name followed by your surname

first = cinget() Get one character

The first parameter is the maximum number of characters to

extract (and ignore) The second parameter is a

delimiting character The function stops extracting characters

as soon as an extracted character matches this one

cinignore(2566 ) Ignore until a space is seen

last = cinget() Get one character

cout ltlt Your initials are ltlt first ltlt last ltlt endl

Casts

On occasions in your programs you may want to store a value in a variable of a different type (when there is a danger of a loss of information the compiler will issue a warning for example when storing a double in an int) If you store a double as an integer you lose information in two ways

any mantissa (fractional part) will be lost

the magnitude of the double being stored may be too large to fit into the integer

Eg it is not possible7 to store 6678 x 10000 as a 16-bit unsigned integer because 667800 is 10000010011011100 in binary (17-bits) and is therefore larger than the maximum storable value of 65535 (1111111111111111) However you can store 1230 as an integer8

When you need to represent a value as a different type you can use the static_cast notation as shown here to change a double to an integer

6 If this is exactly numeric_limitsltstreamsizegtmax() there is no limit As many characters are extracted as needed until delim (or the end-of-file) is found

7 Actually the result of attempting to store 66780 in a 16-bit unsigned integer will be 10011011100 or 1244 Do you see how this value comes about

8 Also see the (demonst rat ion) L imi ts project

23

int anInt

anInt = static_castltintgt(doResult) where dResult is a double

You may also use the following historic classic C-style9 notation to cast to different data types

anInt = (int)dResult

Eg to change an integer to a character

char aChar

aChar = static_castltchargt(bInt) where bInt is an integer

You may also combine this using the

object-constructionfunction-call syntax of C++ eg

double d = 314157

int n = (int)d Convert ds value to an integer

int j = int(d) Ditto

9 C-style casts are usually considered to be too powerful ndash in that they indiscriminately allow unsafe and downright dangerous conversions C++ casts were introduced to solve this problem

24

Other Cast Types

Although outside the scope of this introductory course for reference here is a summary of the cast types in C++ (feel free to skip this for now and come back to it at a later time)

static_castlttypegt(object)

The type parameter must be a data type for which there is a known method for converting object to whether this be a built-in or through a casting function (constructor) All types of conversions that are well-defined and allowed by the compiler are done using static_cast

The static_cast operator may be used for operations such as converting a pointer of a base class to a pointer of a derived class converting numeric data types such as enums to ints or ints to floats However static_cast conversions are not necessarily safe as no run-time type check is done which can cause casting between incompatible data types for example initialised pointers However this is checked at compile time to prevent casting obvious incompatibles Also be aware that a static_cast between pointer of base to pointer of derived may produce an erroneous result (where the actual object pointed to is of type base not derived)

dynamic_castlttypegt(object)

In the C++ programming language the dynamic_cast operator is a part of the run-time type information (RTTI) system that performs a typecast Unlike the static_cast the target of the dynamic_cast must be pointer or reference to class Unlike static_cast and C-style typecast (where a type check is made during compilation) a type safety check is performed at runtime If the types are not compatible an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers)

reinterpret_castlttypegt(object)

Allows any pointer to be converted into any other pointer type Also allows any integral type to be converted into any pointer type and vice versa

The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument (unlike static_cast but like const_cast the reinterpret_cast expression does not compile to any CPU instructions It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type)

You cannot cast away a const or volatile qualification You can explicitly perform the following conversions

const_castlttypegt(object) A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is

25

identical except for the const and volatile qualifiers For pointers and references the result will refer to the original object For pointers to data members the result will refer to the same member as the original (uncast) pointer to data member Depending on the type of the referenced object a write operation through the resulting pointer reference or pointer to data member may produce undefined behaviour

26

Exercise 2 CreatingModifying additional projects

Examine how comments look in a program

Examine the use of some fundamental data types

Using different data types

Using the cast operator

Using the string class

Task 1

Open the skeleton project called EvenI

The project folder is

EvenIEvenI s ln

Modify the projects code in to prompt for two numbers of type double and two numbers of type integer

The program should output the sum the product and the difference of the double numbers Also output the quotient and the fractional part of the two integers10

Youll need something along the lines of hellip

double aDouble double bDouble

etc

To read a number into aDouble you could use

cin gtgt aDouble

Task 2

Modify your EvenI program to read in two characters Enter the characters a and Z

Output the two characters with the character case changed ie a becomes A and Z becomes z

You will need to look online or at in 12120 to establish the ASCII integer values of each character hellip you can alter a characters case by treating it as an integer and

To convert integers (or the results of evaluating integer expressions) to say characters we need to use a cast Eg

int i = 65

cout ltlt static_castltchargt(i + 32)

10 Trivia quotient comes from the Latin quotiens for how many times For example when dividing twenty by three the quotient is six and two thirds You can use a modulus b to get the fractional part

27

then by addingsubtracting tofrom it

Task 3

Open the skeleton project called Address and modify it so that it can be used to collect some user data

Output this collected data to screen as shown in Figure 1

Note that youll have to have include ltstringgt in order to use getline()

Figure 1

Visual Studio builds projects in one of two different modes ndash Debug or Release we will always use the Debug mode (a Release build is normally only used when a product is being beta tested ie late in the cycle)

When using Visual Studio (or most other IDEs for that matter) we normally do not have to concern ourselves with the location of the executable that is built by the program ndash because we normally run it from within Visual Studio itself However and just for your information really the exe for a debug build will always be located in the Debug folder immediately below the projects root folder ie for this project Addressexe is located in the (exercise solut ion) Address Debug folder whilst a version built in Release mode would be in the (exercise solut ion) Address Release folder

Debug builds contain extra diagnostic code that is automatically inserted by the compiler

28

3 Basic Control Flow The programs you have created so far are limited in that they run through a sequence of instructions once and then stop Most computer programs will make decisions and carry out different actions determined by the user input

C++ has three kinds of control structures

Sequence statement - the computer executes the statements one after another All the programs you have written so far use sequence statements

Select ion statements - if ifelse switch

The if selection statement selects an action if a condition is true or skips the action if the condition is false

The ifelse selection statement selects an action if a condition is true or performs a different action if the condition is false

The switch multiple selection statement can be used to perform many different actions based on a character or integer value

Repeti t ion statements - while for do while

The while and for statements perform actions within their bodies zero or more times If the loop condition test is initially false no actions will occur

The dowhile statement will perform the actions in the body at least once (the test ndash as to whether to continue - is at the end)

Selection - ifhellipelse statement

The if selection structure is used to choose among alternative courses of action The structure of the statement is

if(mark gt= 50)

cout ltlt Passed

else

cout ltlt Failed

If the condition (mark gt= 50) is t rue the statement following it is executed cout ltlt Passed

If the condition is false the statement is ignored and control is passed to the else part of the selection and statement following else is then executed cout ltlt Failed

ifelse selection statements can also be nested within other ifelse selection statements

29

Exercise 3 SearchString

Task 4

Open the skeleton project called SearchStr ing

You will need to include ltstringgt at the top of the code to complete this exercise See page 158 for more on the string class functionality

Modify the program to display a string of text to the user

The user should then be prompted to select a word from the sentence and input a replacement word Your program should replace one with the other You will want to See section 12119 on string functionality

The prompting string should be shown both before and after the update

Tips

Given a string s initialised to

string s = C++ at the University of Oxford

string t

int i = sfind(U)

cout ltlt i ltlt endl 11

t = ssubstr(0 i) bit before U in t

t = t + ancient + + ssubstr(i) +

Outputs C++ at the ancient University of Oxford

cout ltlt t ltlt endl

Puzzled Programmers

Using if if else nested ifs switch and the conditional operator -

Task 1

Solving puzzles

Open the I fp project and WITHOUT compilingrunning it determine its output

You will need to consult the operator precedence table in section 1216

You shouldnt compile or run the program to start with ndash the idea here is for you to determine its output on paper11

Tip you might want to consider tidying up the codes layout before attempting to solve it

void out(int n) is a function We havent covered functions yet but it makes sense to use one here and so we have Suffice to say for now that using out(some value) will output the value to the console window

11 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

30

Functions will be explained fully soon

Compile and run the program ndash if your workings from Step 1 differ from the output you should determine where you went wrong

Selection - switch multiple selection statement

The switch multiple selection statement can be used to perform many different actions based only on a single integer value Note however the switch statement can only be applied in narrow circumstances The tests must be constants and be integers Lets compare the two statements

int num switch(num) case 1 cout ltlt num = one

double num switch(num) case 11 cout ltlt num = 11

OK ndash Test is 1 a constant and an integer NOT OK ndash Test is not constant integer

Repetition ndash while dohellipwhile and for loops

The while statement is commonly used to carry out repeated steps perhaps reading in values before doing a calculation on values read in The format of the code is

while(condition)

statement

This can be read as whi le the condition is t rue continue to do the statements until the condition is false

31

The Collatz Conjecture

Win a million dollars

Task 1

Open and complete the project called Col latz (use a while() loop)

Given any positive integer if the number is even divide it by two else treble it and then add one If the result is one stop else repeat the process

The Collatz conjecture says that given any starting value the process above will eventually hal t (goes to one and stops)

Eg setting n to 9 as a starting point successive values would be

28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is not known whether the Collatz conjecture is true Fame and fortune await anyone who can prove it httpenwikipediaorgwikiCollatz_conjecture

A Collatz tree as visualised by Edmund Harriss

32

This image is a sample from the colouring book Visions of the Universe by Alex Bellos and Edmund Harriss

Get your own hi-res version for colouring-in here and see here for an explanation

33

Task 2

Re-implement your code so as to use a for() loop (this will be a lot easier than you might first think)

Not essential for this task but as we mention for loops you might like to look at the for project to see how a for loop can be animated to show how the three sections of it work in order

Mixing loops

Task 1

Open and modify the skeleton project called Factor ial

Modify it to use different repetition statements to calculate and display the factorial of a value entered by the user (they should enter a value between 1 and 10 inclusive)

Example use a while loop to prompt for an input value (between 1 and 10) and a for loop to calculate the factorial result

The output should be like that shown in Figure 2 below

Factorials12

The factorial of 5 (usually written as 5) is

1 x 2 x 3 x 4 x 5 = 120

If factorials are new to you think of them as defining the number of ways to arrange n items

To avoid displaying results in scient i f ic notat ion use

cout ltlt setprecision(0) ltlt fixed

setprecision() requires include ltiomanipgt

12 0 Is defined to be 1

34

Figure 2

PLUSPLUS Recursion

Come back to this after weve covered functions

Note that our solution optionally also uses a function and recursion to find the same factorial If you open it you will see that just after where we perform the output above we have commented out an extra line of code (uncomment and rebuild to see it in action)

We havent covered recursion in this C++ course yet but its basically the process of solving a problem in terms of smaller versions of the same problem Since the problem gets smaller each time the process eventually terminates in a problem (the base case) that can be solved directly When defining a recursive function be sure of three things 1 The problem gets smaller each time 2 Include a solution for the base case And 3 Each case is handled correctly

The recursive function looks like this ndash add then test it in your own solution

Factorial function using recursion

long long int recur_factorial(long long int n)

return n lt 1 1 n recur_factorial(n - 1)

The question mark is the conditional operator and is used with the colon to form the functional equivalent of an if then else

35

If the expression before the is true then the expressionstatement to the left of the is evaluated otherwise the one after the is evaluated Eg these are equivalent

x boo() hoo()

if(x)

boo()

else

hoo()

4 Logical and Bitwise Operators

41 Logical

Quite often we will want to perform some action if two things are true and we can achieve this using nested if statements eg

if(onething == true)

if(secondthing == true)

do something

In C++ we can achieve the same result through the use of the l ogical And operator - ampamp

if(onething == true ampamp secondthing == true)

do something

ampamp is a binary operator ndash meaning that it takes two arguments (nothing to do with base 2) eg Op1 ampamp Op2 The expressions Op1 and Op2 must be capable of evaluating to t rue or false (false in C++ has the value 0 whilst any other value is considered true) and both Op1 and Op2 have to be true in order to have the conditional part execute eg if(x ampamp y) Z = 10 Here both x and y must have non-zero values in order for z to be assigned the value 10 Note again that this is equivalent to

36

if(x)

if(y)

z = 10

The truth table for logical And is as follows ndash note that both Op1 AND Op2 have to be true for the result to be true

Logical And

Op1 Op2 Result

True True True

True False False

False True False

False False False

We also have a Logical Or operator (||) in C++ and its truth table looks like this ndash note that its one OR the other that has to be true in order for the result to be true here

Logical Or

Op1 Op2 Result

True True True

True False True

False True True

False False False

The remaining logical operator we have is the unary Logical Not (the exclamation mark is used for this)

Logical Not

Op1 Result

True False

False True

Logical ampamp and Logical || short-circuit ie for ampamp if the expression on the left-hand side is found to be false then the expression on the right is never evaluated as the whole will evaluate to false (because to be true both sides have to be true and we know that the first one is false at this point)

37

The same is true for logical || in that the right-hand expression is not evaluated if the left is found to be true (the whole will evaluate to true because the left is true so there is no need to evaluate the right-hand expression)

42 Bitwise

PLUSPLUS Base Two and Bits

We also have bitwise versions of the logical operators ndash plus some extra ones Bitwise operators work on a variables individual binary bits ndash rather than the value of all the bits taken as a whole For bitwise And we do not use ampamp but use just a single amp The same is true for bitwise Or we just use a single | and not || Bitwise Not is a little different we use ~ (the tilde) for bitwise Not

The additional bitwise operators we have are for bitwise XOr ndash for which we use the ^ symbol and lastly for left and right bit shifting we use ltlt and gtgt

Bitwise operators work on binary bits (1s and 0s) whereas the logical operators work on values equating to either true or false

For example consider the following code

int w = 10 int x = 42

int y = w amp x

int z = w ampamp x

cout ltlt y ltlt endl

cout ltlt z ltlt endl

The base-2 binary representation of 10 is 001010 and for 42 it is 101010 So w amp x means

001010 101010 amp ------ 001010 ------

Remember And is one and the other

Now let us consider w ampamp x Here were not interested in ws or xs bits just whether when taken together they are zero or something else Here both are non-zero so both are considered to be t rue and if we refer to our truth table from earlier on we will see that the result will be t rue When we assign that to an integer like were doing here the value assigned will be 1

38

Shifts

The shift operators shift the binary bits left or right Bits that do not fit fall off the ends and bits are replaced with zeros when shifting left ie bits do not rotate and come back on the other end again When shifting right the sign-bit may be preserved depending upon whether youre using a signed or unsigned integer

Shifts are useful for all sorts of things but one of the obvious uses is to multiply and divide eg x = 2 x = x ltlt 1 shifts the bits in x one place to the left so given that xs value is 00000010 in binary x = x ltlt 1 turns x into 00000100 which is 4 So x = x ltlt 1 is like saying x = x 2 You can of course divide by right shifting

XOr

The rule for XOr is one or the other but not both ie 1 ^ 0 = 1 (just like 1 | 0) but whereas 1 | 1 = 1 with 1 ^ 1 the answer is 0

Note that we do not have a logical XOr operator in C++ as we can just use = (not equal to) ndash see the (demonstrat ion) Logical XOr project

Practising with Logical and Bitwise operators

You will need to use the Precedence and Associativity table in 1216 to complete these tasks

Task 1

Open the Logical project As earlier DO NOT compilerun this yet

You will need to consult the operator precedence table in section 1216

On paper determine the programs output13

Run the program ndash output as expected

Task 2

Open the Bitwise ndash

unsigned project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Unsigned The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

13 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

39

PLUSPLUS Signs and bits

Task 1

This one is tough as you should really know something about Twos Complement arithmetic to complete this

Open the Bitwise ndash s igned

project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Signed The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

5 Introduction to Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine (which will also be a function) Encapsulat ion is data information or detail hiding If youre mathematically minded you may think of a C++ function as being very similar to one in mathematics ie a mechanism for mapping one thing to another

Once a function is written the detail of how it works is not important It is only necessary to understand what if any inputs the function needs (its parameters) and what output is produced (the functions return value)

The use of functions provides several benefits but the main one is that it makes programs significantly easier to understand and maintain The main program function can consist of a series of function calls rather than hundreds of lines of code A second benefit is that well written functions can be reused across multiple programs

You have to tell the compiler about a function before you use it and this is normally done using a prototype early in the program A function prototype consists of the return type a funct ion name and a parameter l is t - indicating the data the function will receive ndash and is terminated using a semicolon Eg

int someFunc(int int)

This tells the compiler that there is a function (somewhere) called someFunc that takes two integers as its input and returns an integer value for its output

40

Using a prototype is a way of telling the compiler the data types of any return value and of any parameters being passed and enables error checking to be done

The function defini t ion consists of the modified prototype and a function body which is a block of code enclosed in parenthesis which does the work Eg

int someFunc(int a int b)

return a + b

Here we have named the two inputs a and b and we can see that the functions job is to add these two value and to return them As this function returns a value (the sum of a and b) it may be used to expressions like this

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

Arguments can be passed to functions in two ways pass-by-value the default is where a copy of the argument value in the main program is made and then passed to the function The copy in the function only exists in memory as long as the function is active When the code within function has been run to completion the memory is released and the value held there is lost Any changes made to the copy passed to the function do not affect the original variable in any way For example if we altered and used someFunc like this

int someFunc(int a int b)

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 20

41

Note that because we passed a copy of b to the function that the line b = b 2 alters the copy (which then isnt used) and not the original

Arguments can also be passed-by-reference When arguments are passed in this way any changes made to the arguments in the function are reflected by corresponding changes to that data variable in the calling part of the program Pass-by-reference is good for performance reasons because it can eliminate the pass-by-value overhead of copying large amounts of data (In later sections we will examine how pointers can be used to fake pass-by-reference) Eg this will alter b now

int someFunc(int a int amp b) Note the amp

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 40

See section 521 for more on this subject

Creating a function

The format of a function prototype is

return_data_type FunctionName ( argument_l ist )

The function CtoF - void CtoF(int temp) - has no return data type (void) its name is CtoF and it accepts a single input argument called temp of type int (integer)

It is not strictly necessary to give the argument a name (temp) in a function prototype you saw this above in int someFunc(int int) However the argument type must be specified The statement void CtoF(int) is therefore an alternative prototype

The following exercise is an introduction to functions You will learn a lot more about functions in later exercises

42

Writing functions

Task 1

Open the project EvenI you created earlier and change the structure of the program to make use of functions

Solution in (exercise solut ion)

EvenI I

Read two integers in to main() and pass them to a function The prototype is void intCalcs(int int)

intCalcs() function should calculate and display the result of the division and modulus of the two variables passed see Figure 3

Read in two doubles to variables in main() Pass the two doubles and the value of one integer to the second function the prototype is int Calcs(double double int)

Within function Calcs() write statements to produce the output as shown in Figure 3 Most of the code already exists within main()

Return the result of the multiplication of one double and an integer cast this value as an integer

Display the returned value within main() as shown in Figure 3

Figure 3

43

Using a struct

Task 1

Open the project Person

Solution in (exercise solut ion)

Person

As you saw during the presentation we can keep related data together using the struct keyword For example say we define a thing as follows

struct thing

int x

string y

double z

Having done this we can now create as many thing objects as we wish ndash simply by declaring them as we would say an integer

thing a

thing b

Each thing object a and b contains its own x y and z member variables eg

ax = 10 thing as x member set to 10

bx = 20 thing bs x member set to 20

cout ltlt ax ltlt endl outputs 10

cout ltlt bx ltlt endl outputs 20

Complete the exercise by creating and populating a struct Person object Once populated amend the printPerson() function so as to output the persons details

44

PLUSPLUS When Things Go Wrong

Going back to Exercise 8 if you havent tried it already enter zero as your second number What happens

C++ contains mechanisms for catching errors in the form of a trycatch mechanism

cin gtgt y Enter zero

try

intResult = x y

catch(myException amp e)

cout ltlt ewhat() ltlt endl

catch()

cout ltlt Generic oops ltlt endl

Modify your code so as to catch the divide by zero

Hopefully try and catch are fairly self-evident try something and catch any error if something goes wrong

There are two catch blocks here One tries to catch a myException object (we cannot see the definition of this classstruct here) and the other tries to catch anything else that is missed by catch(myException amp e) The amp says that the myException object e is being passed to the catch handler by reference Well learn what this means a little later in section 521

So did you see the Generic oops message appear

Your C++ compiler doesnt have to catch the divide by zero error ndash doing such a thing results in undefined behaviour This is because an arithmetic exception is an OS or processor exception - which is not the same as a C++ exception - hence it cannot be caught by a in a try catch block

To catch errors like this we either need extra support from the compiler14 andor operating system or to write some extra code For example we could do this

14 See also C signal handling httpenwikipediaorgwikiC_signal_handling

45

cin gtgt y Enter zero

if(y gt 0)

intResult = x y

However first we have to realise that this is a possible source of a runtime error and secondly we have to write (correctly) the code to handle the condition

Windows has built-in exception handling ndash called Structured Exception Handl ing (SEH) and we can generate code that uses this in support of the try catch structure used earlier

To enable this we need to tell the compiler to generate code that links into the SEH mechanism

To do this open the Project | ltproject namegt Properties hellip dialog box and in the Code Generation section select Yes wi th SEH Exceptions ( EHa) in the Enable C++

Exceptions line See Figure 4

46

Figure 4

The Monty Hall problem

The Monty Hall problem is a probability puzzle loosely based on the American television game show Lets Make a Deal and named after the shows original host Monty Hall

It goes like this

You are on a game show where you are shown three closed doors You are told that behind one of them is a new car and that behind the other two are goats

Two pieces of essential information at this stage 1 your goal is to win the car 2 the game show host knows what is behind each door

Lets walk through a trial game

The game show hosts asks you to choose a door ndash lets say you choose door number 1 (your door remains closed) The host now opens one of the remaining doors to reveal a goat (as there are two goats they can of course always do this) lets say they open door number 3

47

The situation is now as follows you have chosen door number 1 Only door number 3 is open and it reveals a goat The host now asks you if you would like to switch your door to the only other closed door - door number 2 At this stage you must either stick with door number 1 or switch to door number 2 and at that point the host will open the door youve chosen to reveal your prize

The question is when youre offered the chance should you stick or should you swap - will swapping increase your chance of winning the car or is it just 5050 The claim made here is that by swapping doors you will double your chance of winning the car What does your completed project claim

Task 1

Open and complete the incomplete project MontyHal l

The goal of this project to provide a simulation of problem outlined above

The function

int getRandomDoor(int n = 3)

return rand() n + 1

is used to choose a door number between 1 and 3 (inclusive)

Note that it has a default argument ie if it is called without an argument like this int val = getRandomDoor() the argument n is set to 3 by default and val will be set to a value between 1 and 3 However if it is called like this int val = getRandomDoor(10) then n is set to 10 and val will receive a value in the range of 1 to 10

48

More Functions

Task 1

Open the incomplete project IsLeap

The program asks for a year and determines whether the year is or will be a leap year

You need to complete the function IsLeap(int y) to implement the necessary code

Although the program is incomplete the program contains pseudo code for the algorithm required to compute the answer The pseudo is also show opposite

if year modulo 4 is 0

then

if year modulo 100 is 0

then

if year modulo 400 is 0

then

is_leap_year

else

not_leap_year

else

is_leap_year

else

not_leap_year

Figure 5

49

PLUSPLUS IsLeap in a line

Task 1

Extra points for implementing the IsLeap() function in just a single line of code This could be done using ampamp and || or by using the operator (a short form of if then else)

If you completed this step how readable is your code when compared to the if else version on the right

52 Algorithms

Algorithms

An Aside Big-O notation and Algorithm Complexity feel free to jump over this to Task 1

As programmers we usually implement the various parts of any new program in the simplest and most straight-forward way possible Then later if we find parts of our program are slow (causing what are called hot-spots) we will look again at the code to see if there is a better way to do whatever it is that is taking up the time

As a general rule the most optimal algorithms run in the shortest possible constant t ime ndash such algorithms are often symbolised using O(1) whereas the worst run in quadratic cubic exponential or factorial time (you can think of the O [called Big-Oh] as meaning in the Order of for some input n)

Usually were often happy with those running in O(n) (in the order of n) time ie their running time scales linearly with the number of steps or operations they involve Loops invariably signal O(n) parts of any algorithm

This is best explained using an example

50

Task 1 Understanding Gauss algorithm

Q How would you sum the integers from 1 to n where n is say 100

The obvious way is to use a loop

int tot = 0

for(int i = 1 n = 100 i lt= n ++i)

tot += i

This is fine for small values of n but not so good for very large ones

Interestingly it is said that this self-same problem was once given to a class of children which included one Carl Friedrich Gauss (presumably the teacher wanted to keep his charges occupied for a time) While most of the children started working at the problem (using the loop approach above) Gauss thought about it for a moment and then wrote down the solution 5050

The algorithm Gauss used may be easily demonstrated using the values 1 ndash 10

Gauss realised that if he wrote out the values twice (whether on paper or just in his head) once forward and once in reverse that he could sum each column formed to 11

1 2 3 4 5 6 7 8 9 10

10 9 8 7 6 5 4 3 2 1

1+10 2+9 3+8 4+7 5+6 6+5 7+4 8+3 9+2 10+1

=11 =11 =11 =11 =11 =11 =11 =11 =11 =11

Then sum of 1 ndash 10 is then 11 10 (columns) = 110 2 = 55 (we divided by two because we used each value twice)

Coming back to algorithm runtimes you can see that when using a loop summing 1 ndash 1000 will take ten times longer than summing 1 ndash 100 which will take ten times longer than summing 1 - 10 However by using Gauss approach we can arrive at the answer for any range of values in the same time this is what we mean by a constant time algorithm

51

Task 2

Open the incomplete project SumIntSeries

Complete the project so as to implement Gauss algorithm for any continuous range of integers

The solution project is (exercise solut ion)

SumIntSer ies

The general formula required is

((119948 minus 119947) + 120783)(119947 + 119948)

120784

Or in a more code form

Sum = ((k - j) + 1) (j + k) 2

Where j and k are the starting and ending values in the range respectively (both inclusive)

Functions and Pass by Reference

In the previous section when working with functions all arguments passed to the functions were copies of variable values from main() The arguments were passed by their value

Pass by Value is the default argument passing mechanism for C++ (and the C language)

In pass by value when a function is passed an argument it receives a copy of the value from the calling function (main() in previous examples) This copy remains in scope until the called function has completed and returned at which time the copy is destroyed

Therefore a function that takes value-arguments cannot change a passed variables value because any changes only apply to copies and not to the actual callers variables

An alternate passing scheme is called Pass by Reference

Passing variables to functions by reference is very useful when we need to change or update variable(s) via a function (it is also a faster mechanism than pass by value as no copies have to be made)

Under the covers pass by reference involves passing a memory address and not a copy of the data to the function This is usually more efficient than passing by value because there is no requirement to copy memory However this argument passing mechanism enables a function to modify any argument even if its not supposed to To avoid this we usually declare all read-only parameters as const and pass them by reference

The format of a function prototype when using call by reference is

return-data-type funct ion-name (reference parameter) To indicate a reference parameter an ampersand (amp) is written in the function prototype and header after the parameter type name

The statement void squared(int amp) has no return data type (void) its name is squared and it accepts a reference parameter (amp) of type int (integer)

52

The function definition would be something like this

void squared(int amp inVal)

inVal = inVal inVal inVal

The function call to it would look like this

squared(aValue)

As mentioned above pass by reference is normally used for one of two reasons 1 Because we want to be able to change a passed variable inside a called function 2 Because we want the speed associated with a pass by reference

In 2 we will normally protect our argument by using const in the called function Eg say we want to pass the double argument x to a function f() and take the least possible time about doing it (and given that function f() shouldnt alter x) we would use the following code

void f(const double x)

Use x in some calculation Note that if

x appears on the left hand side of an assignment operator

that it will result in a compilation error

Pass arguments by reference

Task 1

Open the project (demonstrat ion) FunctionRef

Compile and run the program The output should be the same as shown in Figure 6

53

Figure 6

Examine the function prototype

void squared(int amp)

This shows the function squared accepts a reference

parameter of type int The reference parameter is ndash under the covers - the memory address of the argument passed to the function

The function uses this address to both get and set the value stored in variable a (value 21) in main() A reference to this address is passed to the function with the function call squared(a)

Examine the function void squared(int amp x)

Under the covers references to x refer to the address of the variable a in main (that holds the value 21) Ie x and a reference the same piece of memory (the word object was deliberately not used there) So we can think of x and a as two names for the same item

Returning values from functions

In previous programs we have most often produced output (using cout) from within the functions However to be of most use and general utility functions should return resultsinformation rather than output it

Functions may return results in one of two ways 1 via a return value or 2 via arguments ndash either passed as references or via pointer (address)

Non void Functions return a single value ndash if you will they evaluate to this value As such non-void functions may be used in expressions Eg

54

w = x sqrt(y) z

The function sqrt() is replaced with the value of whatever the square root of y happens to be For example if y has the value 4 then to evaluate x sqrt(y) z fully the sqrt() function has to be called ndash where it returns 2 This value is then substituted into the expression for further evaluation ie it becomes w = x 2 z

The second way for functions to return results is via its parameters ndash if they are references or passed via memory addresses Eg

void doubleIt(int amp n)

return n 2 Error The void means doesnt return a value

doubleIt() is a void function ndash so it cannot contain a return statement ndash so it cannot evaluate to anything ndash so it cannot be used in an expression

x = doubleIt(y) error

However the function is still able to return a result (modify something outside of itself is perhaps a better way of putting it)

void doubleIt(int amp n) using amp - a reference

n = n 2

55

doubleIt() cannot (still) be used in an expression but it can change things

int x = 10

doubleIt(x)

cout ltlt x Outputs 20

Why would you use references like this Well references are mainly used for speed (by passing an actual external entity a copy does not have to be made) but they are also useful when multiple values (entities) might best be updated via a single operation (function call)

int x y z

x = y = z = 10

doubleAll(x y z)

void doubleAll(int amp a int amp b int amp c)

a = a 2 b = b 2 c = c 2

Side effects

Going back to w = x sqrt(y) z

Lets replace sqrt() with our own function and cause some havoc

double havoc(double amp d)

++x

d = sqrt(d)

return d

x = 3

w = x havoc(y) z

56

Here the value of y has been changed (yet it is not clear that could happen from the functions call site ndash where it was called from) and so has x Also what value for x will be used in x havoc(y) z Will it be 3 or 4 These sorts of issues are called side-effects

This is one problem (or advantage) with reference arguments ndash and that is that they can cause a change in a variable outside of the function being called

One way to protect against this is to use const references eg

double havoc(const double amp d)

++x

d = sqrt(d) Compilation error here

return d

57

Returning a value from a function

Task 1

Open the TempConver t

project

Run the program The output should be the same as shown in Figure 7

Examine the function prototype

double convert(double temp int mode)

This function prototype has a return type of double When the function is called and calculations are completed a double value is returned to the caller

Examine the function definition The function definition matches the prototype indicating a double and an integer are being passed to the function and a double is being returned

Examine the function body The two statements below convert the temperature input The conversion type required is identified using the user input mode and a switch selection

The statement (temp - 32) 5 9 is used to calculate the temp in Centigrade

The statement 18 temp + 32 is used to calculate the temp in Fahrenheit

Figure 7

58

PLUSPLUS Arithmetic Bases

Task 2

Open compile and run the partially complete Bases project

Note that the project isnt complete

The program uses intrinsic functionality to output values in hexadecimal and octal ndash base 16 and base 8 Both these bases are useful in programming its all to do with binary and the size of a byte

Note that there isnt a bin equivalent to hex and oct and that we have instead written a function called bin1() to convert a value into its binary (base 2) representation

Understanding how bin1() works

bin1 uses the modulus operator () and the right shift operator (gtgt) to work eg 42 in binary is 101010

25 24 23 22 21 20

32 16 8 4 2 1

----------------------

1 0 1 0 1 0

----------------------

1 32 + 0 16 + 1 8 + 0 4 + 1 2 + 0 1 = 42

The function progresses like this

42 2 has remainder zero (false as evaluated in the if) If the if test is true we store a 1 else we store a 0 We then divide 42 by 2 by right shifting it one place ndash but just replace that with n = 42 2 if you prefer We then loop while we have a non-zero value in n to operate on hellip

42 2 = 210 42 2 = 0 if(42 2) = false string value = 0

21 2 = 105 21 2 = 1 if(21 2) = true string value = 1

10 2 = 50 10 2 = 0 if(10 2) = false string value = 0

5 2 = 25 5 2 = 1 if(5 2) = true string value = 1

2 2 = 10 2 2 = 0 if(2 2) = false string value = 0

1 2 = 05 1 2 = 1 if(1 2) = true string value = 1

59

Task 3

The project needs completing specifically it needs the function bin2() writing

We could write such a function as bin1 in a variety of ways and wed like you to write a new function called bin2() that produces the same output as bin1() here

Heres a step by step algorithm for implementing bin2()

Youll use either gtgt or and the bitwise And (amp) operator

Take the functions input (the number to convert) in as a parameter called n To keep it as simple as possible for now you could use plain int types rather than the unsigned long long type we used so the functions signature would look like string bin2(int n)

1 In the function create an integer called i and initialise it to 1

2 Realise that if you left shift the single bit in i (use ltlt or multiply it by 2) it will take on the values 2 4 8 16 32 hellip until it eventually goes to 0 ndash as you shift the bit off of the end

3 Recognise that you could compare your shifting bit with one in the same position in n using bitwise And Ie if((n amp i) == 1) then you know youll need a 1 in your output string for the bit position in n (2 4 8 ) given by is value at this point

4 Build up your result string as you proceed

Change your int n and int i to unsigned long long int and re-run

Try using other integer types ndash signed and unsigned

Lastly examine the solution project in (exercise

solut ion) Bases

60

Figure 8

61

Searching for Sequences

Task 1

Open and modify the incomplete project called called HeadsOrTai ls

When all completed the output should be similar to that shown in

Figure 9

This is the (exercise

solut ion) HeadsOrTai ls project

The programs purpose is to look for a sequence of simulated coin tosses ndash a series consisting of Hs and Ts

The program is complete (as in it runs) but it has some issues At first test it using quite short sequences

The timing information displayed by the application is included simply to demonstrate a timing mechanism that can be used to test the efficiency of the code

The first problem is that the user can currently enter characters other than H or T (h and t are ok as the input is converted to uppercase ndash note the string is passed by reference to toupper() which uses a pointer (which well cover later) to process the string

The second problem is that as it stands the algorithm isnt very optimal if we do not find our pattern we add the result of another coin toss to the current sequence and then re-check the sequence in its entirety

For example if were looking for HHTHH and the generated sequence is currently HTTHHHTTHTHHTTH we will fail to find HHTHH and then proceed to add another coin-toss result at the end ndash HTTHHHTTHTHHTTHH We will then scan this for HHTHH However as we know that we failed to find HHTHH before we added the extra coin-toss re-checking the previously checked sequence is pointless and very time consuming (think how this would (or wouldnt) scale) Your task here is to think of and implement another more optimal approach

62

Figure 9

Task 2

Open the HTTvsHTH project you will find that the project will compile correctly but displays an incorrect result

When completed the program can be used to check how many coin-tosses are required on average to see a particular sequence

Why should that be of interest Because sometimes its rather surprising For example test how many tosses are needed to see say HTH and then HTT

When the program is corrected the output should be as shown in Figure 10

63

Figure 10

PLUSPLUS Optimising Searching for Sequences

Task 1

As it stands the program (yours and ours) encodes a coin toss as a character ndasheither an H or a T Each character is encoded using at least 8-bits and so checking whether a generated sequence is the sequence were looking for means performing a string comparison which is costly in terms of clock-cycles Of course generating and storing the new coin toss also requires the use of these costly string operations

As we have just two tokens as an alternative to generating and storing characters and performing string operations we could encode a sequence as a series of bits For example the sequence HTH could be encoded as 101 in binary (5 in decimal) You can set the corresponding individual bits in an int using the bitwise Or operator | (a vertical bar) eg int n = 0 n = n | i which youd most likely do as a result of scanning the users entered search-sequence string a character at a time In this way you could encode the sequence HTHHTHHTHHTHHTHH in a single sixteen bit unsigned int

Additional operators needed to implement sequence checking and H or T bit manipulation are bitwise And (amp) and the left shift operator (ltlt)

You will find more information on some of these operators just a little below

64

Evolving Searching for Sequences

Task 1

Looking for sequences in stringssequences is an interesting and complex problem in computing and also in genetics where the string being searched could be a DNA sequence and pattern could represent a gene perhaps with a snip (a modificationmutation)

Modify your HeadsOrTai ls program (or our solution) so that instead of Hs and Ts it generates and searches for Gs As Ts and Cs instead

Randomly generate a GCTA sequence and a similar pattern to find within the sequence

How much more time and variation is required in this slightly more complex situation

Conduct a few experiments and using Excel graph your results (copy and paste some data highlight it and then select Excels line graph ndash Excel should then automatically plot your data)

Extrapolate The human genome is how long A gene might contain how many bases How difficult is the task of finding interesting sequences in the human genome How about checking for the odd mutation (insertion transposition deletion) ndash fuzzy matching

A solution for this problem can be found in the (demonstrat ion) GATTACA project

6 Classes and Objects In the previous section we have been working with simple programs that display messages to the user store data input as different data types manipulate the data in some way and output the results to screen

We will now start to look at C++ objects and classes

In the real world there are objects everywhere students staff cars birds houses and many more All objects have at tr ibutes these are similar to the variables created in previous tasks Some attributes of a student may be height weight race course of study etc All objects exhibit behaviours or operations cars accelerate and decelerate students matriculate enrol on courses and leave university

65

Now what is the relationship between a class and an object A good analogy would be from an architects blueprint for a house it would be possible to build many houses Similarly from a class in C++ it would be possible to build many objects

If we had a student class we could create many objects from the student class to represent the many students enrolling Each of these objects would be uniquely identified They would share common attributes and exhibit common behaviours If we wanted an object to perform some task we would call the appropriate member function allowing an operationaction to take place changing the behaviour of that object

Member functions are different from the functions you have created so far Member functions are always associated with objects and are usually called or invoked using a dot notation object member funct ionname() An example is student1getName() The object instance is student1 and the member function is getName()

Member functions contain the detail of how the technical aspects of some operation will be processed When member functions are invoked these technical issues are hidden from the end user When the member function is asked to do some operation a message is sent (a member-function call) telling the member function of that object to perform the operation detailed in the function

Functions are not completely new we have had a brief introduction and you have already created some of your own Note also that main() is a function that is called automatically when you run your program However it is not a member function as there is no object associated with it

Creating your first class

Creating a class

Task 1

Open the project called StudentUG

Compile and run the program It should look like Figure 11

66

Figure 11

Before you can create the object myName it is necessary to define the class from which the object will be created The class definition is shown below

class StudentUG Start of class definition

public

void displayName() Start of member function

cout ltlt My name is Michael Cain ltlt endl

Note a semicolon is required at the end of the class definition

Within main() the statement StudentUG myName creates the object myName of class StudentUG In effect StudentUG is a new type

The statement myNamedisplayName() is used to call the member function displayName() of object myName

As we have seen previously the function main() is called automatically when our programs are executed However member functions (displayname() is one we could have many) must be called in this way objectInstanceNamefunctionName() when dealing with an

67

object directly and like this objectInstanceName-gtfunctionName() if working through a pointer to an object (more on pointers later)

The member function displayName() is preceded by the word void All functions can return values this one does not The word void preceding the function name indicates nothing is being returned If this function returned an integer the definition would be int displayName()

When you use functions it is common to pass data (called parameters) to the function The function then manipulates the data before displaying an output andor returning a value

To pass a parameter to the function in the studentUG class the calling statement in main() would be

myNamedisplayName(name) where name is a string (a series of characters) that contains a value read in from the keyboard

In order for the function displayName() to recognise the parameter being passed the function declaration is changed to include the parameter (name) and type (string) as shown in below

void displayName(string name)

cout ltlt My name is ltlt name ltlt endl

Figure 12

Member functions and Passing parameters

Passing parameters

Task 1

Modify StudentUG to read in a student name The name should be passed to a member function The parameter should be output from within the function to welcome the user to C++ programming

68

Task 2

Modify the program in the above task to read in two more names Each name will be for a different student and you will need to create additional objects (instances) of the class

Data Members

In most of the programs written so far the variables have been declared inside the main() function Variables declared inside a function are local to that function and cannot be accessed from outside that function

You have created a student class and it would be reasonable to assume that a student would be following a particular course So courseName might be one of several attributes of a StudentUG object Attributes are represented as variables in a class defini t ion These variables are called data members and must be declared inside a class definition When you create an object of a StudentUG class each object has a unique memory location for its data members

Figure 13 shows data member name declared in the class definition The access specifier private means that only member functions of the class in which the attribute was declared can use this data member

private string name

Figure 13

When data members are declared as private the data is hidden This is called encapsulat ion and means the attributes of the object are hidden and can only be accessed via member functions

As there is no direct way to change a data member you will also need to create a member

funct ion to set the data member to a value and create a second member funct ion to output the value held there

Data members can also be declared public A data member that is declared public can be accessed from any (non-member) function

A protected data member can only be accessed by member functions of its own class and by member functions of classes derived from this class We will learn more about derived classes and inheritance later

69

Using data members

Task 1

Open the project called StudentCoursesln

Compile and run the program it should look like Figure 14

Figure 14

Task 2

Examine the member function getCourse() shown in Figure 15

string getCourse()

return course

Figure 15

Task 3

Modify the StudentCourse source file to enable the user to add a student name enrolment date and number of years of course Once entered this data should be output to screen You will need to create additional data members and member funct ions to achieve this

70

More Objects

Task 1

So far you have created one StudentCourse object It is about time we had a second student on the course Create a second object of the class StudentCourse You will need to add the second statement shown in Figure 16 to add the new object student2 Call the member functions passing parameters as necessary

Figure 16

Constructors

When you create objects from the StudentCourse class it is necessary to give initial values to all the data members If we were entering data for five people and they were all following the same course of study it would make sense to initialise the course data member (it is possible to initialise some or all of the data members) when each object is created

A constructor is a special kind of function that must have the same name as the class Constructors are normally defined to be publ ic and never have a return type They can be used to automatically initialise data members

In previous programs you have written a defaul t constructor has been provided by the compiler However it is not possible to pass parameters to a default constructor function so the data members in the programs created so far have not been automatically

71

initialised To initialise these data members you created member functions that assigned values to data members

Although a default constructor is provided at compilation time it is a good idea to create your own so that the data members can be initialised

It is worth noting here that functions (constructors are functions) can be over loaded This means it is possible to have more than one function with the same name Note that overloaded functions (functions with the same name) must have different types of or number of arguments

Constructors (functions) can also be overloaded with more than one function with the same name but different types or number of parameters Fortunately for us the compiler automatically calls the correct function whose parameters match the arguments used in the function call

Using constructors

Task 1

Open the project called Constructorss ln

Compile and run the program it should look like Figure 17

Figure 17

72

Task 2

In the constructor shown in Figure 18 what is the purpose behind course = Note that as the string parameter name has the same name as the class variable that we use the hidden this pointer to access the class variable in the assignment If we didnt do this and simply used name = name instead then all we would be doing is assigning the value in the parameter back to the parameter

StudentCourse(string name)

this -gt name = name

course =

Figure 18

Task 3

Create a third constructor that will take an argument enrolment_date

Add a third object call it student3

Write code that will test this additional constructor

Solution in (exercise

solut ion) Constructors

If time allows add other useful properties (data members) access methods (functions) and constructors

Separating use from declaration and definition

C++ is all about objects and any decent project will usually make use of a number of application or domain specific classes

To keeps things maintainable and to promote code reuse C++ projects usually contain a number of cpp and h files where each h files will usually contain a declaration of a class (sometimes called an interface) Note though that the definition of the class (sometimes called the implementation) ndash the code that implements it ndash will be absent from the h file and will instead reside in an accompanying cpp file

Aside from allowing different teams to more easily work on separate parts of the program one of the main reasons for separating definition from declaration is to enforce abstraction which is a programming (and design) technique that relies on the separation of declaration and implementation For example lets say that your team needs a class that acts a bit like a stack (a last-in first-out or LIFO structure) and as this is required

73

urgently you decide to implement it using a simple array You would then only want to give your team what is absolutely necessary to use this class a single h file for your team members to include in their cpp files If they look in the h file they will only see information on how to use the class but how it does what it does is kept elsewhere in the cpp and that youve withheld Consumers shouldnt need to know how a thing works in order to use it

An obvious advantage to this is that there is no danger in you changing how it works Perhaps you later decide to use a vector instead of the array You go ahead and alter the implementation and your team members are none the wiser ndash after all the interface hasnt altered just the implementation

So how does the project get built Of course the implementation of this class will be required at compile time and you can either do that by including the cpp file directly (which will give away the implementation details of course) or by including it as object code ie compiled C++ code (binary machine code) This is how valuable commercial source code is kept in-house while the binary implementation complete with a h file is provided to customers (you will see an example of this just below in Using external

l ibrar ies and thi rd par ty header f i les )

Any discussion on separating use from declaration and definition should include something on namespaces You introduce a namespace by simply using the keyword and braces Anything entered inside these braces is inside the namespace eg

namespace securityModule class Encryptor using namespace std using namespace securityModule int main() Encryptor e Without the using we would have had to use securityModuleEncryptor e securityModuleEncryptor e2

See the (demonstrat ion) Namespaces project for more on this

74

Separating declaration and definition

Using a header and source file to separate class declaration from definition

Task 1

Open and modify the partially complete skeleton project called Precis ionTimers

Like HeadsOrTai ls this project makes use of the Windows operating system to very precisely measure elapsed time However unlike HeadsOrTai ls we have separated the stopWatch class interface from its implementation

As weve previously mentioned Gauss and algorithm efficiency we could test our theory that summing in a loop is O(n) ie that the time taken scales with n

Examine the project files hrTimercpp and hrTimerh noting that the h file contains just enough information for someone to use the declared class stopWatch whilst htTimercpp contains the implementation of the class

Now look in PrecisionTimerscpp You will see that an instance of the stopWatch class is declared Also note that we include hrTimerh but make no reference to hrTimercpp

As it stands the code calls two functions to calculate the sum of a range of integers sumGauss() and sumLoop() The program outputs the clock-ticks used and time taken in seconds

Note that sumLoop() is incomplete

Complete the sumLoop() function and then choosing suitable values for the ranges upper-bound carry out a few experiments to test if the loop is really O(n)

What is this used to do in hrTimerh15

ifndef HRTIMER

define HRTIMER

endif

15 You should also see pragma once as this is rapidly becoming the alternate way to do this ndash whatever this is of course

75

PLUSPLUS Providing object code only

Task 2

We have provided a separate demonstration project that takes the discussion on this one step further (demonstrat ion)

Separat ingThings

In its current form the project wont compile To compile the project in the Solution Explorer add the existing carcpp file to the source files list that just contains SeparatingThingscpp and recompile carcpp is in the same folder as SeparatingThingscpp

Once youve done that right-click on carcpp in the Solution Explorer and select Remove Very importantly when youre prompted for confirmation choose Remove do not choose Delete Now recompile once more youll see that the project fails to compile as the definition of car has been removed

76

But hold on we created carobj - the compiled object-code version of carcpp during our previous compilation so we could tell the linker about that and all should be well (this more or less duplicates the scene whereby you do not provide source code but provide only object code)

The carobj file will be located somewhere like

CUsersDesktopCourse(demonstration) Separating Things(demonstration) Separating Thingsbincarobj

To add this to your project go to Project | Properties | Configuration Properties | Linker | Input

77

In the right-hand window select Additional Dependencies drop down the list and select ltEdit gt

In the dialog that appears add the full path to carobj (see earlier in Step 2) and press Ok

Lastly recompile the code once more It should compile and run At this point you could if you wanted to delete carcpp altogether

One last thing

If you look in the comments in SeparatingThingscpp you will find a discussion that goes into the advanced topic of hiding things even further This includes a brief discussion of the the so called pimpl pattern (pronounced Pimple this stands for Pointer to Implementation16)

16 httpenwikipediaorgwikiOpaque_pointer

78

PLUSPLUS Using external libraries and third party

header files

Task 3

Open and modify the project called Lot to

Examine the projects comments to understand the programs function Run the program ndash does it work

It is supposed to compute the odds of winning the UKs lottery httpwwwnational-lotterycouk (try as we might we couldnt find the odds on their own website)

The program uses the recursive factorial function used earlier in the course (with bigint being typedef ed as unsigned long long int)

Factorial function using recursion

bigint recur_factorial(bigint n)

return n lt 1 1 n recur_factorial(n - 1)

There is a problem here however in that to compute the odds we must compute some significant factorials ie

49 = 608281864034267560872252163321295376887552831379210240000000000

and

6 (49 - 6) = 43498989405629161658895695089330078205230448640000000000

Sadly our bigint (unsigned long long) can hold a maximum value of 2^64 ndash 1 = 18446744073709551615 ie not hardly big enough

Fortunately in C++ we can define new types like an arbitrarily sized integer (outside of the scope of this course but see the (demonstrat ion) newINT project for a small taste) However this is object orientation ndash surely we can just use an existing already defined arbitrarily sized integer class

79

Task 4

The good news is that in this class you can You can use LEDA (The L ibrary of

Eff ic ient Data types and Algor i thms ) a professional class library of advanced numerical functionality

You will need to download the program called

LEDA-63 i386 msc 10 ( NET 2010) 32 bi t

or

LEDA-63 i386 msc 10 ( NET 2010) 64 bi t

Go to wwwalgorithmic-solutionsinfofreeindexphp Accept the licence terms and download the appropriate version (usually the 64 bit version)

The LEDA installation program will install additional numerical libraries and header files from the Algorithmic Solutions company

Once the setup is complete modify the Lotto program

In the Solut ion Explorer right-click on your project (Lot to ) and left-click on Proper t ies A dialog-box appears

Under the CC++ section

1 Click on General Choose Addi t ional include di rec tor ies and enter the directory CAlgor i thmic Solut ions LEDA-63- free-win-msc10-

s td incl

2 Click on Preprocessor and add LEDA_DLL to the end of Preprocessor

Defini t ions Note the semicolon is required

3 Click on Code Generat ion and check that Runtime Library is set to Mult i - threaded Debug DLL ( MDd)

Under the Linker section

4 Click on General

5 Choose Addi t ional l ibrary di rector ies and enter the directory CAlgor i thmic Solut ionsLEDA-63- free-win-msc10-s td

6 Click on Input and add l ibGeoW_mdd_dl l l ib leda_mddl ib to the end of Addi t ional Dependencies Again the semicolon is significant

You may now close Properties dialog-box

7 Modify your code Add the following under include ltiostreamgt

include ltLEDAnumbersintegerhgt using ledainteger using namespace std

80

Then modify the recur_factorial() function so that it accepts and returns a type called simply integer rather than bigint

Save the project and exit Visual Studio

In order to build and execute Lottoexe Windows needs to have l eda_mdddl l in its search path for DLLs Therefore we need to add the path to the folder containing leda_mdddll to the PATH environment variable

8 In Windows Explorer navigate to My Computer then right-click on it and select Propert ies

9 Click on the Advanced tab and then on the Environment Var iables button

10 In the bottom section (System var iables ) of the dialog box highlight Path and then click the Edi t button

At the end of the existing path add -

11 CAlgor i thmic Solut ions LEDA-63- free-win-msc10-s td

Once more note the leading semicolon is significant

81

12 Restart Visual Studio and re-open Lot to Build and run the application as normal

It might seem that this was a lot of work for such an apparently trivial result but the fact is that you now have access to (and have seen how to use) an advanced numerical library of functionality And anyway when all is said and done you must admit that at least you got a return here ndash which is more than you should reasonably expect from the lottery

Figure 19

Task 5

Explore the LEDA samples and documentation ndash if you installed it there should be a shortcut in your start menu to LEDA-63-free-win-msc10-s td

Task 6

Modify the Lotto program to see how the odds change when there are more balls andor when more balls need to be matched (you might also display more of the intermediate results of calculations ndash like 49)

Destructors

Both constructors and destructors are special class methods We have seen how a constructor is called whenever an object is defined

A destructor has the class name prefixed by a tilde ~ Like constructors destructors cannot return values and therefore they have no return type specified but unlike constructors destructors have no arguments and thus cannot be overloaded

An objects destructor is called whenever an object goes out of scope The purpose of the destructor is to clean up eg to free any dynamically allocated memory that the object was using and release other system resources such as files and database connections etc

In the examples used so far no destructor has been provided for any class created In these programs it has been unnecessary If the programmer does not explicitly provide a

82

destructor the compiler will create an empty destructor in the same way that an empty constructor is created if one is not explicitly created

When classes are created any objects instantiated from them that contain dynamically allocated memory will need destructor methods added to implicitly free any dynamically allocated memory when the object goes out of scope

In the class example shown below the destructor function is ~StudentCourse()

~StudentCourse()

cout ltlt Im being destroyed

7 Arrays vectors lists and hash-tables Arrays vectors and lists are all types of data structures Data structures are areas of memory where collections of the same data type are held The main difference between arrays vectors and lists is that arrays stay the same size throughout the program execution whereas vectors and lists can grow automatically

Arrays consist of a series of elements (variables) all of the same type placed consecutively in memory Each of the elements can be individually referenced by adding an index to the arrays name We saw this type of notation earlier when using arrays

Eg

int examMarks[10]

This declares an array of ten scores score 1 is accessed via an index of zero ndash examMarks[0] and score 10 is access through an index of nine ndash examMarks[9] Very important note that indexes start at zero

The advantage of using arrays compared to using discrete variables (the way we have stored values so far) is it is possible to store any number of values of the same type in an array using the same identifier

With arrays it is possible to store 100 student exam marks or 100 student names with using one unique identifier

Vectors and lists are container classes which were originally part of the Standard

Template Library (STL) The STL evolved into C++ Standard Library ndash which includes iostream etc This is the general-purpose C++ library of functions algorithms and data structures that we can use in our programs While some aspects of the library are very complex it can often be applied in a very straightforward way that allows reuse of sophisticated data structures and algorithms

There are many container classes in the library ndash note that C++ now also provides such a class for the more primitive array

ltarraygt

New in C++11 and TR1 (Technical Report One)

83

A container for a fixed sized array

ltbitsetgt

A bit array

ltdequegt

A double-ended queue

ltforward_listgt

New in C++11 and TR1 A singly linked list

ltlistgt

A doubly linked list

ltmapgt

Sorted associative array and multi-map

ltqueuegt

A single-ended queue

ltsetgt

Sorted associative containers or sets

ltstackgt

A stack

ltunordered_mapgt

New in C++11 and TR1 Hash tables

ltunordered_setgt

An unordered_set unordered_multiset

ltvectorgt

A dynamic array

As with an array vector and l is t can hold objects of various types However unlike arrays vectors and lists can resize shrink and grow as elements are added or removed

The standard library provides access via iterators or subscripting Iterators are classes that are abstractions of pointers (more on pointers later) They provide access to container classes using pointer-like syntax and have other useful methods as well

The use of vectors lists and iterators is preferred to arrays and pointers By using containers common problems involving accessing past the bounds of an array are avoided Additionally the C++ standard library includes generic algorithms (an algorithm is a set of instructions on how to perform a task) that can be applied to vectors lists and other container classes

Declaring and using arrays

Arrays are declared indicating the type and number of elements in the following way

type ar rayName[arraySize]

84

Examples are

int inNumbers[20] an array called i nNumbers of 20 in tegers

char inName [20] an array called i nName of 20 characters

float ExamMarks[5] = 0 an array called ExamMarks of 5 floats with all elements explicitly initialised to zero

const int size = 5 declaring a constant variable size

float ExamMarks[size] When the constant variable size is applied to the array declaration the number of elements is set to 5 This cannot be changed during runtime of the program However it is handy when the number of array elements needs to be changed Changing the constant value size changes the number of elements wherever the ExamMarks array is used in the program

int numArray [2][3] is a multidimensional array with 2 rows and 3 columns

Note Arrays have been used in C++ for many years and there will be code you work with that was written before vectors became available Vectors are are usually preferred to using arrays and pointers Common problems involving accessing past the bounds of an array are avoided when using vectors

Creating an array to hold exam results

Task 1

Open the project Array s ln

Compile and run the program

Run the program adding five exam results The output should be similar to Figure 20

Figure 20

85

Examine the following statements

double ExamMarks[5] = 0 This statement declares the array setting its size to 5 elements and explicitly initialising all elements to zero

cout ltlt Enter Exam Mark ltlt i + 1 ltlt This statement prompts the user to enter an Exam mark into the array at element i + 1

Using the notation i + 1 indicates to the user to enter Exam Mark 1 not exam mark 0 which would be less intuitive

Array elements are numbered from 0 to n - 1 So an array that holds 20 integers will be addressed from element 0 to 19

ExamMarks[0] -ExamMarks[19]

The first number will be entered into element [0 ] The last into element [19]

cin gtgt ExamMarks[i]

This statement reads in the user input and stores the values in the array elements of ExamMarks[i] i is incremented within the for loop and starts at 0

Task 2

As it stands the program could be generally improved ndash see the notes in the code and consider how you might make such improvements

Next modify the program to output the highest and lowest marks entered

Task 3

Modify the program so that the number of marks may be easily changed (at compile time)

86

Task 4

Modify the program so as to break out the part that calculates the average and put it into a separate function

Write another function that given an array of this sort returns the mode mean and median values ndash you will need to pass in references as the function will need to return three values

Lastly put your two new functions into a separate cpp (you will also have to create a h file for Arraycpp to use ndash this will contain the new functions prototypes)

87

Searching Arrays with Linear Search

Linear search allows the user to search the array and establish whether the array contains a value that matches a search criteria defined by the user

The search compares each element of the array with the user input The array is not sorted and this method of searching works well for small arrays For large arrays linear searching is inefficient and it is necessary to use other forms of array searching after the array has been sorted

Linear Search

Task 1

Open the project LinearSearch

Compile and run the program - choose a number between 1 and 100 The output should be similar to Figure 21

Figure 21

88

Examine the following statements

myArray[i] = (1 + rand() 100) This statement uses the rand function part of the ltstdlibhgt header file (included via iostream being included) 1 + rand() 100 produces integers in the range 0 to 99

The function l inearSearch takes three arguments The array name the size of the array the third argument is the search value

if(theArray[j] == value)

return j

This selection statement compares each element to the search value If the search value is in the array the element number is returned to main() otherwise -1 is returned

The if selection statement if(containingElement = -1) in main() is used select the output indicating a successful or unsuccessful search

Task 2

Currently the program searches for the first occurrence the search value only

Modify the program so that it outputs al l matching element locations

This function can be used for turning an int value into a string See also the comment below about C++11s to_string() functions

string convertInt(int number)

stringstream ss

ss ltlt number

return ssstr()

Youll need to include ltsstreamgt to use the stringstream class

89

Task 3

Modify the program so that repeated searches may be carried out

See Figure 22

If using C++11 or later you can also use the to_string() helper functions of the string class eg to_string(10) yields 10

Figure 22

PLUSPLUS Debugging Linear Search

Task 1

For debugging purposes modify the program so as to output the contents of the array

Open and run (exercise solution) LinearSearch to see what this might look like You might want to use the modulus operator () to work out when to neatly break a line

You may or may not like to have the program generate varying sets of random numbers To facilitate this youll need to seed the random number generator by inserting a line of code like this

srand((unsigned)time(NULL))

Note the use of the cast

To use srand() include timeh at the top of your program

90

Sorting Arrays with Insertion Sort

When working with large quantities of data in an array you will need to sort the data at some point This makes searching for information quicker and there are many algorithms available that can be used In the following exercise you will learn how to sort numbers stored in an array in ascending order

SortingSearching an array

Task 1

Open the project Sorts

Run the program and examine the code

The program currently uses a class (sorts) which is defined in sortsh to implement one popular sorting algorithm called Inser t ion Sor t

For details on this algorithm see

httpenwikipediaorgwikiInsertion_sort

91

Task 2

Add a new sort to the sorts class

The text file quicksor t txt (in the Sorts folder) contains the C++ code required to implement another popular sorting algorithm called Quicksor t17

For details on this algorithm see

httpenwikipediaorgwikiQuicksort

Add the quicksort code found in quicksor t tx t to the sorts class - considering what parts of it need to be publicprivate

quicksort tx t is in the same folder as the Sortss ln project file

Step 2

Test the quicksort implementation on a range of values

Alter the quicksort implementation so as to have it sort in descending order

Following on from Step 3 parameterise the quickSort() function so as to add an option to have the array sorted in either ascending or descending order

17 Invented by C A R Hoare ndash Sir Tony Hoare with Christopher Strachey the most distinguished computer scientists Oxfords ever produced

92

Figure 23

93

PLUSPLUS Binary Search (Binary Chop)

Task 1

Now that the array is sorted we can implement a very efficient searching algorithm usually called either binary search or binary chop search

See Figure 24

Modify your project to allow the sorted array to be searched for a value using the binary chop algorithm See opposite

The algorithm for binary chop is quite straight forward

1 Look at the value of the middle element of the array If the value = target then youre done

2 If the value is lt than target discard the lower half of the array treating the upper half as though it were the complete array

If the value found is gt than target you obviously want to look in the lower half

3 Repeat step 1 until the item is found or else the index value becomes invalid

Pseudo code for this algorithm is here

first integer = 0

mid integer = 0

last integer = NumberOfItems

while first ltgt last

begin

mid = first + last 2

if List[mid] = target

exit while Found item

If List[mid]gt target

last = mid In the first half

else

first = mid + 1 In the last half

end

found boolean = List[mid] = target

94

Figure 24

Multidimensional Arrays

Multidimensional arrays with two dimensions (arrays can have more than two dimensions) may be thought of as consisting of data arranged in rows and columns see Table 3

Each element in the array is identified by using two subscripts as shown in Table 3 The first subscript identifies the element row and the second identifies the element column a[0] [1] identifies a value in Row 0 Column 1

The array in Table 3 contains two rows and three columns and can be called a 2 by 3 array

Column 0 Column 1 Column 2

Row 0 a[0] [0] a[0] [1] a[0] [2]

Row 1 a[1] [0] a[1] [1] a[1] [2]

Table 3 ndash Array Layout

A multidimensional (2 by 3) array of doubles is shown in Table 4

Column 0 Column 1 Column 2

Row 0 2367 6792 8557

Row 1 1276 9132 2789

Table 4 ndash Array Values

95

Creating a multidimensional array

Task 1

Open the Mult iDimArray

project

Compile and run the program adding 2 exam results for each of the two students The output should be similar to Figure 25

Figure 25

96

Task 2

Examine the code used to write values to and read from a multidimensional array

Examine the following code segments

double ExamMarks[2][2] = 0 This statement creates a two-dimensional array having two rows and two columns and initialises the elements to 0

Every element in the array is identified by an element name in the form a[x] [y] where a is the name of the array and x and y are the subscripts that uniquely identify each element in a Notice that the names of the elements in row 0 all have a first subscript of 0 see Table 5 The names of the elements in column 1 all have a second subscript of 1

Note multidimensional arrays can have two or more dimensions (subscripts) Three-dimensional arrays are uncommon

Column 0 Column 1

Row 0

a[0] [0] a[0] [1]

Row 1

a[1] [0] a[1] [1]

Table 5 ndash Array Indexing

97

Examine the following code segment used to read values in to the array

for(int row = 0 row lt 2 ++row)

for(int col = 0 col lt 2 ++col)

cout ltlt Enter Exam Mark No

ltlt col + 1

ltlt for student No

ltlt row + 1 ltlt

cin gtgt ExamMarks[row][col]

cout ltlt endl

The two for loops work taking one row at a time (the outer for loop) and looping through the columns in that row (the inner for loop) When the marks have been entered for all the columns in row 0 row 1 is selected and values entered for each column cell in row 1

Table 6 shows how four results would be allocated in a 2 x 2 multidimensional array

Exam mark 1 Exam mark 2

Student 1 67 71

Student 2 61 58

Table 6 ndash Populated Array

98

Examine the following code segment used to calculate the total of each students marks

if(row == 0)

r1total += ExamMarks[row][col]

else

r2total += ExamMarks[row][col]

r1total is a variable to hold the sum of values in column 0 and 1 for row 0 (Stud1) r2total sums the values in the columns for row 1 (Stud 2)

Selection for each row is made with if(row == 0) this is Stud1 If row is not 0 then row must be 1 and the mark can be added to r2total If three exam marks were input per student the code for selecting the marks would need to change

Task 3

Modify the program to read in four exam marks for f ive students

Establish the highest and average mark for each student Output the results

One way to do this is to keep a separate array to record the students statistics An alternative would be to extend the existing arrays row so that it may hold the necessary student data

99

Declaring and using vectors

Vectors are declared indicating the type and number of elements in the following way

vectorlttypegtvectorName

vectorlttypegtvectorName(initialSize)

vectorlttypegtvectorName(initialSize elementValues)

Examples

A vector called i nNumbers with no initial size to hold doubles

vectorltdoublegt inNumbers

A vector called Name with an initial size 20 to hold characters

vectorltchargt Name(20)

A vector called ExamMarks holding integers with initial size of 4 elements each with the value 6

vectorltintgt ExamMarks(46)

Note In previous exercises you have created your own member functions In the following exercises you will use some of the vector class member functions Some of these are begin() end() erase() and size() See section 12115 for more detail

The standard library also includes a large collection of algor i thms that manipulate the data stored in containers (vectors are one of several types of container)

You can sort the order of elements in a vector (vec) for example by using the sort algorithm

sort(vecbegin() vecend()) C++11 sort(begin(vec) end(vec))

You can find a value (69) in a vector by using the find algorithm

ptr = find(vecbegin() vecend() 69) See C++ note above

100

ptr is an iterator to store the memory location of the element found

You can reverse the order of elements in a vector for example by using the reverse algorithm

reverse(vecbegin() vecend()) See C++ note above

There are two important points to notice about the call to reverse First it is a global

function (as are find and sort) not a member function Second it takes two arguments rather than one and operates on a range of elements rather than on the container (vector container in this case)

With the above examples the range is the entire container from begin() to end() (vecbegin() to vecend()) reverse like the other standard algorithms is decoupled from the libraries container classes The reverse algorithm can be used to reverse elements in vectors in lists (another container) and even elements in C arrays

int myArray[] = 1 6 20 4

reverse(myArray myArray + 4)

for(int i = 0 i lt 4 ++i) Lets see the reversed array

cout ltlt Array[ ltlt i ltlt ] = ltlt myArray[i]

In the above example the first argument to reverse is a pointer (pointers are covered in Section 8 but for now we can say the first argument points to the address in memory that is the start of the vector ) to the beginning of the range and the second argument points one element past the end of the range This range is denoted (myArray myArray + 4)

Arguments to reverse are i terators which are a generalization of pointers which is why it is possible to reverse the elements of a C array using the array address and pointer notation

Creating a vector to hold exam results

Task 1

Open the Vector project

Compile and run the program adding five exam results The output should be similar to Figure 26

101

Figure 26

Examine the following statements

include ltvectorgt This statement includes the header file vector enabling the program to use the class template vector (templates allow the use of generic functions that admit any data type as parameters and return a value more on this later)

vectorltdoublegt ExamMarks(5) This statement declares the vector to hold doubles and sets the initial size to 5 elements

Note Although vectors can grow to any size it is good practice and more efficient to specify the size when this is known When no size is given and the contiguous memory spaces have been exhausted the elements must be copied to a larger memory space to increase the size of the vector

cin gtgt ExamMarks[i] This statement reads in the user input and stores the values in the vector slot i of ExamMarks[i] i is incremented within the for loop Note that we the same indexingsubscripting syntax as we used previously with arrays ie[ ]

102

Task 2

Modify the code so as to accommodate the adding of an extra exam mark

Note this should not be done (simply) as part of the loop but as a separate action later and you should use the vectors push_back() method to facilitate this

push_back() is a member function of the vector class that adds an additional vector element at the end

After adding the extra mark you will need to generate a new set of statistics ie the average will have changed now To do this separate out the statistical code and place it in a separate function so that you may re-use later (after the new data has been entered)

size() is a member function (method) of the vector class It can be used to establish the size of a vector

The statement for(int i = 0 i lt ExamMarkssize() i++) uses the vector member function size() available to the vector ExamMarks to obtain the size (number of elements) in the vector The size of the vector is used to identify a terminating value that ends iteration of the for loop

Task 3

Open VectorSor t

You will see three TODO sections in the code which need completing

1 Populate a vector with 100 randomly generated numbers

2 Sort the vector

3 Reverse the vector

For sortingreversing you will can use the algorithms sort() and reverse()

Heres a useful link hellip

httpwwwcpluspluscomreferencealgorithm

103

Using insert() and iterators

Task 1

Open and modify the skeleton project called Inser t

Important areas of the program are explained in the steps opposite

Examine the code

vectorltintgtiterator it

This statement creates an iterator that is used to access members of the vector

Iterators are used to access members of the container classes (the container type vector in this case) and can be used in a similar manner to pointers

In the example iterator it is used with the insert() function to place the value (200) at the beginning of the vector nums

it = numsbegin()

This statement uses the vector member function begin() to initialise the iterator it with the address of the start of the vector

it = numsinsert(it 200)

This statement uses the member function insert() and iterator it to insert 200 at the beginning of the vector (it)

Note that an iterator is returned by the function insert() that points to the newly inserted element

104

numsinsert(it + 1 numsTwobegin()

numsTwoend())

This version of the insert() function takes 3 arguments and is used for copying in part or full another collection This may be a vector a plain C++ array or some other collection that is accessed using pointersiterators

This statement inserts a second vector (numsTwo) into nums The three parameters are (copy to nums+1 from star t of numsTwo to end of numsTwo)

it = numsinsert(it + 2 696 )

This version of the insert() function takes 2 arguments The iterator it + 2 points to element number three it points to the beginning of the vector and the 2 moves two elements in The value 696 is inserted at that element

void display(vectorltintgt amp vec)

cout ltlt Vector contains

for(

unsigned int i = 0

i lt vecsize()

++i

)

cout ltlt vecat(i) ltlt

Function display() is passed a reference to a vector and outputs the vector contents used throughout program

105

Task 2

Add the code shown in Figure 27 to the program and using the insert() member function add the array to the nums vector at position two (in the vector) Output the contents of the nums vector to screen

int myArray[] = 5 6 3 4

Figure 27

stdarray

C++11 Introduced a new template array type called stdarray

stdvector is a template class that encapsulates a dynamic array that is stored on the heap and that grows and shrinks automatically if elements are added or removed It provides all the hooks (begin() end() i terators etc) that make it work fine with the rest of the STL It also has several useful methods that let you perform operations that on a normal array would be cumbersome like inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes) Since it stores the elements in memory allocated on the heap it has some overhead in respect to static arrays

stdarray is a template class that encapsulates a static array that is stored inside the object itself which means that if you instantiate the class on the stack the static array will be on the stack Its size has to be known at compile time (it is passed as a template parameter) and it cannot grow or shrink

It is more limited than stdvector but it is often more efficient especially for small sizes because in practice it is mostly a lightweight wrapper around a C-style array However it is more secure since the implicit conversion to a pointer is disabled and it provides much of the STL-related functionality of stdvector and of the other containers so you can use it easily with STL algor i thms

Here is a small example demonstrating the template and some other C++11 extras such as auto and a ranged-based for loop

106

include ltstringgt include ltiteratorgt include ltiostreamgt include ltarraygt using namespace std template ltsize_t N class Tgt arrayltT Ngt make_array(const T amp v) arrayltT Ngt ret retfill(v) return ret int main() The char here can be inferred and so is optional auto a = make_arraylt10 chargt(1) for (const auto amp s a) stdcout ltlt s ltlt system(pause) return 0

1 1 1 1 1 1 1 1 1 1 Press any key to continue

Declaring and using lists

Lists are a kind of sequence container similar to vectors The elements of a list are ordered following a linear sequence with storage handled automatically by the class

List containers are implemented as doubly-linked lists and it is worth noting that elements may be in different and unrelated storage locations

Ordering of a list is kept by a relationship to each element of a link to the element preceding it and a link to the element following it

Because linking information is associated with each element (possibly to different and unrelated storage locations) extra memory may be used to keep the linking This may be important when using a large list

l is ts tend to perform better than vectors at inserting extracting and moving elements in any position within the container but lack direct access to the elements by their position and because of this have a slower access time than vectors Access to an element has to be via a known position (the beginning or the end) and there is a time cost in linking between the known position and the element to be accessed

107

lists are declared indicating the type and number of elements in the following way

listlttypegt listName

listlttypegt listName(initialSize)

listlttypegt listName(initialSize elementValues)

Examples

A list called inNumbers with no initial size to hold doubles

listltdoublegt inNumbers

A list called Name with an initial size 20 to hold characters

listltchargt Name(20)

A list called ExamMarks holding integers with initial size of 4 elements each with the value 6

listltintgt ExamMarks(46)

72 Hash Tables and Cached Calculations

This section has ultimately really been about introducing you to templates and algorithms and well mix both now in a final example

From the binary chop exercise earlier we have seen that sorted arrays provide a very efficient means of storing data for later look-up However we have to bear in mind the algorithmic cost of sorting the array in the first place ie if we have a million unsorted items in our list and we want to find a single item (only) is it better to sort the entire list first and then find the item or is it better to simply walk through the array from the beginning ndash after all we could safely assume that weve a 5050 chance of finding it in the first half of the array Of course as were sorting we could keep an eye open for our item ie we could combine a (partial) sort with look-up operation ndash over time if we repeat this procedure looking for other items we will ultimately sort our array as a side -effect of the look-up operations

But lets move on a little and just consider the fastest look-up method we know so far that carried out on a sorted array using binary chop and think about our programs overall performance when we need to insert additional items into the array When considering problems like this we always think of the worst case hellip despite their often being fans of

108

Monty Python Computer Scientists rarely look on the bright side of life The worst case here is that we need to insert an item into array position zero

Eg say we have this sorted array (look-up operations average O log2 N = fast)

15 24 25 31 78 250 255 262 277

We now have to insert the value 5 into this array Using normal array indexing methods how many operations will this take

5 15 24 25 31 78 250 255 262 277

Each item needs to be shuffled up one position to the right and if weve millions of items that is rather costly especially if the next thing were likely to do is to insert another item

So weve seen that accessing sorted data is very useful and weve also seen that sorting and especially inserting items can be costly The big question is then is there a way we can make both just as efficient - finding andor inserting an item in Olog2N or O(1) (constant time)

Hash Tables

A hash-table is a data structure designed to allow for both rapid insertion and look-up

Although any specific hash-table is implementation specific (there are very many different types of hash-table) well quickly go through the basics

The storage medium well use for our hash-table is an array of strings and we will say that this array has just 10 elements It looks like this

string myhash[10]

Well use this hash-table to store words and well determine the array index for any specific word using a hash- funct ion ndash something that will take a word as its input and return an array index as its output

109

unsigned hashfunc(string s)

unsigned result = 0

for(unsigned i = 0 i lt slength() ++i)

result = result + s[i]

return result 10

hashfunc() iterates through s keeping a running total of the sum of the ASCII codes for each of the characters eg hashfunc(hash-table) computes

h + a + s + h + - + t + a + b + l + e

where the characters ASCII values are

104 + 97 + 115 + 104 + 45 + 116 + 97 + 98 + 108 + 101

The total = 985 and 985 modulus 10 = 5

The final computed value will be used as an index into the array The modulus value used is the size of the hash-table and we use it so as to ensure that resultant computed index value cannot be greater than 9 (remember our arrays indexes are 0 ndash 9)

We can now store words in the myhash array like this

string myhash[10]

string s = hash-table

index = hashfunc(s)

if(myhash[index] = )

myhash[index] = s

else

The complex part is what to do if we have what is called a collision ndash when we find that myhash[index] is already occupied Youll probably have already thought of what value hashfunc(elbat-hsah) will have

One way to help avoid collisions to use a better hash-function and a larger array However in real life collisions are practically impossible to avoid and the only other option to deal with them is to allow more than one string to inhabit an array slot in some way ndash perhaps by having each of the original array slots contain an array ndash rather than an individual string Of course in this case we would also need some way to determine which of the n colliding entries is the one were interested in ndash is it elbat-hsah or hash-table

110

Well briefly leave our examination of hash-tables at this point and instead look at Fibonacci numbers Do not worry we will return to hash-tables very soon

Fibonacci numbers are the numbers in the following integer sequence

0 1 1 2 3 5 8 13 21 34 55 89

By definition the first two numbers in the Fibonacci sequence are 0 and 1 and each subsequent number is the sum of the previous two More formally that is

119865119899 ∶= 119865(119899) ∶=

0 119894119891 119899 = 0 1 119894119891 119899 = 1

119865(119899 minus 1) + 119865 (119899 minus 2) 119894119891 119899 gt 1

Computing Fibonacci Numbers

Task 1

Open Cached_fibonacci

Compile and run the program as is

Examine main() and the calcfib() functions

bigint calcfib(bigint n)

if(n == 1 || n == 0)

return n

else

return calcfib(n - 1) + calcfib(n - 2)

bigint is defined as a unsigned long long int and we have used typedef to save some typing

NOTE The method used to calculate Fibonacci numbers here has been selected because it is perhaps the most obvious way to turn the formal definition into code If you are interested please see the separate Fibonacci project for two other examples of how to calculate Fibonacci numbers

111

Modify the beginning of the calcfib() code

bigint calcfib(bigint n) cout ltlt calcfib was passed ltlt n ltlt endl

Modify main() to set max = 5 and re-run the program

calcfib was passed 0 Fibonacci number 0 is 0 calcfib was passed 1 Fibonacci number 1 is 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 2 is 1 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 Fibonacci number 3 is 2 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 4 is 3 calcfib was passed 5 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1

Fibonacci number 5 is 5

112

Note that to calculate Fibonacci number 5 we calculate Fibonacci number 4 and Fibonacci number 3 - even though weve previously calculated Fibonacci number 3 in order to calculate Fibonacci number 4

To fully appreciate the growth of this process re-run the program adding 10 to max for each subsequent run You maymay not like to comment out the line you inserted in Step 2

Task 2

Getting back to Hash Tables Using a hash-table to store previously computed Fibonacci numbers

As it stands the incomplete solution declares a template hash-table called fibs of the type unordered_map

Read the comments in the function fibCache() and modify the code to as to use the fibs hash-table to store previously computed Fibonacci numbers

fibs[n] = f stores f the n-th Fibonacci number in the n-th slot of fibs (which as you can see you may treat as an array for indexing into)

8 Pointers In C++ programming data (variables) can be referenced via the memory address of the variable This is done using a pointer var iable

A pointer var iable contains the address (location in memory) of a data variable

There are also functional pointers ie those that point to code rather than data and these are briefly explored later

Pointers can be particularly useful when interacting with the operating system andor when working with arrays - as the elements in an array will always occupy consecutive memory places Incrementing the pointer variable by one addresses the next array element

Lastly pointers are also used to fake pass by reference

Declarat ions

int n This is a standard variable declaration n that contains a value as yet unknown of type int

int p This is a pointer p that can hold (point to) an address that contains a variable of type int The type of p is int

Each variable declared as a pointer must be preceded by an asterisk () This modifies the type of the object being declared from thing of type to pointer to thing of type Eg int n means n is an int whereas int n says that n is a pointer to an int

113

int age height age is a pointer to an int height is an int value

double far cent are both pointers to doubles

Pointers can be initialised when they are declared or set using an assignment It is common to initialise pointers to a memory address but they can also be initialised to the predefined constant NULL ndash meaning that they do not (as yet) hold (point to) a valid memory location NULL is defined in the standard library such a pointer is called a nul l pointer

When is used in a variable declaration it indicates the variable being declared is a pointer and not a value

But do beware as is used elsewhere with pointers when the appears before a previously declared pointer variable elsewhere in the program it is said to dereference the pointer and so is used to access data stored at the address which is stored in the pointer A dereferenced pointer is essentially the variable to which the pointer was originally set to point

To complicate matters further using the pointer name without the dereference operator references whatever is stored in the pointer variable itself ndash this is the address of the object it references in memory (which maybe NULL of course)

As we have seen using can mean two things that something is being declared as a pointer or that a previously declared pointer is being dereferenced Experienced programmers sometimes enter the two usages differently ndash a notation we would highly recommend ie

int n n is an object that can hold the address of an int

int k = 0 k is an int holding the value zero

n = ampk n is set to hold ks address amp is explained below

n = 1 k (yes k) is set to hold the value 1

Note the space used in the different usages - int n vs no space in n

Initialising pointers

Pointers can be initialised in two ways

int x = 16 y = 69 variable declaration and initialisation int x_ptr = ampx pointer declaration and initialisation x_ptr holds the address of x int y_ptr pointer declaration yptr is a pointer

y_ptr = ampy pointer assignment yptr holds the address of y

Once declared a pointer variable can be assigned the address of another variable using the amp the addressof operator

114

Note the variable name should not be prefixed by the in the assignment statement unless the pointer is initialised immediately in the variable declaration

We also use pointers when creating objects on the Heap for example we can create and initialise a string object like this string pstring = new string(Hi there) Such objects are not normally tidied away as are the objects created on the stack - objects simply declared in a functionmethod and so they should explicitly be tidied away using delete eg delete pstring For more on this subject see section 9

Using pointers

Task 1

Open the project Pointers

Compile and run the program The output should be as shown in Figure 28

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int x_ptr = ampx This is x_ptr pointer declaration and initialisation

int y_ptr Declaring another pointer y_ptr

y_ptr = ampy Initialising y_ptr

y_ptr = x_ptr Assigning x_ptr contents to y_ptr Both pointers are pointing to variable x (16)

y_ptr = ampy Assigning the address of y back to pointer y_ptr

y_ptr = 170 Assign 170 to the variable at memory location of y_ptr y_ptr points to variable y so 170 has been assigned to y

115

Figure 28

Pointer Arithmetic and Arrays

We have seen that once a pointer is initialised it has a memory address and this address can be reassigned another address It is also possible to change an address using standard arithmetic

The ++ and -- increment and decrement operators can be used to move the pointer along to the next or back to the previous memory address To jump more than one memory address you would have to use the assignment operators += and -=

When using arrays and pointers the array name is the address of the first element in the array

int intArray[] = 1 2 3 4 5

int int_ptr = intArray Same as int int_ptr = ampintArray[0]

The pointer has been declared and initialised with the statement int int_ptr =

intArray Note there is no need to use the address of operator amp when initialising arrays as the array name is the address of the beginning of the array

When working with arrays each element of the array will be the type and size at declaration When an array is declared to hold integers each element will usually be 4 bytes in size An array of doubles will have element sizes of 8 bytes Note ndash these sizes are actually down to the compiler being used and are usually in turn dependent upon the operating system being used

It is not important to know how many bytes make up each element Moving the pointer through the array with the assignment operator x_ptr += 2 will move two elements further through the memory allocated for the array or 16 bytes for an array of doubles

116

Pointers and Arrays

Task 1

Open the project PointerAr i thmetic

Compile and run the program The output should be the same as Figure 29

Examine the program carefully

You may not fully follow the program at first glance as it employees a few potentially new constructs (it depends how far weve got through the lectures)

One slightly truncated new construct is

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

A struct in C++ is just like a class except that the default public and private sections are reversed By default everything in a struct is public

typedef in C++ allows the definition of our own types based on other existing data types

typedef exist ing_type new_type_name

where exist ing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining For example

117

typedef unsigned int WORD

typedef char pChar

You may also remember initialiser lists from earlier eg

s_thing(int a) a(a) b(sqrt((double)a))

If we re-write this

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

We quickly see that a(a) and b() are initialising the a and b struct members const int a and const double b

118

Remember that as these are const we cannot use assignment

typedef struct s_thing

const int a

const double b

s_thing(int a)

Error ndash a and b are const

this -gt a = a

this -gt b = sqrt(a)

thing

Lastly when dealing with pointers to compound types one may access the members of the type via dereferencing or via the so called crows foot operator

(t) dereferences t giving us a thing which was pointed to by t Then we use the dot operator to access the member (t)a

We have to parenthesiset otherwise the would bind to t first ie it would be as though we had done this (ta) which would be an error

The crows foot saves us the dereference t-gta is just like (t)a

119

Figure 29

PLUSPLUS Pointers and Arrays

Task 1

Open and modify the skeleton project called ReverseArray

In main() create an array of 10 integers Fill the array with random numbers between 0 ndash 100

Write a helper function called to output the contents of the array to the console A suitable prototype for this would be void dumpArray(int array[] int size)

Write a helper function to reverse the contents of the array Use a temporary variable as an aid A suitable prototype for this function would be void reverseArray(int array[] int size)

Reverse the values in the array using only pointers

120

Reverse the array without using a temporary variable You should use the XOR operator ^ to achieve this

Pseudo code for an XOR swap is

X = X XOR Y

Y = X XOR Y

X = X XOR Y

The completed program should look like Figure 30

Figure 30

Task 2

Reverse the array using a vector and the standard function template stdreverse()

We can also have pointers to functions in C++ (and C)

The name of a function resolves to be its address in memory (somewhat similar to the case where we use the name of an array) When we call a function we use this name to retrieve the functions address and then use the function invocation operator to execute it The function invocation operator is the set of brackets you use eg

Lets take an example

121

include ltiostreamgt

using namespace std

int lue() life the universe and everything

return 42

int main()

cout ltlt The address of the function lue is

ltlt lue

ltlt invoking it yields

ltlt lue()

ltlt endl

system(pause)

return 0

Typical output is shown in Figure 31

Figure 31

122

We can also store addresses of functions in variables (theyre just numbers) and the type system allows for us to describe and declare scalar variable types for function pointers eg this modified code fragment would produce the same output as that show above

fp is a pointer to a function taking

no arguments and returning an int

int (fp)()

fp = lue

cout ltlt The address of the function lue is

ltlt fp

ltlt invoking it yields

ltlt fp()

ltlt endl

fp is a funct ion pointer var iable so it may be used to point to any other function having the correct signature at runtime

PLUSPLUS Function pointers

Task 1

Open the project Calculator

Compile and run the program The output should be as shown in Figure 32

123

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int (fp)(int int) This is the function pointer declaration It may point to functions that take two integers and return an integer

Like all automatic storage class variables fp will currently be pointing at a random location What happens if you run the program without setting fp to point to an actual function Comment out the switch to find out

switch (Operator)

case 0 fp = Add break

case 1 fp = Subtract break

case 2 fp = Multiply break

The code could do with improving

Modify it to allow for multiple trials eg add the necessary logic to loop and perform multiple calculations ndash youll need to add some way to end the program too therefore

Modify it so that the operator may be inputted as an operator character eg + - etc Allow X x and for multiplication and add for division

All three pieces of information could be entered on a single line eg 6 x 7ltentergt Using cin to read that data just requires you to use three cin statements

cin gtgt X

cin gtgt Operator

cin gtgt Y

Lastly modify the program to that it uses floating point arithmetic

124

Figure 32

9 APIs New Delete and Dynamic Memory As has been stated earlier pointers are useful in a variety of situations However because they are easy to get wrong ndash and when they go wrong everything goes very wrong indeed ndash languages like C++ have tried to make their use the exception rather than the norm For example without reference arguments (eg void someFunc(int amp)) we would have to use pointers to achieve the same functionality and performance

On the whole the underlying philosophy when it comes to pointers is to try to avoid using them whenever possible You can get a real feel for this subject by Googling for smart pointers c++ and from Wikipedia httpenwikipediaorgwikiSmart_pointer

Two areas where we absolutely need pointers are when calling into an external API (Appl icat ion Programming Interface ) and when allocating memory for our own purposes ndash the latter case is also eased by advances in the library support in C++

Using an API

An Appl icat ion Programming Inter face is functionality provided by some third party The most obvious API whether it is Windows Linux or OSX is that exposed by an operating system

If your application needs to interact with the user in any non-portable way you will need to call into your OSs API For example if you want to display a dialog box you will need to access the OSs functionality to do so (perhaps indirectly through a framework like Nokias Qt - httpsenwikipediaorgwikiQt_(framework)) In summary if you ever want to go outside of the standard libraries andor writing consoleterminal applications you will need to call into your operating systems API

When it comes to calling into operating systems pointers are used extensively As an example 1 Google for Linux API 2 Find any website that lists the API functions and then 3 click-through to any function The odds are that the function prototype you see will contain asterisks (pointers)

125

Dynamic Memory Management

The second area where you simply must know something about pointers is when it comes to using the heap

The heap is an area of memory available to your programs You may allocate and use the heap as you wish

Why would you want to do this Normally its to create variable length arrays or to model and use an advanced data structure of some sort a self-balancing red black tree perhaps (httpenwikipediaorgwikiRedAndblack_tree) Of course the more esoteric the data structure and less likely it is that it will be incorporated into the C++ standard library (although the library does contain most of the generally useful and popular ones like doubly l inked l is ts )

To allocate memory from the heap in C++ you use the new keyword and to return it you use the delete eg

int nSize = 12

note nSize does not need to be constant

int pArray = new int[nSize]

pArray[4] = 7

delete [] pArray

10 More on Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine Encapsulation is data information or detail hiding

Once a function is written the detail of how it works is not important to the end user The user needs to understand what data to input and what output will be produced

One of the most important aspects of writing programs using functions is that the functions can be reused from one project to the next Think about the standard functions youve seen already eg the square root function sqrt() Libraries contain atomic generally useful functionality that is likely to be of use at some future time It is useful to bear this thought in mind whenever we build new programs ie we should be on the lookout for generally useful functionality (given our domain) that we should consider coding as functions for later reuse The same goes for classes of course

Probably the most important function in your program in main() ndash without it you do not have a program at all

main() is your programs entry point and as such it may be used in such a way as to inform the rest of your program as to the actions required

126

main() and command-line arguments

Task 1

Open a Command Prompt or PowerShell Prompt and enter the following

dirltreturngt

di r Odltreturngt

t ree ltreturngt

t ree altreturngt

dir and t ree etc are like mini-programs They have default functionality which may be altered by providing additional command-line arguments eg for the dir command dir L N 4 TC

Command-line arguments are passed to your programs by optional parameters eg

int main(int argc char argv[])

Where argc is a count of the number of arguments and argv is an array of pointers to arrays of character (C strings) for each argument being passed Note that argc is always at least 1 and so argv always contains at least one entry ndash this is the name of the program being run

Task 2

Open (demonstrat ion)

CommandLineArgs and Build and run the program

Examine the code

The programs configuration is Debug

In the projects Project | Debugging | Command

Arguments you will see where the programs default command-line arguments are set for debugging purposes

Using the command prompt you opened earlier navigate to your where CommandLineArgsexe is located

CommandLineArgs debug

Run the program by entering its name followed by a variety of arguments eg

gtCommandLineAgs one two threelte ntergt

127

Task 3

Open the project UserPrompter project

Run the program and then examine its code

We will modify this program to use a command-line argument However before doing that its worth pointing out that the primary purpose of this program is to demonstrate the separation of a class declarat ion with its implementat ion (the mechanismfunctionality of class prompter is defined in promptercpp but its capabilities are declared in prompter h )

Its also interesting to note that the optimal strategy is to use an algorithm called binary search or binary chop (we saw this earlier in the course) with each guess you reduce the number of possible solutions by a half This sort of algorithms Big Oh is Log n (where log is base-two logs)

httpenwikipediaorgwikiBig_O_notation

Task 4

Modify the program so that the upper range for the max value is given as a command-line argument

The UserPrompter cpp is the file youll need to modify

Test your program via the setting the projects Command Arguments as detailed above -or- by running the application standalone in a command prompt after building (also as detailed above)

See Figure 33

To convert a string into a number (weve seen one other way of doing this earlier) we can use

include ltcstdlibgt

and the function atoi() eg

atoi(argv[1])

128

Figure 33

EncryptDecrypt a file

Task 1

Open compile and run the EncodeDecode project

Complete the program so that it may be run outside of the IDE and process a file for encryptiondecryption

This is actually quite a simple task as youll only need to add a couple of lines of code However the project also demonstrates how to use the Debug and Release modes to influence the way a program runs ie that in its Debug configuration the program automatically runs through a test

Other things to note include using bitwise XOr to perform the encoding and the use of the C standard library functions putchar() and printf() to perform some of the output eg putchar() is used to output a CR to the console window (CR = char 13)

129

Figure 34

Multiple arguments overloading and default values

In C++ we can over load functions ndash meaning that we can provide different versions of the same function (the different versions must differ by the number andor type of the parameters they take) For example

130

void foo(double d) 1

cout ltlt In void foo(double d)nn

void foo(long int n) 2

cout ltlt In void foo(long int n)nn

void foo(int n) 3

cout ltlt In void foo(int n)nn

double dtest = 0

long int ltest = 0

int ntest = 0

foo(dtest) Calls 1

foo(ltest) Calls 2

foo(ntest) Calls 3

In the above the compiler works out which version of the foo() to call based upon the argument type it is given

We can also overload functions if the number of arguments differ eg

131

void bar(double d)

void bar(double d double t)

We would use a feature like this if sometimes we needed to use extra information ndash in the shape of passing in t in the above eg we would most likely implement void bar(double d) as

void bar(double d)

bar(d 25) Call bar(double d double t)

What were really saying above is that in most cases the implicit double second parameters value is normally 25 ndash perhaps its a standard discount percentage ndash and only occasionally we will need to change that value in which case wed call bar(double d double t) directly and not by going through bar(double d)

Lastly C++ has one extra feature that can make this simpler ndash defaul t arguments

Rewriting bar using this feature we get

void bar(double d double t = 25)

Note that we now only have one bar function now and that we may call it like this

bar(x)

Or like this

132

bar(x y)

In the case of bar(x) the second parameter is omitted and so will receive the default value of 25 in the second example t will receive ys value

Although outside the scope of this class for more on overloading see the (demonstrat ion) Operator Over loading project This shows how to overload the ++ pre and post increment operators overload and provide your own ltlt stream insertion operator (and one use of a friend function) and using an enum with a typedef

Passing Arrays to Functions

To pass an array to a function it is only necessary to pass the array name and the number of elements in the array

The array name is the position (address) in memory of the first element The number of elements is passed to enable the function to establish the array size

An array declared as double somearray[10] would require a function call somefunction(somearray 10)

Passing Arrays to functions

Task 1

Open and modify the skeleton project called the project called ArrayReturnValue

Pass an array to a function to read in five numbers

Pass the array to another function to calculate the average value in the array return this to main() and output to screen

Lastly at the end of the program output the values in the array from within main() The finished program should look something that that in Figure 35

Create two function prototypes

void enterMarks(double ExamMarks[] int num)

double calcAverage(double ExamMarks[] int num)

ExamMarks[] is the array to be passed As with passing variables it is not strictly necessary to give the argument a name in the prototype just its type This could have been written as calcAverage(double [] int) However it is sometimes useful to include this information as it might help explain the functions operation

It is also necessary to pass the size of the array num is the number of elements in the array its size

Within main() declare the array and initialise the elements to zero with the following statement double ExamMarks[5] = 0

This declaration explicitly initialises the first element to zero and implicitly initialises the remaining four to zero

133

Create both functions

enterMarks to read in the values and calcAverage to calculate the average (you will need a for loop in each function)

Return the average value from calcAverage to main() and output the value using cout

Call the functions from within main() with the following statements

enterMarks(ExamMarks 5)

average = calcAverage(ExamMarks 5)

You may output the average directly of course ie without first storing the value in average

At the end of main() add the statements

for(int i = 0 i lt 5 ++i)

cout ltlt Exam Mark Number

ltlt i + 1

ltlt is

ltlt ExamMarks[i]

ltlt endl

ltlt endl

134

Explain how it is possible at the end of the program to output from within main() all the values in the array entered within the function

Modify the program so that the number of exam marks (5) appears only once

In previous exercises when parameters (variables) were passed to functions the function received a value When a value is used in a function a copy is stored in a part of memory that only exists from the time the function is called to when it ends After this the memory and any value in it are lost

However the array in this exercise was initialised in main() with zeros and then passed to the function Data was then added to the array and calculations done At the end of main() the values in the array elements are output The array contains values input from within the function

The name of the array is the address of the first element of the array in the machines memory As the starting address is passed (the name of the array) the called function knows where the array is stored in memory

Because we are working with memory addresses (references ) any changes made to array elements in the function affect the memory location set up in main() for the array

C++ passes arrays to functions by reference (to the memory location of the first element) In previous exercises functions were passed values copies of the variables in main()

135

Figure 35

Passing Two-dimensional Arrays to Functions

It is common to want to store numbers in a two dimensional layout of rows and columns as shown in Table 7

187645 783473 298372

871223 629399 561201

Table 7

This arrangement is known as a two-dimensional array or matrix

C++ uses an array with two subscripts to store a two dimensional array

double Balance[2][3]

When we specify a one-dimensional array the number of elements must be given

When a two-dimensional array is specified it is necessary to specify the array elements in both dimensions We therefore specify the number of rows and columns

The Balance array in the statement above has two rows and three columns

11 Inheritance and (not presented) Polymorphism

111 Inheritance

In Object Oriented languages like C++ inheritance describes a relationship between classes of objects and which usually implies some sort of a sub-division of labour

For example lets say that we want to build an IT system that has something to do with the members of the university

136

In an OO world the first question usually is how would we categorise our significant entities and that always means naming things what names would we use to categorise university members When modelling (for that is what were going to be doing) real-world objects its sensible to use proper names So heres an attempt ndash to broadly categorise university membership

Members are members of the sets

Students

Staff

Other

What is other though

The Bodleian and the card-office issue Readers cards ndash so is a Reader a university members or are they something else And if they are something else does our system really want to concern itself them Or more broadly does our system really want to concern itself with holders of cards issued by the card-office

Are all students really the same

What sort of students do we have at Oxford (and do we want a system ndash either now or in the future ndash that might be interested in recording the differences) Lets see we have undergraduates and graduates We also have Rhodes scholars ndash but are these sorts of student that are distinct (or should be in our system) from our underpost-graduates categories And how about graduates would we want to have some sort of sub-groups Masters students MScMBAMPhil or Doctoral students DPhilDScDLitt etc Perhaps wed like to know something about how theyre being funded ndash and we might want that piece of functionality shared by our undergraduates

We can of course go through the same process when thinking about members of staff (university staff departmental staff members of congregation academic staff fulltimepart-time staff casual staff ndash and how about staff that are sometimes (or also) students) We can go on thinking about this sort of thing for a very long time and we should as its important and when its important it has a name ndash Object Oriented Design or OOD

One of the things wed hope to see appear as part of the OOD phase is the relationship between entities For example if we were to say that a common property of all university members is that they have a date-of-birth we wouldnt want to have our Student and Staff C++ objects contain this information directly by way of some datastate class member (which might seem a little odd at first) But think about it If we performed some validation on the members DoB (perhaps when its being set) we would need to include this in both Student and Staff classes Or as an alternative we would capture the validation in some external function ndash which we would call from the separate classes (if we remember) No its messy and it would be much better if we thought of things this way that all university members are people and that people all have dates of birth

To put it another way we would say that studentsstaffother are just specialisations of people ndash they are people but with a bit of extra something tagged on to them ndash like a bod card number

Now if we also had some way of capturing people stuff in say a basic Person class and could somehow use that automatically ndash perhaps by deriving a Member class from it and then doing the same from Member to both Staff and Student classes from Member One thing though ndash we wouldnt want someone to be able to instantiate a Member object

137

perhaps ie in our system Member is an abstract class Imagine a generic Car vs a Renault Clio ndash it makes no sense to create a Car object ndash there are no generic cars on the road they are all specific cars Similarly we wouldnt want a generic Member wandering around our system (if you remain unconvinced well see why later)

Modelling a student - a first attempt

Please note that in this Introduction to C++ we do not expect you to complete an exercise that requires coding from now on Please just look through the code and follow along with the discussion

Base classes

Task 1

Open the project UnivMember1

Examine the program carefully

The project contains three classes Person Member Student In main() we create a Student and then attempt to output the students name ndash which fails

name is in the protected section of Person ndash which means only Person methods or methods in derived-from-Person classes can access it

Add a public section to the Person class and relocate the name there

Eg

public

string name

Any better now

The problem now is that Student only by default inherits the private side of Person

Change class Student so that we also inherit the public members of Person hellip

class Student public Person

138

Before we tackle further problems with name lets bring in the Member class (left doing nothing until now)

We really want Student to inherit from Member and not Person Change the code to reflect this

People have dates-of-birth and Members have bod cards Add a string member dateOfBirth to Person and move the bodCardNumber member out of Student and into Member ndash make them both strings

Change the code in main() to set these extra pieces of data

If you havent done it already Persons dateOfBirth and Members bodCardNumber should be set via constructors

139

Task 2

Open and examine the project called UnivMember2

UnivMember2 is a copy of the (exercise solut ion)

UnivMember1 solution

One of the problems we have in UnivMember1 is that too much of it is public eg given Student object s we can change name to simply by using assignment eg sname =

We should protect data members at each level using the maximum level of protection we can ie private

However if we do that then cout ltlt sname will no longer work and so well need to provide access methods to the data members Eg heres a modified Member class showing the basic scheme

class Member public Person

public

Member(string bodCardNumber)

this-gtbodCardNumber = bodCardNumber

string getBodCardNumber() For access

return bodCardNumber

private

string bodCardNumber

140

Another problem is that wed really like to not use assignment at all Eg in the above ctor snippet

this -gt bodCardNumber = bodCardNumber

is using assignment

Change string bodCardNumber to const string bodCardNumber Youll see now that assignment wont now work (you have to initialise constants)

What wed really like (most likely) is to use in i t ial isat ion

We can do this via initialiser lists Ie we could change the above to the following

class Member public Person

public

Member(string bodCardNumber)

bodCardNumber(bodCardNumber)

const string getBodCardNumber()

return bodCardNumber

private

const string bodCardNumber

The initialiser list is read thus

bodCardNumber(bodCardNumber)

^^member^^ ^^parameter^^

Note that weve also modified getBodCardNumber() to show that it returns a const string

141

Modify all three classes to use initialiser lists private const data members and use access functions (getBlah() etc)

Task 3

Open and examine the project called UnivMember3

UnivMember3 is a copy of the (exercise solut ion)

UnivMember2 solution

We will now finish this project to the level of an introductory course

Things to note

The main problem with the solution as it stands is that one may create a Member object

Remember that this is analogous to being able to create a generic Car object ndash we should not be allowed to create one

Going right back to UnivMember1 you may remember a comment in there about a protected constructor

protected Protected ctor Person()

At that point in your project we were thinking two things 1) we wont want to create a generic person and 2) a protected constructor will facilitate this

And we were wrong to think both thoughts

1) A properly thought through Person class would be perfectly good to model generic people But although this is true one question here ndash would we ever want just a generic person

2) A protected constructor in a (more) base class doesnt prevent a derived class from creating a base object So what about the Member class ndash would it be ok to instantiate that

The proper means to prevent a Member being created would be to use what is called a pure v i r tual funct ion as part of its definition (such a function is one that must be overridden in a derived class) But what function

142

If you look at the classes derived from Member ndash you can take it from us that one might want to interrogate at runtime ndash to ask them what they are

So a suitable member function to declare in Member would be something like string getRole() A function that does return Student for a student and return Staff for a Staff object

If its pure virtual in in Member wed best define it in our derived classes

class Member public Person

public

virtual const string getRole() = 0

class Student public Member

public

const string getRole() return Student

143

1 Why did we want duplicate (named) functions in Member Student and Staff 2 And what does virtual really mean

We require both 1 and 2 so that we can provide specific responses when being asked the same question and all when being treated in a rather basic way

Being asked the same question means having a method invoked eg getRole() and in a rather basic way means treating us all Students and Staff (etc) as Persons and Members

112 Polymorphism

Polymorphism comes in a few forms

Ad-hoc Polymorphism via function overloading

Parametric Polymorphism or Compile-Time Polymorphism via templates

Subtype Polymorphism or Runtime Polymorphism via virtual functions and

Coercion Polymorphism via casting

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class (after all a derived from base must have or contain all that a base has) Polymorphism is the art of taking advantage of this simple but powerful and versatile feature

One way Subtype Polymorphism is applied is to use a base reference to access a collection of instances of different types that are derived from a common base ndash one way to paraphrase that is to say that related (derived from a common class) objects respond according to their type rather than according to the type of the reference one uses to access them (a base class pointer type) That is the dynamic type of the object is used instead of its static type

All of this is best demonstrated via an example of course

144

PLUSPLUS Polymorphism

Task 1

Open and examine the project called (exercise

solut ion) UnivMember3

Run the program the output should be the same as shown in Figure 36

The crucial code here is as follows

Member arr[6]

Student studs1()

Student studs2()

Staff staff1()

Student studs3()

Staff staff2()

Student studs4()

arr[0] = ampstuds1

arr[1] = ampstaff1

arr[2] = ampstuds2

arr[3] = ampstaff2

arr[4] = ampstuds3

arr[5] = ampstuds4

for(int i = 0 i lt ++i)

cout ltlt arr[i]

ltlt i ltlt s name is

ltlt arr[i]-gtgetName()

ltlt t Their role is

ltlt arr[i]-gtgetRole()

ltlt endl

Weve created an array of Members (it isnt important that weve used pointers) and note that we have set some of the members of this to be pointers to Student and Staff objects We are allowed to do this as both Student and Staff are derived from Member

However when and if we invoke member functions on these objects wed really like it if they responded as what they really are ndash Student and Staff objects

145

From the output below you can see that they indeed do respond accordingly

Figure 36

The mechanism behind allowing this is the virtualisation of the getRole() member function Remember that this was declared and made virtual in the Member class

Play about with the code eg change

Member arr[6] to Person arr[6] Everything still ok How about not using pointers here ndash easy to do

146

Lastly weve implemented (for no good reason but to show you how its done) some instance counting in all three classes Have a look for the static members and the inserted lines immediately below the class definitions that look like this int PersonCount = 0

The End Thank you for coming and we hope that you enjoyed the class

Oh and please Please PLEASE fill out the feedback form email when it arrives

147

12 Appendices

Arithmetical Operators

Operator Operation

+ Addition

- Subtraction

Multiplication

Division

Modulus

++ Increment

-- Decrement

Table 8 ndash Arithmetical Operators

Assignment Operators

Operator Example Equivalent

= a = b a = b

+= a += b a = a + b

-= a -= b a = a - b

= a = b a = a b

= a = b a = a b

= a = b a = a b

Table 9 ndash Assignment Operators

148

Assignment and Arithmetic examples

The assignment operator in C++ is =

The format is var iable = expression this can be read as assign to the var iable the value of the expression

An example to calculate the number of pence in a value in pounds would be

pence = pounds 100

Note it is easy to confuse the assignment operator = with the equals notation used in mathematics The equals notation in C++ is ==

Incrementing a var iable

month = month + 1 adds the value one to the variable month This can be written as

month++

Decrementing a var iable

month = month - 1 deducts the value one from the variable month This can be written as month--

Note that ++ and ndash can be used before or after the thing being modified eg ++x x++ --y y-- However there are some subtle differences which will be explained in the lectures

In C++ it is also possible to combine arithmetic and assignment operations

To add 2 to a variable total

total = total + 2 or total +=2

To subtract 2 from to tal

total = total - 2 or total -=2

To multiply total by 2

total = total 2 or total =2

Relational and Equality Operators

The equality operator is used to compare two operands (a == b) and returns 1 (t rue) if both are equal otherwise 0 (false ) is returned

The inequality operator (=) returns 1 (t rue) if both are NOT equal otherwise 0 (false) is returned

Both the above operators are commonly used to test the state of two variables to perform conditional branching

The relational operators also return either true or false (a gt= b) returns 1 (t rue ) if a is greater than or equal to b otherwise 0 (false ) is returned

149

Standard algebraic equality or relational

operator

C++ equality or relational operator

Sample C++ condition

Meaning of C++ condition

Relational operators

gt gt a gt b a is greater than b

lt lt a lt b a is less than b

gt= a gt= b a is greater than or equal to b

lt= a lt= b a is less than or equal to b

Equality operators

= == a == b a is equal to b

= a = b a is not equal to b

Table 10 ndash Relational Operators

Logical Operators

When using i f selection statements it is common to use the relational operators as part of the test if(num gt 5) if(size lt= 14) if(Char == A) These are fine for testing one condition

To test multiple conditions it is possible to nest i f statements but this can be a bit cumbersome

Logical Operators can be used to form more complex conditions by combining simple conditions

Logical AND (ampamp) Operator allows a test to see if two conditions are true

if(leaveBooked gt LeaveLeft ampamp staffCover == false)

cout ltlt Take your holidays sometime else

Logical OR (||) Operator allows a test to see if either or both of the conditions are true

if(Temperature lt 16 || windspeed gt 15)

cout ltlt Too cold or windy to sunbath today then

Logical Negation ( ) Operator reverses the meaning of a condition

if((windspeed == 20))

150

cout ltlt The wind speed is not 20 its ltlt windspeed

This could be written equally as well with the equality operator

if(windspeed = 20)

cout ltlt The wind speed is not 20 its ltlt windspeed

Precedence and Associativity Table

Precedence Operator Description Associativity

1 Scope resolution Left-to-right

2

++ -- Suffixpostfix increment and decrement

() Function call

[] Array subscripting

Element selection by reference

-gt Element selection through pointer

typeid() Run-time type information (see typeid)

const_cast Type cast (see const_cast)

dynamic_cast Type cast (see dynamic_cast)

reinterpret_cast Type cast (see reinterpret_cast)

static_cast Type cast (see static_cast)

3

++ -- Prefix increment and decrement Right-to-left

+ - Unary plus and minus

~ Logical NOT and bitwise NOT

(type) Type cast

Indirection (dereference)

amp Address-of

sizeof Size-of

new new[] Dynamic memory allocation

delete delete[] Dynamic memory deallocation

151

4 -gt Pointer to member Left-to-right

5 Multiplication division and remainder

6 + - Addition and subtraction

7 ltlt gtgt Bitwise left shift and right shift

8 lt lt= For relational operators lt and le respectively

gt gt= For relational operators gt and ge respectively

9 == = For relational = and ne respectively

10 amp Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 ampamp Logical AND

14 || Logical OR

15 Ternary conditional Right-to-Left

16

= Direct assignment (provided by default for C++ classes)

+= -= Assignment by sum and difference

= = = Assignment by product quotient and remainder

ltlt= gtgt= Assignment by bitwise left shift and right shift

amp= ^= |= Assignment by bitwise AND XOR and OR

17 throw Throw operator (exceptions throwing)

18 Comma Left-to-right

Table 11 ndash Precedence and Associativity Table

Escape Sequences

Escape Sequence

Description

n Newline Position the screen cursor at the beginning of the next line

152

t Horizontal tab Move the cursor to the next tab stop

r Carriage return Position the cursor at the beginning of the current line

a Alert Sound the system bell

Backslash used to print a backslash

Single quote Use to print a single quote character

Double quote Used to print a double quote character

Table 12 ndash Escape Sequences

Cast Operator

Is where the programmer explicitly asks for a change in data type It may be that the result of a calculation is a double and the user wants it to be of type integer

A double can be cast to an integer in the following way

double aNum = 237

int anInt = 0

anInt = static_castltintgt(aNum)

A C style cast may also be used eg

anInt = (int)aNum OR anInt = int(aNum)

Formatted Output

When several numbers are displayed each is printed with the minimum number of digits needed to show the value This can yield some unexpected output

The width of an output field can be set using a stream manipulator To set the next number to be printed to a width of 5 digits use cout ltlt setw(5) This command does not produce any output it manipulates the stream to change the output format of the next value Note setw() must be specified for every item output

To use any stream manipulators you must include the header include ltiomanipgt

setprecision is another manipulator and is used to set the precision of the next floating point number Note setprecis ion only has to be set once as the stream remembers the formatting directive and does not affect integer fields The format is cout ltlt

setprecision(3)

To set precision for trailing zeros (0100 will appear as 01) it is necessary to use the fixed format The notation is cout ltlt fixed Note f ixed only has to be set once

The three manipulators can be combined to achieve the required precision and field width when used in this way

153

cout ltlt fixed ltlt setprecision(3) ltlt setw(5) ltlt myDouble

Alternatively as fixed and setprecision only have to be set once this statement could be written as

cout ltlt fixed ltlt setprecision(3)

cout ltlt setw(5) ltlt myDouble

Header Files

Every program that you create will have at least one header file If you use input or output you will have to include the iostream header

If you use mathematical functions you will need cmath It can be difficult to know which header files to use for each function Some of the common header files used together with some of the older ones you may find with inherited code are shown below It is a good idea to use the help if you are unsure which header files are associated with particular functions

Standard C++ header Old header

iostream iostreamh

iomanip iomaniph

fstream fstreamh

cmath mathh

cstdlib stdlibh

string No equivalent

vector vectorh

Table 13 ndash Header Files Old and New

Matrix Libraries

The STL does not contain a Matrix type and so we must look elsewhere for a suitable implementation that suits the individuals needs

The table below lists the third party libraries that we are aware of

Some Linear AlgebraMatrix Libraries

Armadillo Blitz++ Boost

CPPLapack CPPScaLapack CVM Class Library

Eigen Elemental FLENS

Gmm++ GNU Scientific Library (GSL) HSL

154

IML++ IT++ LA library

Lapack++ LinBox Matrix Template Library (MTL)

MV++ Newmat PETSc

RNM Seldon SimuNova

SL++ (Scientific Library)

SparseLib++ SuiteSparse

TCBI (Temporary Base Class Idiom)

Template Numerical Toolkit (TNT)

Trilinos

uBlas ViennaCL

Table 14 ndash Matrix Libraries

Scope

The portion of a program where an identifier can be used is known as its scope

An identifier declared outside any function or class has f i le scope This type of identifier is known by all functions Global variables and function prototypes all have file scope

Identifiers declared inside a block of code have block scope This type of scope begins at the identifiers declaration and ends at the termination right brace ( ) of the block in which the identifier is declared

Any block can contain local variable declarations If blocks are nested it is possible to declare variables with the same name in each nested block The variable in the outer block is hidden while the inner block is being executed

Enumerating constants

The enum keyword provides a handy way to create a sequence of integer constants An example of enumeration is shown below

enum Months JAN = 1 FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC

Each of the constants will have a default value 1 greater than the constants that it follows in the list The first value in the enumeration above is explicitly set to 1 and the remaining values increment by 1 The values assigned from JAN to DEC will be 1 to 12

The statement cout ltlt DECEMBER is month number ltlt DEC ltlt endl would be output as DECEMBER is month number 12

Constants

Data that will not change during the execution of a program should be stored in a constant container rather than a variable If the program attempts to change the value stored in a constant the compiler will report an error and compilation will fail

Constant can be created for any data type by prefixing the declaration with const keyword followed by a space Note Constants must always be initialised at declaration

The following declaration declares a constant for the speed of sound at sea level ms

155

const double SpeedOfSound = 34029

Vector member functions

Some commonly used member functions of the vector class are

Vector member Functions Effect

at(element number) Gets the value contained in the specified element

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

push_back(value) Adds an element to the end of the vector containing the specified value

size() Gets the number of elements

Table 15 ndash Vector Member Functions

Global functions

Global functions are not member functions They take more than one argument and operate on a range of elements rather than on the vector container ie they can be used on other types of containers

Vector global Functions Effect

find()

ptr = find(vbegin() vend() 67)

Finds the element in the vector containing number 67 Needs iterator (ptr) to store location of element

reverse()

reverse(vbegin() vend()) Reverses the values in a vector (v)

sort()

sort(vbegin() vend()) Sorts the vector (v)

Table 16 ndash Vector Global Functions

156

list member functions

Some commonly used member functions of the list class are

List member Functions Effect

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

pop_front Removes the first element

push_back(value) Adds an element to the end of the vector containing the specified value

sort() Sorts the elements in the container from lower to higher

size() Gets the number of elements

swap() Exchanges the content of the list

Table 17 ndash List class Member Functions

cmath functions

Function Argument Result Returned Value Example Result

ceil(x) double double Smallest integer ge x

ceil(21) 30

cos(x) double double Cosine of x radians cos(10) 054

fabs(x) double double Absolute value of x

fabs(-15) 15

floor(x) double double Largest integer le 29

floor(29) 20

157

pow(x y) double double x to the yth power pow(24) 160

sin(x) double double Sine of x radians sin(10) 084

sqrt(x) double double Square root of x sqrt(4) 20

tan(x) double double Tangent of x radians

tan(10) 156

Table 18 ndash cmath Functions

158

String class

The string class defines many member funct ions A few of the basic ones are described below

Initialisation - constructors form

A string expression string str2 = str1

A character string literal string Intro = Programming with C++

A substring of another string object

string Intro = Capetown

string Mytown = Boars

string MyTown(Intro 4 5)

starts at character 4 (t)

with a length of 5 (or the rest of the string if shorter)

cout ltlt myTown ltlt endl

will produce an output town

Member Functions

length()

string myName = Sebastion

myNamelength()

will produce an output of 9

insert ()

Inserts a string into the current string starting at the specified position

string myName = Sebastion

string nameAdd = rjio

myNameinsert (2nameAdd)

cout ltlt myName ltlt endl

will produce an output Serjiobastion

erase()

Delete a substring from the current string

string myName = Sebastion

myNameerase (02)

cout ltlt myName ltlt endl

will produce an output bastion

replace()

Delete a substring from the current string and replace it with another string

string myName = Sebastion

string aName = renna

159

Member Functions

myNamereplace(3 6 aName)

cout ltlt myName ltlt endl

will produce an output Sebrenna

find()

Search for the first occurrence of the substring in the current string If the word is found return the position of the first character If not return -1

string sName

string findWord

position = sNamefind(findWord)

substr()

Returns a substring of the current string

string myName = Sebastion

string aName = myNamesubstr(0 3)

cout ltlt aName ltlt endl

will produce an output Seb

Non-member functions

getline()

string name

getline(cin name)

Table 19 ndash String Class Member Functions

160

A number of C++ operators also work with str ing objects

Operator

=

string fString = Hello

string lString

lString = fString

Assign a character (char ) to a str ing object

string aStringC

aStringC = Z

+

Concatenate two str ing objects

string str1 = C++

string str2 = Programming

string str3 = str1 + str2

+

Concatenate a string object and a character string literal

string str = Hello

string str1 = str + there

The same concatenation can be done in this way

str += there

+

Concatenate a string object and a single character

string str = Bye Bye

string strBye = str +

161

ASCII Character set

Decimal Octal Hexadecimal Binary Value Meaning

0 0 0 0 NUL (Null char)

1 1 1 1 SOH (Start of Header)

2 2 2 10 STX (Start of Text)

3 3 3 11 ETX (End of Text)

4 4 4 100 EOT (End of Transmission)

5 5 5 101 ENQ (Enquiry)

6 6 6 110 ACK (Acknowledgment)

7 7 7 111 BEL (Bell)

8 10 8 1000 BS (Backspace)

9 11 9 1001 HT (Horizontal Tab)

10 12 00A 1010 LF (Line Feed)

11 13 00B 1011 VT (Vertical Tab)

12 14 00C 1100 FF (Form Feed)

13 15 00D 1101 CR (Carriage Return)

14 16 00E 1110 SO (Shift Out)

15 17 00F 1111 SI (Shift In)

16 20 10 10000 DLE (Data Link Escape)

162

Decimal Octal Hexadecimal Binary Value Meaning

17 21 11 10001 DC1 (X ON) (Device Control 1)

18 22 12 10010 DC2 (Device Control 2)

19 23 13 10011 DC3 (X OFF)(Device Control 3)

20 24 14 10100 DC4 (Device Control 4)

21 25 15 10101 NAK (Negative Acknowledgement)

22 26 16 10110 SYN (Synchronous Idle)

23 27 17 10111 ETB (End of Trans Block)

24 30 18 11000 CAN (Cancel)

25 31 19 11001 EM (End of Medium)

26 32 01A 11010 SUB (Substitute)

27 33 01B 11011 ESC (Escape)

28 34 01C 11100 FS (File Separator)

29 35 01D 11101 GS (Group Separator)

30 36 01E 11110 RS (Request to Send)(Record Separator)

31 37 01F 11111 US (Unit Separator)

32 40 20 100000 SP (Space)

33 41 21 100001 (exclamation mark)

34 42 22 100010 (double quote)

163

Decimal Octal Hexadecimal Binary Value Meaning

35 43 23 100011 (number sign)

36 44 24 100100 $ (dollar sign)

37 45 25 100101 (percent)

38 46 26 100110 amp (ampersand)

39 47 27 100111 (single quote)

40 50 28 101000 ( (leftopening parenthesis)

41 51 29 101001 ) (rightclosing parenthesis)

42 52 02A 101010 (asterisk)

43 53 02B 101011 + (plus)

44 54 02C 101100 (comma)

45 55 02D 101101 - (minus or dash)

46 56 02E 101110 (dot)

47 57 02F 101111 (forward slash)

48 60 30 110000 0

49 61 31 110001 1

50 62 32 110010 2

51 63 33 110011 3

52 64 34 110100 4

164

Decimal Octal Hexadecimal Binary Value Meaning

53 65 35 110101 5

54 66 36 110110 6

55 67 37 110111 7

56 70 38 111000 8

57 71 39 111001 9

58 72 03A 111010 (colon)

59 73 03B 111011 (semi-colon)

60 74 03C 111100 lt (less than)

61 75 03D 111101 = (equal sign)

62 76 03E 111110 gt (greater than)

63 77 03F 111111 (question mark)

64 100 40 1000000 (AT symbol)

65 101 41 1000001 A

66 102 42 1000010 B

67 103 43 1000011 C

68 104 44 1000100 D

69 105 45 1000101 E

70 106 46 1000110 F

165

Decimal Octal Hexadecimal Binary Value Meaning

71 107 47 1000111 G

72 110 48 1001000 H

73 111 49 1001001 I

74 112 04A 1001010 J

75 113 04B 1001011 K

76 114 04C 1001100 L

77 115 04D 1001101 M

78 116 04E 1001110 N

79 117 04F 1001111 O

80 120 50 1010000 P

81 121 51 1010001 Q

82 122 52 1010010 R

83 123 53 1010011 S

84 124 54 1010100 T

85 125 55 1010101 U

86 126 56 1010110 V

87 127 57 1010111 W

88 130 58 1011000 X

166

Decimal Octal Hexadecimal Binary Value Meaning

89 131 59 1011001 Y

90 132 05A 1011010 Z

91 133 05B 1011011 [ (leftopening bracket)

92 134 05C 1011100 (back slash)

93 135 05D 1011101 ] (rightclosing bracket)

94 136 05E 1011110 ^ (caretcirumflex)

95 137 05F 1011111 _ (underscore)

96 140 60 1100000 `

97 141 61 1100001 a

98 142 62 1100010 b

99 143 63 1100011 c

100 144 64 1100100 d

101 145 65 1100101 e

102 146 66 1100110 f

103 147 67 1100111 g

104 150 68 1101000 h

105 151 69 1101001 i

106 152 06A 1101010 j

167

Decimal Octal Hexadecimal Binary Value Meaning

107 153 06B 1101011 k

108 154 06C 1101100 l

109 155 06D 1101101 m

110 156 06E 1101110 n

111 157 06F 1101111 o

112 160 70 1110000 p

113 161 71 1110001 q

114 162 72 1110010 r

115 163 73 1110011 s

116 164 74 1110100 t

117 165 75 1110101 u

118 166 76 1110110 v

119 167 77 1110111 w

120 170 78 1111000 x

121 171 79 1111001 y

122 172 07A 1111010 z

123 173 07B 1111011 (leftopening brace)

124 174 07C 1111100 | (vertical bar)

168

Decimal Octal Hexadecimal Binary Value Meaning

125 175 07D 1111101 (rightclosing brace)

126 176 07E 1111110 ~ (tilde)

127 177 07F 1111111 DEL (delete)

Table 20 ndash Full ASCII Table

169

Handy IDE Settings

Line Numbers onoff Tools | Options | Text Editor | CC++ | Line Numbers

Auto closing the console Tools | Options | Debugging | Automatically close the console window when debugging stops

Saves having to use system(pause)

170

REMAINING PAGES LEFT BLANK FOR NOTE TAKING

171

172

173

Peet Morris

peetmorrisgmailcom

C++ A Comprehensive Introduction

Arrangements

bull We Startfinish at 915am 500pm

bull Format two lectures per day (ask questions) hands-on at all other times

bull You should have Course book (copy of the slides at the back)

bull The course software is pre-installed on the machines

And also separately available from

The compilerIDE wwwvisualstudiocom

Notesslidesexercise files wwwpeetmcomC++introcoursezip

Your safety is important

Where is the fire exit

Beware of hazards

Tripping over bags and coats

Please tell us if anything does not work

Let us know if you have any other concerns

Your comfort is important

The toilets are along the corridor just outside the teaching rooms

The rest area is where you registered it has vending machines and

a water cooler

The seats are adjustable

You can adjust the monitors for brightness

What we assumehellip

What we assume

Experience of using another programming

language

Comprehensive Lots to get through

C++ and OOP

bull Created in 1985 by Bjarne Stroustrup C++ is a highly efficient

multiplatform low level Object Oriented Programming language

bull Latest version is C++17

stroustrupcom

Standard C++ Library

bull Written in the core language it is a collection of classes

(object definitions) functions and algorithms

See wwwcpluspluscomreference

IDEs amp Compilers

Visual Studio 2017

First Program

First application

include ltiostreamgt

using namespace std

int main()

int aNum = 0 aNum(0) or aNum0

cout ltlt Enter a number-

cin gtgt aNum

cout ltlt You entered ltlt aNum

return 0

hellip hellip

First Program

bull include ltiostreamgt

Adds the contents of the iostream header file into the program (for cout and cin)

bull using namespace std

So we donrsquot have to write stdcout ltlt and stdcin gtgt all of the time

bull cin is the standard input stream object that allows input from the keyboard

bull cout is the standard output stream object that allows output to the screen

bull int main() The programs entry point

Mandatory main function in every C++ program ndash always returns an integer value

First Program

bull int aNum = 0

Variable to hold a value of type integer (piece of machine memory referred to via the name aNum)

bull ltlt stream insertion operator ndash outputs to console

cout ltlt Enter a number-

bull gtgt stream extraction operator ndash waits for keyboard input

cin gtgt aNum

Other Types

Microsoft data types summary httpsdocsmicrosoftcomen-gbcppcppfundamental-types-cpp

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststack

Lots

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

x 1

y 2

x 3

y 4

p1

p2

x

y

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 copies the bit pattern from p1 to p2

x 1

y 2

x 1

y 2

p1

p2

Compound Types

Cannot define operators other than assignment

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 p2 compilation error

x 1

y 2

x 3

y 4

p1

p2

Compound Types

We can arbitrarily further compound things

struct point

int xint y

struct rectangle

point tlpoint br

struct line

point startpoint end

startxy

endxy tlxy

brxy

Compound Types

We can also group things using struct to create compound

types

struct point

int xint y

struct rectangle

point tlpoint br

int main()

rectangle r

rtlx = 1rtly = 2

rbrx = 3rbry = 4

int diff_x = abs(rtopLeftx - rbottomRightx)int diff_y = abs(rtopLefty - rbottomRighty)

cout ltlt area ltlt diff_x diff_y ltlt endl

r

tl

br

x 1

y 2

x 3

y 4

Using a Library Type

include ltstringgt

string s

cout ltlt What is your name

getline(cin s)

cout ltlt s ltlt

ltlt is

ltlt slength() ltlt

ltlt characters long ltlt endl

s

Other Types

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststackcomplex

Lots

8 bit Binary signed unsigned

00000001 1 1

00000010 2 2

00000011 3 3

01111111 127 127

10000000 -128 128

10000001 -127 129

10000010 -126 130

11111101 -3 253

11111110 -2 254

11111111 -1 255

00000000 0 0

00000001 1 1

00000010 2 2

signed vs unsigned ndash its all just 1s and 0s and adding

Adding rules

0 + 0 = 0

1 + 0 = 1

0 + 1 = 1

1 + 1 = 0 (carry 1)

1 + 1 + 1 = 1 (carry 1)

-126 + +3 =

10000010

00000011 +

10000101 = -123

-126 + -3

10000010

11111101 +

01111111 = 127 (why not -129)

Arithmetic Operators

+ Addition

- Subtraction and unary minus

Multiplication

Division

Remainder after division (moduloclock arithmetic)

int j k l = 10

j = l 3 js value will be three

k = l 3 ks value will be 1

Relational Operators

Evaluate to either true or false represented by integer values 1 and 0

== Equal to

= Not equal to

gt Greater than

lt Less than

gt= Greater than or equal to

lt= Less than or equal to

Increment and Decrement Operators

++ Increment

-- Decrement

Can be prefix or postfix

b = 3

a = b++ + 6 Add 6 to b then increment b a is 9 b is 4

b = 3

a = ++b + 6 Increment b then add 6 to b a is 10 b is 4

Assignment Operators

Symbol Operation Long Short

= Assign a = 2 a = 2

+= Assign with add a = a + 2 a += 2

-= Assign with subtract a = a ndash 2 a -= 2

= Assign with multiply a = a 2 a = 2

= Assign with divide a = a 2 a = 2

= Assign with remainder a = a 2 a = 2

Basic Control Flow - if

Sequence

What we have been doing already

Selection

if statement if this then that

if (boolean expression) if (score gt= 50)

statement cout ltlt Passed

Logical Operators

Boolean expressions may be combined using

ampamp And

|| Or

Not

Operands and result resolves being either true or false

if (x ampamp (y || z))

else

Precedence and Associativity table in course book

Logical Operators

a b =

true true true

true false false

false true false

false false false

a b =

true true true

true false true

false true true

false false false

a =

true false

false true

a ampamp b a || b a

Logical Operators

if (x ampamp (y || z))

else

The value 0 (zero) is evaluated to mean false any other value is true

x ampamp (y || z) result

false ampamp (false || false) falsefalse ampamp (false || true ) falsefalse ampamp (true || false) falsefalse ampamp (true || true ) falsetrue ampamp (false || true ) falsetrue ampamp (false || false) truetrue ampamp (true || false) truetrue ampamp (true || true ) true

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp (y | ~z))

else

Bitwise Operators

unsigned int x = 11

unsigned int y = 7

unsigned int z = 25

if (x amp (y | ~z))

else

11 (x) = 000010117 (y) = 0000011125 (z) = 00011001

~z = 11100110 (230 or -26)

y | ~z = 11100111 (231 or -25)

x amp (y | ~z) = 00000011 = 3

Operands and the result resolve to a values

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp 1) x is odd

if (x gt y)

x = x ^ y

y = y ^ x XOr swap

x = x ^ y

Control Flow - if else

Selection

ifelse statements

if (boolean exp) if (score gt= 50)

statement cout ltlt Passed

else else

statement cout ltlt Failed

Control Flow -

Selection

Conditional (or Ternary) Operator

boolean exp true result false result

cout ltlt score gt= 50 Passed Failed

Control Flow

if (x gt= y)

if (y 2)

else

if (x gt= y)

if (y 2)

else

Control Flow ndash else if

if (exp)

else if (exp)

else if (exp)

else catch all remaining

if (aNum == 0)

else if (aNum == 1 || aNum == 2)

else if (aNum == 3)

else catch all remaining

aNum not 0123

Control Flow - switch

Selection

switch multiple selection statements

bull test must be an integral value 1 10 A x eg not 1056

bull case values must be constants

switch (aNum)

case 0

break

case 1 Fall through

case 2

break

default catch all

break

Repetition - while

while (exp)

statements

while (n lt k)

cout ltlt Enter mark

cin gtgt mark

t += mark

n++

Repetition - for

for (init exp inc)

statements

for (t = 0 n lt k n++)

cout ltlt Enter mark

cin gtgt mark

t += mark

Preferable to while if the range is known

Repetition - for

for (init exp inc)

statements

for () infinite loop

break causes loop to exit

Preferable to while if the range is known

Repetition - do

do

statements

while (exp)

do

cout ltlt Continue yn

cin gtgt yn

yn = tolower(yn)

while (yn = y ampamp yn = n)

There are a huge number of exercises and we donrsquot expect you to attempt

them all during this course

bull If yoursquore completely new to programming itrsquos probably best to tackle

them in sequence

bull If yoursquove some programming experience you should read through the

exercise summaries and then start wherever you feel comfortable

Exercises

Exercises

Topics covered in ex1 ndash ex6

Functions = mini programs

bull Used to combine data with operations and through functional

decomposition to promote code re-use

bull Simplifies coding

bull Functions for discrete tasks

bull Not hundreds of lines of code

bull Consumer only needs to know

bull What goes in and what comes out

Functions

Like everything else the compiler needs to have seen a prototype or a

definition of a function before we can use it

Prototypes lets the compiler generate the correct code

int min(int int)

int min(int int int)

void drawLine(point to point from = 00)

int square(int)

int main()

void beep()

string getNextPacket(void)

Return type Function name (Parameter list)

min

int min(int int) min prototypes (forward declarations)int min(int int int)

int main()

Having seen the prototypes the compilerc = min(x y) can generate the required code

int min (int a int b) min function definition 1

return a lt b a b

int min (int a int b int c) min function definition 2

return min(min(a b) c)

inline min

int main()

c = min(x y)

inline int min (int a int b)

return a lt b a b

int main()

c = x lt y x y

inline int min (int a int b)

return a lt b a b

Function Parameters

bull Pass by Value

bull A Copy of the parameter is passed to the called function

bull Pass by Reference

bull The actual parameter is passed to the called function

bull Pass by Memory Address (pointer)

bull Same effect as Pass by Reference (tomorrow)

Pass by value

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

return n_copy n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 10

n_copy 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp x)

x just another name for real_n

return x x

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

x 10

Pass by value (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

n_copy = n_copy n_copy

return n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 100

n_copy 100

Pass by reference (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

real_n = real_n real_n

return real_n

100

100

Mem Addr Contents

0x2786 100

real_n 100

Mem Addr Contents

0x2786 100

real_n 100

const Parameters

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Recursion

unsigned long long int fibonacci(int n)

switch(n)

case 0 Fall through - [[fallthrough]]

case 1

return n

break

default

return fibonacci(n - 1) + fibonacci(n - 2) Very inefficient

Arrays (Part 1)

Data structure containing same type of data (int double string char object)

bull Built in to C++

bull Series of elements each containing one item of data (contiguous memory locations)

Size (number of elements) set at compile time

Arrays (1)

int numbers[10] an array of 10 integers Each box sizeof(int) bytes wide

numbers

index values - 0 to 9

0 1 2 3 4 5 6 7 8 9

Arrays (1)

int numbers[10] an array of 10 integers

int n = 0

cout ltlt numbers ltlt endl address of the first element

cout ltlt numbers[n] ltlt endl contents of the nth element

cout ltlt ampnumbers[n] ltlt endl address of the nth element

cout ltlt numbers + n ltlt endl address of the nth element

0 1 2 3 4 5 6 7 8 9

42 hellip hellip hellip hellip hellip hellip hellip hellip hellip

0x1526

Arrays

char name[5] name - an array of five characters

thing t[5] t - an array of five things

examMarks ndash an array of three doubles initialised to 12 39 95double examMarks[] = 12 39 95 C++11 - double examMarks[] 12 39 95

header ndash an array of fifty unsigned chars (bytes) first three elements set to 0 1 255 and the rest to zerotypedef unsigned char bytebyte header[50] = 0 1 -1

Arrays

Accessing array data

define MARKS 5 or const int MARKS = 5

double examMarks[MARKS]

for(int i = 0 i lt MARKS i++)

cout ltlt Enter Exam Mark

ltlt i + 1 ltlt

cin gtgt examMarks[i]

for(i = 0 i lt MARKS i++)

cout ltlt examMarks[i]

Multidimensional Arrays

Two dimensional array Two subscripts First identifies row second identifies column

const int students = 6 const int marks = 3

double examMarks[students][marks] = 0 set to zero

for (int s = 0 s lt students ++s)

for (int m = 0 m lt marks ++m)

cout ltlt Enter mark ltlt m + 1 ltlt for student ltlt s + 1 ltlt endl

cin gtgt examMarks[s][m]

00 01 02

10 11 12

20 21 22

30 31 32

40 41 42

50 51 52

Memory laid out in row column order (more later)

00 01 02 10 11 12 20 21 22 30 31 32 40 41 42 50 51 52

Matrices

Provider Link

Armadillo armasourceforgenet

Blitz blitzsourceforgenet

Boost boostorg

Eigen eigentuxfamilyorg

Elemental libelementalorg

FLENS apfelmathematikuni-ulmde

HSL hslrlacuk

LEDA algorithmic-solutionscom

PETSc mcsanlgov

SimuNova simunovacom

SuiteSparse facultycsetamuedu

TNT mathnistgov

Trilinos trilinosorg

ViennaCL viennaclsourceforgenet

Exercises

Topics covered in ex7 ndash ex16

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people and dice

Recap Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

1 61 61 61 61 6

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

3 11 24 56 12 3

C++ and OOP

Encapsulation Keeping related stuff together

Member functionsmethods

an objectrsquos capabilities functionality and performable actions

int Throw()

Member variablesproperties

an objectrsquos current state values its dumb data

int sides

Dice throwing 3

struct dice

int sides State

dice(int n) Constructor

sides = n

int Throw() Member function (method)

return (rand() sides) + 1

int main()

Could also use dice d1 = 6 or d16 syntaxdice d1(6) d2(6)

d1sides = 6 d2sides = 10 Allow this

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

struct diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

class diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing ndash professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

diceh my-appcpp

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

dicecpp

Compiler

diceobj my-appobj

Linker

my-appexe

other librarycode objectfiles

Dice throwing - professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Compiler

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

diceobj my-appobj

diceh dicecpp my-appcpp

Linker

my-appexe

other librarycode objectfiles

Only items provided to the end-usercustomer

Classes and Objects

the includeltstringgt header file from the standard library

class string

your cpp source code files

include ltstringgt include information about class string

string Name a class string instance

string Address a class string instance

Classes and Objects

the include carh header file

class car

your cpp source code files

include carh include information about class car

car c a class car instance

Classes and Objects

the include househpp header file

class house

your cpp source code files

include househpp include information about class house

house no1 a class house instance

house no2 a class house instance

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do with it

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

cstart()

cenginestart() Or should cstart() internally use enginestart()

OOD

Time for a break

class student

What properties and methods do we need

class student

public

string name

string DoB

string college

string bodCardNumber

float age()

int main()

student s

sname =

sDoB =

How to guarantee an objectrsquos integrity

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s

sname = Compilation errors

sDoB =

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s( )

cout ltlt sage()

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB Error ndash cant assign to a constant

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_name(name) m_DoB(DoB)

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_namename m_DoBDoB

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Exceptions

class student

int main()

try

student s( )

catch(const char msg)

cout ltlt msg ltlt endl

student initialisation failed

Exceptions

try

catch(const char msg)

cout ltlt msg ltlt endl

catch (const invalid_argument amp e)

cout ltlt ewhat() ltlt endl

catch (exception amp e)

cout ltlt ewhat() ltlt endl

catch ()

cout ltlt Something went wrong ltlt endl

student invalid arg 2

if using C++11 see stdcurrent_exception

Reuse and inheritance

Say we now want to add a new type to our system ndash class academic With what we have seen so far we would proceed something like this

class academic

private

string m_name string m_DoB

Duplicating everything we had in class student

class person (generalisation)

OOP is sometimes called Programming by Describing the differences

student and academic are all specialisations of a more generalised and abstract class ndash person

class student public personpublic

student(string name) person(name)

class academic public personpublic

academic(string name) person(name)

class personprotected

person(string name) m_name(name)

private

string m_name

public

base class derived class

derived class

Specialised State

class student public person

private

const string m_bodCard

public

student(string name string DoB string bc ) person(name DoB) m_bodCard(bc)

Multiple inheritance

class student public person public oxMember

public

student(string name int age string bc) person(name age) oxMember(bc)

class academic public person public oxMember

public

academic(string name int age string bc) person(name age) oxMember(bc)

Destructors

class foo

private

int m_x int m_y

public

foo() foo(0 0)

foo(int x) foo(x 0)

foo(int x int y) m_x(x) m_y(y) only ctor that accesses private state

~foo() any necessary tidy up code

Dice throwing 5

class diceprivate

int sides

public

dice(int n) sides(n)

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

srand((unsigned)time(0)) Happy with this

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 6

class diceprivate

int sides

public

dice(int n) sides(n)

classshared state static bool seeded = false

if (seeded)srand((unsigned)time(0))seeded = true

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

3 65 21 44 22 6

Dice throwing 7

class dice private

int sides

public

dice(int n) sides(n)

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

Dice throwing 7

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyesDouble 14 33 5

Dice throwing 8

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6) int t

for(int n = 0 n lt 5 ++n)

cout ltlt (t = d1Throw()) ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp t = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Dice throwing 9

class dice private

int sidesint _lastThrow

public

const int amp lastThrow read-only stateproperty

dice(int n) _lastThrow(-1) lastThrow(_lastThrow) sides(n)

int Throw()

return _lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp d1lastThrow = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Exercises

Topics covered in ex17 ndash ex22

Vectors

Like an array a data structure containing same type of data (int double object)

bull A container class part of the standard library a wrapper similar to arrays

Need to includeltvectorgt

bull Can resize grow shrink as elements are added or removed from the end

bull Algorithms to manipulate data

bull Iterators to cycle through all the elements

Vectors

vectorltchargt name(5) vector of five characters

vectorltthinggt t(5) vector of five things

vectorltdoublegt examMarks 12 39 95 initialised vector of three doubles

typedef unsigned char byte

a vector of fifty bytes first three elements set to 0 1 255 and the rest to zerobyte char b[50] = 0 1 255 fully populate array

calc itemCountint itemCount = sizeof(b) sizeof(b[0])

vectorltbytegt bytes (b ampb[0] + itemCount) then init with vector 50 items

Vectors (iteration 1)

include ltvectorgt

vectorltintgt vec(20) 20 ints

for(int i = 0 i lt vecsize() i++) input values into vec

cin gtgt vec[i]

for(i = 0 i lt vecsize() i++) output vec

cout ltlt vec[i] ltlt

Vectors (iteration 2) (C++11 and later)

for(type identifier container)

statements

vectorltintgt vec(20)

for (int amp i vec)

Vectors

Adding an extra element

cout ltlt Enter an Extra Value

cin gtgt aNum

vecpush_back(aNum)

for (int i = 0 i lt vecsize() i++)

cout ltlt vec[i] ltlt endl

cout ltlt vecat(i) ltlt endl same as above but range checked (ie slowsafe)

Vectors (most of the methods)

docsmicrosoftcomen-uscppstandard-libraryvector-classFull list

Method Purpose

assign Erases a vector and copies the specified elements to the empty vector

at Returns a reference to the element at a specified location in the vector

back Returns a reference to the last element of the vector

begin Returns a random-access iterator to the first element in the vector

capacity Returns the number of elements that the vector could contain without allocating more storage

clear Erases the elements of the vector

C++11 data Returns a pointer to the first element in the vector

C++11 emplace Inserts an element constructed in place into the vector at a specified position

C++11 emplace_back Adds an element constructed in place to the end of the vector

empty Tests if the vector container is empty

end Returns a random-access iterator that points to the end of the vector

erase Removes an element or a range of elements in a vector from specified positions

front Returns a reference to the first element in a vector

insert Inserts an element or a number of elements into the vector at a specified position

max_size Returns the maximum length of the vector

pop_back Deletes the element at the end of the vector

push_back Add an element to the end of the vector

rbegin Returns an iterator to the first element in a reversed vector

rend Returns an iterator to the end of a reversed vector

reserve Reserves a minimum length of storage for a vector object

resize Specifies a new size for a vector

C++11 shrink_to_fit Discards excess capacity

size Returns the number of elements in the vector

swap Exchanges the elements of two vectors

Vectors (iteration 3)

include ltalgorithmgt

vectorltintgt vec

for(int i = 1 i lt= 5 ++i)vecpush_back(i)

1 2 3 4 5

5 4 3 2 1

vectorltintgtiterator it

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Reverse the vectorreverse(vecbegin() vecend())

cout ltlt endl

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Arrays (2) (C++11 and later)

arrayltint 5gt arr Thin veneer over an array ndash so requires fixed size

arrfill(0) int j = 0

for (int amp i arr)

supports latest iteration style

reverse(arrbegin() arrend()) and iterators for use with algorithms

C++11 - Uniform initialisers

C++98

complexltdoublegt c( 271828 314159 )

int a[] = 1 2 3 4

vectorltintgt v

for( int i = 1 i lt= 4 ++i )

vpush_back(i)

C++11

complexltdoublegt c 271828 314159

int a[] 1 2 3 4

vectorltintgt v 1 2 3 4

Pointers ndash What

A pointer is a scalar variable that is used to hold the memory-address of

another variable or function the stored address is said to point to the thing

it holds ndash thus the name

Pointers have a type ndash the type of the thing they point to

int n = 10I (p) am a pointer to an integer and I point to n over thereint p = ampn

Pointers ndash Why

In no particular order

bull Because external libraries and APIs (like the operating system (all of them)) are written using them

bull Create custom data structures like linked-lists trees graphs etc

bull Create tables of functions or single functions for handling events callback or signals

bull Access data on to the heap (allocate memory dynamically)

bull Writecall functions that change their input parameters

1 2

3

4 5 6 nilhead

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

Recap - Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference using Pointers

int main()

int real_n = 10

cout ltlt square(ampreal_n)

cout ltlt real_n

return 0

int square(const int real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x5110 0x2786

real_n 0x2786

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt pcout ltlt pcout ltlt ampxcout ltlt xcout ltlt ampp

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

15438

11

15438

11

17216

Pointers

int main(int argc char argv)

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )(argv + n) ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv + 0 C

argv + 1

argv + 2

argv + 3

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

int main(int argc char argv[])

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )argv[n] ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv[0] C

argv[1]

argv[2]

argv[3]

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

Memory Stack vs Heap

Stack (last in first out - LIFO)

Space automatically allocated

The place where arguments of a function call are stored

The place where local function data is allocated (eg variables)

The place where a function leaves its result (if any)

Heap

Space must be explicitly allocated

A place for allocating memory that is not part of last-in first-out approach

ie dynamically allocated data structures that survive function calls

Stack vs Heap

int stackArray[100] Allocate 100 ints on the stack

stackArray[n] = 0 Do something with it

int heapArray = new int[100] 100 ints on the heap C++

int heapArray = malloc(100 sizeof(int)) 100 ints on the heap C

heapArray[n] = 0 Or (heapArray + n) = 0 Do something with it C++ and C

delete [] heapArray When youre done C++

free(heapArray) When youre done C

Exercises

Topics covered in ex22 onwards

If time allows look through the remaining

exercises and attempt those that fit best

with your requirements

  • C++ Notes TPLO 12-11-2019 Blackbox
  • C++ Slides TPLO 12-11-2019 - Copy

Contents

1 Introduction 1

11 What you should already know 1

12 What you will learn 1

13 Where can I get a copy of the softwaretools used 1

2 Things to understand 1

21 Compilers new and old 1

22 The C++ Standard Template Library (STL) 2

23 Visual Studio 2019 3

Creating your first program in Visual Studio 2019 6

Explanation 10

Your projects default code template 13

Arithmetic Operators 15

Characters 16

Header (include) Files 17

Strings 18

The LF (Line Feed) Problem and Reading Keys 20

Casts 22

Other Cast Types 24

3 Basic Control Flow 28

Selection - ifhellipelse statement 28

Selection - switch multiple selection statement 30

Repetition ndash while dohellipwhile and for loops 30

4 Logical and Bitwise Operators 35

41 Logical 35

42 Bitwise 37

Shifts 38

XOr 38

5 Introduction to Functions 39

Creating a function 41

52 Algorithms 49

Functions and Pass by Reference 51

Returning values from functions 53

Side effects 55

6 Classes and Objects 64

Creating your first class 65

Member functions and Passing parameters 67

Data Members 68

Constructors 70

Separating use from declaration and definition 72

Destructors 81

7 Arrays vectors lists and hash-tables 82

Declaring and using arrays 83

Searching Arrays with Linear Search 87

Sorting Arrays with Insertion Sort 90

Multidimensional Arrays 94

Declaring and using vectors 99

stdarray 105

Declaring and using lists 106

72 Hash Tables and Cached Calculations 107

Hash Tables 108

8 Pointers 112

Initialising pointers 113

Pointer Arithmetic and Arrays 115

9 APIs New Delete and Dynamic Memory 124

Using an API 124

Dynamic Memory Management 125

10 More on Functions 125

Multiple arguments overloading and default values 129

Passing Arrays to Functions 132

Passing Two-dimensional Arrays to Functions 135

11 Inheritance and (not presented) Polymorphism 135

111 Inheritance 135

Modelling a student - a first attempt 137

112 Polymorphism 143

12 Appendices 147

Arithmetical Operators 147

Assignment Operators 147

Assignment and Arithmetic examples 148

Relational and Equality Operators 148

Logical Operators 149

Precedence and Associativity Table 150

Escape Sequences 151

Cast Operator 152

Formatted Output 152

Header Files 153

Matrix Libraries 153

Scope 154

Enumerating constants 154

Constants 154

Vector member functions 155

Global functions 155

list member functions 156

cmath functions 156

String class 158

ASCII Character set 161

Handy IDE Settings 169

Exercises

Exercise 1 (Optional) Creating a first and default program 6

Exercise 2 CreatingModifying additional projects 26

Exercise 3 SearchString 29

Puzzled Programmers 29

The Collatz Conjecture 31

Mixing loops 33

PLUSPLUS Recursion 34

PLUSPLUS Base Two and Bits 37

Practising with Logical and Bitwise operators 38

Writing functions 42

Using a struct 43

PLUSPLUS When Things Go Wrong 44

The Monty Hall problem 46

More Functions 48

PLUSPLUS IsLeap in a line 49

Algorithms 49

Pass arguments by reference 52

Returning a value from a function 57

PLUSPLUS Arithmetic Bases 58

Searching for Sequences 61

PLUSPLUS Optimising Searching for Sequences 63

Evolving Searching for Sequences 64

Creating a class 65

Passing parameters 67

Using data members 69

More Objects 70

Using constructors 71

Separating declaration and definition 74

PLUSPLUS Using external libraries and third party header files 78

Creating an array to hold exam results 84

Linear Search 87

PLUSPLUS Debugging Linear Search 89

SortingSearching an array 90

PLUSPLUS Binary Search (Binary Chop) 93

Creating a multidimensional array 95

Creating a vector to hold exam results 100

Using insert() and iterators 103

Computing Fibonacci Numbers 110

Using pointers 114

Pointers and Arrays 116

PLUSPLUS Pointers and Arrays 119

PLUSPLUS Function pointers 122

main() and command-line arguments 126

EncryptDecrypt a file 128

Passing Arrays to functions 132

Base classes 137

PLUSPLUS Polymorphism 144

The PowerPoint slides entitled Exercises show the inclusive fromto exercise numbers which cover the topics discussed in the previous section It is not at all necessary to attempt to work through the entire quoted range variety is the spice of life ndash just choose those that appeal

1

1 Introduction Welcome to C++ A Comprehensive Introduction

These notes accompany the course delivered by Oxfords IT Services IT Learning Programme

If at any time you are not clear about any aspect of the course please make sure you ask your lecturer or demonstrator for some help If you are away from the class you can get help by email from your lecturer or from helpitoxacuk

Please also note that the university subscribes to Lyndacom ndash please check there for other C++ resources

11 What you should already know

The prerequisite for this course says that Either experience in another programming language or attendance on one of the PHP JavaScript or Python Kick-Start courses Is required

The more programming knowledge you have the better That said the documentation and lectures are structured such that those with very little knowledge should still be able to work through the course at their own pace

12 What you will learn

We will cover the following topics

Working with Microsofts Visual Studio Fundamental data types

Control Flow amp Iteration Header Files

Strings Functions

Arrays and Vectors Classes and Objects

Constructors and Destructors Member functions

Pointers And much more

13 Where can I get a copy of the softwaretools used

wwwvisualstudiocom (Microsofts C++ Compiler IDE and tools)

wwwpeetmcomC++introcoursezip (latest course code notes slides etc)

2 Things to understand

21 Compilers new and old

Students on this course often have to work with enhance or bug-fix existing code This sub-section is primarily for their consideration (it assumes some prior C++ knowledge)

2

Not all C++ compilers comply with the latest official ISO C++ standard (C++17) which was finally approved in December 20171

What does this mean It means that the code you write compile and run on one machine may not compile on the next machine if you are using a different compiler (even if it is using the same operating system) In this course you will be using Microsofts C++ Compiler (part of Visual Studio 2019)

Some older header files you may see with inherited C++ code are

include ltiostreamhgt have a h extension The C++ standard for this header file is include ltiostreamgt Your program may run correctly by adding a h but simply adding a h suffix will not work for all included files

include ltstringhgt has been replaced with include ltstringgt The stringh header file does not include C++ strings it includes C strings

include ltmathhgt has been replaced with include ltmathgt

The lesson to be learnt here is that a lot of C++ code you come across will have been created using older compilers Some of the header file and other code will not be recognised and may cause compilation errors when compiled on a machine which is more compliant with the C++ standard

If you are using the Gnu Compiler Collection (gcc g++ etc) you can specify standards compliancy via the ndashstd option eg -std=c++17 (other options are C++98

C++11 C++14)

Visual Studio can also be configured to use LLVM and clang Please see the relevant online documentation of how to install and use these if you wish to use them httpsllvmorgdocsGettingStartedVShtml

22 The C++ Standard Template Library (STL)

enwikipediaorgwikiStandard_Template_Library

The C++ programs you write will consist of the classes and functions that you write or modify (we provide partial solutions to every exercise)

However we will also look at what is still commonly referred to as the STL (now just part of the C++ Standard Library ) which holds a collection of existing classes functions and algorithms that you can use in the programs you will be creating

Some of the classes and template classes we will be looking at are

The string class The vector container template

The sort algorithm The list container template

The find algorithm

In addition you should also look at and be aware of another powerful library called Boost (parts of the STL come directly from the Boost library) wwwboostorg

The Boost library is easy to install (on any platform) as most Boost libraries are what is called header-only ie they consist entirely of header files containing templates and inline

1 A draft of this is included with your course files (n4660pdf) Its worth mentioning that this draft is in effect the published C++17 standard

3

functions and require no separately-compiled library binaries or special treatment when linking

23 Visual Studio 2019

What is Visual Studio (VS) VS is Microsofts freely available integrated development environment (IDE) and comes complete with optional compilerstools for a variety of languages We have only installed the IDE and the C++ compi ler (clexe etc) for this course

So what is a compiler

A compiler is a computer program that allows us to write programs in some specially defined language (unfortunately not English yet) in our case C++ (a so called high- level

language ) As you heard earlier the tex t we write in C++ is called source-code it is just simple text that one could write in Notepadexe for example

Sadly source-code is not directly understood by operat ing systems such as Windows Linux and macOS etc and it is the compilers job to convert our source-code into the terse concise and highly optimised machine-code that computers understand directly

Machine-code is often called executable or object-code and the compiled version of the source code is really just a file that contains numbers ndash a series of 8-bit bytes each holding a value between 0 and 255 The numbers either encode l ow-level instruct ions (code) or data that working together define the program Because these numbers may not encode displayable characters (see the ASCII table in the appendices to see a mapping between the numbers and the displayable characters) opening such a file an exe file in something like Windows notepad application would result in something like this being displayed (just the beginning shown)

However if we open this same executable file in a program that simply displays the files content as numbers and not what characters if any are represented by those numbers as Notepad is doing) we see this (the numbers are shown in base-16 or hexadecimal format)

4

The first two numbers 4D and 5A can be displayed as the text M and Z2 (see the first two characters at the top left in the previous notepad view of this file) 4D in base 10 is 77 and 5A is 90 ie the ASCII values for M amp Z (you can look these up in the ASCII table in the back of your course book)

Also take note of the line sequence starting 55 8B EC Then read on

2 MZ (0x4D5A) at the beginning of a file is an example of whats known as a magic number these are often used to identify a file type ndash in this case an MS-DOS executable file Trivia MZ are the initials of Mark Zbikowski the designer of the MS-DOS executable file format

5

If we have Visual Studio we can open the same file to see how such numbers translate into instructions and data

55 8B EC is the real beginning of our program In the above we see the numbers on the left and on the right what they actually mean Eg the first number 55 means push ebp which is an Intel CPU instruction Likewise 8B and EC together mean mov ebp esp The next line 81 EC C0 00 00 00 combines instructions and data and translate into sub esp 0C0h (subtract from esp the value C0 or 192 in base-10)

This is the entire program really the extra data shown in the previous views are for housekeeping

What does this program actually do then

Well youre about to find out ndash youre optionally now going to recreate it in Exercise 1

6

Creating your first program in Visual Studio 2019

Exercise 1 (Optional) Creating a first and default program

IMPORTANT

This exercise starts with a walk-through of using Visual Studio to create a new solution which you then go on to modify You should have already seen the steps needed to create a new solution in class so if youd rather just get on with the modification part simply open the (exercise solut ion)

f i rs t folder (in the Course folder) and double click the f i rs t s ln file If you choose to do this you can skip over the next few pages to the Explanation section (232) or even jump further on to Task 1 on page 14

Note You will not need to create any completely new programs during the course so even if you didnt fully follow the steps you can still safely move on to the modification part However if you really want to walk it through for yourself

Start the Visual Studio 2019 Integrated Development Environment (IDE) and create a new C++ Console application project You should have a shortcut to Visual Studio on your desktop failing that look for it on the Start menu

If they appear follow the prompts as shown below (if youre asked about keyboard mappings or Develop options select the C++ option)

7

Click Create a new project

Select Console App and click Next

8

Well locate the first project in a folder called first in your C drives Temp folder If the folder doesnt exist it will be created for you Click Create

Something like the above should appear (if you dont see the Solution Explorer panel open it via the View menu)

9

Alter the code adding the lines in bold as show here

include ltiostreamgt using namespace std int main() stdcout ltlt Hello Worldn system(pause)

Build and run the project by pressing the green arrow or by pressing F5

10

Explanation

Disclaimer at this stage you do not need to fully follow all of this just now

include ltiostreamgt

iostream is a standard C++ library file Files of this type are called header files They are text files usually containing C++ declarations definitions and code

Including iostream allows us to use some pre-defined objects to output messages to a console window This file must be included for any program that outputs data to the screen - or inputs data from the keyboard for that matter

The C++ compiler operates in passes through our code In the first pass ndash called the pre-processing pass ndash include directives are processed which are really text-substitution directives To be precise what include ltiostreamgt says is ldquoGo and find the text file called iostream and replace the directive with the contents of that filerdquo

The file name following a include directive can be enclosed in double quotes or chevrons ie include iostream or include ltiostreamgt The meaning of each is defined by the implementation (Microsofts C++ compiler in our case)

However it is common practice that if file name is in quotes it will be looked for locally first - in the same folder as the cpp file containing it and before being sought elsewhere Conversely if it is in chevrons the compiler will usually look for the file in a central include folder that was installed with the compiler ndash this folder is usually reserved for include files that come with the compiler as opposed to those that you might write yourself eg standard includes (like iostream) We therefore usually use quotes when we want to include our own custom project specific include files and chevrons when wanting to use include files that come with the compiler

You may also see that the filename sometimes has a h file extension This typically means that the header file being used is a C language header file and not a C++ one There are other variations (you are welcome to use your own) for example you might also see the occasional hxx file extension or something else entirely

using namespace std

The using namespace std code above doesnt actually appear in the automatically generated code In our project and solution files we will add it just after any include directives

namespaces in summary are very simple Everything within a namespace has a unique name and so theyre often used to help divide larger projects into more manageable chunks and to avoid name clashes

Standard C++ places a lot of its routines and functionality within a namespace call std Wed like to use this functionality and so we say we want to use all of the std namespace In the real world this isnt terribly good practice

11

However by declaring that were using namespace std throughout we can access members of this namespace without having to say exactly where they are (in which namespace) or worry about name clashes - where two objects in different files have been given the same name

The members of std that we will be using throughout are

cin (Console In) and cout (Console Out) and we must use include ltiostreamgt in order to use them

endl - is a stream manipulator that writes a new line to output endl stands for end

of l ine and is pronounced end all

If we dont declare that we were using the std namespace (which is the case in the automatically generated code) we have to prefix any use of cin cout and endl with std eg stdcin stdcout stdendl If youve added the using namespace std directive you may now remove the std in front of the stdcout ltlt Hello Worldn line

int main()

This is the entry point to our program ndash every C++ program must have this same entry point defined main() is a function the body of a function is defined within the opening and closing braces that come after its name The int to the left of main() says that this function returns (or resolves to beevaluates to) an integer value Returning a value requires you to use a return statement However as it is normal practice to simply return the value zero if you omit the return statement a value of zero is returned for you (only where main is concerned) If you want to explicitly return the value yourself you could modify the code to read

int main() stdcout ltlt Hello Worldn system(pause) return 0

So why return a value anyway Our added line return 0 means in this case that our main doing whatever it does as part of its function eventually resolves to the value 0 The value is returned to whatever called our programs entry point in this case and as usually that is the operating system ndash which has been waiting for us to return a value at this point However the operating system will simply ignore whatever value we ultimately return Why do it then

12

Consider the case when one of your programs needs to run another program to perform a part of its entire function Your main program needs to start this other program and wait until it completes successfully before continuing See the description of the system(pause) code line below

stdcout ltlt Hello Worldn

cout is an object declared in iostream ndash think of its name meaning console out Anything sent to cout using the double chevron operator ltlt appears on the console the

The n in the text means that cout should also output a carriage-return linefeed sequence (terms taken from the days of typewriters and telex machines) basically it means start any new output on a newline underneath the current line An alternative to using n is to use endl eg stdcout ltlt Hello World ltlt endl endl does more or less the same thing as n

system(pause)

system() is a standard function that is used to run an external program (here thats a standard Windows program called pauseexe) The system() function waits for the pause program to complete before continuing Going back to the discussion on return 0 earlier this is an example of one program starting another ndash here thats our program starting the pause program The pause program returns a value as part of its completion and we can examine that if we want Programs usually return 0 for success or some other integer value that means something went wrong ndash the value returned indicates what went wrong Ie a returned value of say 42 might mean that we cant answer the ultimate question with this computer3

So what is pause pauseexe is a standard Windows program that simply outputs the message Press any key to continue and then waits for a key to be pressed before exiting We use that facility here so that our program doesnt simply shutdown and disappear as it falls off the end of main()s closing or encounters a return statement If we did allow it to exit we would hardly have time to examine our programs output before it disappeared off the screen Try that and see (comment out the line using a double-slash like this system(pause))

If you run any of the course code on Linux or a Mac youll need to change this line to something like cinget()

3 An unashamed reference to the Hitch Hikers Guide to the Galaxy and the Deep Thought computer

13

Your projects default code template

In the course exercises when it comes to you writing code we will always ask you to open and then modify a partially complete projectsolution so you wont have to fiddle with projects and boilerplate code like this again

Nevertheless should you wish to start from scratch or simply experiment with Visual Studio we recommend using the code below as a starting point

include ltiostreamgt using namespace std int main() Start coding after here system(pause) return 0

14

Task 1

Immediately above system(pause) Replace the stdcout ltlt Hello Worldn line with the code shown here

int anum = 0

cout ltlt Enter a number

cin gtgt anum

cout ltlt The number you entered is

ltlt anum

ltlt endl

Test your modified program Tip remember you may hit the F5 key to build and then run your program

Try entering some text instead of a number Did it work

Alter the spacing (use of spaces and tab characters) in your code ndash does the C++ compiler care about this so called whi tespace

The statement int anum = 0 defines a variable (a memory location) which we will refer to in our code as anum to store a number of type int to hold an in teger (ie 1 -4 27) The memory location is being initialised with a value of 0 here It is good practice to initialise variables when you define them In C++11 a new type of uniform initialisation syntax was introduced and also encouraged eg int anum 0

cout ltlt Enter a number cout is a name that belongs to the namespace std The ltlt is called the stream insert ion operator When the program executes the value to the right of the operator (Enter a number) is inserted in the output stream and ultimately output to console window

cin gtgt anum cin is the input stream object of the namespace std gtgt is called the stream extract ion operator and is used here to read a number from the keyboard

cout ltlt The number you entered is ltlt anum ltlt endl This statement concatenates the output by using multiple stream insertion operators ltlt endl is the stream manipulator that adds a new line

The next Exercise starts on page 26 The pages between here and page 26 contain

code that you may like to try out by further modifying this project if not just read through the textcode until you get to page 26

15

Arithmetic Operators

Most computer programs perform arithmetic calculations Table 1 summarises the standard C++ arithmetic operators When working with integer division where both the numerator and denominator are integer the expression 15 6 evaluates to 2 To get the remainder after integer division you would use the modulus operator Note the modulus operator can only be used with integer operands

To establish the complete result of the following integer division 156 requires two operations

15 6 = 2

15 6 = 3

The result being 2 remainder 3

C++ Operation C++

arithmetic operator

Algebraic expression C++ expression

Addition + y + 6 y + 6

Subtraction - a - b a - b

Multiplication c times d or cd c d

Division xy or y

x or yx x y

Modulus p mod q p q

Table 1 - C++ arithmetic operators

Other fundamental data types Table 2 shows how you would declare and initialise four other data types for use in programs (there are more data types available)

16

Data type Example

Float float aFloat = 1234

Double (the precision of a Float) double aDouble = 123456

Char char aChar = A

Bool bool aBoolean = true

Table 2 - C++ numerical types4

Characters

Characters are normally stored in variables of type char but can also be stored as in t(eger) data types Characters are represented as single byte integers in the computer so it is possible to output a character as an integer or as a character

All characters have a numerical representation in the computer and the ASCII (American Standard Code for Information Interchange) character set shows each character and its decimal equivalent (also note that a combination of characters may be used to form more complex Unicode characters) See appendix 111

Characters can be read in with the following statements

char aChar declares a variable (aChar) of type char

cin gtgt aChar this statement is used to read a character into the variable aChar

Note After entering a character the ltENTERgtkey must be pressed before the character is read by the program

The following four statements correctly declare a variable of type char output a user prompt then read a character and store it in the variable aChar

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar

4 See httpencppreferencecomwcpplanguagetypes for a complete list (or the official ISO standard of course)

17

Header (include) Files

So far weve seen that to use certain functionality we had to include ltiostreamgt We have to do similar to use other functionality which is not part of the code C++ language ie we will need to include anything that comes as part of the standard library

In its current form Visual Studio comes with the following include files (most of which are standard files)

h files (95 C language files)

agentsh agileh ammintrinh amph amprth amprt_exceptionsh amp_graphicsh amp_mathh amp_short_vectorsh armintrh arm_neonh cfguardh collectionh comdefh comdefsph comiph comutilh concrth concrtrmh ConcurrencySalh concurrent_priority_queueh concurrent_queueh concurrent_unordered_maph concurrent_unordered_seth concurrent_vectorh crtdefsh crtversionh delayimph dloadsuph dvech ehh emmintrinh excpth fvech gcrooth immintrinh internal_concurrent_hashh internal_split_ordered_listh intrinh intrin0h invkprxyh iso646h ivech limitsh mm3dnowh mmintrinh nmmintrinh omph pgobootrunh pmmintrinh pplh pplawaith pplcancellation_tokenh pplinterfaceh ppltasksh ppltaskschedulerh pplwinh rtcapih salh setjmph setjmpexh smmintrinh srvh stdargh stdboolh stdexcpth stdinth tmmintrinh typeinfoh use_ansih vadefsh varargsh vcclrh vccorlibh vcruntimeh vcruntime_exceptionh vcruntime_newh vcruntime_new_debugh vcruntime_startuph vcruntime_stringh vcruntime_typeinfoh wmmintrinh xatomich xatomic0h xkeycheckh xlocinfoh xmmintrinh xsmf_controlh xstring_inserth xtgmathh xxamph xxamp_inlh ymathh yvalsh zmmintrinh

115 C++ files

algorithm allocators any array atomic bitset cassert ccomplex cctype cerrno cfenv cfloat chrono cinttypes ciso646 cliext climits clocale cmath CodeAnalysis codecvt complex condition_variable csetjmp csignal cstdalign cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cuchar cvt cwchar cwctype deque exception experimental filesystem forward_list fstream functional future hash_map hash_set initializer_list iomanip ios iosfwd iostream istream iterator limits list locale Manifest

18

map memory msclr mutex new numeric optional ostream queue random ratio regex scoped_allocator set shared_mutex sstream stack stdexcept streambuf string string_view strstream system_error thr thread tuple typeindex typeinfo type_traits unordered_map unordered_set utility valarray variant vector xcomplex xfacet xfunctional xhash xiosbase xlocale xlocbuf xlocinfo xlocmes xlocmon xlocnum xloctime xmemory xmemory0 xstddef xstring xtr1common xtree xutility xxatomic

Strings

Next to numbers strings are the most commonly used data type in programming

A string is both a datatype (string) and also literal character data ie a sequence of characters such as Oxford or StAndrews In C++ string literals are enclosed in quotes The quotes are not part of the string they identify the data type as a string

Actually this isnt quite true the double quoted strings are a sequence of characters and are taken from the C programming language The things declared of the string type are C++ string objects ndash which may be initialised using the C language literal

C++ strings can be declared and initialised in this way

string institution = Oxford

string name = Peet

To use the string type in your programs add the header file include ltstringgt at the top of your program This allows the use of part of the C++ library of classes called the string class (and its member functionsmethods explanations will follow soon)

Of course strings are normally used when requesting an input Consider this code

string aName aDept Two string objects

cout ltlt Enter your full name

cin gtgt aName

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

19

If in answer to the first prompt we were to enter say Fred Brooks 5 the interaction and output of our program would immediately result in this

Enter your full name Fred Brooks

Enter your department Fred is associated with Brooks

Why When reading in a string with a space such as FredltspgtBrooks only the first part Fred is read into aName ndash and the input is said to be space delimited by cin ndash and consists of two separate inputs (so the Brooks parts is read into the aDept string variable)

We could use multiple prompts to read in a name of course but this is inconvenient

To handle this situation we can use the standard getline(cin aName) function to read in a name instead of using cin gtgt aName This reads all key-strokes into aName until the ltENTERgt key is pressed at which point it returns a string containing all of the characters from the input

cout ltlt Enter your full name

getline(cin aName)

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

The string class has many useful functions you can use to manipulate strings An example is the length() member functionmethod

string aName = Fred Brooks

cout ltlt The length of the string aName is ltlt aNamelength() ltlt endl

This statement will output - The length of the str ing aName is 11

See section 12119 for more information on the string class and its member functions

5 Fred Brooks is a real person and a legendary computer scientist httpenwikipediaorgwikiFred_Brooks

20

The LF (Line Feed) Problem and Reading Keys

Continuing on consider the following code

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

string aName

cout ltlt Enter your full name

getline(cin aName)

cout ltlt You entered ltlt aName ltlt endl

system(pause)

The intent here is to first ask for a character and then to use getline() to ask for a name

If only things were that simple

If we were to enter say a Z to satisfy the first prompt the program would immediately output

Enter a character Z

You entered Z

Enter your full name You entered

Press any key to continue

The problem here is that being a keyboard key theltENTERgt key is itself being seen as a valid input so when we enter Z followed by the ltENTERgt key were actually entering two keys ndash Z and the ltENTERgt key The first keys placed into aChar whilst the enter key is left in the keyboards buffer This is quite reasonable if you think about it you entered two keys (Z and ltENTERgt) but provided a home for just one of them in aChar

Ok so whats the problem Well the problem is that we really need to use something like getline() to read text that contains spaces and it just so happens that getline() given this scenario will see the residual ltENTERgt key left in the buffer and it will assume that you didnt enter anything you just hit the enter key

This problem - that of having a mischievous ltENTERgt key waiting to surprise us ndash will occur whenever you read a key from the keyboard using cin Luckily theres an easy fix as we can use another input function to read and then discard the waiting ltENTERgt key Its called cinget() Here is a modified version of the code above that fixes the problem

21

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

cinget() REMOVE THE ENTER KEY discarding the got character

string aName

cout ltlt Enter your full name

getline(cin aName)

Used like this cinget() reads and discards a character from the input stream You can do the same using cinignore() cinget extracts a single character from the stream and returns it cinignore() extracts any number of characters and discards them (the details are specified via passed parameters to the function) or a single character if no arguments to the function are provided

You can easily use cinignore() to ignore a number of characters or until a certain token (character) is met eg the following code reads in a users first and last names and then outputs their initials

22

char first last Two 8-bit characters

cout ltlt Please enter your first name followed by your surname

first = cinget() Get one character

The first parameter is the maximum number of characters to

extract (and ignore) The second parameter is a

delimiting character The function stops extracting characters

as soon as an extracted character matches this one

cinignore(2566 ) Ignore until a space is seen

last = cinget() Get one character

cout ltlt Your initials are ltlt first ltlt last ltlt endl

Casts

On occasions in your programs you may want to store a value in a variable of a different type (when there is a danger of a loss of information the compiler will issue a warning for example when storing a double in an int) If you store a double as an integer you lose information in two ways

any mantissa (fractional part) will be lost

the magnitude of the double being stored may be too large to fit into the integer

Eg it is not possible7 to store 6678 x 10000 as a 16-bit unsigned integer because 667800 is 10000010011011100 in binary (17-bits) and is therefore larger than the maximum storable value of 65535 (1111111111111111) However you can store 1230 as an integer8

When you need to represent a value as a different type you can use the static_cast notation as shown here to change a double to an integer

6 If this is exactly numeric_limitsltstreamsizegtmax() there is no limit As many characters are extracted as needed until delim (or the end-of-file) is found

7 Actually the result of attempting to store 66780 in a 16-bit unsigned integer will be 10011011100 or 1244 Do you see how this value comes about

8 Also see the (demonst rat ion) L imi ts project

23

int anInt

anInt = static_castltintgt(doResult) where dResult is a double

You may also use the following historic classic C-style9 notation to cast to different data types

anInt = (int)dResult

Eg to change an integer to a character

char aChar

aChar = static_castltchargt(bInt) where bInt is an integer

You may also combine this using the

object-constructionfunction-call syntax of C++ eg

double d = 314157

int n = (int)d Convert ds value to an integer

int j = int(d) Ditto

9 C-style casts are usually considered to be too powerful ndash in that they indiscriminately allow unsafe and downright dangerous conversions C++ casts were introduced to solve this problem

24

Other Cast Types

Although outside the scope of this introductory course for reference here is a summary of the cast types in C++ (feel free to skip this for now and come back to it at a later time)

static_castlttypegt(object)

The type parameter must be a data type for which there is a known method for converting object to whether this be a built-in or through a casting function (constructor) All types of conversions that are well-defined and allowed by the compiler are done using static_cast

The static_cast operator may be used for operations such as converting a pointer of a base class to a pointer of a derived class converting numeric data types such as enums to ints or ints to floats However static_cast conversions are not necessarily safe as no run-time type check is done which can cause casting between incompatible data types for example initialised pointers However this is checked at compile time to prevent casting obvious incompatibles Also be aware that a static_cast between pointer of base to pointer of derived may produce an erroneous result (where the actual object pointed to is of type base not derived)

dynamic_castlttypegt(object)

In the C++ programming language the dynamic_cast operator is a part of the run-time type information (RTTI) system that performs a typecast Unlike the static_cast the target of the dynamic_cast must be pointer or reference to class Unlike static_cast and C-style typecast (where a type check is made during compilation) a type safety check is performed at runtime If the types are not compatible an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers)

reinterpret_castlttypegt(object)

Allows any pointer to be converted into any other pointer type Also allows any integral type to be converted into any pointer type and vice versa

The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument (unlike static_cast but like const_cast the reinterpret_cast expression does not compile to any CPU instructions It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type)

You cannot cast away a const or volatile qualification You can explicitly perform the following conversions

const_castlttypegt(object) A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is

25

identical except for the const and volatile qualifiers For pointers and references the result will refer to the original object For pointers to data members the result will refer to the same member as the original (uncast) pointer to data member Depending on the type of the referenced object a write operation through the resulting pointer reference or pointer to data member may produce undefined behaviour

26

Exercise 2 CreatingModifying additional projects

Examine how comments look in a program

Examine the use of some fundamental data types

Using different data types

Using the cast operator

Using the string class

Task 1

Open the skeleton project called EvenI

The project folder is

EvenIEvenI s ln

Modify the projects code in to prompt for two numbers of type double and two numbers of type integer

The program should output the sum the product and the difference of the double numbers Also output the quotient and the fractional part of the two integers10

Youll need something along the lines of hellip

double aDouble double bDouble

etc

To read a number into aDouble you could use

cin gtgt aDouble

Task 2

Modify your EvenI program to read in two characters Enter the characters a and Z

Output the two characters with the character case changed ie a becomes A and Z becomes z

You will need to look online or at in 12120 to establish the ASCII integer values of each character hellip you can alter a characters case by treating it as an integer and

To convert integers (or the results of evaluating integer expressions) to say characters we need to use a cast Eg

int i = 65

cout ltlt static_castltchargt(i + 32)

10 Trivia quotient comes from the Latin quotiens for how many times For example when dividing twenty by three the quotient is six and two thirds You can use a modulus b to get the fractional part

27

then by addingsubtracting tofrom it

Task 3

Open the skeleton project called Address and modify it so that it can be used to collect some user data

Output this collected data to screen as shown in Figure 1

Note that youll have to have include ltstringgt in order to use getline()

Figure 1

Visual Studio builds projects in one of two different modes ndash Debug or Release we will always use the Debug mode (a Release build is normally only used when a product is being beta tested ie late in the cycle)

When using Visual Studio (or most other IDEs for that matter) we normally do not have to concern ourselves with the location of the executable that is built by the program ndash because we normally run it from within Visual Studio itself However and just for your information really the exe for a debug build will always be located in the Debug folder immediately below the projects root folder ie for this project Addressexe is located in the (exercise solut ion) Address Debug folder whilst a version built in Release mode would be in the (exercise solut ion) Address Release folder

Debug builds contain extra diagnostic code that is automatically inserted by the compiler

28

3 Basic Control Flow The programs you have created so far are limited in that they run through a sequence of instructions once and then stop Most computer programs will make decisions and carry out different actions determined by the user input

C++ has three kinds of control structures

Sequence statement - the computer executes the statements one after another All the programs you have written so far use sequence statements

Select ion statements - if ifelse switch

The if selection statement selects an action if a condition is true or skips the action if the condition is false

The ifelse selection statement selects an action if a condition is true or performs a different action if the condition is false

The switch multiple selection statement can be used to perform many different actions based on a character or integer value

Repeti t ion statements - while for do while

The while and for statements perform actions within their bodies zero or more times If the loop condition test is initially false no actions will occur

The dowhile statement will perform the actions in the body at least once (the test ndash as to whether to continue - is at the end)

Selection - ifhellipelse statement

The if selection structure is used to choose among alternative courses of action The structure of the statement is

if(mark gt= 50)

cout ltlt Passed

else

cout ltlt Failed

If the condition (mark gt= 50) is t rue the statement following it is executed cout ltlt Passed

If the condition is false the statement is ignored and control is passed to the else part of the selection and statement following else is then executed cout ltlt Failed

ifelse selection statements can also be nested within other ifelse selection statements

29

Exercise 3 SearchString

Task 4

Open the skeleton project called SearchStr ing

You will need to include ltstringgt at the top of the code to complete this exercise See page 158 for more on the string class functionality

Modify the program to display a string of text to the user

The user should then be prompted to select a word from the sentence and input a replacement word Your program should replace one with the other You will want to See section 12119 on string functionality

The prompting string should be shown both before and after the update

Tips

Given a string s initialised to

string s = C++ at the University of Oxford

string t

int i = sfind(U)

cout ltlt i ltlt endl 11

t = ssubstr(0 i) bit before U in t

t = t + ancient + + ssubstr(i) +

Outputs C++ at the ancient University of Oxford

cout ltlt t ltlt endl

Puzzled Programmers

Using if if else nested ifs switch and the conditional operator -

Task 1

Solving puzzles

Open the I fp project and WITHOUT compilingrunning it determine its output

You will need to consult the operator precedence table in section 1216

You shouldnt compile or run the program to start with ndash the idea here is for you to determine its output on paper11

Tip you might want to consider tidying up the codes layout before attempting to solve it

void out(int n) is a function We havent covered functions yet but it makes sense to use one here and so we have Suffice to say for now that using out(some value) will output the value to the console window

11 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

30

Functions will be explained fully soon

Compile and run the program ndash if your workings from Step 1 differ from the output you should determine where you went wrong

Selection - switch multiple selection statement

The switch multiple selection statement can be used to perform many different actions based only on a single integer value Note however the switch statement can only be applied in narrow circumstances The tests must be constants and be integers Lets compare the two statements

int num switch(num) case 1 cout ltlt num = one

double num switch(num) case 11 cout ltlt num = 11

OK ndash Test is 1 a constant and an integer NOT OK ndash Test is not constant integer

Repetition ndash while dohellipwhile and for loops

The while statement is commonly used to carry out repeated steps perhaps reading in values before doing a calculation on values read in The format of the code is

while(condition)

statement

This can be read as whi le the condition is t rue continue to do the statements until the condition is false

31

The Collatz Conjecture

Win a million dollars

Task 1

Open and complete the project called Col latz (use a while() loop)

Given any positive integer if the number is even divide it by two else treble it and then add one If the result is one stop else repeat the process

The Collatz conjecture says that given any starting value the process above will eventually hal t (goes to one and stops)

Eg setting n to 9 as a starting point successive values would be

28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is not known whether the Collatz conjecture is true Fame and fortune await anyone who can prove it httpenwikipediaorgwikiCollatz_conjecture

A Collatz tree as visualised by Edmund Harriss

32

This image is a sample from the colouring book Visions of the Universe by Alex Bellos and Edmund Harriss

Get your own hi-res version for colouring-in here and see here for an explanation

33

Task 2

Re-implement your code so as to use a for() loop (this will be a lot easier than you might first think)

Not essential for this task but as we mention for loops you might like to look at the for project to see how a for loop can be animated to show how the three sections of it work in order

Mixing loops

Task 1

Open and modify the skeleton project called Factor ial

Modify it to use different repetition statements to calculate and display the factorial of a value entered by the user (they should enter a value between 1 and 10 inclusive)

Example use a while loop to prompt for an input value (between 1 and 10) and a for loop to calculate the factorial result

The output should be like that shown in Figure 2 below

Factorials12

The factorial of 5 (usually written as 5) is

1 x 2 x 3 x 4 x 5 = 120

If factorials are new to you think of them as defining the number of ways to arrange n items

To avoid displaying results in scient i f ic notat ion use

cout ltlt setprecision(0) ltlt fixed

setprecision() requires include ltiomanipgt

12 0 Is defined to be 1

34

Figure 2

PLUSPLUS Recursion

Come back to this after weve covered functions

Note that our solution optionally also uses a function and recursion to find the same factorial If you open it you will see that just after where we perform the output above we have commented out an extra line of code (uncomment and rebuild to see it in action)

We havent covered recursion in this C++ course yet but its basically the process of solving a problem in terms of smaller versions of the same problem Since the problem gets smaller each time the process eventually terminates in a problem (the base case) that can be solved directly When defining a recursive function be sure of three things 1 The problem gets smaller each time 2 Include a solution for the base case And 3 Each case is handled correctly

The recursive function looks like this ndash add then test it in your own solution

Factorial function using recursion

long long int recur_factorial(long long int n)

return n lt 1 1 n recur_factorial(n - 1)

The question mark is the conditional operator and is used with the colon to form the functional equivalent of an if then else

35

If the expression before the is true then the expressionstatement to the left of the is evaluated otherwise the one after the is evaluated Eg these are equivalent

x boo() hoo()

if(x)

boo()

else

hoo()

4 Logical and Bitwise Operators

41 Logical

Quite often we will want to perform some action if two things are true and we can achieve this using nested if statements eg

if(onething == true)

if(secondthing == true)

do something

In C++ we can achieve the same result through the use of the l ogical And operator - ampamp

if(onething == true ampamp secondthing == true)

do something

ampamp is a binary operator ndash meaning that it takes two arguments (nothing to do with base 2) eg Op1 ampamp Op2 The expressions Op1 and Op2 must be capable of evaluating to t rue or false (false in C++ has the value 0 whilst any other value is considered true) and both Op1 and Op2 have to be true in order to have the conditional part execute eg if(x ampamp y) Z = 10 Here both x and y must have non-zero values in order for z to be assigned the value 10 Note again that this is equivalent to

36

if(x)

if(y)

z = 10

The truth table for logical And is as follows ndash note that both Op1 AND Op2 have to be true for the result to be true

Logical And

Op1 Op2 Result

True True True

True False False

False True False

False False False

We also have a Logical Or operator (||) in C++ and its truth table looks like this ndash note that its one OR the other that has to be true in order for the result to be true here

Logical Or

Op1 Op2 Result

True True True

True False True

False True True

False False False

The remaining logical operator we have is the unary Logical Not (the exclamation mark is used for this)

Logical Not

Op1 Result

True False

False True

Logical ampamp and Logical || short-circuit ie for ampamp if the expression on the left-hand side is found to be false then the expression on the right is never evaluated as the whole will evaluate to false (because to be true both sides have to be true and we know that the first one is false at this point)

37

The same is true for logical || in that the right-hand expression is not evaluated if the left is found to be true (the whole will evaluate to true because the left is true so there is no need to evaluate the right-hand expression)

42 Bitwise

PLUSPLUS Base Two and Bits

We also have bitwise versions of the logical operators ndash plus some extra ones Bitwise operators work on a variables individual binary bits ndash rather than the value of all the bits taken as a whole For bitwise And we do not use ampamp but use just a single amp The same is true for bitwise Or we just use a single | and not || Bitwise Not is a little different we use ~ (the tilde) for bitwise Not

The additional bitwise operators we have are for bitwise XOr ndash for which we use the ^ symbol and lastly for left and right bit shifting we use ltlt and gtgt

Bitwise operators work on binary bits (1s and 0s) whereas the logical operators work on values equating to either true or false

For example consider the following code

int w = 10 int x = 42

int y = w amp x

int z = w ampamp x

cout ltlt y ltlt endl

cout ltlt z ltlt endl

The base-2 binary representation of 10 is 001010 and for 42 it is 101010 So w amp x means

001010 101010 amp ------ 001010 ------

Remember And is one and the other

Now let us consider w ampamp x Here were not interested in ws or xs bits just whether when taken together they are zero or something else Here both are non-zero so both are considered to be t rue and if we refer to our truth table from earlier on we will see that the result will be t rue When we assign that to an integer like were doing here the value assigned will be 1

38

Shifts

The shift operators shift the binary bits left or right Bits that do not fit fall off the ends and bits are replaced with zeros when shifting left ie bits do not rotate and come back on the other end again When shifting right the sign-bit may be preserved depending upon whether youre using a signed or unsigned integer

Shifts are useful for all sorts of things but one of the obvious uses is to multiply and divide eg x = 2 x = x ltlt 1 shifts the bits in x one place to the left so given that xs value is 00000010 in binary x = x ltlt 1 turns x into 00000100 which is 4 So x = x ltlt 1 is like saying x = x 2 You can of course divide by right shifting

XOr

The rule for XOr is one or the other but not both ie 1 ^ 0 = 1 (just like 1 | 0) but whereas 1 | 1 = 1 with 1 ^ 1 the answer is 0

Note that we do not have a logical XOr operator in C++ as we can just use = (not equal to) ndash see the (demonstrat ion) Logical XOr project

Practising with Logical and Bitwise operators

You will need to use the Precedence and Associativity table in 1216 to complete these tasks

Task 1

Open the Logical project As earlier DO NOT compilerun this yet

You will need to consult the operator precedence table in section 1216

On paper determine the programs output13

Run the program ndash output as expected

Task 2

Open the Bitwise ndash

unsigned project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Unsigned The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

13 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

39

PLUSPLUS Signs and bits

Task 1

This one is tough as you should really know something about Twos Complement arithmetic to complete this

Open the Bitwise ndash s igned

project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Signed The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

5 Introduction to Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine (which will also be a function) Encapsulat ion is data information or detail hiding If youre mathematically minded you may think of a C++ function as being very similar to one in mathematics ie a mechanism for mapping one thing to another

Once a function is written the detail of how it works is not important It is only necessary to understand what if any inputs the function needs (its parameters) and what output is produced (the functions return value)

The use of functions provides several benefits but the main one is that it makes programs significantly easier to understand and maintain The main program function can consist of a series of function calls rather than hundreds of lines of code A second benefit is that well written functions can be reused across multiple programs

You have to tell the compiler about a function before you use it and this is normally done using a prototype early in the program A function prototype consists of the return type a funct ion name and a parameter l is t - indicating the data the function will receive ndash and is terminated using a semicolon Eg

int someFunc(int int)

This tells the compiler that there is a function (somewhere) called someFunc that takes two integers as its input and returns an integer value for its output

40

Using a prototype is a way of telling the compiler the data types of any return value and of any parameters being passed and enables error checking to be done

The function defini t ion consists of the modified prototype and a function body which is a block of code enclosed in parenthesis which does the work Eg

int someFunc(int a int b)

return a + b

Here we have named the two inputs a and b and we can see that the functions job is to add these two value and to return them As this function returns a value (the sum of a and b) it may be used to expressions like this

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

Arguments can be passed to functions in two ways pass-by-value the default is where a copy of the argument value in the main program is made and then passed to the function The copy in the function only exists in memory as long as the function is active When the code within function has been run to completion the memory is released and the value held there is lost Any changes made to the copy passed to the function do not affect the original variable in any way For example if we altered and used someFunc like this

int someFunc(int a int b)

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 20

41

Note that because we passed a copy of b to the function that the line b = b 2 alters the copy (which then isnt used) and not the original

Arguments can also be passed-by-reference When arguments are passed in this way any changes made to the arguments in the function are reflected by corresponding changes to that data variable in the calling part of the program Pass-by-reference is good for performance reasons because it can eliminate the pass-by-value overhead of copying large amounts of data (In later sections we will examine how pointers can be used to fake pass-by-reference) Eg this will alter b now

int someFunc(int a int amp b) Note the amp

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 40

See section 521 for more on this subject

Creating a function

The format of a function prototype is

return_data_type FunctionName ( argument_l ist )

The function CtoF - void CtoF(int temp) - has no return data type (void) its name is CtoF and it accepts a single input argument called temp of type int (integer)

It is not strictly necessary to give the argument a name (temp) in a function prototype you saw this above in int someFunc(int int) However the argument type must be specified The statement void CtoF(int) is therefore an alternative prototype

The following exercise is an introduction to functions You will learn a lot more about functions in later exercises

42

Writing functions

Task 1

Open the project EvenI you created earlier and change the structure of the program to make use of functions

Solution in (exercise solut ion)

EvenI I

Read two integers in to main() and pass them to a function The prototype is void intCalcs(int int)

intCalcs() function should calculate and display the result of the division and modulus of the two variables passed see Figure 3

Read in two doubles to variables in main() Pass the two doubles and the value of one integer to the second function the prototype is int Calcs(double double int)

Within function Calcs() write statements to produce the output as shown in Figure 3 Most of the code already exists within main()

Return the result of the multiplication of one double and an integer cast this value as an integer

Display the returned value within main() as shown in Figure 3

Figure 3

43

Using a struct

Task 1

Open the project Person

Solution in (exercise solut ion)

Person

As you saw during the presentation we can keep related data together using the struct keyword For example say we define a thing as follows

struct thing

int x

string y

double z

Having done this we can now create as many thing objects as we wish ndash simply by declaring them as we would say an integer

thing a

thing b

Each thing object a and b contains its own x y and z member variables eg

ax = 10 thing as x member set to 10

bx = 20 thing bs x member set to 20

cout ltlt ax ltlt endl outputs 10

cout ltlt bx ltlt endl outputs 20

Complete the exercise by creating and populating a struct Person object Once populated amend the printPerson() function so as to output the persons details

44

PLUSPLUS When Things Go Wrong

Going back to Exercise 8 if you havent tried it already enter zero as your second number What happens

C++ contains mechanisms for catching errors in the form of a trycatch mechanism

cin gtgt y Enter zero

try

intResult = x y

catch(myException amp e)

cout ltlt ewhat() ltlt endl

catch()

cout ltlt Generic oops ltlt endl

Modify your code so as to catch the divide by zero

Hopefully try and catch are fairly self-evident try something and catch any error if something goes wrong

There are two catch blocks here One tries to catch a myException object (we cannot see the definition of this classstruct here) and the other tries to catch anything else that is missed by catch(myException amp e) The amp says that the myException object e is being passed to the catch handler by reference Well learn what this means a little later in section 521

So did you see the Generic oops message appear

Your C++ compiler doesnt have to catch the divide by zero error ndash doing such a thing results in undefined behaviour This is because an arithmetic exception is an OS or processor exception - which is not the same as a C++ exception - hence it cannot be caught by a in a try catch block

To catch errors like this we either need extra support from the compiler14 andor operating system or to write some extra code For example we could do this

14 See also C signal handling httpenwikipediaorgwikiC_signal_handling

45

cin gtgt y Enter zero

if(y gt 0)

intResult = x y

However first we have to realise that this is a possible source of a runtime error and secondly we have to write (correctly) the code to handle the condition

Windows has built-in exception handling ndash called Structured Exception Handl ing (SEH) and we can generate code that uses this in support of the try catch structure used earlier

To enable this we need to tell the compiler to generate code that links into the SEH mechanism

To do this open the Project | ltproject namegt Properties hellip dialog box and in the Code Generation section select Yes wi th SEH Exceptions ( EHa) in the Enable C++

Exceptions line See Figure 4

46

Figure 4

The Monty Hall problem

The Monty Hall problem is a probability puzzle loosely based on the American television game show Lets Make a Deal and named after the shows original host Monty Hall

It goes like this

You are on a game show where you are shown three closed doors You are told that behind one of them is a new car and that behind the other two are goats

Two pieces of essential information at this stage 1 your goal is to win the car 2 the game show host knows what is behind each door

Lets walk through a trial game

The game show hosts asks you to choose a door ndash lets say you choose door number 1 (your door remains closed) The host now opens one of the remaining doors to reveal a goat (as there are two goats they can of course always do this) lets say they open door number 3

47

The situation is now as follows you have chosen door number 1 Only door number 3 is open and it reveals a goat The host now asks you if you would like to switch your door to the only other closed door - door number 2 At this stage you must either stick with door number 1 or switch to door number 2 and at that point the host will open the door youve chosen to reveal your prize

The question is when youre offered the chance should you stick or should you swap - will swapping increase your chance of winning the car or is it just 5050 The claim made here is that by swapping doors you will double your chance of winning the car What does your completed project claim

Task 1

Open and complete the incomplete project MontyHal l

The goal of this project to provide a simulation of problem outlined above

The function

int getRandomDoor(int n = 3)

return rand() n + 1

is used to choose a door number between 1 and 3 (inclusive)

Note that it has a default argument ie if it is called without an argument like this int val = getRandomDoor() the argument n is set to 3 by default and val will be set to a value between 1 and 3 However if it is called like this int val = getRandomDoor(10) then n is set to 10 and val will receive a value in the range of 1 to 10

48

More Functions

Task 1

Open the incomplete project IsLeap

The program asks for a year and determines whether the year is or will be a leap year

You need to complete the function IsLeap(int y) to implement the necessary code

Although the program is incomplete the program contains pseudo code for the algorithm required to compute the answer The pseudo is also show opposite

if year modulo 4 is 0

then

if year modulo 100 is 0

then

if year modulo 400 is 0

then

is_leap_year

else

not_leap_year

else

is_leap_year

else

not_leap_year

Figure 5

49

PLUSPLUS IsLeap in a line

Task 1

Extra points for implementing the IsLeap() function in just a single line of code This could be done using ampamp and || or by using the operator (a short form of if then else)

If you completed this step how readable is your code when compared to the if else version on the right

52 Algorithms

Algorithms

An Aside Big-O notation and Algorithm Complexity feel free to jump over this to Task 1

As programmers we usually implement the various parts of any new program in the simplest and most straight-forward way possible Then later if we find parts of our program are slow (causing what are called hot-spots) we will look again at the code to see if there is a better way to do whatever it is that is taking up the time

As a general rule the most optimal algorithms run in the shortest possible constant t ime ndash such algorithms are often symbolised using O(1) whereas the worst run in quadratic cubic exponential or factorial time (you can think of the O [called Big-Oh] as meaning in the Order of for some input n)

Usually were often happy with those running in O(n) (in the order of n) time ie their running time scales linearly with the number of steps or operations they involve Loops invariably signal O(n) parts of any algorithm

This is best explained using an example

50

Task 1 Understanding Gauss algorithm

Q How would you sum the integers from 1 to n where n is say 100

The obvious way is to use a loop

int tot = 0

for(int i = 1 n = 100 i lt= n ++i)

tot += i

This is fine for small values of n but not so good for very large ones

Interestingly it is said that this self-same problem was once given to a class of children which included one Carl Friedrich Gauss (presumably the teacher wanted to keep his charges occupied for a time) While most of the children started working at the problem (using the loop approach above) Gauss thought about it for a moment and then wrote down the solution 5050

The algorithm Gauss used may be easily demonstrated using the values 1 ndash 10

Gauss realised that if he wrote out the values twice (whether on paper or just in his head) once forward and once in reverse that he could sum each column formed to 11

1 2 3 4 5 6 7 8 9 10

10 9 8 7 6 5 4 3 2 1

1+10 2+9 3+8 4+7 5+6 6+5 7+4 8+3 9+2 10+1

=11 =11 =11 =11 =11 =11 =11 =11 =11 =11

Then sum of 1 ndash 10 is then 11 10 (columns) = 110 2 = 55 (we divided by two because we used each value twice)

Coming back to algorithm runtimes you can see that when using a loop summing 1 ndash 1000 will take ten times longer than summing 1 ndash 100 which will take ten times longer than summing 1 - 10 However by using Gauss approach we can arrive at the answer for any range of values in the same time this is what we mean by a constant time algorithm

51

Task 2

Open the incomplete project SumIntSeries

Complete the project so as to implement Gauss algorithm for any continuous range of integers

The solution project is (exercise solut ion)

SumIntSer ies

The general formula required is

((119948 minus 119947) + 120783)(119947 + 119948)

120784

Or in a more code form

Sum = ((k - j) + 1) (j + k) 2

Where j and k are the starting and ending values in the range respectively (both inclusive)

Functions and Pass by Reference

In the previous section when working with functions all arguments passed to the functions were copies of variable values from main() The arguments were passed by their value

Pass by Value is the default argument passing mechanism for C++ (and the C language)

In pass by value when a function is passed an argument it receives a copy of the value from the calling function (main() in previous examples) This copy remains in scope until the called function has completed and returned at which time the copy is destroyed

Therefore a function that takes value-arguments cannot change a passed variables value because any changes only apply to copies and not to the actual callers variables

An alternate passing scheme is called Pass by Reference

Passing variables to functions by reference is very useful when we need to change or update variable(s) via a function (it is also a faster mechanism than pass by value as no copies have to be made)

Under the covers pass by reference involves passing a memory address and not a copy of the data to the function This is usually more efficient than passing by value because there is no requirement to copy memory However this argument passing mechanism enables a function to modify any argument even if its not supposed to To avoid this we usually declare all read-only parameters as const and pass them by reference

The format of a function prototype when using call by reference is

return-data-type funct ion-name (reference parameter) To indicate a reference parameter an ampersand (amp) is written in the function prototype and header after the parameter type name

The statement void squared(int amp) has no return data type (void) its name is squared and it accepts a reference parameter (amp) of type int (integer)

52

The function definition would be something like this

void squared(int amp inVal)

inVal = inVal inVal inVal

The function call to it would look like this

squared(aValue)

As mentioned above pass by reference is normally used for one of two reasons 1 Because we want to be able to change a passed variable inside a called function 2 Because we want the speed associated with a pass by reference

In 2 we will normally protect our argument by using const in the called function Eg say we want to pass the double argument x to a function f() and take the least possible time about doing it (and given that function f() shouldnt alter x) we would use the following code

void f(const double x)

Use x in some calculation Note that if

x appears on the left hand side of an assignment operator

that it will result in a compilation error

Pass arguments by reference

Task 1

Open the project (demonstrat ion) FunctionRef

Compile and run the program The output should be the same as shown in Figure 6

53

Figure 6

Examine the function prototype

void squared(int amp)

This shows the function squared accepts a reference

parameter of type int The reference parameter is ndash under the covers - the memory address of the argument passed to the function

The function uses this address to both get and set the value stored in variable a (value 21) in main() A reference to this address is passed to the function with the function call squared(a)

Examine the function void squared(int amp x)

Under the covers references to x refer to the address of the variable a in main (that holds the value 21) Ie x and a reference the same piece of memory (the word object was deliberately not used there) So we can think of x and a as two names for the same item

Returning values from functions

In previous programs we have most often produced output (using cout) from within the functions However to be of most use and general utility functions should return resultsinformation rather than output it

Functions may return results in one of two ways 1 via a return value or 2 via arguments ndash either passed as references or via pointer (address)

Non void Functions return a single value ndash if you will they evaluate to this value As such non-void functions may be used in expressions Eg

54

w = x sqrt(y) z

The function sqrt() is replaced with the value of whatever the square root of y happens to be For example if y has the value 4 then to evaluate x sqrt(y) z fully the sqrt() function has to be called ndash where it returns 2 This value is then substituted into the expression for further evaluation ie it becomes w = x 2 z

The second way for functions to return results is via its parameters ndash if they are references or passed via memory addresses Eg

void doubleIt(int amp n)

return n 2 Error The void means doesnt return a value

doubleIt() is a void function ndash so it cannot contain a return statement ndash so it cannot evaluate to anything ndash so it cannot be used in an expression

x = doubleIt(y) error

However the function is still able to return a result (modify something outside of itself is perhaps a better way of putting it)

void doubleIt(int amp n) using amp - a reference

n = n 2

55

doubleIt() cannot (still) be used in an expression but it can change things

int x = 10

doubleIt(x)

cout ltlt x Outputs 20

Why would you use references like this Well references are mainly used for speed (by passing an actual external entity a copy does not have to be made) but they are also useful when multiple values (entities) might best be updated via a single operation (function call)

int x y z

x = y = z = 10

doubleAll(x y z)

void doubleAll(int amp a int amp b int amp c)

a = a 2 b = b 2 c = c 2

Side effects

Going back to w = x sqrt(y) z

Lets replace sqrt() with our own function and cause some havoc

double havoc(double amp d)

++x

d = sqrt(d)

return d

x = 3

w = x havoc(y) z

56

Here the value of y has been changed (yet it is not clear that could happen from the functions call site ndash where it was called from) and so has x Also what value for x will be used in x havoc(y) z Will it be 3 or 4 These sorts of issues are called side-effects

This is one problem (or advantage) with reference arguments ndash and that is that they can cause a change in a variable outside of the function being called

One way to protect against this is to use const references eg

double havoc(const double amp d)

++x

d = sqrt(d) Compilation error here

return d

57

Returning a value from a function

Task 1

Open the TempConver t

project

Run the program The output should be the same as shown in Figure 7

Examine the function prototype

double convert(double temp int mode)

This function prototype has a return type of double When the function is called and calculations are completed a double value is returned to the caller

Examine the function definition The function definition matches the prototype indicating a double and an integer are being passed to the function and a double is being returned

Examine the function body The two statements below convert the temperature input The conversion type required is identified using the user input mode and a switch selection

The statement (temp - 32) 5 9 is used to calculate the temp in Centigrade

The statement 18 temp + 32 is used to calculate the temp in Fahrenheit

Figure 7

58

PLUSPLUS Arithmetic Bases

Task 2

Open compile and run the partially complete Bases project

Note that the project isnt complete

The program uses intrinsic functionality to output values in hexadecimal and octal ndash base 16 and base 8 Both these bases are useful in programming its all to do with binary and the size of a byte

Note that there isnt a bin equivalent to hex and oct and that we have instead written a function called bin1() to convert a value into its binary (base 2) representation

Understanding how bin1() works

bin1 uses the modulus operator () and the right shift operator (gtgt) to work eg 42 in binary is 101010

25 24 23 22 21 20

32 16 8 4 2 1

----------------------

1 0 1 0 1 0

----------------------

1 32 + 0 16 + 1 8 + 0 4 + 1 2 + 0 1 = 42

The function progresses like this

42 2 has remainder zero (false as evaluated in the if) If the if test is true we store a 1 else we store a 0 We then divide 42 by 2 by right shifting it one place ndash but just replace that with n = 42 2 if you prefer We then loop while we have a non-zero value in n to operate on hellip

42 2 = 210 42 2 = 0 if(42 2) = false string value = 0

21 2 = 105 21 2 = 1 if(21 2) = true string value = 1

10 2 = 50 10 2 = 0 if(10 2) = false string value = 0

5 2 = 25 5 2 = 1 if(5 2) = true string value = 1

2 2 = 10 2 2 = 0 if(2 2) = false string value = 0

1 2 = 05 1 2 = 1 if(1 2) = true string value = 1

59

Task 3

The project needs completing specifically it needs the function bin2() writing

We could write such a function as bin1 in a variety of ways and wed like you to write a new function called bin2() that produces the same output as bin1() here

Heres a step by step algorithm for implementing bin2()

Youll use either gtgt or and the bitwise And (amp) operator

Take the functions input (the number to convert) in as a parameter called n To keep it as simple as possible for now you could use plain int types rather than the unsigned long long type we used so the functions signature would look like string bin2(int n)

1 In the function create an integer called i and initialise it to 1

2 Realise that if you left shift the single bit in i (use ltlt or multiply it by 2) it will take on the values 2 4 8 16 32 hellip until it eventually goes to 0 ndash as you shift the bit off of the end

3 Recognise that you could compare your shifting bit with one in the same position in n using bitwise And Ie if((n amp i) == 1) then you know youll need a 1 in your output string for the bit position in n (2 4 8 ) given by is value at this point

4 Build up your result string as you proceed

Change your int n and int i to unsigned long long int and re-run

Try using other integer types ndash signed and unsigned

Lastly examine the solution project in (exercise

solut ion) Bases

60

Figure 8

61

Searching for Sequences

Task 1

Open and modify the incomplete project called called HeadsOrTai ls

When all completed the output should be similar to that shown in

Figure 9

This is the (exercise

solut ion) HeadsOrTai ls project

The programs purpose is to look for a sequence of simulated coin tosses ndash a series consisting of Hs and Ts

The program is complete (as in it runs) but it has some issues At first test it using quite short sequences

The timing information displayed by the application is included simply to demonstrate a timing mechanism that can be used to test the efficiency of the code

The first problem is that the user can currently enter characters other than H or T (h and t are ok as the input is converted to uppercase ndash note the string is passed by reference to toupper() which uses a pointer (which well cover later) to process the string

The second problem is that as it stands the algorithm isnt very optimal if we do not find our pattern we add the result of another coin toss to the current sequence and then re-check the sequence in its entirety

For example if were looking for HHTHH and the generated sequence is currently HTTHHHTTHTHHTTH we will fail to find HHTHH and then proceed to add another coin-toss result at the end ndash HTTHHHTTHTHHTTHH We will then scan this for HHTHH However as we know that we failed to find HHTHH before we added the extra coin-toss re-checking the previously checked sequence is pointless and very time consuming (think how this would (or wouldnt) scale) Your task here is to think of and implement another more optimal approach

62

Figure 9

Task 2

Open the HTTvsHTH project you will find that the project will compile correctly but displays an incorrect result

When completed the program can be used to check how many coin-tosses are required on average to see a particular sequence

Why should that be of interest Because sometimes its rather surprising For example test how many tosses are needed to see say HTH and then HTT

When the program is corrected the output should be as shown in Figure 10

63

Figure 10

PLUSPLUS Optimising Searching for Sequences

Task 1

As it stands the program (yours and ours) encodes a coin toss as a character ndasheither an H or a T Each character is encoded using at least 8-bits and so checking whether a generated sequence is the sequence were looking for means performing a string comparison which is costly in terms of clock-cycles Of course generating and storing the new coin toss also requires the use of these costly string operations

As we have just two tokens as an alternative to generating and storing characters and performing string operations we could encode a sequence as a series of bits For example the sequence HTH could be encoded as 101 in binary (5 in decimal) You can set the corresponding individual bits in an int using the bitwise Or operator | (a vertical bar) eg int n = 0 n = n | i which youd most likely do as a result of scanning the users entered search-sequence string a character at a time In this way you could encode the sequence HTHHTHHTHHTHHTHH in a single sixteen bit unsigned int

Additional operators needed to implement sequence checking and H or T bit manipulation are bitwise And (amp) and the left shift operator (ltlt)

You will find more information on some of these operators just a little below

64

Evolving Searching for Sequences

Task 1

Looking for sequences in stringssequences is an interesting and complex problem in computing and also in genetics where the string being searched could be a DNA sequence and pattern could represent a gene perhaps with a snip (a modificationmutation)

Modify your HeadsOrTai ls program (or our solution) so that instead of Hs and Ts it generates and searches for Gs As Ts and Cs instead

Randomly generate a GCTA sequence and a similar pattern to find within the sequence

How much more time and variation is required in this slightly more complex situation

Conduct a few experiments and using Excel graph your results (copy and paste some data highlight it and then select Excels line graph ndash Excel should then automatically plot your data)

Extrapolate The human genome is how long A gene might contain how many bases How difficult is the task of finding interesting sequences in the human genome How about checking for the odd mutation (insertion transposition deletion) ndash fuzzy matching

A solution for this problem can be found in the (demonstrat ion) GATTACA project

6 Classes and Objects In the previous section we have been working with simple programs that display messages to the user store data input as different data types manipulate the data in some way and output the results to screen

We will now start to look at C++ objects and classes

In the real world there are objects everywhere students staff cars birds houses and many more All objects have at tr ibutes these are similar to the variables created in previous tasks Some attributes of a student may be height weight race course of study etc All objects exhibit behaviours or operations cars accelerate and decelerate students matriculate enrol on courses and leave university

65

Now what is the relationship between a class and an object A good analogy would be from an architects blueprint for a house it would be possible to build many houses Similarly from a class in C++ it would be possible to build many objects

If we had a student class we could create many objects from the student class to represent the many students enrolling Each of these objects would be uniquely identified They would share common attributes and exhibit common behaviours If we wanted an object to perform some task we would call the appropriate member function allowing an operationaction to take place changing the behaviour of that object

Member functions are different from the functions you have created so far Member functions are always associated with objects and are usually called or invoked using a dot notation object member funct ionname() An example is student1getName() The object instance is student1 and the member function is getName()

Member functions contain the detail of how the technical aspects of some operation will be processed When member functions are invoked these technical issues are hidden from the end user When the member function is asked to do some operation a message is sent (a member-function call) telling the member function of that object to perform the operation detailed in the function

Functions are not completely new we have had a brief introduction and you have already created some of your own Note also that main() is a function that is called automatically when you run your program However it is not a member function as there is no object associated with it

Creating your first class

Creating a class

Task 1

Open the project called StudentUG

Compile and run the program It should look like Figure 11

66

Figure 11

Before you can create the object myName it is necessary to define the class from which the object will be created The class definition is shown below

class StudentUG Start of class definition

public

void displayName() Start of member function

cout ltlt My name is Michael Cain ltlt endl

Note a semicolon is required at the end of the class definition

Within main() the statement StudentUG myName creates the object myName of class StudentUG In effect StudentUG is a new type

The statement myNamedisplayName() is used to call the member function displayName() of object myName

As we have seen previously the function main() is called automatically when our programs are executed However member functions (displayname() is one we could have many) must be called in this way objectInstanceNamefunctionName() when dealing with an

67

object directly and like this objectInstanceName-gtfunctionName() if working through a pointer to an object (more on pointers later)

The member function displayName() is preceded by the word void All functions can return values this one does not The word void preceding the function name indicates nothing is being returned If this function returned an integer the definition would be int displayName()

When you use functions it is common to pass data (called parameters) to the function The function then manipulates the data before displaying an output andor returning a value

To pass a parameter to the function in the studentUG class the calling statement in main() would be

myNamedisplayName(name) where name is a string (a series of characters) that contains a value read in from the keyboard

In order for the function displayName() to recognise the parameter being passed the function declaration is changed to include the parameter (name) and type (string) as shown in below

void displayName(string name)

cout ltlt My name is ltlt name ltlt endl

Figure 12

Member functions and Passing parameters

Passing parameters

Task 1

Modify StudentUG to read in a student name The name should be passed to a member function The parameter should be output from within the function to welcome the user to C++ programming

68

Task 2

Modify the program in the above task to read in two more names Each name will be for a different student and you will need to create additional objects (instances) of the class

Data Members

In most of the programs written so far the variables have been declared inside the main() function Variables declared inside a function are local to that function and cannot be accessed from outside that function

You have created a student class and it would be reasonable to assume that a student would be following a particular course So courseName might be one of several attributes of a StudentUG object Attributes are represented as variables in a class defini t ion These variables are called data members and must be declared inside a class definition When you create an object of a StudentUG class each object has a unique memory location for its data members

Figure 13 shows data member name declared in the class definition The access specifier private means that only member functions of the class in which the attribute was declared can use this data member

private string name

Figure 13

When data members are declared as private the data is hidden This is called encapsulat ion and means the attributes of the object are hidden and can only be accessed via member functions

As there is no direct way to change a data member you will also need to create a member

funct ion to set the data member to a value and create a second member funct ion to output the value held there

Data members can also be declared public A data member that is declared public can be accessed from any (non-member) function

A protected data member can only be accessed by member functions of its own class and by member functions of classes derived from this class We will learn more about derived classes and inheritance later

69

Using data members

Task 1

Open the project called StudentCoursesln

Compile and run the program it should look like Figure 14

Figure 14

Task 2

Examine the member function getCourse() shown in Figure 15

string getCourse()

return course

Figure 15

Task 3

Modify the StudentCourse source file to enable the user to add a student name enrolment date and number of years of course Once entered this data should be output to screen You will need to create additional data members and member funct ions to achieve this

70

More Objects

Task 1

So far you have created one StudentCourse object It is about time we had a second student on the course Create a second object of the class StudentCourse You will need to add the second statement shown in Figure 16 to add the new object student2 Call the member functions passing parameters as necessary

Figure 16

Constructors

When you create objects from the StudentCourse class it is necessary to give initial values to all the data members If we were entering data for five people and they were all following the same course of study it would make sense to initialise the course data member (it is possible to initialise some or all of the data members) when each object is created

A constructor is a special kind of function that must have the same name as the class Constructors are normally defined to be publ ic and never have a return type They can be used to automatically initialise data members

In previous programs you have written a defaul t constructor has been provided by the compiler However it is not possible to pass parameters to a default constructor function so the data members in the programs created so far have not been automatically

71

initialised To initialise these data members you created member functions that assigned values to data members

Although a default constructor is provided at compilation time it is a good idea to create your own so that the data members can be initialised

It is worth noting here that functions (constructors are functions) can be over loaded This means it is possible to have more than one function with the same name Note that overloaded functions (functions with the same name) must have different types of or number of arguments

Constructors (functions) can also be overloaded with more than one function with the same name but different types or number of parameters Fortunately for us the compiler automatically calls the correct function whose parameters match the arguments used in the function call

Using constructors

Task 1

Open the project called Constructorss ln

Compile and run the program it should look like Figure 17

Figure 17

72

Task 2

In the constructor shown in Figure 18 what is the purpose behind course = Note that as the string parameter name has the same name as the class variable that we use the hidden this pointer to access the class variable in the assignment If we didnt do this and simply used name = name instead then all we would be doing is assigning the value in the parameter back to the parameter

StudentCourse(string name)

this -gt name = name

course =

Figure 18

Task 3

Create a third constructor that will take an argument enrolment_date

Add a third object call it student3

Write code that will test this additional constructor

Solution in (exercise

solut ion) Constructors

If time allows add other useful properties (data members) access methods (functions) and constructors

Separating use from declaration and definition

C++ is all about objects and any decent project will usually make use of a number of application or domain specific classes

To keeps things maintainable and to promote code reuse C++ projects usually contain a number of cpp and h files where each h files will usually contain a declaration of a class (sometimes called an interface) Note though that the definition of the class (sometimes called the implementation) ndash the code that implements it ndash will be absent from the h file and will instead reside in an accompanying cpp file

Aside from allowing different teams to more easily work on separate parts of the program one of the main reasons for separating definition from declaration is to enforce abstraction which is a programming (and design) technique that relies on the separation of declaration and implementation For example lets say that your team needs a class that acts a bit like a stack (a last-in first-out or LIFO structure) and as this is required

73

urgently you decide to implement it using a simple array You would then only want to give your team what is absolutely necessary to use this class a single h file for your team members to include in their cpp files If they look in the h file they will only see information on how to use the class but how it does what it does is kept elsewhere in the cpp and that youve withheld Consumers shouldnt need to know how a thing works in order to use it

An obvious advantage to this is that there is no danger in you changing how it works Perhaps you later decide to use a vector instead of the array You go ahead and alter the implementation and your team members are none the wiser ndash after all the interface hasnt altered just the implementation

So how does the project get built Of course the implementation of this class will be required at compile time and you can either do that by including the cpp file directly (which will give away the implementation details of course) or by including it as object code ie compiled C++ code (binary machine code) This is how valuable commercial source code is kept in-house while the binary implementation complete with a h file is provided to customers (you will see an example of this just below in Using external

l ibrar ies and thi rd par ty header f i les )

Any discussion on separating use from declaration and definition should include something on namespaces You introduce a namespace by simply using the keyword and braces Anything entered inside these braces is inside the namespace eg

namespace securityModule class Encryptor using namespace std using namespace securityModule int main() Encryptor e Without the using we would have had to use securityModuleEncryptor e securityModuleEncryptor e2

See the (demonstrat ion) Namespaces project for more on this

74

Separating declaration and definition

Using a header and source file to separate class declaration from definition

Task 1

Open and modify the partially complete skeleton project called Precis ionTimers

Like HeadsOrTai ls this project makes use of the Windows operating system to very precisely measure elapsed time However unlike HeadsOrTai ls we have separated the stopWatch class interface from its implementation

As weve previously mentioned Gauss and algorithm efficiency we could test our theory that summing in a loop is O(n) ie that the time taken scales with n

Examine the project files hrTimercpp and hrTimerh noting that the h file contains just enough information for someone to use the declared class stopWatch whilst htTimercpp contains the implementation of the class

Now look in PrecisionTimerscpp You will see that an instance of the stopWatch class is declared Also note that we include hrTimerh but make no reference to hrTimercpp

As it stands the code calls two functions to calculate the sum of a range of integers sumGauss() and sumLoop() The program outputs the clock-ticks used and time taken in seconds

Note that sumLoop() is incomplete

Complete the sumLoop() function and then choosing suitable values for the ranges upper-bound carry out a few experiments to test if the loop is really O(n)

What is this used to do in hrTimerh15

ifndef HRTIMER

define HRTIMER

endif

15 You should also see pragma once as this is rapidly becoming the alternate way to do this ndash whatever this is of course

75

PLUSPLUS Providing object code only

Task 2

We have provided a separate demonstration project that takes the discussion on this one step further (demonstrat ion)

Separat ingThings

In its current form the project wont compile To compile the project in the Solution Explorer add the existing carcpp file to the source files list that just contains SeparatingThingscpp and recompile carcpp is in the same folder as SeparatingThingscpp

Once youve done that right-click on carcpp in the Solution Explorer and select Remove Very importantly when youre prompted for confirmation choose Remove do not choose Delete Now recompile once more youll see that the project fails to compile as the definition of car has been removed

76

But hold on we created carobj - the compiled object-code version of carcpp during our previous compilation so we could tell the linker about that and all should be well (this more or less duplicates the scene whereby you do not provide source code but provide only object code)

The carobj file will be located somewhere like

CUsersDesktopCourse(demonstration) Separating Things(demonstration) Separating Thingsbincarobj

To add this to your project go to Project | Properties | Configuration Properties | Linker | Input

77

In the right-hand window select Additional Dependencies drop down the list and select ltEdit gt

In the dialog that appears add the full path to carobj (see earlier in Step 2) and press Ok

Lastly recompile the code once more It should compile and run At this point you could if you wanted to delete carcpp altogether

One last thing

If you look in the comments in SeparatingThingscpp you will find a discussion that goes into the advanced topic of hiding things even further This includes a brief discussion of the the so called pimpl pattern (pronounced Pimple this stands for Pointer to Implementation16)

16 httpenwikipediaorgwikiOpaque_pointer

78

PLUSPLUS Using external libraries and third party

header files

Task 3

Open and modify the project called Lot to

Examine the projects comments to understand the programs function Run the program ndash does it work

It is supposed to compute the odds of winning the UKs lottery httpwwwnational-lotterycouk (try as we might we couldnt find the odds on their own website)

The program uses the recursive factorial function used earlier in the course (with bigint being typedef ed as unsigned long long int)

Factorial function using recursion

bigint recur_factorial(bigint n)

return n lt 1 1 n recur_factorial(n - 1)

There is a problem here however in that to compute the odds we must compute some significant factorials ie

49 = 608281864034267560872252163321295376887552831379210240000000000

and

6 (49 - 6) = 43498989405629161658895695089330078205230448640000000000

Sadly our bigint (unsigned long long) can hold a maximum value of 2^64 ndash 1 = 18446744073709551615 ie not hardly big enough

Fortunately in C++ we can define new types like an arbitrarily sized integer (outside of the scope of this course but see the (demonstrat ion) newINT project for a small taste) However this is object orientation ndash surely we can just use an existing already defined arbitrarily sized integer class

79

Task 4

The good news is that in this class you can You can use LEDA (The L ibrary of

Eff ic ient Data types and Algor i thms ) a professional class library of advanced numerical functionality

You will need to download the program called

LEDA-63 i386 msc 10 ( NET 2010) 32 bi t

or

LEDA-63 i386 msc 10 ( NET 2010) 64 bi t

Go to wwwalgorithmic-solutionsinfofreeindexphp Accept the licence terms and download the appropriate version (usually the 64 bit version)

The LEDA installation program will install additional numerical libraries and header files from the Algorithmic Solutions company

Once the setup is complete modify the Lotto program

In the Solut ion Explorer right-click on your project (Lot to ) and left-click on Proper t ies A dialog-box appears

Under the CC++ section

1 Click on General Choose Addi t ional include di rec tor ies and enter the directory CAlgor i thmic Solut ions LEDA-63- free-win-msc10-

s td incl

2 Click on Preprocessor and add LEDA_DLL to the end of Preprocessor

Defini t ions Note the semicolon is required

3 Click on Code Generat ion and check that Runtime Library is set to Mult i - threaded Debug DLL ( MDd)

Under the Linker section

4 Click on General

5 Choose Addi t ional l ibrary di rector ies and enter the directory CAlgor i thmic Solut ionsLEDA-63- free-win-msc10-s td

6 Click on Input and add l ibGeoW_mdd_dl l l ib leda_mddl ib to the end of Addi t ional Dependencies Again the semicolon is significant

You may now close Properties dialog-box

7 Modify your code Add the following under include ltiostreamgt

include ltLEDAnumbersintegerhgt using ledainteger using namespace std

80

Then modify the recur_factorial() function so that it accepts and returns a type called simply integer rather than bigint

Save the project and exit Visual Studio

In order to build and execute Lottoexe Windows needs to have l eda_mdddl l in its search path for DLLs Therefore we need to add the path to the folder containing leda_mdddll to the PATH environment variable

8 In Windows Explorer navigate to My Computer then right-click on it and select Propert ies

9 Click on the Advanced tab and then on the Environment Var iables button

10 In the bottom section (System var iables ) of the dialog box highlight Path and then click the Edi t button

At the end of the existing path add -

11 CAlgor i thmic Solut ions LEDA-63- free-win-msc10-s td

Once more note the leading semicolon is significant

81

12 Restart Visual Studio and re-open Lot to Build and run the application as normal

It might seem that this was a lot of work for such an apparently trivial result but the fact is that you now have access to (and have seen how to use) an advanced numerical library of functionality And anyway when all is said and done you must admit that at least you got a return here ndash which is more than you should reasonably expect from the lottery

Figure 19

Task 5

Explore the LEDA samples and documentation ndash if you installed it there should be a shortcut in your start menu to LEDA-63-free-win-msc10-s td

Task 6

Modify the Lotto program to see how the odds change when there are more balls andor when more balls need to be matched (you might also display more of the intermediate results of calculations ndash like 49)

Destructors

Both constructors and destructors are special class methods We have seen how a constructor is called whenever an object is defined

A destructor has the class name prefixed by a tilde ~ Like constructors destructors cannot return values and therefore they have no return type specified but unlike constructors destructors have no arguments and thus cannot be overloaded

An objects destructor is called whenever an object goes out of scope The purpose of the destructor is to clean up eg to free any dynamically allocated memory that the object was using and release other system resources such as files and database connections etc

In the examples used so far no destructor has been provided for any class created In these programs it has been unnecessary If the programmer does not explicitly provide a

82

destructor the compiler will create an empty destructor in the same way that an empty constructor is created if one is not explicitly created

When classes are created any objects instantiated from them that contain dynamically allocated memory will need destructor methods added to implicitly free any dynamically allocated memory when the object goes out of scope

In the class example shown below the destructor function is ~StudentCourse()

~StudentCourse()

cout ltlt Im being destroyed

7 Arrays vectors lists and hash-tables Arrays vectors and lists are all types of data structures Data structures are areas of memory where collections of the same data type are held The main difference between arrays vectors and lists is that arrays stay the same size throughout the program execution whereas vectors and lists can grow automatically

Arrays consist of a series of elements (variables) all of the same type placed consecutively in memory Each of the elements can be individually referenced by adding an index to the arrays name We saw this type of notation earlier when using arrays

Eg

int examMarks[10]

This declares an array of ten scores score 1 is accessed via an index of zero ndash examMarks[0] and score 10 is access through an index of nine ndash examMarks[9] Very important note that indexes start at zero

The advantage of using arrays compared to using discrete variables (the way we have stored values so far) is it is possible to store any number of values of the same type in an array using the same identifier

With arrays it is possible to store 100 student exam marks or 100 student names with using one unique identifier

Vectors and lists are container classes which were originally part of the Standard

Template Library (STL) The STL evolved into C++ Standard Library ndash which includes iostream etc This is the general-purpose C++ library of functions algorithms and data structures that we can use in our programs While some aspects of the library are very complex it can often be applied in a very straightforward way that allows reuse of sophisticated data structures and algorithms

There are many container classes in the library ndash note that C++ now also provides such a class for the more primitive array

ltarraygt

New in C++11 and TR1 (Technical Report One)

83

A container for a fixed sized array

ltbitsetgt

A bit array

ltdequegt

A double-ended queue

ltforward_listgt

New in C++11 and TR1 A singly linked list

ltlistgt

A doubly linked list

ltmapgt

Sorted associative array and multi-map

ltqueuegt

A single-ended queue

ltsetgt

Sorted associative containers or sets

ltstackgt

A stack

ltunordered_mapgt

New in C++11 and TR1 Hash tables

ltunordered_setgt

An unordered_set unordered_multiset

ltvectorgt

A dynamic array

As with an array vector and l is t can hold objects of various types However unlike arrays vectors and lists can resize shrink and grow as elements are added or removed

The standard library provides access via iterators or subscripting Iterators are classes that are abstractions of pointers (more on pointers later) They provide access to container classes using pointer-like syntax and have other useful methods as well

The use of vectors lists and iterators is preferred to arrays and pointers By using containers common problems involving accessing past the bounds of an array are avoided Additionally the C++ standard library includes generic algorithms (an algorithm is a set of instructions on how to perform a task) that can be applied to vectors lists and other container classes

Declaring and using arrays

Arrays are declared indicating the type and number of elements in the following way

type ar rayName[arraySize]

84

Examples are

int inNumbers[20] an array called i nNumbers of 20 in tegers

char inName [20] an array called i nName of 20 characters

float ExamMarks[5] = 0 an array called ExamMarks of 5 floats with all elements explicitly initialised to zero

const int size = 5 declaring a constant variable size

float ExamMarks[size] When the constant variable size is applied to the array declaration the number of elements is set to 5 This cannot be changed during runtime of the program However it is handy when the number of array elements needs to be changed Changing the constant value size changes the number of elements wherever the ExamMarks array is used in the program

int numArray [2][3] is a multidimensional array with 2 rows and 3 columns

Note Arrays have been used in C++ for many years and there will be code you work with that was written before vectors became available Vectors are are usually preferred to using arrays and pointers Common problems involving accessing past the bounds of an array are avoided when using vectors

Creating an array to hold exam results

Task 1

Open the project Array s ln

Compile and run the program

Run the program adding five exam results The output should be similar to Figure 20

Figure 20

85

Examine the following statements

double ExamMarks[5] = 0 This statement declares the array setting its size to 5 elements and explicitly initialising all elements to zero

cout ltlt Enter Exam Mark ltlt i + 1 ltlt This statement prompts the user to enter an Exam mark into the array at element i + 1

Using the notation i + 1 indicates to the user to enter Exam Mark 1 not exam mark 0 which would be less intuitive

Array elements are numbered from 0 to n - 1 So an array that holds 20 integers will be addressed from element 0 to 19

ExamMarks[0] -ExamMarks[19]

The first number will be entered into element [0 ] The last into element [19]

cin gtgt ExamMarks[i]

This statement reads in the user input and stores the values in the array elements of ExamMarks[i] i is incremented within the for loop and starts at 0

Task 2

As it stands the program could be generally improved ndash see the notes in the code and consider how you might make such improvements

Next modify the program to output the highest and lowest marks entered

Task 3

Modify the program so that the number of marks may be easily changed (at compile time)

86

Task 4

Modify the program so as to break out the part that calculates the average and put it into a separate function

Write another function that given an array of this sort returns the mode mean and median values ndash you will need to pass in references as the function will need to return three values

Lastly put your two new functions into a separate cpp (you will also have to create a h file for Arraycpp to use ndash this will contain the new functions prototypes)

87

Searching Arrays with Linear Search

Linear search allows the user to search the array and establish whether the array contains a value that matches a search criteria defined by the user

The search compares each element of the array with the user input The array is not sorted and this method of searching works well for small arrays For large arrays linear searching is inefficient and it is necessary to use other forms of array searching after the array has been sorted

Linear Search

Task 1

Open the project LinearSearch

Compile and run the program - choose a number between 1 and 100 The output should be similar to Figure 21

Figure 21

88

Examine the following statements

myArray[i] = (1 + rand() 100) This statement uses the rand function part of the ltstdlibhgt header file (included via iostream being included) 1 + rand() 100 produces integers in the range 0 to 99

The function l inearSearch takes three arguments The array name the size of the array the third argument is the search value

if(theArray[j] == value)

return j

This selection statement compares each element to the search value If the search value is in the array the element number is returned to main() otherwise -1 is returned

The if selection statement if(containingElement = -1) in main() is used select the output indicating a successful or unsuccessful search

Task 2

Currently the program searches for the first occurrence the search value only

Modify the program so that it outputs al l matching element locations

This function can be used for turning an int value into a string See also the comment below about C++11s to_string() functions

string convertInt(int number)

stringstream ss

ss ltlt number

return ssstr()

Youll need to include ltsstreamgt to use the stringstream class

89

Task 3

Modify the program so that repeated searches may be carried out

See Figure 22

If using C++11 or later you can also use the to_string() helper functions of the string class eg to_string(10) yields 10

Figure 22

PLUSPLUS Debugging Linear Search

Task 1

For debugging purposes modify the program so as to output the contents of the array

Open and run (exercise solution) LinearSearch to see what this might look like You might want to use the modulus operator () to work out when to neatly break a line

You may or may not like to have the program generate varying sets of random numbers To facilitate this youll need to seed the random number generator by inserting a line of code like this

srand((unsigned)time(NULL))

Note the use of the cast

To use srand() include timeh at the top of your program

90

Sorting Arrays with Insertion Sort

When working with large quantities of data in an array you will need to sort the data at some point This makes searching for information quicker and there are many algorithms available that can be used In the following exercise you will learn how to sort numbers stored in an array in ascending order

SortingSearching an array

Task 1

Open the project Sorts

Run the program and examine the code

The program currently uses a class (sorts) which is defined in sortsh to implement one popular sorting algorithm called Inser t ion Sor t

For details on this algorithm see

httpenwikipediaorgwikiInsertion_sort

91

Task 2

Add a new sort to the sorts class

The text file quicksor t txt (in the Sorts folder) contains the C++ code required to implement another popular sorting algorithm called Quicksor t17

For details on this algorithm see

httpenwikipediaorgwikiQuicksort

Add the quicksort code found in quicksor t tx t to the sorts class - considering what parts of it need to be publicprivate

quicksort tx t is in the same folder as the Sortss ln project file

Step 2

Test the quicksort implementation on a range of values

Alter the quicksort implementation so as to have it sort in descending order

Following on from Step 3 parameterise the quickSort() function so as to add an option to have the array sorted in either ascending or descending order

17 Invented by C A R Hoare ndash Sir Tony Hoare with Christopher Strachey the most distinguished computer scientists Oxfords ever produced

92

Figure 23

93

PLUSPLUS Binary Search (Binary Chop)

Task 1

Now that the array is sorted we can implement a very efficient searching algorithm usually called either binary search or binary chop search

See Figure 24

Modify your project to allow the sorted array to be searched for a value using the binary chop algorithm See opposite

The algorithm for binary chop is quite straight forward

1 Look at the value of the middle element of the array If the value = target then youre done

2 If the value is lt than target discard the lower half of the array treating the upper half as though it were the complete array

If the value found is gt than target you obviously want to look in the lower half

3 Repeat step 1 until the item is found or else the index value becomes invalid

Pseudo code for this algorithm is here

first integer = 0

mid integer = 0

last integer = NumberOfItems

while first ltgt last

begin

mid = first + last 2

if List[mid] = target

exit while Found item

If List[mid]gt target

last = mid In the first half

else

first = mid + 1 In the last half

end

found boolean = List[mid] = target

94

Figure 24

Multidimensional Arrays

Multidimensional arrays with two dimensions (arrays can have more than two dimensions) may be thought of as consisting of data arranged in rows and columns see Table 3

Each element in the array is identified by using two subscripts as shown in Table 3 The first subscript identifies the element row and the second identifies the element column a[0] [1] identifies a value in Row 0 Column 1

The array in Table 3 contains two rows and three columns and can be called a 2 by 3 array

Column 0 Column 1 Column 2

Row 0 a[0] [0] a[0] [1] a[0] [2]

Row 1 a[1] [0] a[1] [1] a[1] [2]

Table 3 ndash Array Layout

A multidimensional (2 by 3) array of doubles is shown in Table 4

Column 0 Column 1 Column 2

Row 0 2367 6792 8557

Row 1 1276 9132 2789

Table 4 ndash Array Values

95

Creating a multidimensional array

Task 1

Open the Mult iDimArray

project

Compile and run the program adding 2 exam results for each of the two students The output should be similar to Figure 25

Figure 25

96

Task 2

Examine the code used to write values to and read from a multidimensional array

Examine the following code segments

double ExamMarks[2][2] = 0 This statement creates a two-dimensional array having two rows and two columns and initialises the elements to 0

Every element in the array is identified by an element name in the form a[x] [y] where a is the name of the array and x and y are the subscripts that uniquely identify each element in a Notice that the names of the elements in row 0 all have a first subscript of 0 see Table 5 The names of the elements in column 1 all have a second subscript of 1

Note multidimensional arrays can have two or more dimensions (subscripts) Three-dimensional arrays are uncommon

Column 0 Column 1

Row 0

a[0] [0] a[0] [1]

Row 1

a[1] [0] a[1] [1]

Table 5 ndash Array Indexing

97

Examine the following code segment used to read values in to the array

for(int row = 0 row lt 2 ++row)

for(int col = 0 col lt 2 ++col)

cout ltlt Enter Exam Mark No

ltlt col + 1

ltlt for student No

ltlt row + 1 ltlt

cin gtgt ExamMarks[row][col]

cout ltlt endl

The two for loops work taking one row at a time (the outer for loop) and looping through the columns in that row (the inner for loop) When the marks have been entered for all the columns in row 0 row 1 is selected and values entered for each column cell in row 1

Table 6 shows how four results would be allocated in a 2 x 2 multidimensional array

Exam mark 1 Exam mark 2

Student 1 67 71

Student 2 61 58

Table 6 ndash Populated Array

98

Examine the following code segment used to calculate the total of each students marks

if(row == 0)

r1total += ExamMarks[row][col]

else

r2total += ExamMarks[row][col]

r1total is a variable to hold the sum of values in column 0 and 1 for row 0 (Stud1) r2total sums the values in the columns for row 1 (Stud 2)

Selection for each row is made with if(row == 0) this is Stud1 If row is not 0 then row must be 1 and the mark can be added to r2total If three exam marks were input per student the code for selecting the marks would need to change

Task 3

Modify the program to read in four exam marks for f ive students

Establish the highest and average mark for each student Output the results

One way to do this is to keep a separate array to record the students statistics An alternative would be to extend the existing arrays row so that it may hold the necessary student data

99

Declaring and using vectors

Vectors are declared indicating the type and number of elements in the following way

vectorlttypegtvectorName

vectorlttypegtvectorName(initialSize)

vectorlttypegtvectorName(initialSize elementValues)

Examples

A vector called i nNumbers with no initial size to hold doubles

vectorltdoublegt inNumbers

A vector called Name with an initial size 20 to hold characters

vectorltchargt Name(20)

A vector called ExamMarks holding integers with initial size of 4 elements each with the value 6

vectorltintgt ExamMarks(46)

Note In previous exercises you have created your own member functions In the following exercises you will use some of the vector class member functions Some of these are begin() end() erase() and size() See section 12115 for more detail

The standard library also includes a large collection of algor i thms that manipulate the data stored in containers (vectors are one of several types of container)

You can sort the order of elements in a vector (vec) for example by using the sort algorithm

sort(vecbegin() vecend()) C++11 sort(begin(vec) end(vec))

You can find a value (69) in a vector by using the find algorithm

ptr = find(vecbegin() vecend() 69) See C++ note above

100

ptr is an iterator to store the memory location of the element found

You can reverse the order of elements in a vector for example by using the reverse algorithm

reverse(vecbegin() vecend()) See C++ note above

There are two important points to notice about the call to reverse First it is a global

function (as are find and sort) not a member function Second it takes two arguments rather than one and operates on a range of elements rather than on the container (vector container in this case)

With the above examples the range is the entire container from begin() to end() (vecbegin() to vecend()) reverse like the other standard algorithms is decoupled from the libraries container classes The reverse algorithm can be used to reverse elements in vectors in lists (another container) and even elements in C arrays

int myArray[] = 1 6 20 4

reverse(myArray myArray + 4)

for(int i = 0 i lt 4 ++i) Lets see the reversed array

cout ltlt Array[ ltlt i ltlt ] = ltlt myArray[i]

In the above example the first argument to reverse is a pointer (pointers are covered in Section 8 but for now we can say the first argument points to the address in memory that is the start of the vector ) to the beginning of the range and the second argument points one element past the end of the range This range is denoted (myArray myArray + 4)

Arguments to reverse are i terators which are a generalization of pointers which is why it is possible to reverse the elements of a C array using the array address and pointer notation

Creating a vector to hold exam results

Task 1

Open the Vector project

Compile and run the program adding five exam results The output should be similar to Figure 26

101

Figure 26

Examine the following statements

include ltvectorgt This statement includes the header file vector enabling the program to use the class template vector (templates allow the use of generic functions that admit any data type as parameters and return a value more on this later)

vectorltdoublegt ExamMarks(5) This statement declares the vector to hold doubles and sets the initial size to 5 elements

Note Although vectors can grow to any size it is good practice and more efficient to specify the size when this is known When no size is given and the contiguous memory spaces have been exhausted the elements must be copied to a larger memory space to increase the size of the vector

cin gtgt ExamMarks[i] This statement reads in the user input and stores the values in the vector slot i of ExamMarks[i] i is incremented within the for loop Note that we the same indexingsubscripting syntax as we used previously with arrays ie[ ]

102

Task 2

Modify the code so as to accommodate the adding of an extra exam mark

Note this should not be done (simply) as part of the loop but as a separate action later and you should use the vectors push_back() method to facilitate this

push_back() is a member function of the vector class that adds an additional vector element at the end

After adding the extra mark you will need to generate a new set of statistics ie the average will have changed now To do this separate out the statistical code and place it in a separate function so that you may re-use later (after the new data has been entered)

size() is a member function (method) of the vector class It can be used to establish the size of a vector

The statement for(int i = 0 i lt ExamMarkssize() i++) uses the vector member function size() available to the vector ExamMarks to obtain the size (number of elements) in the vector The size of the vector is used to identify a terminating value that ends iteration of the for loop

Task 3

Open VectorSor t

You will see three TODO sections in the code which need completing

1 Populate a vector with 100 randomly generated numbers

2 Sort the vector

3 Reverse the vector

For sortingreversing you will can use the algorithms sort() and reverse()

Heres a useful link hellip

httpwwwcpluspluscomreferencealgorithm

103

Using insert() and iterators

Task 1

Open and modify the skeleton project called Inser t

Important areas of the program are explained in the steps opposite

Examine the code

vectorltintgtiterator it

This statement creates an iterator that is used to access members of the vector

Iterators are used to access members of the container classes (the container type vector in this case) and can be used in a similar manner to pointers

In the example iterator it is used with the insert() function to place the value (200) at the beginning of the vector nums

it = numsbegin()

This statement uses the vector member function begin() to initialise the iterator it with the address of the start of the vector

it = numsinsert(it 200)

This statement uses the member function insert() and iterator it to insert 200 at the beginning of the vector (it)

Note that an iterator is returned by the function insert() that points to the newly inserted element

104

numsinsert(it + 1 numsTwobegin()

numsTwoend())

This version of the insert() function takes 3 arguments and is used for copying in part or full another collection This may be a vector a plain C++ array or some other collection that is accessed using pointersiterators

This statement inserts a second vector (numsTwo) into nums The three parameters are (copy to nums+1 from star t of numsTwo to end of numsTwo)

it = numsinsert(it + 2 696 )

This version of the insert() function takes 2 arguments The iterator it + 2 points to element number three it points to the beginning of the vector and the 2 moves two elements in The value 696 is inserted at that element

void display(vectorltintgt amp vec)

cout ltlt Vector contains

for(

unsigned int i = 0

i lt vecsize()

++i

)

cout ltlt vecat(i) ltlt

Function display() is passed a reference to a vector and outputs the vector contents used throughout program

105

Task 2

Add the code shown in Figure 27 to the program and using the insert() member function add the array to the nums vector at position two (in the vector) Output the contents of the nums vector to screen

int myArray[] = 5 6 3 4

Figure 27

stdarray

C++11 Introduced a new template array type called stdarray

stdvector is a template class that encapsulates a dynamic array that is stored on the heap and that grows and shrinks automatically if elements are added or removed It provides all the hooks (begin() end() i terators etc) that make it work fine with the rest of the STL It also has several useful methods that let you perform operations that on a normal array would be cumbersome like inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes) Since it stores the elements in memory allocated on the heap it has some overhead in respect to static arrays

stdarray is a template class that encapsulates a static array that is stored inside the object itself which means that if you instantiate the class on the stack the static array will be on the stack Its size has to be known at compile time (it is passed as a template parameter) and it cannot grow or shrink

It is more limited than stdvector but it is often more efficient especially for small sizes because in practice it is mostly a lightweight wrapper around a C-style array However it is more secure since the implicit conversion to a pointer is disabled and it provides much of the STL-related functionality of stdvector and of the other containers so you can use it easily with STL algor i thms

Here is a small example demonstrating the template and some other C++11 extras such as auto and a ranged-based for loop

106

include ltstringgt include ltiteratorgt include ltiostreamgt include ltarraygt using namespace std template ltsize_t N class Tgt arrayltT Ngt make_array(const T amp v) arrayltT Ngt ret retfill(v) return ret int main() The char here can be inferred and so is optional auto a = make_arraylt10 chargt(1) for (const auto amp s a) stdcout ltlt s ltlt system(pause) return 0

1 1 1 1 1 1 1 1 1 1 Press any key to continue

Declaring and using lists

Lists are a kind of sequence container similar to vectors The elements of a list are ordered following a linear sequence with storage handled automatically by the class

List containers are implemented as doubly-linked lists and it is worth noting that elements may be in different and unrelated storage locations

Ordering of a list is kept by a relationship to each element of a link to the element preceding it and a link to the element following it

Because linking information is associated with each element (possibly to different and unrelated storage locations) extra memory may be used to keep the linking This may be important when using a large list

l is ts tend to perform better than vectors at inserting extracting and moving elements in any position within the container but lack direct access to the elements by their position and because of this have a slower access time than vectors Access to an element has to be via a known position (the beginning or the end) and there is a time cost in linking between the known position and the element to be accessed

107

lists are declared indicating the type and number of elements in the following way

listlttypegt listName

listlttypegt listName(initialSize)

listlttypegt listName(initialSize elementValues)

Examples

A list called inNumbers with no initial size to hold doubles

listltdoublegt inNumbers

A list called Name with an initial size 20 to hold characters

listltchargt Name(20)

A list called ExamMarks holding integers with initial size of 4 elements each with the value 6

listltintgt ExamMarks(46)

72 Hash Tables and Cached Calculations

This section has ultimately really been about introducing you to templates and algorithms and well mix both now in a final example

From the binary chop exercise earlier we have seen that sorted arrays provide a very efficient means of storing data for later look-up However we have to bear in mind the algorithmic cost of sorting the array in the first place ie if we have a million unsorted items in our list and we want to find a single item (only) is it better to sort the entire list first and then find the item or is it better to simply walk through the array from the beginning ndash after all we could safely assume that weve a 5050 chance of finding it in the first half of the array Of course as were sorting we could keep an eye open for our item ie we could combine a (partial) sort with look-up operation ndash over time if we repeat this procedure looking for other items we will ultimately sort our array as a side -effect of the look-up operations

But lets move on a little and just consider the fastest look-up method we know so far that carried out on a sorted array using binary chop and think about our programs overall performance when we need to insert additional items into the array When considering problems like this we always think of the worst case hellip despite their often being fans of

108

Monty Python Computer Scientists rarely look on the bright side of life The worst case here is that we need to insert an item into array position zero

Eg say we have this sorted array (look-up operations average O log2 N = fast)

15 24 25 31 78 250 255 262 277

We now have to insert the value 5 into this array Using normal array indexing methods how many operations will this take

5 15 24 25 31 78 250 255 262 277

Each item needs to be shuffled up one position to the right and if weve millions of items that is rather costly especially if the next thing were likely to do is to insert another item

So weve seen that accessing sorted data is very useful and weve also seen that sorting and especially inserting items can be costly The big question is then is there a way we can make both just as efficient - finding andor inserting an item in Olog2N or O(1) (constant time)

Hash Tables

A hash-table is a data structure designed to allow for both rapid insertion and look-up

Although any specific hash-table is implementation specific (there are very many different types of hash-table) well quickly go through the basics

The storage medium well use for our hash-table is an array of strings and we will say that this array has just 10 elements It looks like this

string myhash[10]

Well use this hash-table to store words and well determine the array index for any specific word using a hash- funct ion ndash something that will take a word as its input and return an array index as its output

109

unsigned hashfunc(string s)

unsigned result = 0

for(unsigned i = 0 i lt slength() ++i)

result = result + s[i]

return result 10

hashfunc() iterates through s keeping a running total of the sum of the ASCII codes for each of the characters eg hashfunc(hash-table) computes

h + a + s + h + - + t + a + b + l + e

where the characters ASCII values are

104 + 97 + 115 + 104 + 45 + 116 + 97 + 98 + 108 + 101

The total = 985 and 985 modulus 10 = 5

The final computed value will be used as an index into the array The modulus value used is the size of the hash-table and we use it so as to ensure that resultant computed index value cannot be greater than 9 (remember our arrays indexes are 0 ndash 9)

We can now store words in the myhash array like this

string myhash[10]

string s = hash-table

index = hashfunc(s)

if(myhash[index] = )

myhash[index] = s

else

The complex part is what to do if we have what is called a collision ndash when we find that myhash[index] is already occupied Youll probably have already thought of what value hashfunc(elbat-hsah) will have

One way to help avoid collisions to use a better hash-function and a larger array However in real life collisions are practically impossible to avoid and the only other option to deal with them is to allow more than one string to inhabit an array slot in some way ndash perhaps by having each of the original array slots contain an array ndash rather than an individual string Of course in this case we would also need some way to determine which of the n colliding entries is the one were interested in ndash is it elbat-hsah or hash-table

110

Well briefly leave our examination of hash-tables at this point and instead look at Fibonacci numbers Do not worry we will return to hash-tables very soon

Fibonacci numbers are the numbers in the following integer sequence

0 1 1 2 3 5 8 13 21 34 55 89

By definition the first two numbers in the Fibonacci sequence are 0 and 1 and each subsequent number is the sum of the previous two More formally that is

119865119899 ∶= 119865(119899) ∶=

0 119894119891 119899 = 0 1 119894119891 119899 = 1

119865(119899 minus 1) + 119865 (119899 minus 2) 119894119891 119899 gt 1

Computing Fibonacci Numbers

Task 1

Open Cached_fibonacci

Compile and run the program as is

Examine main() and the calcfib() functions

bigint calcfib(bigint n)

if(n == 1 || n == 0)

return n

else

return calcfib(n - 1) + calcfib(n - 2)

bigint is defined as a unsigned long long int and we have used typedef to save some typing

NOTE The method used to calculate Fibonacci numbers here has been selected because it is perhaps the most obvious way to turn the formal definition into code If you are interested please see the separate Fibonacci project for two other examples of how to calculate Fibonacci numbers

111

Modify the beginning of the calcfib() code

bigint calcfib(bigint n) cout ltlt calcfib was passed ltlt n ltlt endl

Modify main() to set max = 5 and re-run the program

calcfib was passed 0 Fibonacci number 0 is 0 calcfib was passed 1 Fibonacci number 1 is 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 2 is 1 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 Fibonacci number 3 is 2 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 4 is 3 calcfib was passed 5 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1

Fibonacci number 5 is 5

112

Note that to calculate Fibonacci number 5 we calculate Fibonacci number 4 and Fibonacci number 3 - even though weve previously calculated Fibonacci number 3 in order to calculate Fibonacci number 4

To fully appreciate the growth of this process re-run the program adding 10 to max for each subsequent run You maymay not like to comment out the line you inserted in Step 2

Task 2

Getting back to Hash Tables Using a hash-table to store previously computed Fibonacci numbers

As it stands the incomplete solution declares a template hash-table called fibs of the type unordered_map

Read the comments in the function fibCache() and modify the code to as to use the fibs hash-table to store previously computed Fibonacci numbers

fibs[n] = f stores f the n-th Fibonacci number in the n-th slot of fibs (which as you can see you may treat as an array for indexing into)

8 Pointers In C++ programming data (variables) can be referenced via the memory address of the variable This is done using a pointer var iable

A pointer var iable contains the address (location in memory) of a data variable

There are also functional pointers ie those that point to code rather than data and these are briefly explored later

Pointers can be particularly useful when interacting with the operating system andor when working with arrays - as the elements in an array will always occupy consecutive memory places Incrementing the pointer variable by one addresses the next array element

Lastly pointers are also used to fake pass by reference

Declarat ions

int n This is a standard variable declaration n that contains a value as yet unknown of type int

int p This is a pointer p that can hold (point to) an address that contains a variable of type int The type of p is int

Each variable declared as a pointer must be preceded by an asterisk () This modifies the type of the object being declared from thing of type to pointer to thing of type Eg int n means n is an int whereas int n says that n is a pointer to an int

113

int age height age is a pointer to an int height is an int value

double far cent are both pointers to doubles

Pointers can be initialised when they are declared or set using an assignment It is common to initialise pointers to a memory address but they can also be initialised to the predefined constant NULL ndash meaning that they do not (as yet) hold (point to) a valid memory location NULL is defined in the standard library such a pointer is called a nul l pointer

When is used in a variable declaration it indicates the variable being declared is a pointer and not a value

But do beware as is used elsewhere with pointers when the appears before a previously declared pointer variable elsewhere in the program it is said to dereference the pointer and so is used to access data stored at the address which is stored in the pointer A dereferenced pointer is essentially the variable to which the pointer was originally set to point

To complicate matters further using the pointer name without the dereference operator references whatever is stored in the pointer variable itself ndash this is the address of the object it references in memory (which maybe NULL of course)

As we have seen using can mean two things that something is being declared as a pointer or that a previously declared pointer is being dereferenced Experienced programmers sometimes enter the two usages differently ndash a notation we would highly recommend ie

int n n is an object that can hold the address of an int

int k = 0 k is an int holding the value zero

n = ampk n is set to hold ks address amp is explained below

n = 1 k (yes k) is set to hold the value 1

Note the space used in the different usages - int n vs no space in n

Initialising pointers

Pointers can be initialised in two ways

int x = 16 y = 69 variable declaration and initialisation int x_ptr = ampx pointer declaration and initialisation x_ptr holds the address of x int y_ptr pointer declaration yptr is a pointer

y_ptr = ampy pointer assignment yptr holds the address of y

Once declared a pointer variable can be assigned the address of another variable using the amp the addressof operator

114

Note the variable name should not be prefixed by the in the assignment statement unless the pointer is initialised immediately in the variable declaration

We also use pointers when creating objects on the Heap for example we can create and initialise a string object like this string pstring = new string(Hi there) Such objects are not normally tidied away as are the objects created on the stack - objects simply declared in a functionmethod and so they should explicitly be tidied away using delete eg delete pstring For more on this subject see section 9

Using pointers

Task 1

Open the project Pointers

Compile and run the program The output should be as shown in Figure 28

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int x_ptr = ampx This is x_ptr pointer declaration and initialisation

int y_ptr Declaring another pointer y_ptr

y_ptr = ampy Initialising y_ptr

y_ptr = x_ptr Assigning x_ptr contents to y_ptr Both pointers are pointing to variable x (16)

y_ptr = ampy Assigning the address of y back to pointer y_ptr

y_ptr = 170 Assign 170 to the variable at memory location of y_ptr y_ptr points to variable y so 170 has been assigned to y

115

Figure 28

Pointer Arithmetic and Arrays

We have seen that once a pointer is initialised it has a memory address and this address can be reassigned another address It is also possible to change an address using standard arithmetic

The ++ and -- increment and decrement operators can be used to move the pointer along to the next or back to the previous memory address To jump more than one memory address you would have to use the assignment operators += and -=

When using arrays and pointers the array name is the address of the first element in the array

int intArray[] = 1 2 3 4 5

int int_ptr = intArray Same as int int_ptr = ampintArray[0]

The pointer has been declared and initialised with the statement int int_ptr =

intArray Note there is no need to use the address of operator amp when initialising arrays as the array name is the address of the beginning of the array

When working with arrays each element of the array will be the type and size at declaration When an array is declared to hold integers each element will usually be 4 bytes in size An array of doubles will have element sizes of 8 bytes Note ndash these sizes are actually down to the compiler being used and are usually in turn dependent upon the operating system being used

It is not important to know how many bytes make up each element Moving the pointer through the array with the assignment operator x_ptr += 2 will move two elements further through the memory allocated for the array or 16 bytes for an array of doubles

116

Pointers and Arrays

Task 1

Open the project PointerAr i thmetic

Compile and run the program The output should be the same as Figure 29

Examine the program carefully

You may not fully follow the program at first glance as it employees a few potentially new constructs (it depends how far weve got through the lectures)

One slightly truncated new construct is

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

A struct in C++ is just like a class except that the default public and private sections are reversed By default everything in a struct is public

typedef in C++ allows the definition of our own types based on other existing data types

typedef exist ing_type new_type_name

where exist ing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining For example

117

typedef unsigned int WORD

typedef char pChar

You may also remember initialiser lists from earlier eg

s_thing(int a) a(a) b(sqrt((double)a))

If we re-write this

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

We quickly see that a(a) and b() are initialising the a and b struct members const int a and const double b

118

Remember that as these are const we cannot use assignment

typedef struct s_thing

const int a

const double b

s_thing(int a)

Error ndash a and b are const

this -gt a = a

this -gt b = sqrt(a)

thing

Lastly when dealing with pointers to compound types one may access the members of the type via dereferencing or via the so called crows foot operator

(t) dereferences t giving us a thing which was pointed to by t Then we use the dot operator to access the member (t)a

We have to parenthesiset otherwise the would bind to t first ie it would be as though we had done this (ta) which would be an error

The crows foot saves us the dereference t-gta is just like (t)a

119

Figure 29

PLUSPLUS Pointers and Arrays

Task 1

Open and modify the skeleton project called ReverseArray

In main() create an array of 10 integers Fill the array with random numbers between 0 ndash 100

Write a helper function called to output the contents of the array to the console A suitable prototype for this would be void dumpArray(int array[] int size)

Write a helper function to reverse the contents of the array Use a temporary variable as an aid A suitable prototype for this function would be void reverseArray(int array[] int size)

Reverse the values in the array using only pointers

120

Reverse the array without using a temporary variable You should use the XOR operator ^ to achieve this

Pseudo code for an XOR swap is

X = X XOR Y

Y = X XOR Y

X = X XOR Y

The completed program should look like Figure 30

Figure 30

Task 2

Reverse the array using a vector and the standard function template stdreverse()

We can also have pointers to functions in C++ (and C)

The name of a function resolves to be its address in memory (somewhat similar to the case where we use the name of an array) When we call a function we use this name to retrieve the functions address and then use the function invocation operator to execute it The function invocation operator is the set of brackets you use eg

Lets take an example

121

include ltiostreamgt

using namespace std

int lue() life the universe and everything

return 42

int main()

cout ltlt The address of the function lue is

ltlt lue

ltlt invoking it yields

ltlt lue()

ltlt endl

system(pause)

return 0

Typical output is shown in Figure 31

Figure 31

122

We can also store addresses of functions in variables (theyre just numbers) and the type system allows for us to describe and declare scalar variable types for function pointers eg this modified code fragment would produce the same output as that show above

fp is a pointer to a function taking

no arguments and returning an int

int (fp)()

fp = lue

cout ltlt The address of the function lue is

ltlt fp

ltlt invoking it yields

ltlt fp()

ltlt endl

fp is a funct ion pointer var iable so it may be used to point to any other function having the correct signature at runtime

PLUSPLUS Function pointers

Task 1

Open the project Calculator

Compile and run the program The output should be as shown in Figure 32

123

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int (fp)(int int) This is the function pointer declaration It may point to functions that take two integers and return an integer

Like all automatic storage class variables fp will currently be pointing at a random location What happens if you run the program without setting fp to point to an actual function Comment out the switch to find out

switch (Operator)

case 0 fp = Add break

case 1 fp = Subtract break

case 2 fp = Multiply break

The code could do with improving

Modify it to allow for multiple trials eg add the necessary logic to loop and perform multiple calculations ndash youll need to add some way to end the program too therefore

Modify it so that the operator may be inputted as an operator character eg + - etc Allow X x and for multiplication and add for division

All three pieces of information could be entered on a single line eg 6 x 7ltentergt Using cin to read that data just requires you to use three cin statements

cin gtgt X

cin gtgt Operator

cin gtgt Y

Lastly modify the program to that it uses floating point arithmetic

124

Figure 32

9 APIs New Delete and Dynamic Memory As has been stated earlier pointers are useful in a variety of situations However because they are easy to get wrong ndash and when they go wrong everything goes very wrong indeed ndash languages like C++ have tried to make their use the exception rather than the norm For example without reference arguments (eg void someFunc(int amp)) we would have to use pointers to achieve the same functionality and performance

On the whole the underlying philosophy when it comes to pointers is to try to avoid using them whenever possible You can get a real feel for this subject by Googling for smart pointers c++ and from Wikipedia httpenwikipediaorgwikiSmart_pointer

Two areas where we absolutely need pointers are when calling into an external API (Appl icat ion Programming Interface ) and when allocating memory for our own purposes ndash the latter case is also eased by advances in the library support in C++

Using an API

An Appl icat ion Programming Inter face is functionality provided by some third party The most obvious API whether it is Windows Linux or OSX is that exposed by an operating system

If your application needs to interact with the user in any non-portable way you will need to call into your OSs API For example if you want to display a dialog box you will need to access the OSs functionality to do so (perhaps indirectly through a framework like Nokias Qt - httpsenwikipediaorgwikiQt_(framework)) In summary if you ever want to go outside of the standard libraries andor writing consoleterminal applications you will need to call into your operating systems API

When it comes to calling into operating systems pointers are used extensively As an example 1 Google for Linux API 2 Find any website that lists the API functions and then 3 click-through to any function The odds are that the function prototype you see will contain asterisks (pointers)

125

Dynamic Memory Management

The second area where you simply must know something about pointers is when it comes to using the heap

The heap is an area of memory available to your programs You may allocate and use the heap as you wish

Why would you want to do this Normally its to create variable length arrays or to model and use an advanced data structure of some sort a self-balancing red black tree perhaps (httpenwikipediaorgwikiRedAndblack_tree) Of course the more esoteric the data structure and less likely it is that it will be incorporated into the C++ standard library (although the library does contain most of the generally useful and popular ones like doubly l inked l is ts )

To allocate memory from the heap in C++ you use the new keyword and to return it you use the delete eg

int nSize = 12

note nSize does not need to be constant

int pArray = new int[nSize]

pArray[4] = 7

delete [] pArray

10 More on Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine Encapsulation is data information or detail hiding

Once a function is written the detail of how it works is not important to the end user The user needs to understand what data to input and what output will be produced

One of the most important aspects of writing programs using functions is that the functions can be reused from one project to the next Think about the standard functions youve seen already eg the square root function sqrt() Libraries contain atomic generally useful functionality that is likely to be of use at some future time It is useful to bear this thought in mind whenever we build new programs ie we should be on the lookout for generally useful functionality (given our domain) that we should consider coding as functions for later reuse The same goes for classes of course

Probably the most important function in your program in main() ndash without it you do not have a program at all

main() is your programs entry point and as such it may be used in such a way as to inform the rest of your program as to the actions required

126

main() and command-line arguments

Task 1

Open a Command Prompt or PowerShell Prompt and enter the following

dirltreturngt

di r Odltreturngt

t ree ltreturngt

t ree altreturngt

dir and t ree etc are like mini-programs They have default functionality which may be altered by providing additional command-line arguments eg for the dir command dir L N 4 TC

Command-line arguments are passed to your programs by optional parameters eg

int main(int argc char argv[])

Where argc is a count of the number of arguments and argv is an array of pointers to arrays of character (C strings) for each argument being passed Note that argc is always at least 1 and so argv always contains at least one entry ndash this is the name of the program being run

Task 2

Open (demonstrat ion)

CommandLineArgs and Build and run the program

Examine the code

The programs configuration is Debug

In the projects Project | Debugging | Command

Arguments you will see where the programs default command-line arguments are set for debugging purposes

Using the command prompt you opened earlier navigate to your where CommandLineArgsexe is located

CommandLineArgs debug

Run the program by entering its name followed by a variety of arguments eg

gtCommandLineAgs one two threelte ntergt

127

Task 3

Open the project UserPrompter project

Run the program and then examine its code

We will modify this program to use a command-line argument However before doing that its worth pointing out that the primary purpose of this program is to demonstrate the separation of a class declarat ion with its implementat ion (the mechanismfunctionality of class prompter is defined in promptercpp but its capabilities are declared in prompter h )

Its also interesting to note that the optimal strategy is to use an algorithm called binary search or binary chop (we saw this earlier in the course) with each guess you reduce the number of possible solutions by a half This sort of algorithms Big Oh is Log n (where log is base-two logs)

httpenwikipediaorgwikiBig_O_notation

Task 4

Modify the program so that the upper range for the max value is given as a command-line argument

The UserPrompter cpp is the file youll need to modify

Test your program via the setting the projects Command Arguments as detailed above -or- by running the application standalone in a command prompt after building (also as detailed above)

See Figure 33

To convert a string into a number (weve seen one other way of doing this earlier) we can use

include ltcstdlibgt

and the function atoi() eg

atoi(argv[1])

128

Figure 33

EncryptDecrypt a file

Task 1

Open compile and run the EncodeDecode project

Complete the program so that it may be run outside of the IDE and process a file for encryptiondecryption

This is actually quite a simple task as youll only need to add a couple of lines of code However the project also demonstrates how to use the Debug and Release modes to influence the way a program runs ie that in its Debug configuration the program automatically runs through a test

Other things to note include using bitwise XOr to perform the encoding and the use of the C standard library functions putchar() and printf() to perform some of the output eg putchar() is used to output a CR to the console window (CR = char 13)

129

Figure 34

Multiple arguments overloading and default values

In C++ we can over load functions ndash meaning that we can provide different versions of the same function (the different versions must differ by the number andor type of the parameters they take) For example

130

void foo(double d) 1

cout ltlt In void foo(double d)nn

void foo(long int n) 2

cout ltlt In void foo(long int n)nn

void foo(int n) 3

cout ltlt In void foo(int n)nn

double dtest = 0

long int ltest = 0

int ntest = 0

foo(dtest) Calls 1

foo(ltest) Calls 2

foo(ntest) Calls 3

In the above the compiler works out which version of the foo() to call based upon the argument type it is given

We can also overload functions if the number of arguments differ eg

131

void bar(double d)

void bar(double d double t)

We would use a feature like this if sometimes we needed to use extra information ndash in the shape of passing in t in the above eg we would most likely implement void bar(double d) as

void bar(double d)

bar(d 25) Call bar(double d double t)

What were really saying above is that in most cases the implicit double second parameters value is normally 25 ndash perhaps its a standard discount percentage ndash and only occasionally we will need to change that value in which case wed call bar(double d double t) directly and not by going through bar(double d)

Lastly C++ has one extra feature that can make this simpler ndash defaul t arguments

Rewriting bar using this feature we get

void bar(double d double t = 25)

Note that we now only have one bar function now and that we may call it like this

bar(x)

Or like this

132

bar(x y)

In the case of bar(x) the second parameter is omitted and so will receive the default value of 25 in the second example t will receive ys value

Although outside the scope of this class for more on overloading see the (demonstrat ion) Operator Over loading project This shows how to overload the ++ pre and post increment operators overload and provide your own ltlt stream insertion operator (and one use of a friend function) and using an enum with a typedef

Passing Arrays to Functions

To pass an array to a function it is only necessary to pass the array name and the number of elements in the array

The array name is the position (address) in memory of the first element The number of elements is passed to enable the function to establish the array size

An array declared as double somearray[10] would require a function call somefunction(somearray 10)

Passing Arrays to functions

Task 1

Open and modify the skeleton project called the project called ArrayReturnValue

Pass an array to a function to read in five numbers

Pass the array to another function to calculate the average value in the array return this to main() and output to screen

Lastly at the end of the program output the values in the array from within main() The finished program should look something that that in Figure 35

Create two function prototypes

void enterMarks(double ExamMarks[] int num)

double calcAverage(double ExamMarks[] int num)

ExamMarks[] is the array to be passed As with passing variables it is not strictly necessary to give the argument a name in the prototype just its type This could have been written as calcAverage(double [] int) However it is sometimes useful to include this information as it might help explain the functions operation

It is also necessary to pass the size of the array num is the number of elements in the array its size

Within main() declare the array and initialise the elements to zero with the following statement double ExamMarks[5] = 0

This declaration explicitly initialises the first element to zero and implicitly initialises the remaining four to zero

133

Create both functions

enterMarks to read in the values and calcAverage to calculate the average (you will need a for loop in each function)

Return the average value from calcAverage to main() and output the value using cout

Call the functions from within main() with the following statements

enterMarks(ExamMarks 5)

average = calcAverage(ExamMarks 5)

You may output the average directly of course ie without first storing the value in average

At the end of main() add the statements

for(int i = 0 i lt 5 ++i)

cout ltlt Exam Mark Number

ltlt i + 1

ltlt is

ltlt ExamMarks[i]

ltlt endl

ltlt endl

134

Explain how it is possible at the end of the program to output from within main() all the values in the array entered within the function

Modify the program so that the number of exam marks (5) appears only once

In previous exercises when parameters (variables) were passed to functions the function received a value When a value is used in a function a copy is stored in a part of memory that only exists from the time the function is called to when it ends After this the memory and any value in it are lost

However the array in this exercise was initialised in main() with zeros and then passed to the function Data was then added to the array and calculations done At the end of main() the values in the array elements are output The array contains values input from within the function

The name of the array is the address of the first element of the array in the machines memory As the starting address is passed (the name of the array) the called function knows where the array is stored in memory

Because we are working with memory addresses (references ) any changes made to array elements in the function affect the memory location set up in main() for the array

C++ passes arrays to functions by reference (to the memory location of the first element) In previous exercises functions were passed values copies of the variables in main()

135

Figure 35

Passing Two-dimensional Arrays to Functions

It is common to want to store numbers in a two dimensional layout of rows and columns as shown in Table 7

187645 783473 298372

871223 629399 561201

Table 7

This arrangement is known as a two-dimensional array or matrix

C++ uses an array with two subscripts to store a two dimensional array

double Balance[2][3]

When we specify a one-dimensional array the number of elements must be given

When a two-dimensional array is specified it is necessary to specify the array elements in both dimensions We therefore specify the number of rows and columns

The Balance array in the statement above has two rows and three columns

11 Inheritance and (not presented) Polymorphism

111 Inheritance

In Object Oriented languages like C++ inheritance describes a relationship between classes of objects and which usually implies some sort of a sub-division of labour

For example lets say that we want to build an IT system that has something to do with the members of the university

136

In an OO world the first question usually is how would we categorise our significant entities and that always means naming things what names would we use to categorise university members When modelling (for that is what were going to be doing) real-world objects its sensible to use proper names So heres an attempt ndash to broadly categorise university membership

Members are members of the sets

Students

Staff

Other

What is other though

The Bodleian and the card-office issue Readers cards ndash so is a Reader a university members or are they something else And if they are something else does our system really want to concern itself them Or more broadly does our system really want to concern itself with holders of cards issued by the card-office

Are all students really the same

What sort of students do we have at Oxford (and do we want a system ndash either now or in the future ndash that might be interested in recording the differences) Lets see we have undergraduates and graduates We also have Rhodes scholars ndash but are these sorts of student that are distinct (or should be in our system) from our underpost-graduates categories And how about graduates would we want to have some sort of sub-groups Masters students MScMBAMPhil or Doctoral students DPhilDScDLitt etc Perhaps wed like to know something about how theyre being funded ndash and we might want that piece of functionality shared by our undergraduates

We can of course go through the same process when thinking about members of staff (university staff departmental staff members of congregation academic staff fulltimepart-time staff casual staff ndash and how about staff that are sometimes (or also) students) We can go on thinking about this sort of thing for a very long time and we should as its important and when its important it has a name ndash Object Oriented Design or OOD

One of the things wed hope to see appear as part of the OOD phase is the relationship between entities For example if we were to say that a common property of all university members is that they have a date-of-birth we wouldnt want to have our Student and Staff C++ objects contain this information directly by way of some datastate class member (which might seem a little odd at first) But think about it If we performed some validation on the members DoB (perhaps when its being set) we would need to include this in both Student and Staff classes Or as an alternative we would capture the validation in some external function ndash which we would call from the separate classes (if we remember) No its messy and it would be much better if we thought of things this way that all university members are people and that people all have dates of birth

To put it another way we would say that studentsstaffother are just specialisations of people ndash they are people but with a bit of extra something tagged on to them ndash like a bod card number

Now if we also had some way of capturing people stuff in say a basic Person class and could somehow use that automatically ndash perhaps by deriving a Member class from it and then doing the same from Member to both Staff and Student classes from Member One thing though ndash we wouldnt want someone to be able to instantiate a Member object

137

perhaps ie in our system Member is an abstract class Imagine a generic Car vs a Renault Clio ndash it makes no sense to create a Car object ndash there are no generic cars on the road they are all specific cars Similarly we wouldnt want a generic Member wandering around our system (if you remain unconvinced well see why later)

Modelling a student - a first attempt

Please note that in this Introduction to C++ we do not expect you to complete an exercise that requires coding from now on Please just look through the code and follow along with the discussion

Base classes

Task 1

Open the project UnivMember1

Examine the program carefully

The project contains three classes Person Member Student In main() we create a Student and then attempt to output the students name ndash which fails

name is in the protected section of Person ndash which means only Person methods or methods in derived-from-Person classes can access it

Add a public section to the Person class and relocate the name there

Eg

public

string name

Any better now

The problem now is that Student only by default inherits the private side of Person

Change class Student so that we also inherit the public members of Person hellip

class Student public Person

138

Before we tackle further problems with name lets bring in the Member class (left doing nothing until now)

We really want Student to inherit from Member and not Person Change the code to reflect this

People have dates-of-birth and Members have bod cards Add a string member dateOfBirth to Person and move the bodCardNumber member out of Student and into Member ndash make them both strings

Change the code in main() to set these extra pieces of data

If you havent done it already Persons dateOfBirth and Members bodCardNumber should be set via constructors

139

Task 2

Open and examine the project called UnivMember2

UnivMember2 is a copy of the (exercise solut ion)

UnivMember1 solution

One of the problems we have in UnivMember1 is that too much of it is public eg given Student object s we can change name to simply by using assignment eg sname =

We should protect data members at each level using the maximum level of protection we can ie private

However if we do that then cout ltlt sname will no longer work and so well need to provide access methods to the data members Eg heres a modified Member class showing the basic scheme

class Member public Person

public

Member(string bodCardNumber)

this-gtbodCardNumber = bodCardNumber

string getBodCardNumber() For access

return bodCardNumber

private

string bodCardNumber

140

Another problem is that wed really like to not use assignment at all Eg in the above ctor snippet

this -gt bodCardNumber = bodCardNumber

is using assignment

Change string bodCardNumber to const string bodCardNumber Youll see now that assignment wont now work (you have to initialise constants)

What wed really like (most likely) is to use in i t ial isat ion

We can do this via initialiser lists Ie we could change the above to the following

class Member public Person

public

Member(string bodCardNumber)

bodCardNumber(bodCardNumber)

const string getBodCardNumber()

return bodCardNumber

private

const string bodCardNumber

The initialiser list is read thus

bodCardNumber(bodCardNumber)

^^member^^ ^^parameter^^

Note that weve also modified getBodCardNumber() to show that it returns a const string

141

Modify all three classes to use initialiser lists private const data members and use access functions (getBlah() etc)

Task 3

Open and examine the project called UnivMember3

UnivMember3 is a copy of the (exercise solut ion)

UnivMember2 solution

We will now finish this project to the level of an introductory course

Things to note

The main problem with the solution as it stands is that one may create a Member object

Remember that this is analogous to being able to create a generic Car object ndash we should not be allowed to create one

Going right back to UnivMember1 you may remember a comment in there about a protected constructor

protected Protected ctor Person()

At that point in your project we were thinking two things 1) we wont want to create a generic person and 2) a protected constructor will facilitate this

And we were wrong to think both thoughts

1) A properly thought through Person class would be perfectly good to model generic people But although this is true one question here ndash would we ever want just a generic person

2) A protected constructor in a (more) base class doesnt prevent a derived class from creating a base object So what about the Member class ndash would it be ok to instantiate that

The proper means to prevent a Member being created would be to use what is called a pure v i r tual funct ion as part of its definition (such a function is one that must be overridden in a derived class) But what function

142

If you look at the classes derived from Member ndash you can take it from us that one might want to interrogate at runtime ndash to ask them what they are

So a suitable member function to declare in Member would be something like string getRole() A function that does return Student for a student and return Staff for a Staff object

If its pure virtual in in Member wed best define it in our derived classes

class Member public Person

public

virtual const string getRole() = 0

class Student public Member

public

const string getRole() return Student

143

1 Why did we want duplicate (named) functions in Member Student and Staff 2 And what does virtual really mean

We require both 1 and 2 so that we can provide specific responses when being asked the same question and all when being treated in a rather basic way

Being asked the same question means having a method invoked eg getRole() and in a rather basic way means treating us all Students and Staff (etc) as Persons and Members

112 Polymorphism

Polymorphism comes in a few forms

Ad-hoc Polymorphism via function overloading

Parametric Polymorphism or Compile-Time Polymorphism via templates

Subtype Polymorphism or Runtime Polymorphism via virtual functions and

Coercion Polymorphism via casting

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class (after all a derived from base must have or contain all that a base has) Polymorphism is the art of taking advantage of this simple but powerful and versatile feature

One way Subtype Polymorphism is applied is to use a base reference to access a collection of instances of different types that are derived from a common base ndash one way to paraphrase that is to say that related (derived from a common class) objects respond according to their type rather than according to the type of the reference one uses to access them (a base class pointer type) That is the dynamic type of the object is used instead of its static type

All of this is best demonstrated via an example of course

144

PLUSPLUS Polymorphism

Task 1

Open and examine the project called (exercise

solut ion) UnivMember3

Run the program the output should be the same as shown in Figure 36

The crucial code here is as follows

Member arr[6]

Student studs1()

Student studs2()

Staff staff1()

Student studs3()

Staff staff2()

Student studs4()

arr[0] = ampstuds1

arr[1] = ampstaff1

arr[2] = ampstuds2

arr[3] = ampstaff2

arr[4] = ampstuds3

arr[5] = ampstuds4

for(int i = 0 i lt ++i)

cout ltlt arr[i]

ltlt i ltlt s name is

ltlt arr[i]-gtgetName()

ltlt t Their role is

ltlt arr[i]-gtgetRole()

ltlt endl

Weve created an array of Members (it isnt important that weve used pointers) and note that we have set some of the members of this to be pointers to Student and Staff objects We are allowed to do this as both Student and Staff are derived from Member

However when and if we invoke member functions on these objects wed really like it if they responded as what they really are ndash Student and Staff objects

145

From the output below you can see that they indeed do respond accordingly

Figure 36

The mechanism behind allowing this is the virtualisation of the getRole() member function Remember that this was declared and made virtual in the Member class

Play about with the code eg change

Member arr[6] to Person arr[6] Everything still ok How about not using pointers here ndash easy to do

146

Lastly weve implemented (for no good reason but to show you how its done) some instance counting in all three classes Have a look for the static members and the inserted lines immediately below the class definitions that look like this int PersonCount = 0

The End Thank you for coming and we hope that you enjoyed the class

Oh and please Please PLEASE fill out the feedback form email when it arrives

147

12 Appendices

Arithmetical Operators

Operator Operation

+ Addition

- Subtraction

Multiplication

Division

Modulus

++ Increment

-- Decrement

Table 8 ndash Arithmetical Operators

Assignment Operators

Operator Example Equivalent

= a = b a = b

+= a += b a = a + b

-= a -= b a = a - b

= a = b a = a b

= a = b a = a b

= a = b a = a b

Table 9 ndash Assignment Operators

148

Assignment and Arithmetic examples

The assignment operator in C++ is =

The format is var iable = expression this can be read as assign to the var iable the value of the expression

An example to calculate the number of pence in a value in pounds would be

pence = pounds 100

Note it is easy to confuse the assignment operator = with the equals notation used in mathematics The equals notation in C++ is ==

Incrementing a var iable

month = month + 1 adds the value one to the variable month This can be written as

month++

Decrementing a var iable

month = month - 1 deducts the value one from the variable month This can be written as month--

Note that ++ and ndash can be used before or after the thing being modified eg ++x x++ --y y-- However there are some subtle differences which will be explained in the lectures

In C++ it is also possible to combine arithmetic and assignment operations

To add 2 to a variable total

total = total + 2 or total +=2

To subtract 2 from to tal

total = total - 2 or total -=2

To multiply total by 2

total = total 2 or total =2

Relational and Equality Operators

The equality operator is used to compare two operands (a == b) and returns 1 (t rue) if both are equal otherwise 0 (false ) is returned

The inequality operator (=) returns 1 (t rue) if both are NOT equal otherwise 0 (false) is returned

Both the above operators are commonly used to test the state of two variables to perform conditional branching

The relational operators also return either true or false (a gt= b) returns 1 (t rue ) if a is greater than or equal to b otherwise 0 (false ) is returned

149

Standard algebraic equality or relational

operator

C++ equality or relational operator

Sample C++ condition

Meaning of C++ condition

Relational operators

gt gt a gt b a is greater than b

lt lt a lt b a is less than b

gt= a gt= b a is greater than or equal to b

lt= a lt= b a is less than or equal to b

Equality operators

= == a == b a is equal to b

= a = b a is not equal to b

Table 10 ndash Relational Operators

Logical Operators

When using i f selection statements it is common to use the relational operators as part of the test if(num gt 5) if(size lt= 14) if(Char == A) These are fine for testing one condition

To test multiple conditions it is possible to nest i f statements but this can be a bit cumbersome

Logical Operators can be used to form more complex conditions by combining simple conditions

Logical AND (ampamp) Operator allows a test to see if two conditions are true

if(leaveBooked gt LeaveLeft ampamp staffCover == false)

cout ltlt Take your holidays sometime else

Logical OR (||) Operator allows a test to see if either or both of the conditions are true

if(Temperature lt 16 || windspeed gt 15)

cout ltlt Too cold or windy to sunbath today then

Logical Negation ( ) Operator reverses the meaning of a condition

if((windspeed == 20))

150

cout ltlt The wind speed is not 20 its ltlt windspeed

This could be written equally as well with the equality operator

if(windspeed = 20)

cout ltlt The wind speed is not 20 its ltlt windspeed

Precedence and Associativity Table

Precedence Operator Description Associativity

1 Scope resolution Left-to-right

2

++ -- Suffixpostfix increment and decrement

() Function call

[] Array subscripting

Element selection by reference

-gt Element selection through pointer

typeid() Run-time type information (see typeid)

const_cast Type cast (see const_cast)

dynamic_cast Type cast (see dynamic_cast)

reinterpret_cast Type cast (see reinterpret_cast)

static_cast Type cast (see static_cast)

3

++ -- Prefix increment and decrement Right-to-left

+ - Unary plus and minus

~ Logical NOT and bitwise NOT

(type) Type cast

Indirection (dereference)

amp Address-of

sizeof Size-of

new new[] Dynamic memory allocation

delete delete[] Dynamic memory deallocation

151

4 -gt Pointer to member Left-to-right

5 Multiplication division and remainder

6 + - Addition and subtraction

7 ltlt gtgt Bitwise left shift and right shift

8 lt lt= For relational operators lt and le respectively

gt gt= For relational operators gt and ge respectively

9 == = For relational = and ne respectively

10 amp Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 ampamp Logical AND

14 || Logical OR

15 Ternary conditional Right-to-Left

16

= Direct assignment (provided by default for C++ classes)

+= -= Assignment by sum and difference

= = = Assignment by product quotient and remainder

ltlt= gtgt= Assignment by bitwise left shift and right shift

amp= ^= |= Assignment by bitwise AND XOR and OR

17 throw Throw operator (exceptions throwing)

18 Comma Left-to-right

Table 11 ndash Precedence and Associativity Table

Escape Sequences

Escape Sequence

Description

n Newline Position the screen cursor at the beginning of the next line

152

t Horizontal tab Move the cursor to the next tab stop

r Carriage return Position the cursor at the beginning of the current line

a Alert Sound the system bell

Backslash used to print a backslash

Single quote Use to print a single quote character

Double quote Used to print a double quote character

Table 12 ndash Escape Sequences

Cast Operator

Is where the programmer explicitly asks for a change in data type It may be that the result of a calculation is a double and the user wants it to be of type integer

A double can be cast to an integer in the following way

double aNum = 237

int anInt = 0

anInt = static_castltintgt(aNum)

A C style cast may also be used eg

anInt = (int)aNum OR anInt = int(aNum)

Formatted Output

When several numbers are displayed each is printed with the minimum number of digits needed to show the value This can yield some unexpected output

The width of an output field can be set using a stream manipulator To set the next number to be printed to a width of 5 digits use cout ltlt setw(5) This command does not produce any output it manipulates the stream to change the output format of the next value Note setw() must be specified for every item output

To use any stream manipulators you must include the header include ltiomanipgt

setprecision is another manipulator and is used to set the precision of the next floating point number Note setprecis ion only has to be set once as the stream remembers the formatting directive and does not affect integer fields The format is cout ltlt

setprecision(3)

To set precision for trailing zeros (0100 will appear as 01) it is necessary to use the fixed format The notation is cout ltlt fixed Note f ixed only has to be set once

The three manipulators can be combined to achieve the required precision and field width when used in this way

153

cout ltlt fixed ltlt setprecision(3) ltlt setw(5) ltlt myDouble

Alternatively as fixed and setprecision only have to be set once this statement could be written as

cout ltlt fixed ltlt setprecision(3)

cout ltlt setw(5) ltlt myDouble

Header Files

Every program that you create will have at least one header file If you use input or output you will have to include the iostream header

If you use mathematical functions you will need cmath It can be difficult to know which header files to use for each function Some of the common header files used together with some of the older ones you may find with inherited code are shown below It is a good idea to use the help if you are unsure which header files are associated with particular functions

Standard C++ header Old header

iostream iostreamh

iomanip iomaniph

fstream fstreamh

cmath mathh

cstdlib stdlibh

string No equivalent

vector vectorh

Table 13 ndash Header Files Old and New

Matrix Libraries

The STL does not contain a Matrix type and so we must look elsewhere for a suitable implementation that suits the individuals needs

The table below lists the third party libraries that we are aware of

Some Linear AlgebraMatrix Libraries

Armadillo Blitz++ Boost

CPPLapack CPPScaLapack CVM Class Library

Eigen Elemental FLENS

Gmm++ GNU Scientific Library (GSL) HSL

154

IML++ IT++ LA library

Lapack++ LinBox Matrix Template Library (MTL)

MV++ Newmat PETSc

RNM Seldon SimuNova

SL++ (Scientific Library)

SparseLib++ SuiteSparse

TCBI (Temporary Base Class Idiom)

Template Numerical Toolkit (TNT)

Trilinos

uBlas ViennaCL

Table 14 ndash Matrix Libraries

Scope

The portion of a program where an identifier can be used is known as its scope

An identifier declared outside any function or class has f i le scope This type of identifier is known by all functions Global variables and function prototypes all have file scope

Identifiers declared inside a block of code have block scope This type of scope begins at the identifiers declaration and ends at the termination right brace ( ) of the block in which the identifier is declared

Any block can contain local variable declarations If blocks are nested it is possible to declare variables with the same name in each nested block The variable in the outer block is hidden while the inner block is being executed

Enumerating constants

The enum keyword provides a handy way to create a sequence of integer constants An example of enumeration is shown below

enum Months JAN = 1 FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC

Each of the constants will have a default value 1 greater than the constants that it follows in the list The first value in the enumeration above is explicitly set to 1 and the remaining values increment by 1 The values assigned from JAN to DEC will be 1 to 12

The statement cout ltlt DECEMBER is month number ltlt DEC ltlt endl would be output as DECEMBER is month number 12

Constants

Data that will not change during the execution of a program should be stored in a constant container rather than a variable If the program attempts to change the value stored in a constant the compiler will report an error and compilation will fail

Constant can be created for any data type by prefixing the declaration with const keyword followed by a space Note Constants must always be initialised at declaration

The following declaration declares a constant for the speed of sound at sea level ms

155

const double SpeedOfSound = 34029

Vector member functions

Some commonly used member functions of the vector class are

Vector member Functions Effect

at(element number) Gets the value contained in the specified element

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

push_back(value) Adds an element to the end of the vector containing the specified value

size() Gets the number of elements

Table 15 ndash Vector Member Functions

Global functions

Global functions are not member functions They take more than one argument and operate on a range of elements rather than on the vector container ie they can be used on other types of containers

Vector global Functions Effect

find()

ptr = find(vbegin() vend() 67)

Finds the element in the vector containing number 67 Needs iterator (ptr) to store location of element

reverse()

reverse(vbegin() vend()) Reverses the values in a vector (v)

sort()

sort(vbegin() vend()) Sorts the vector (v)

Table 16 ndash Vector Global Functions

156

list member functions

Some commonly used member functions of the list class are

List member Functions Effect

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

pop_front Removes the first element

push_back(value) Adds an element to the end of the vector containing the specified value

sort() Sorts the elements in the container from lower to higher

size() Gets the number of elements

swap() Exchanges the content of the list

Table 17 ndash List class Member Functions

cmath functions

Function Argument Result Returned Value Example Result

ceil(x) double double Smallest integer ge x

ceil(21) 30

cos(x) double double Cosine of x radians cos(10) 054

fabs(x) double double Absolute value of x

fabs(-15) 15

floor(x) double double Largest integer le 29

floor(29) 20

157

pow(x y) double double x to the yth power pow(24) 160

sin(x) double double Sine of x radians sin(10) 084

sqrt(x) double double Square root of x sqrt(4) 20

tan(x) double double Tangent of x radians

tan(10) 156

Table 18 ndash cmath Functions

158

String class

The string class defines many member funct ions A few of the basic ones are described below

Initialisation - constructors form

A string expression string str2 = str1

A character string literal string Intro = Programming with C++

A substring of another string object

string Intro = Capetown

string Mytown = Boars

string MyTown(Intro 4 5)

starts at character 4 (t)

with a length of 5 (or the rest of the string if shorter)

cout ltlt myTown ltlt endl

will produce an output town

Member Functions

length()

string myName = Sebastion

myNamelength()

will produce an output of 9

insert ()

Inserts a string into the current string starting at the specified position

string myName = Sebastion

string nameAdd = rjio

myNameinsert (2nameAdd)

cout ltlt myName ltlt endl

will produce an output Serjiobastion

erase()

Delete a substring from the current string

string myName = Sebastion

myNameerase (02)

cout ltlt myName ltlt endl

will produce an output bastion

replace()

Delete a substring from the current string and replace it with another string

string myName = Sebastion

string aName = renna

159

Member Functions

myNamereplace(3 6 aName)

cout ltlt myName ltlt endl

will produce an output Sebrenna

find()

Search for the first occurrence of the substring in the current string If the word is found return the position of the first character If not return -1

string sName

string findWord

position = sNamefind(findWord)

substr()

Returns a substring of the current string

string myName = Sebastion

string aName = myNamesubstr(0 3)

cout ltlt aName ltlt endl

will produce an output Seb

Non-member functions

getline()

string name

getline(cin name)

Table 19 ndash String Class Member Functions

160

A number of C++ operators also work with str ing objects

Operator

=

string fString = Hello

string lString

lString = fString

Assign a character (char ) to a str ing object

string aStringC

aStringC = Z

+

Concatenate two str ing objects

string str1 = C++

string str2 = Programming

string str3 = str1 + str2

+

Concatenate a string object and a character string literal

string str = Hello

string str1 = str + there

The same concatenation can be done in this way

str += there

+

Concatenate a string object and a single character

string str = Bye Bye

string strBye = str +

161

ASCII Character set

Decimal Octal Hexadecimal Binary Value Meaning

0 0 0 0 NUL (Null char)

1 1 1 1 SOH (Start of Header)

2 2 2 10 STX (Start of Text)

3 3 3 11 ETX (End of Text)

4 4 4 100 EOT (End of Transmission)

5 5 5 101 ENQ (Enquiry)

6 6 6 110 ACK (Acknowledgment)

7 7 7 111 BEL (Bell)

8 10 8 1000 BS (Backspace)

9 11 9 1001 HT (Horizontal Tab)

10 12 00A 1010 LF (Line Feed)

11 13 00B 1011 VT (Vertical Tab)

12 14 00C 1100 FF (Form Feed)

13 15 00D 1101 CR (Carriage Return)

14 16 00E 1110 SO (Shift Out)

15 17 00F 1111 SI (Shift In)

16 20 10 10000 DLE (Data Link Escape)

162

Decimal Octal Hexadecimal Binary Value Meaning

17 21 11 10001 DC1 (X ON) (Device Control 1)

18 22 12 10010 DC2 (Device Control 2)

19 23 13 10011 DC3 (X OFF)(Device Control 3)

20 24 14 10100 DC4 (Device Control 4)

21 25 15 10101 NAK (Negative Acknowledgement)

22 26 16 10110 SYN (Synchronous Idle)

23 27 17 10111 ETB (End of Trans Block)

24 30 18 11000 CAN (Cancel)

25 31 19 11001 EM (End of Medium)

26 32 01A 11010 SUB (Substitute)

27 33 01B 11011 ESC (Escape)

28 34 01C 11100 FS (File Separator)

29 35 01D 11101 GS (Group Separator)

30 36 01E 11110 RS (Request to Send)(Record Separator)

31 37 01F 11111 US (Unit Separator)

32 40 20 100000 SP (Space)

33 41 21 100001 (exclamation mark)

34 42 22 100010 (double quote)

163

Decimal Octal Hexadecimal Binary Value Meaning

35 43 23 100011 (number sign)

36 44 24 100100 $ (dollar sign)

37 45 25 100101 (percent)

38 46 26 100110 amp (ampersand)

39 47 27 100111 (single quote)

40 50 28 101000 ( (leftopening parenthesis)

41 51 29 101001 ) (rightclosing parenthesis)

42 52 02A 101010 (asterisk)

43 53 02B 101011 + (plus)

44 54 02C 101100 (comma)

45 55 02D 101101 - (minus or dash)

46 56 02E 101110 (dot)

47 57 02F 101111 (forward slash)

48 60 30 110000 0

49 61 31 110001 1

50 62 32 110010 2

51 63 33 110011 3

52 64 34 110100 4

164

Decimal Octal Hexadecimal Binary Value Meaning

53 65 35 110101 5

54 66 36 110110 6

55 67 37 110111 7

56 70 38 111000 8

57 71 39 111001 9

58 72 03A 111010 (colon)

59 73 03B 111011 (semi-colon)

60 74 03C 111100 lt (less than)

61 75 03D 111101 = (equal sign)

62 76 03E 111110 gt (greater than)

63 77 03F 111111 (question mark)

64 100 40 1000000 (AT symbol)

65 101 41 1000001 A

66 102 42 1000010 B

67 103 43 1000011 C

68 104 44 1000100 D

69 105 45 1000101 E

70 106 46 1000110 F

165

Decimal Octal Hexadecimal Binary Value Meaning

71 107 47 1000111 G

72 110 48 1001000 H

73 111 49 1001001 I

74 112 04A 1001010 J

75 113 04B 1001011 K

76 114 04C 1001100 L

77 115 04D 1001101 M

78 116 04E 1001110 N

79 117 04F 1001111 O

80 120 50 1010000 P

81 121 51 1010001 Q

82 122 52 1010010 R

83 123 53 1010011 S

84 124 54 1010100 T

85 125 55 1010101 U

86 126 56 1010110 V

87 127 57 1010111 W

88 130 58 1011000 X

166

Decimal Octal Hexadecimal Binary Value Meaning

89 131 59 1011001 Y

90 132 05A 1011010 Z

91 133 05B 1011011 [ (leftopening bracket)

92 134 05C 1011100 (back slash)

93 135 05D 1011101 ] (rightclosing bracket)

94 136 05E 1011110 ^ (caretcirumflex)

95 137 05F 1011111 _ (underscore)

96 140 60 1100000 `

97 141 61 1100001 a

98 142 62 1100010 b

99 143 63 1100011 c

100 144 64 1100100 d

101 145 65 1100101 e

102 146 66 1100110 f

103 147 67 1100111 g

104 150 68 1101000 h

105 151 69 1101001 i

106 152 06A 1101010 j

167

Decimal Octal Hexadecimal Binary Value Meaning

107 153 06B 1101011 k

108 154 06C 1101100 l

109 155 06D 1101101 m

110 156 06E 1101110 n

111 157 06F 1101111 o

112 160 70 1110000 p

113 161 71 1110001 q

114 162 72 1110010 r

115 163 73 1110011 s

116 164 74 1110100 t

117 165 75 1110101 u

118 166 76 1110110 v

119 167 77 1110111 w

120 170 78 1111000 x

121 171 79 1111001 y

122 172 07A 1111010 z

123 173 07B 1111011 (leftopening brace)

124 174 07C 1111100 | (vertical bar)

168

Decimal Octal Hexadecimal Binary Value Meaning

125 175 07D 1111101 (rightclosing brace)

126 176 07E 1111110 ~ (tilde)

127 177 07F 1111111 DEL (delete)

Table 20 ndash Full ASCII Table

169

Handy IDE Settings

Line Numbers onoff Tools | Options | Text Editor | CC++ | Line Numbers

Auto closing the console Tools | Options | Debugging | Automatically close the console window when debugging stops

Saves having to use system(pause)

170

REMAINING PAGES LEFT BLANK FOR NOTE TAKING

171

172

173

Peet Morris

peetmorrisgmailcom

C++ A Comprehensive Introduction

Arrangements

bull We Startfinish at 915am 500pm

bull Format two lectures per day (ask questions) hands-on at all other times

bull You should have Course book (copy of the slides at the back)

bull The course software is pre-installed on the machines

And also separately available from

The compilerIDE wwwvisualstudiocom

Notesslidesexercise files wwwpeetmcomC++introcoursezip

Your safety is important

Where is the fire exit

Beware of hazards

Tripping over bags and coats

Please tell us if anything does not work

Let us know if you have any other concerns

Your comfort is important

The toilets are along the corridor just outside the teaching rooms

The rest area is where you registered it has vending machines and

a water cooler

The seats are adjustable

You can adjust the monitors for brightness

What we assumehellip

What we assume

Experience of using another programming

language

Comprehensive Lots to get through

C++ and OOP

bull Created in 1985 by Bjarne Stroustrup C++ is a highly efficient

multiplatform low level Object Oriented Programming language

bull Latest version is C++17

stroustrupcom

Standard C++ Library

bull Written in the core language it is a collection of classes

(object definitions) functions and algorithms

See wwwcpluspluscomreference

IDEs amp Compilers

Visual Studio 2017

First Program

First application

include ltiostreamgt

using namespace std

int main()

int aNum = 0 aNum(0) or aNum0

cout ltlt Enter a number-

cin gtgt aNum

cout ltlt You entered ltlt aNum

return 0

hellip hellip

First Program

bull include ltiostreamgt

Adds the contents of the iostream header file into the program (for cout and cin)

bull using namespace std

So we donrsquot have to write stdcout ltlt and stdcin gtgt all of the time

bull cin is the standard input stream object that allows input from the keyboard

bull cout is the standard output stream object that allows output to the screen

bull int main() The programs entry point

Mandatory main function in every C++ program ndash always returns an integer value

First Program

bull int aNum = 0

Variable to hold a value of type integer (piece of machine memory referred to via the name aNum)

bull ltlt stream insertion operator ndash outputs to console

cout ltlt Enter a number-

bull gtgt stream extraction operator ndash waits for keyboard input

cin gtgt aNum

Other Types

Microsoft data types summary httpsdocsmicrosoftcomen-gbcppcppfundamental-types-cpp

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststack

Lots

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

x 1

y 2

x 3

y 4

p1

p2

x

y

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 copies the bit pattern from p1 to p2

x 1

y 2

x 1

y 2

p1

p2

Compound Types

Cannot define operators other than assignment

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 p2 compilation error

x 1

y 2

x 3

y 4

p1

p2

Compound Types

We can arbitrarily further compound things

struct point

int xint y

struct rectangle

point tlpoint br

struct line

point startpoint end

startxy

endxy tlxy

brxy

Compound Types

We can also group things using struct to create compound

types

struct point

int xint y

struct rectangle

point tlpoint br

int main()

rectangle r

rtlx = 1rtly = 2

rbrx = 3rbry = 4

int diff_x = abs(rtopLeftx - rbottomRightx)int diff_y = abs(rtopLefty - rbottomRighty)

cout ltlt area ltlt diff_x diff_y ltlt endl

r

tl

br

x 1

y 2

x 3

y 4

Using a Library Type

include ltstringgt

string s

cout ltlt What is your name

getline(cin s)

cout ltlt s ltlt

ltlt is

ltlt slength() ltlt

ltlt characters long ltlt endl

s

Other Types

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststackcomplex

Lots

8 bit Binary signed unsigned

00000001 1 1

00000010 2 2

00000011 3 3

01111111 127 127

10000000 -128 128

10000001 -127 129

10000010 -126 130

11111101 -3 253

11111110 -2 254

11111111 -1 255

00000000 0 0

00000001 1 1

00000010 2 2

signed vs unsigned ndash its all just 1s and 0s and adding

Adding rules

0 + 0 = 0

1 + 0 = 1

0 + 1 = 1

1 + 1 = 0 (carry 1)

1 + 1 + 1 = 1 (carry 1)

-126 + +3 =

10000010

00000011 +

10000101 = -123

-126 + -3

10000010

11111101 +

01111111 = 127 (why not -129)

Arithmetic Operators

+ Addition

- Subtraction and unary minus

Multiplication

Division

Remainder after division (moduloclock arithmetic)

int j k l = 10

j = l 3 js value will be three

k = l 3 ks value will be 1

Relational Operators

Evaluate to either true or false represented by integer values 1 and 0

== Equal to

= Not equal to

gt Greater than

lt Less than

gt= Greater than or equal to

lt= Less than or equal to

Increment and Decrement Operators

++ Increment

-- Decrement

Can be prefix or postfix

b = 3

a = b++ + 6 Add 6 to b then increment b a is 9 b is 4

b = 3

a = ++b + 6 Increment b then add 6 to b a is 10 b is 4

Assignment Operators

Symbol Operation Long Short

= Assign a = 2 a = 2

+= Assign with add a = a + 2 a += 2

-= Assign with subtract a = a ndash 2 a -= 2

= Assign with multiply a = a 2 a = 2

= Assign with divide a = a 2 a = 2

= Assign with remainder a = a 2 a = 2

Basic Control Flow - if

Sequence

What we have been doing already

Selection

if statement if this then that

if (boolean expression) if (score gt= 50)

statement cout ltlt Passed

Logical Operators

Boolean expressions may be combined using

ampamp And

|| Or

Not

Operands and result resolves being either true or false

if (x ampamp (y || z))

else

Precedence and Associativity table in course book

Logical Operators

a b =

true true true

true false false

false true false

false false false

a b =

true true true

true false true

false true true

false false false

a =

true false

false true

a ampamp b a || b a

Logical Operators

if (x ampamp (y || z))

else

The value 0 (zero) is evaluated to mean false any other value is true

x ampamp (y || z) result

false ampamp (false || false) falsefalse ampamp (false || true ) falsefalse ampamp (true || false) falsefalse ampamp (true || true ) falsetrue ampamp (false || true ) falsetrue ampamp (false || false) truetrue ampamp (true || false) truetrue ampamp (true || true ) true

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp (y | ~z))

else

Bitwise Operators

unsigned int x = 11

unsigned int y = 7

unsigned int z = 25

if (x amp (y | ~z))

else

11 (x) = 000010117 (y) = 0000011125 (z) = 00011001

~z = 11100110 (230 or -26)

y | ~z = 11100111 (231 or -25)

x amp (y | ~z) = 00000011 = 3

Operands and the result resolve to a values

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp 1) x is odd

if (x gt y)

x = x ^ y

y = y ^ x XOr swap

x = x ^ y

Control Flow - if else

Selection

ifelse statements

if (boolean exp) if (score gt= 50)

statement cout ltlt Passed

else else

statement cout ltlt Failed

Control Flow -

Selection

Conditional (or Ternary) Operator

boolean exp true result false result

cout ltlt score gt= 50 Passed Failed

Control Flow

if (x gt= y)

if (y 2)

else

if (x gt= y)

if (y 2)

else

Control Flow ndash else if

if (exp)

else if (exp)

else if (exp)

else catch all remaining

if (aNum == 0)

else if (aNum == 1 || aNum == 2)

else if (aNum == 3)

else catch all remaining

aNum not 0123

Control Flow - switch

Selection

switch multiple selection statements

bull test must be an integral value 1 10 A x eg not 1056

bull case values must be constants

switch (aNum)

case 0

break

case 1 Fall through

case 2

break

default catch all

break

Repetition - while

while (exp)

statements

while (n lt k)

cout ltlt Enter mark

cin gtgt mark

t += mark

n++

Repetition - for

for (init exp inc)

statements

for (t = 0 n lt k n++)

cout ltlt Enter mark

cin gtgt mark

t += mark

Preferable to while if the range is known

Repetition - for

for (init exp inc)

statements

for () infinite loop

break causes loop to exit

Preferable to while if the range is known

Repetition - do

do

statements

while (exp)

do

cout ltlt Continue yn

cin gtgt yn

yn = tolower(yn)

while (yn = y ampamp yn = n)

There are a huge number of exercises and we donrsquot expect you to attempt

them all during this course

bull If yoursquore completely new to programming itrsquos probably best to tackle

them in sequence

bull If yoursquove some programming experience you should read through the

exercise summaries and then start wherever you feel comfortable

Exercises

Exercises

Topics covered in ex1 ndash ex6

Functions = mini programs

bull Used to combine data with operations and through functional

decomposition to promote code re-use

bull Simplifies coding

bull Functions for discrete tasks

bull Not hundreds of lines of code

bull Consumer only needs to know

bull What goes in and what comes out

Functions

Like everything else the compiler needs to have seen a prototype or a

definition of a function before we can use it

Prototypes lets the compiler generate the correct code

int min(int int)

int min(int int int)

void drawLine(point to point from = 00)

int square(int)

int main()

void beep()

string getNextPacket(void)

Return type Function name (Parameter list)

min

int min(int int) min prototypes (forward declarations)int min(int int int)

int main()

Having seen the prototypes the compilerc = min(x y) can generate the required code

int min (int a int b) min function definition 1

return a lt b a b

int min (int a int b int c) min function definition 2

return min(min(a b) c)

inline min

int main()

c = min(x y)

inline int min (int a int b)

return a lt b a b

int main()

c = x lt y x y

inline int min (int a int b)

return a lt b a b

Function Parameters

bull Pass by Value

bull A Copy of the parameter is passed to the called function

bull Pass by Reference

bull The actual parameter is passed to the called function

bull Pass by Memory Address (pointer)

bull Same effect as Pass by Reference (tomorrow)

Pass by value

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

return n_copy n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 10

n_copy 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp x)

x just another name for real_n

return x x

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

x 10

Pass by value (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

n_copy = n_copy n_copy

return n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 100

n_copy 100

Pass by reference (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

real_n = real_n real_n

return real_n

100

100

Mem Addr Contents

0x2786 100

real_n 100

Mem Addr Contents

0x2786 100

real_n 100

const Parameters

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Recursion

unsigned long long int fibonacci(int n)

switch(n)

case 0 Fall through - [[fallthrough]]

case 1

return n

break

default

return fibonacci(n - 1) + fibonacci(n - 2) Very inefficient

Arrays (Part 1)

Data structure containing same type of data (int double string char object)

bull Built in to C++

bull Series of elements each containing one item of data (contiguous memory locations)

Size (number of elements) set at compile time

Arrays (1)

int numbers[10] an array of 10 integers Each box sizeof(int) bytes wide

numbers

index values - 0 to 9

0 1 2 3 4 5 6 7 8 9

Arrays (1)

int numbers[10] an array of 10 integers

int n = 0

cout ltlt numbers ltlt endl address of the first element

cout ltlt numbers[n] ltlt endl contents of the nth element

cout ltlt ampnumbers[n] ltlt endl address of the nth element

cout ltlt numbers + n ltlt endl address of the nth element

0 1 2 3 4 5 6 7 8 9

42 hellip hellip hellip hellip hellip hellip hellip hellip hellip

0x1526

Arrays

char name[5] name - an array of five characters

thing t[5] t - an array of five things

examMarks ndash an array of three doubles initialised to 12 39 95double examMarks[] = 12 39 95 C++11 - double examMarks[] 12 39 95

header ndash an array of fifty unsigned chars (bytes) first three elements set to 0 1 255 and the rest to zerotypedef unsigned char bytebyte header[50] = 0 1 -1

Arrays

Accessing array data

define MARKS 5 or const int MARKS = 5

double examMarks[MARKS]

for(int i = 0 i lt MARKS i++)

cout ltlt Enter Exam Mark

ltlt i + 1 ltlt

cin gtgt examMarks[i]

for(i = 0 i lt MARKS i++)

cout ltlt examMarks[i]

Multidimensional Arrays

Two dimensional array Two subscripts First identifies row second identifies column

const int students = 6 const int marks = 3

double examMarks[students][marks] = 0 set to zero

for (int s = 0 s lt students ++s)

for (int m = 0 m lt marks ++m)

cout ltlt Enter mark ltlt m + 1 ltlt for student ltlt s + 1 ltlt endl

cin gtgt examMarks[s][m]

00 01 02

10 11 12

20 21 22

30 31 32

40 41 42

50 51 52

Memory laid out in row column order (more later)

00 01 02 10 11 12 20 21 22 30 31 32 40 41 42 50 51 52

Matrices

Provider Link

Armadillo armasourceforgenet

Blitz blitzsourceforgenet

Boost boostorg

Eigen eigentuxfamilyorg

Elemental libelementalorg

FLENS apfelmathematikuni-ulmde

HSL hslrlacuk

LEDA algorithmic-solutionscom

PETSc mcsanlgov

SimuNova simunovacom

SuiteSparse facultycsetamuedu

TNT mathnistgov

Trilinos trilinosorg

ViennaCL viennaclsourceforgenet

Exercises

Topics covered in ex7 ndash ex16

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people and dice

Recap Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

1 61 61 61 61 6

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

3 11 24 56 12 3

C++ and OOP

Encapsulation Keeping related stuff together

Member functionsmethods

an objectrsquos capabilities functionality and performable actions

int Throw()

Member variablesproperties

an objectrsquos current state values its dumb data

int sides

Dice throwing 3

struct dice

int sides State

dice(int n) Constructor

sides = n

int Throw() Member function (method)

return (rand() sides) + 1

int main()

Could also use dice d1 = 6 or d16 syntaxdice d1(6) d2(6)

d1sides = 6 d2sides = 10 Allow this

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

struct diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

class diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing ndash professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

diceh my-appcpp

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

dicecpp

Compiler

diceobj my-appobj

Linker

my-appexe

other librarycode objectfiles

Dice throwing - professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Compiler

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

diceobj my-appobj

diceh dicecpp my-appcpp

Linker

my-appexe

other librarycode objectfiles

Only items provided to the end-usercustomer

Classes and Objects

the includeltstringgt header file from the standard library

class string

your cpp source code files

include ltstringgt include information about class string

string Name a class string instance

string Address a class string instance

Classes and Objects

the include carh header file

class car

your cpp source code files

include carh include information about class car

car c a class car instance

Classes and Objects

the include househpp header file

class house

your cpp source code files

include househpp include information about class house

house no1 a class house instance

house no2 a class house instance

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do with it

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

cstart()

cenginestart() Or should cstart() internally use enginestart()

OOD

Time for a break

class student

What properties and methods do we need

class student

public

string name

string DoB

string college

string bodCardNumber

float age()

int main()

student s

sname =

sDoB =

How to guarantee an objectrsquos integrity

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s

sname = Compilation errors

sDoB =

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s( )

cout ltlt sage()

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB Error ndash cant assign to a constant

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_name(name) m_DoB(DoB)

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_namename m_DoBDoB

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Exceptions

class student

int main()

try

student s( )

catch(const char msg)

cout ltlt msg ltlt endl

student initialisation failed

Exceptions

try

catch(const char msg)

cout ltlt msg ltlt endl

catch (const invalid_argument amp e)

cout ltlt ewhat() ltlt endl

catch (exception amp e)

cout ltlt ewhat() ltlt endl

catch ()

cout ltlt Something went wrong ltlt endl

student invalid arg 2

if using C++11 see stdcurrent_exception

Reuse and inheritance

Say we now want to add a new type to our system ndash class academic With what we have seen so far we would proceed something like this

class academic

private

string m_name string m_DoB

Duplicating everything we had in class student

class person (generalisation)

OOP is sometimes called Programming by Describing the differences

student and academic are all specialisations of a more generalised and abstract class ndash person

class student public personpublic

student(string name) person(name)

class academic public personpublic

academic(string name) person(name)

class personprotected

person(string name) m_name(name)

private

string m_name

public

base class derived class

derived class

Specialised State

class student public person

private

const string m_bodCard

public

student(string name string DoB string bc ) person(name DoB) m_bodCard(bc)

Multiple inheritance

class student public person public oxMember

public

student(string name int age string bc) person(name age) oxMember(bc)

class academic public person public oxMember

public

academic(string name int age string bc) person(name age) oxMember(bc)

Destructors

class foo

private

int m_x int m_y

public

foo() foo(0 0)

foo(int x) foo(x 0)

foo(int x int y) m_x(x) m_y(y) only ctor that accesses private state

~foo() any necessary tidy up code

Dice throwing 5

class diceprivate

int sides

public

dice(int n) sides(n)

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

srand((unsigned)time(0)) Happy with this

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 6

class diceprivate

int sides

public

dice(int n) sides(n)

classshared state static bool seeded = false

if (seeded)srand((unsigned)time(0))seeded = true

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

3 65 21 44 22 6

Dice throwing 7

class dice private

int sides

public

dice(int n) sides(n)

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

Dice throwing 7

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyesDouble 14 33 5

Dice throwing 8

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6) int t

for(int n = 0 n lt 5 ++n)

cout ltlt (t = d1Throw()) ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp t = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Dice throwing 9

class dice private

int sidesint _lastThrow

public

const int amp lastThrow read-only stateproperty

dice(int n) _lastThrow(-1) lastThrow(_lastThrow) sides(n)

int Throw()

return _lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp d1lastThrow = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Exercises

Topics covered in ex17 ndash ex22

Vectors

Like an array a data structure containing same type of data (int double object)

bull A container class part of the standard library a wrapper similar to arrays

Need to includeltvectorgt

bull Can resize grow shrink as elements are added or removed from the end

bull Algorithms to manipulate data

bull Iterators to cycle through all the elements

Vectors

vectorltchargt name(5) vector of five characters

vectorltthinggt t(5) vector of five things

vectorltdoublegt examMarks 12 39 95 initialised vector of three doubles

typedef unsigned char byte

a vector of fifty bytes first three elements set to 0 1 255 and the rest to zerobyte char b[50] = 0 1 255 fully populate array

calc itemCountint itemCount = sizeof(b) sizeof(b[0])

vectorltbytegt bytes (b ampb[0] + itemCount) then init with vector 50 items

Vectors (iteration 1)

include ltvectorgt

vectorltintgt vec(20) 20 ints

for(int i = 0 i lt vecsize() i++) input values into vec

cin gtgt vec[i]

for(i = 0 i lt vecsize() i++) output vec

cout ltlt vec[i] ltlt

Vectors (iteration 2) (C++11 and later)

for(type identifier container)

statements

vectorltintgt vec(20)

for (int amp i vec)

Vectors

Adding an extra element

cout ltlt Enter an Extra Value

cin gtgt aNum

vecpush_back(aNum)

for (int i = 0 i lt vecsize() i++)

cout ltlt vec[i] ltlt endl

cout ltlt vecat(i) ltlt endl same as above but range checked (ie slowsafe)

Vectors (most of the methods)

docsmicrosoftcomen-uscppstandard-libraryvector-classFull list

Method Purpose

assign Erases a vector and copies the specified elements to the empty vector

at Returns a reference to the element at a specified location in the vector

back Returns a reference to the last element of the vector

begin Returns a random-access iterator to the first element in the vector

capacity Returns the number of elements that the vector could contain without allocating more storage

clear Erases the elements of the vector

C++11 data Returns a pointer to the first element in the vector

C++11 emplace Inserts an element constructed in place into the vector at a specified position

C++11 emplace_back Adds an element constructed in place to the end of the vector

empty Tests if the vector container is empty

end Returns a random-access iterator that points to the end of the vector

erase Removes an element or a range of elements in a vector from specified positions

front Returns a reference to the first element in a vector

insert Inserts an element or a number of elements into the vector at a specified position

max_size Returns the maximum length of the vector

pop_back Deletes the element at the end of the vector

push_back Add an element to the end of the vector

rbegin Returns an iterator to the first element in a reversed vector

rend Returns an iterator to the end of a reversed vector

reserve Reserves a minimum length of storage for a vector object

resize Specifies a new size for a vector

C++11 shrink_to_fit Discards excess capacity

size Returns the number of elements in the vector

swap Exchanges the elements of two vectors

Vectors (iteration 3)

include ltalgorithmgt

vectorltintgt vec

for(int i = 1 i lt= 5 ++i)vecpush_back(i)

1 2 3 4 5

5 4 3 2 1

vectorltintgtiterator it

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Reverse the vectorreverse(vecbegin() vecend())

cout ltlt endl

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Arrays (2) (C++11 and later)

arrayltint 5gt arr Thin veneer over an array ndash so requires fixed size

arrfill(0) int j = 0

for (int amp i arr)

supports latest iteration style

reverse(arrbegin() arrend()) and iterators for use with algorithms

C++11 - Uniform initialisers

C++98

complexltdoublegt c( 271828 314159 )

int a[] = 1 2 3 4

vectorltintgt v

for( int i = 1 i lt= 4 ++i )

vpush_back(i)

C++11

complexltdoublegt c 271828 314159

int a[] 1 2 3 4

vectorltintgt v 1 2 3 4

Pointers ndash What

A pointer is a scalar variable that is used to hold the memory-address of

another variable or function the stored address is said to point to the thing

it holds ndash thus the name

Pointers have a type ndash the type of the thing they point to

int n = 10I (p) am a pointer to an integer and I point to n over thereint p = ampn

Pointers ndash Why

In no particular order

bull Because external libraries and APIs (like the operating system (all of them)) are written using them

bull Create custom data structures like linked-lists trees graphs etc

bull Create tables of functions or single functions for handling events callback or signals

bull Access data on to the heap (allocate memory dynamically)

bull Writecall functions that change their input parameters

1 2

3

4 5 6 nilhead

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

Recap - Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference using Pointers

int main()

int real_n = 10

cout ltlt square(ampreal_n)

cout ltlt real_n

return 0

int square(const int real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x5110 0x2786

real_n 0x2786

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt pcout ltlt pcout ltlt ampxcout ltlt xcout ltlt ampp

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

15438

11

15438

11

17216

Pointers

int main(int argc char argv)

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )(argv + n) ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv + 0 C

argv + 1

argv + 2

argv + 3

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

int main(int argc char argv[])

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )argv[n] ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv[0] C

argv[1]

argv[2]

argv[3]

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

Memory Stack vs Heap

Stack (last in first out - LIFO)

Space automatically allocated

The place where arguments of a function call are stored

The place where local function data is allocated (eg variables)

The place where a function leaves its result (if any)

Heap

Space must be explicitly allocated

A place for allocating memory that is not part of last-in first-out approach

ie dynamically allocated data structures that survive function calls

Stack vs Heap

int stackArray[100] Allocate 100 ints on the stack

stackArray[n] = 0 Do something with it

int heapArray = new int[100] 100 ints on the heap C++

int heapArray = malloc(100 sizeof(int)) 100 ints on the heap C

heapArray[n] = 0 Or (heapArray + n) = 0 Do something with it C++ and C

delete [] heapArray When youre done C++

free(heapArray) When youre done C

Exercises

Topics covered in ex22 onwards

If time allows look through the remaining

exercises and attempt those that fit best

with your requirements

  • C++ Notes TPLO 12-11-2019 Blackbox
  • C++ Slides TPLO 12-11-2019 - Copy

Creating your first class 65

Member functions and Passing parameters 67

Data Members 68

Constructors 70

Separating use from declaration and definition 72

Destructors 81

7 Arrays vectors lists and hash-tables 82

Declaring and using arrays 83

Searching Arrays with Linear Search 87

Sorting Arrays with Insertion Sort 90

Multidimensional Arrays 94

Declaring and using vectors 99

stdarray 105

Declaring and using lists 106

72 Hash Tables and Cached Calculations 107

Hash Tables 108

8 Pointers 112

Initialising pointers 113

Pointer Arithmetic and Arrays 115

9 APIs New Delete and Dynamic Memory 124

Using an API 124

Dynamic Memory Management 125

10 More on Functions 125

Multiple arguments overloading and default values 129

Passing Arrays to Functions 132

Passing Two-dimensional Arrays to Functions 135

11 Inheritance and (not presented) Polymorphism 135

111 Inheritance 135

Modelling a student - a first attempt 137

112 Polymorphism 143

12 Appendices 147

Arithmetical Operators 147

Assignment Operators 147

Assignment and Arithmetic examples 148

Relational and Equality Operators 148

Logical Operators 149

Precedence and Associativity Table 150

Escape Sequences 151

Cast Operator 152

Formatted Output 152

Header Files 153

Matrix Libraries 153

Scope 154

Enumerating constants 154

Constants 154

Vector member functions 155

Global functions 155

list member functions 156

cmath functions 156

String class 158

ASCII Character set 161

Handy IDE Settings 169

Exercises

Exercise 1 (Optional) Creating a first and default program 6

Exercise 2 CreatingModifying additional projects 26

Exercise 3 SearchString 29

Puzzled Programmers 29

The Collatz Conjecture 31

Mixing loops 33

PLUSPLUS Recursion 34

PLUSPLUS Base Two and Bits 37

Practising with Logical and Bitwise operators 38

Writing functions 42

Using a struct 43

PLUSPLUS When Things Go Wrong 44

The Monty Hall problem 46

More Functions 48

PLUSPLUS IsLeap in a line 49

Algorithms 49

Pass arguments by reference 52

Returning a value from a function 57

PLUSPLUS Arithmetic Bases 58

Searching for Sequences 61

PLUSPLUS Optimising Searching for Sequences 63

Evolving Searching for Sequences 64

Creating a class 65

Passing parameters 67

Using data members 69

More Objects 70

Using constructors 71

Separating declaration and definition 74

PLUSPLUS Using external libraries and third party header files 78

Creating an array to hold exam results 84

Linear Search 87

PLUSPLUS Debugging Linear Search 89

SortingSearching an array 90

PLUSPLUS Binary Search (Binary Chop) 93

Creating a multidimensional array 95

Creating a vector to hold exam results 100

Using insert() and iterators 103

Computing Fibonacci Numbers 110

Using pointers 114

Pointers and Arrays 116

PLUSPLUS Pointers and Arrays 119

PLUSPLUS Function pointers 122

main() and command-line arguments 126

EncryptDecrypt a file 128

Passing Arrays to functions 132

Base classes 137

PLUSPLUS Polymorphism 144

The PowerPoint slides entitled Exercises show the inclusive fromto exercise numbers which cover the topics discussed in the previous section It is not at all necessary to attempt to work through the entire quoted range variety is the spice of life ndash just choose those that appeal

1

1 Introduction Welcome to C++ A Comprehensive Introduction

These notes accompany the course delivered by Oxfords IT Services IT Learning Programme

If at any time you are not clear about any aspect of the course please make sure you ask your lecturer or demonstrator for some help If you are away from the class you can get help by email from your lecturer or from helpitoxacuk

Please also note that the university subscribes to Lyndacom ndash please check there for other C++ resources

11 What you should already know

The prerequisite for this course says that Either experience in another programming language or attendance on one of the PHP JavaScript or Python Kick-Start courses Is required

The more programming knowledge you have the better That said the documentation and lectures are structured such that those with very little knowledge should still be able to work through the course at their own pace

12 What you will learn

We will cover the following topics

Working with Microsofts Visual Studio Fundamental data types

Control Flow amp Iteration Header Files

Strings Functions

Arrays and Vectors Classes and Objects

Constructors and Destructors Member functions

Pointers And much more

13 Where can I get a copy of the softwaretools used

wwwvisualstudiocom (Microsofts C++ Compiler IDE and tools)

wwwpeetmcomC++introcoursezip (latest course code notes slides etc)

2 Things to understand

21 Compilers new and old

Students on this course often have to work with enhance or bug-fix existing code This sub-section is primarily for their consideration (it assumes some prior C++ knowledge)

2

Not all C++ compilers comply with the latest official ISO C++ standard (C++17) which was finally approved in December 20171

What does this mean It means that the code you write compile and run on one machine may not compile on the next machine if you are using a different compiler (even if it is using the same operating system) In this course you will be using Microsofts C++ Compiler (part of Visual Studio 2019)

Some older header files you may see with inherited C++ code are

include ltiostreamhgt have a h extension The C++ standard for this header file is include ltiostreamgt Your program may run correctly by adding a h but simply adding a h suffix will not work for all included files

include ltstringhgt has been replaced with include ltstringgt The stringh header file does not include C++ strings it includes C strings

include ltmathhgt has been replaced with include ltmathgt

The lesson to be learnt here is that a lot of C++ code you come across will have been created using older compilers Some of the header file and other code will not be recognised and may cause compilation errors when compiled on a machine which is more compliant with the C++ standard

If you are using the Gnu Compiler Collection (gcc g++ etc) you can specify standards compliancy via the ndashstd option eg -std=c++17 (other options are C++98

C++11 C++14)

Visual Studio can also be configured to use LLVM and clang Please see the relevant online documentation of how to install and use these if you wish to use them httpsllvmorgdocsGettingStartedVShtml

22 The C++ Standard Template Library (STL)

enwikipediaorgwikiStandard_Template_Library

The C++ programs you write will consist of the classes and functions that you write or modify (we provide partial solutions to every exercise)

However we will also look at what is still commonly referred to as the STL (now just part of the C++ Standard Library ) which holds a collection of existing classes functions and algorithms that you can use in the programs you will be creating

Some of the classes and template classes we will be looking at are

The string class The vector container template

The sort algorithm The list container template

The find algorithm

In addition you should also look at and be aware of another powerful library called Boost (parts of the STL come directly from the Boost library) wwwboostorg

The Boost library is easy to install (on any platform) as most Boost libraries are what is called header-only ie they consist entirely of header files containing templates and inline

1 A draft of this is included with your course files (n4660pdf) Its worth mentioning that this draft is in effect the published C++17 standard

3

functions and require no separately-compiled library binaries or special treatment when linking

23 Visual Studio 2019

What is Visual Studio (VS) VS is Microsofts freely available integrated development environment (IDE) and comes complete with optional compilerstools for a variety of languages We have only installed the IDE and the C++ compi ler (clexe etc) for this course

So what is a compiler

A compiler is a computer program that allows us to write programs in some specially defined language (unfortunately not English yet) in our case C++ (a so called high- level

language ) As you heard earlier the tex t we write in C++ is called source-code it is just simple text that one could write in Notepadexe for example

Sadly source-code is not directly understood by operat ing systems such as Windows Linux and macOS etc and it is the compilers job to convert our source-code into the terse concise and highly optimised machine-code that computers understand directly

Machine-code is often called executable or object-code and the compiled version of the source code is really just a file that contains numbers ndash a series of 8-bit bytes each holding a value between 0 and 255 The numbers either encode l ow-level instruct ions (code) or data that working together define the program Because these numbers may not encode displayable characters (see the ASCII table in the appendices to see a mapping between the numbers and the displayable characters) opening such a file an exe file in something like Windows notepad application would result in something like this being displayed (just the beginning shown)

However if we open this same executable file in a program that simply displays the files content as numbers and not what characters if any are represented by those numbers as Notepad is doing) we see this (the numbers are shown in base-16 or hexadecimal format)

4

The first two numbers 4D and 5A can be displayed as the text M and Z2 (see the first two characters at the top left in the previous notepad view of this file) 4D in base 10 is 77 and 5A is 90 ie the ASCII values for M amp Z (you can look these up in the ASCII table in the back of your course book)

Also take note of the line sequence starting 55 8B EC Then read on

2 MZ (0x4D5A) at the beginning of a file is an example of whats known as a magic number these are often used to identify a file type ndash in this case an MS-DOS executable file Trivia MZ are the initials of Mark Zbikowski the designer of the MS-DOS executable file format

5

If we have Visual Studio we can open the same file to see how such numbers translate into instructions and data

55 8B EC is the real beginning of our program In the above we see the numbers on the left and on the right what they actually mean Eg the first number 55 means push ebp which is an Intel CPU instruction Likewise 8B and EC together mean mov ebp esp The next line 81 EC C0 00 00 00 combines instructions and data and translate into sub esp 0C0h (subtract from esp the value C0 or 192 in base-10)

This is the entire program really the extra data shown in the previous views are for housekeeping

What does this program actually do then

Well youre about to find out ndash youre optionally now going to recreate it in Exercise 1

6

Creating your first program in Visual Studio 2019

Exercise 1 (Optional) Creating a first and default program

IMPORTANT

This exercise starts with a walk-through of using Visual Studio to create a new solution which you then go on to modify You should have already seen the steps needed to create a new solution in class so if youd rather just get on with the modification part simply open the (exercise solut ion)

f i rs t folder (in the Course folder) and double click the f i rs t s ln file If you choose to do this you can skip over the next few pages to the Explanation section (232) or even jump further on to Task 1 on page 14

Note You will not need to create any completely new programs during the course so even if you didnt fully follow the steps you can still safely move on to the modification part However if you really want to walk it through for yourself

Start the Visual Studio 2019 Integrated Development Environment (IDE) and create a new C++ Console application project You should have a shortcut to Visual Studio on your desktop failing that look for it on the Start menu

If they appear follow the prompts as shown below (if youre asked about keyboard mappings or Develop options select the C++ option)

7

Click Create a new project

Select Console App and click Next

8

Well locate the first project in a folder called first in your C drives Temp folder If the folder doesnt exist it will be created for you Click Create

Something like the above should appear (if you dont see the Solution Explorer panel open it via the View menu)

9

Alter the code adding the lines in bold as show here

include ltiostreamgt using namespace std int main() stdcout ltlt Hello Worldn system(pause)

Build and run the project by pressing the green arrow or by pressing F5

10

Explanation

Disclaimer at this stage you do not need to fully follow all of this just now

include ltiostreamgt

iostream is a standard C++ library file Files of this type are called header files They are text files usually containing C++ declarations definitions and code

Including iostream allows us to use some pre-defined objects to output messages to a console window This file must be included for any program that outputs data to the screen - or inputs data from the keyboard for that matter

The C++ compiler operates in passes through our code In the first pass ndash called the pre-processing pass ndash include directives are processed which are really text-substitution directives To be precise what include ltiostreamgt says is ldquoGo and find the text file called iostream and replace the directive with the contents of that filerdquo

The file name following a include directive can be enclosed in double quotes or chevrons ie include iostream or include ltiostreamgt The meaning of each is defined by the implementation (Microsofts C++ compiler in our case)

However it is common practice that if file name is in quotes it will be looked for locally first - in the same folder as the cpp file containing it and before being sought elsewhere Conversely if it is in chevrons the compiler will usually look for the file in a central include folder that was installed with the compiler ndash this folder is usually reserved for include files that come with the compiler as opposed to those that you might write yourself eg standard includes (like iostream) We therefore usually use quotes when we want to include our own custom project specific include files and chevrons when wanting to use include files that come with the compiler

You may also see that the filename sometimes has a h file extension This typically means that the header file being used is a C language header file and not a C++ one There are other variations (you are welcome to use your own) for example you might also see the occasional hxx file extension or something else entirely

using namespace std

The using namespace std code above doesnt actually appear in the automatically generated code In our project and solution files we will add it just after any include directives

namespaces in summary are very simple Everything within a namespace has a unique name and so theyre often used to help divide larger projects into more manageable chunks and to avoid name clashes

Standard C++ places a lot of its routines and functionality within a namespace call std Wed like to use this functionality and so we say we want to use all of the std namespace In the real world this isnt terribly good practice

11

However by declaring that were using namespace std throughout we can access members of this namespace without having to say exactly where they are (in which namespace) or worry about name clashes - where two objects in different files have been given the same name

The members of std that we will be using throughout are

cin (Console In) and cout (Console Out) and we must use include ltiostreamgt in order to use them

endl - is a stream manipulator that writes a new line to output endl stands for end

of l ine and is pronounced end all

If we dont declare that we were using the std namespace (which is the case in the automatically generated code) we have to prefix any use of cin cout and endl with std eg stdcin stdcout stdendl If youve added the using namespace std directive you may now remove the std in front of the stdcout ltlt Hello Worldn line

int main()

This is the entry point to our program ndash every C++ program must have this same entry point defined main() is a function the body of a function is defined within the opening and closing braces that come after its name The int to the left of main() says that this function returns (or resolves to beevaluates to) an integer value Returning a value requires you to use a return statement However as it is normal practice to simply return the value zero if you omit the return statement a value of zero is returned for you (only where main is concerned) If you want to explicitly return the value yourself you could modify the code to read

int main() stdcout ltlt Hello Worldn system(pause) return 0

So why return a value anyway Our added line return 0 means in this case that our main doing whatever it does as part of its function eventually resolves to the value 0 The value is returned to whatever called our programs entry point in this case and as usually that is the operating system ndash which has been waiting for us to return a value at this point However the operating system will simply ignore whatever value we ultimately return Why do it then

12

Consider the case when one of your programs needs to run another program to perform a part of its entire function Your main program needs to start this other program and wait until it completes successfully before continuing See the description of the system(pause) code line below

stdcout ltlt Hello Worldn

cout is an object declared in iostream ndash think of its name meaning console out Anything sent to cout using the double chevron operator ltlt appears on the console the

The n in the text means that cout should also output a carriage-return linefeed sequence (terms taken from the days of typewriters and telex machines) basically it means start any new output on a newline underneath the current line An alternative to using n is to use endl eg stdcout ltlt Hello World ltlt endl endl does more or less the same thing as n

system(pause)

system() is a standard function that is used to run an external program (here thats a standard Windows program called pauseexe) The system() function waits for the pause program to complete before continuing Going back to the discussion on return 0 earlier this is an example of one program starting another ndash here thats our program starting the pause program The pause program returns a value as part of its completion and we can examine that if we want Programs usually return 0 for success or some other integer value that means something went wrong ndash the value returned indicates what went wrong Ie a returned value of say 42 might mean that we cant answer the ultimate question with this computer3

So what is pause pauseexe is a standard Windows program that simply outputs the message Press any key to continue and then waits for a key to be pressed before exiting We use that facility here so that our program doesnt simply shutdown and disappear as it falls off the end of main()s closing or encounters a return statement If we did allow it to exit we would hardly have time to examine our programs output before it disappeared off the screen Try that and see (comment out the line using a double-slash like this system(pause))

If you run any of the course code on Linux or a Mac youll need to change this line to something like cinget()

3 An unashamed reference to the Hitch Hikers Guide to the Galaxy and the Deep Thought computer

13

Your projects default code template

In the course exercises when it comes to you writing code we will always ask you to open and then modify a partially complete projectsolution so you wont have to fiddle with projects and boilerplate code like this again

Nevertheless should you wish to start from scratch or simply experiment with Visual Studio we recommend using the code below as a starting point

include ltiostreamgt using namespace std int main() Start coding after here system(pause) return 0

14

Task 1

Immediately above system(pause) Replace the stdcout ltlt Hello Worldn line with the code shown here

int anum = 0

cout ltlt Enter a number

cin gtgt anum

cout ltlt The number you entered is

ltlt anum

ltlt endl

Test your modified program Tip remember you may hit the F5 key to build and then run your program

Try entering some text instead of a number Did it work

Alter the spacing (use of spaces and tab characters) in your code ndash does the C++ compiler care about this so called whi tespace

The statement int anum = 0 defines a variable (a memory location) which we will refer to in our code as anum to store a number of type int to hold an in teger (ie 1 -4 27) The memory location is being initialised with a value of 0 here It is good practice to initialise variables when you define them In C++11 a new type of uniform initialisation syntax was introduced and also encouraged eg int anum 0

cout ltlt Enter a number cout is a name that belongs to the namespace std The ltlt is called the stream insert ion operator When the program executes the value to the right of the operator (Enter a number) is inserted in the output stream and ultimately output to console window

cin gtgt anum cin is the input stream object of the namespace std gtgt is called the stream extract ion operator and is used here to read a number from the keyboard

cout ltlt The number you entered is ltlt anum ltlt endl This statement concatenates the output by using multiple stream insertion operators ltlt endl is the stream manipulator that adds a new line

The next Exercise starts on page 26 The pages between here and page 26 contain

code that you may like to try out by further modifying this project if not just read through the textcode until you get to page 26

15

Arithmetic Operators

Most computer programs perform arithmetic calculations Table 1 summarises the standard C++ arithmetic operators When working with integer division where both the numerator and denominator are integer the expression 15 6 evaluates to 2 To get the remainder after integer division you would use the modulus operator Note the modulus operator can only be used with integer operands

To establish the complete result of the following integer division 156 requires two operations

15 6 = 2

15 6 = 3

The result being 2 remainder 3

C++ Operation C++

arithmetic operator

Algebraic expression C++ expression

Addition + y + 6 y + 6

Subtraction - a - b a - b

Multiplication c times d or cd c d

Division xy or y

x or yx x y

Modulus p mod q p q

Table 1 - C++ arithmetic operators

Other fundamental data types Table 2 shows how you would declare and initialise four other data types for use in programs (there are more data types available)

16

Data type Example

Float float aFloat = 1234

Double (the precision of a Float) double aDouble = 123456

Char char aChar = A

Bool bool aBoolean = true

Table 2 - C++ numerical types4

Characters

Characters are normally stored in variables of type char but can also be stored as in t(eger) data types Characters are represented as single byte integers in the computer so it is possible to output a character as an integer or as a character

All characters have a numerical representation in the computer and the ASCII (American Standard Code for Information Interchange) character set shows each character and its decimal equivalent (also note that a combination of characters may be used to form more complex Unicode characters) See appendix 111

Characters can be read in with the following statements

char aChar declares a variable (aChar) of type char

cin gtgt aChar this statement is used to read a character into the variable aChar

Note After entering a character the ltENTERgtkey must be pressed before the character is read by the program

The following four statements correctly declare a variable of type char output a user prompt then read a character and store it in the variable aChar

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar

4 See httpencppreferencecomwcpplanguagetypes for a complete list (or the official ISO standard of course)

17

Header (include) Files

So far weve seen that to use certain functionality we had to include ltiostreamgt We have to do similar to use other functionality which is not part of the code C++ language ie we will need to include anything that comes as part of the standard library

In its current form Visual Studio comes with the following include files (most of which are standard files)

h files (95 C language files)

agentsh agileh ammintrinh amph amprth amprt_exceptionsh amp_graphicsh amp_mathh amp_short_vectorsh armintrh arm_neonh cfguardh collectionh comdefh comdefsph comiph comutilh concrth concrtrmh ConcurrencySalh concurrent_priority_queueh concurrent_queueh concurrent_unordered_maph concurrent_unordered_seth concurrent_vectorh crtdefsh crtversionh delayimph dloadsuph dvech ehh emmintrinh excpth fvech gcrooth immintrinh internal_concurrent_hashh internal_split_ordered_listh intrinh intrin0h invkprxyh iso646h ivech limitsh mm3dnowh mmintrinh nmmintrinh omph pgobootrunh pmmintrinh pplh pplawaith pplcancellation_tokenh pplinterfaceh ppltasksh ppltaskschedulerh pplwinh rtcapih salh setjmph setjmpexh smmintrinh srvh stdargh stdboolh stdexcpth stdinth tmmintrinh typeinfoh use_ansih vadefsh varargsh vcclrh vccorlibh vcruntimeh vcruntime_exceptionh vcruntime_newh vcruntime_new_debugh vcruntime_startuph vcruntime_stringh vcruntime_typeinfoh wmmintrinh xatomich xatomic0h xkeycheckh xlocinfoh xmmintrinh xsmf_controlh xstring_inserth xtgmathh xxamph xxamp_inlh ymathh yvalsh zmmintrinh

115 C++ files

algorithm allocators any array atomic bitset cassert ccomplex cctype cerrno cfenv cfloat chrono cinttypes ciso646 cliext climits clocale cmath CodeAnalysis codecvt complex condition_variable csetjmp csignal cstdalign cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cuchar cvt cwchar cwctype deque exception experimental filesystem forward_list fstream functional future hash_map hash_set initializer_list iomanip ios iosfwd iostream istream iterator limits list locale Manifest

18

map memory msclr mutex new numeric optional ostream queue random ratio regex scoped_allocator set shared_mutex sstream stack stdexcept streambuf string string_view strstream system_error thr thread tuple typeindex typeinfo type_traits unordered_map unordered_set utility valarray variant vector xcomplex xfacet xfunctional xhash xiosbase xlocale xlocbuf xlocinfo xlocmes xlocmon xlocnum xloctime xmemory xmemory0 xstddef xstring xtr1common xtree xutility xxatomic

Strings

Next to numbers strings are the most commonly used data type in programming

A string is both a datatype (string) and also literal character data ie a sequence of characters such as Oxford or StAndrews In C++ string literals are enclosed in quotes The quotes are not part of the string they identify the data type as a string

Actually this isnt quite true the double quoted strings are a sequence of characters and are taken from the C programming language The things declared of the string type are C++ string objects ndash which may be initialised using the C language literal

C++ strings can be declared and initialised in this way

string institution = Oxford

string name = Peet

To use the string type in your programs add the header file include ltstringgt at the top of your program This allows the use of part of the C++ library of classes called the string class (and its member functionsmethods explanations will follow soon)

Of course strings are normally used when requesting an input Consider this code

string aName aDept Two string objects

cout ltlt Enter your full name

cin gtgt aName

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

19

If in answer to the first prompt we were to enter say Fred Brooks 5 the interaction and output of our program would immediately result in this

Enter your full name Fred Brooks

Enter your department Fred is associated with Brooks

Why When reading in a string with a space such as FredltspgtBrooks only the first part Fred is read into aName ndash and the input is said to be space delimited by cin ndash and consists of two separate inputs (so the Brooks parts is read into the aDept string variable)

We could use multiple prompts to read in a name of course but this is inconvenient

To handle this situation we can use the standard getline(cin aName) function to read in a name instead of using cin gtgt aName This reads all key-strokes into aName until the ltENTERgt key is pressed at which point it returns a string containing all of the characters from the input

cout ltlt Enter your full name

getline(cin aName)

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

The string class has many useful functions you can use to manipulate strings An example is the length() member functionmethod

string aName = Fred Brooks

cout ltlt The length of the string aName is ltlt aNamelength() ltlt endl

This statement will output - The length of the str ing aName is 11

See section 12119 for more information on the string class and its member functions

5 Fred Brooks is a real person and a legendary computer scientist httpenwikipediaorgwikiFred_Brooks

20

The LF (Line Feed) Problem and Reading Keys

Continuing on consider the following code

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

string aName

cout ltlt Enter your full name

getline(cin aName)

cout ltlt You entered ltlt aName ltlt endl

system(pause)

The intent here is to first ask for a character and then to use getline() to ask for a name

If only things were that simple

If we were to enter say a Z to satisfy the first prompt the program would immediately output

Enter a character Z

You entered Z

Enter your full name You entered

Press any key to continue

The problem here is that being a keyboard key theltENTERgt key is itself being seen as a valid input so when we enter Z followed by the ltENTERgt key were actually entering two keys ndash Z and the ltENTERgt key The first keys placed into aChar whilst the enter key is left in the keyboards buffer This is quite reasonable if you think about it you entered two keys (Z and ltENTERgt) but provided a home for just one of them in aChar

Ok so whats the problem Well the problem is that we really need to use something like getline() to read text that contains spaces and it just so happens that getline() given this scenario will see the residual ltENTERgt key left in the buffer and it will assume that you didnt enter anything you just hit the enter key

This problem - that of having a mischievous ltENTERgt key waiting to surprise us ndash will occur whenever you read a key from the keyboard using cin Luckily theres an easy fix as we can use another input function to read and then discard the waiting ltENTERgt key Its called cinget() Here is a modified version of the code above that fixes the problem

21

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

cinget() REMOVE THE ENTER KEY discarding the got character

string aName

cout ltlt Enter your full name

getline(cin aName)

Used like this cinget() reads and discards a character from the input stream You can do the same using cinignore() cinget extracts a single character from the stream and returns it cinignore() extracts any number of characters and discards them (the details are specified via passed parameters to the function) or a single character if no arguments to the function are provided

You can easily use cinignore() to ignore a number of characters or until a certain token (character) is met eg the following code reads in a users first and last names and then outputs their initials

22

char first last Two 8-bit characters

cout ltlt Please enter your first name followed by your surname

first = cinget() Get one character

The first parameter is the maximum number of characters to

extract (and ignore) The second parameter is a

delimiting character The function stops extracting characters

as soon as an extracted character matches this one

cinignore(2566 ) Ignore until a space is seen

last = cinget() Get one character

cout ltlt Your initials are ltlt first ltlt last ltlt endl

Casts

On occasions in your programs you may want to store a value in a variable of a different type (when there is a danger of a loss of information the compiler will issue a warning for example when storing a double in an int) If you store a double as an integer you lose information in two ways

any mantissa (fractional part) will be lost

the magnitude of the double being stored may be too large to fit into the integer

Eg it is not possible7 to store 6678 x 10000 as a 16-bit unsigned integer because 667800 is 10000010011011100 in binary (17-bits) and is therefore larger than the maximum storable value of 65535 (1111111111111111) However you can store 1230 as an integer8

When you need to represent a value as a different type you can use the static_cast notation as shown here to change a double to an integer

6 If this is exactly numeric_limitsltstreamsizegtmax() there is no limit As many characters are extracted as needed until delim (or the end-of-file) is found

7 Actually the result of attempting to store 66780 in a 16-bit unsigned integer will be 10011011100 or 1244 Do you see how this value comes about

8 Also see the (demonst rat ion) L imi ts project

23

int anInt

anInt = static_castltintgt(doResult) where dResult is a double

You may also use the following historic classic C-style9 notation to cast to different data types

anInt = (int)dResult

Eg to change an integer to a character

char aChar

aChar = static_castltchargt(bInt) where bInt is an integer

You may also combine this using the

object-constructionfunction-call syntax of C++ eg

double d = 314157

int n = (int)d Convert ds value to an integer

int j = int(d) Ditto

9 C-style casts are usually considered to be too powerful ndash in that they indiscriminately allow unsafe and downright dangerous conversions C++ casts were introduced to solve this problem

24

Other Cast Types

Although outside the scope of this introductory course for reference here is a summary of the cast types in C++ (feel free to skip this for now and come back to it at a later time)

static_castlttypegt(object)

The type parameter must be a data type for which there is a known method for converting object to whether this be a built-in or through a casting function (constructor) All types of conversions that are well-defined and allowed by the compiler are done using static_cast

The static_cast operator may be used for operations such as converting a pointer of a base class to a pointer of a derived class converting numeric data types such as enums to ints or ints to floats However static_cast conversions are not necessarily safe as no run-time type check is done which can cause casting between incompatible data types for example initialised pointers However this is checked at compile time to prevent casting obvious incompatibles Also be aware that a static_cast between pointer of base to pointer of derived may produce an erroneous result (where the actual object pointed to is of type base not derived)

dynamic_castlttypegt(object)

In the C++ programming language the dynamic_cast operator is a part of the run-time type information (RTTI) system that performs a typecast Unlike the static_cast the target of the dynamic_cast must be pointer or reference to class Unlike static_cast and C-style typecast (where a type check is made during compilation) a type safety check is performed at runtime If the types are not compatible an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers)

reinterpret_castlttypegt(object)

Allows any pointer to be converted into any other pointer type Also allows any integral type to be converted into any pointer type and vice versa

The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument (unlike static_cast but like const_cast the reinterpret_cast expression does not compile to any CPU instructions It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type)

You cannot cast away a const or volatile qualification You can explicitly perform the following conversions

const_castlttypegt(object) A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is

25

identical except for the const and volatile qualifiers For pointers and references the result will refer to the original object For pointers to data members the result will refer to the same member as the original (uncast) pointer to data member Depending on the type of the referenced object a write operation through the resulting pointer reference or pointer to data member may produce undefined behaviour

26

Exercise 2 CreatingModifying additional projects

Examine how comments look in a program

Examine the use of some fundamental data types

Using different data types

Using the cast operator

Using the string class

Task 1

Open the skeleton project called EvenI

The project folder is

EvenIEvenI s ln

Modify the projects code in to prompt for two numbers of type double and two numbers of type integer

The program should output the sum the product and the difference of the double numbers Also output the quotient and the fractional part of the two integers10

Youll need something along the lines of hellip

double aDouble double bDouble

etc

To read a number into aDouble you could use

cin gtgt aDouble

Task 2

Modify your EvenI program to read in two characters Enter the characters a and Z

Output the two characters with the character case changed ie a becomes A and Z becomes z

You will need to look online or at in 12120 to establish the ASCII integer values of each character hellip you can alter a characters case by treating it as an integer and

To convert integers (or the results of evaluating integer expressions) to say characters we need to use a cast Eg

int i = 65

cout ltlt static_castltchargt(i + 32)

10 Trivia quotient comes from the Latin quotiens for how many times For example when dividing twenty by three the quotient is six and two thirds You can use a modulus b to get the fractional part

27

then by addingsubtracting tofrom it

Task 3

Open the skeleton project called Address and modify it so that it can be used to collect some user data

Output this collected data to screen as shown in Figure 1

Note that youll have to have include ltstringgt in order to use getline()

Figure 1

Visual Studio builds projects in one of two different modes ndash Debug or Release we will always use the Debug mode (a Release build is normally only used when a product is being beta tested ie late in the cycle)

When using Visual Studio (or most other IDEs for that matter) we normally do not have to concern ourselves with the location of the executable that is built by the program ndash because we normally run it from within Visual Studio itself However and just for your information really the exe for a debug build will always be located in the Debug folder immediately below the projects root folder ie for this project Addressexe is located in the (exercise solut ion) Address Debug folder whilst a version built in Release mode would be in the (exercise solut ion) Address Release folder

Debug builds contain extra diagnostic code that is automatically inserted by the compiler

28

3 Basic Control Flow The programs you have created so far are limited in that they run through a sequence of instructions once and then stop Most computer programs will make decisions and carry out different actions determined by the user input

C++ has three kinds of control structures

Sequence statement - the computer executes the statements one after another All the programs you have written so far use sequence statements

Select ion statements - if ifelse switch

The if selection statement selects an action if a condition is true or skips the action if the condition is false

The ifelse selection statement selects an action if a condition is true or performs a different action if the condition is false

The switch multiple selection statement can be used to perform many different actions based on a character or integer value

Repeti t ion statements - while for do while

The while and for statements perform actions within their bodies zero or more times If the loop condition test is initially false no actions will occur

The dowhile statement will perform the actions in the body at least once (the test ndash as to whether to continue - is at the end)

Selection - ifhellipelse statement

The if selection structure is used to choose among alternative courses of action The structure of the statement is

if(mark gt= 50)

cout ltlt Passed

else

cout ltlt Failed

If the condition (mark gt= 50) is t rue the statement following it is executed cout ltlt Passed

If the condition is false the statement is ignored and control is passed to the else part of the selection and statement following else is then executed cout ltlt Failed

ifelse selection statements can also be nested within other ifelse selection statements

29

Exercise 3 SearchString

Task 4

Open the skeleton project called SearchStr ing

You will need to include ltstringgt at the top of the code to complete this exercise See page 158 for more on the string class functionality

Modify the program to display a string of text to the user

The user should then be prompted to select a word from the sentence and input a replacement word Your program should replace one with the other You will want to See section 12119 on string functionality

The prompting string should be shown both before and after the update

Tips

Given a string s initialised to

string s = C++ at the University of Oxford

string t

int i = sfind(U)

cout ltlt i ltlt endl 11

t = ssubstr(0 i) bit before U in t

t = t + ancient + + ssubstr(i) +

Outputs C++ at the ancient University of Oxford

cout ltlt t ltlt endl

Puzzled Programmers

Using if if else nested ifs switch and the conditional operator -

Task 1

Solving puzzles

Open the I fp project and WITHOUT compilingrunning it determine its output

You will need to consult the operator precedence table in section 1216

You shouldnt compile or run the program to start with ndash the idea here is for you to determine its output on paper11

Tip you might want to consider tidying up the codes layout before attempting to solve it

void out(int n) is a function We havent covered functions yet but it makes sense to use one here and so we have Suffice to say for now that using out(some value) will output the value to the console window

11 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

30

Functions will be explained fully soon

Compile and run the program ndash if your workings from Step 1 differ from the output you should determine where you went wrong

Selection - switch multiple selection statement

The switch multiple selection statement can be used to perform many different actions based only on a single integer value Note however the switch statement can only be applied in narrow circumstances The tests must be constants and be integers Lets compare the two statements

int num switch(num) case 1 cout ltlt num = one

double num switch(num) case 11 cout ltlt num = 11

OK ndash Test is 1 a constant and an integer NOT OK ndash Test is not constant integer

Repetition ndash while dohellipwhile and for loops

The while statement is commonly used to carry out repeated steps perhaps reading in values before doing a calculation on values read in The format of the code is

while(condition)

statement

This can be read as whi le the condition is t rue continue to do the statements until the condition is false

31

The Collatz Conjecture

Win a million dollars

Task 1

Open and complete the project called Col latz (use a while() loop)

Given any positive integer if the number is even divide it by two else treble it and then add one If the result is one stop else repeat the process

The Collatz conjecture says that given any starting value the process above will eventually hal t (goes to one and stops)

Eg setting n to 9 as a starting point successive values would be

28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is not known whether the Collatz conjecture is true Fame and fortune await anyone who can prove it httpenwikipediaorgwikiCollatz_conjecture

A Collatz tree as visualised by Edmund Harriss

32

This image is a sample from the colouring book Visions of the Universe by Alex Bellos and Edmund Harriss

Get your own hi-res version for colouring-in here and see here for an explanation

33

Task 2

Re-implement your code so as to use a for() loop (this will be a lot easier than you might first think)

Not essential for this task but as we mention for loops you might like to look at the for project to see how a for loop can be animated to show how the three sections of it work in order

Mixing loops

Task 1

Open and modify the skeleton project called Factor ial

Modify it to use different repetition statements to calculate and display the factorial of a value entered by the user (they should enter a value between 1 and 10 inclusive)

Example use a while loop to prompt for an input value (between 1 and 10) and a for loop to calculate the factorial result

The output should be like that shown in Figure 2 below

Factorials12

The factorial of 5 (usually written as 5) is

1 x 2 x 3 x 4 x 5 = 120

If factorials are new to you think of them as defining the number of ways to arrange n items

To avoid displaying results in scient i f ic notat ion use

cout ltlt setprecision(0) ltlt fixed

setprecision() requires include ltiomanipgt

12 0 Is defined to be 1

34

Figure 2

PLUSPLUS Recursion

Come back to this after weve covered functions

Note that our solution optionally also uses a function and recursion to find the same factorial If you open it you will see that just after where we perform the output above we have commented out an extra line of code (uncomment and rebuild to see it in action)

We havent covered recursion in this C++ course yet but its basically the process of solving a problem in terms of smaller versions of the same problem Since the problem gets smaller each time the process eventually terminates in a problem (the base case) that can be solved directly When defining a recursive function be sure of three things 1 The problem gets smaller each time 2 Include a solution for the base case And 3 Each case is handled correctly

The recursive function looks like this ndash add then test it in your own solution

Factorial function using recursion

long long int recur_factorial(long long int n)

return n lt 1 1 n recur_factorial(n - 1)

The question mark is the conditional operator and is used with the colon to form the functional equivalent of an if then else

35

If the expression before the is true then the expressionstatement to the left of the is evaluated otherwise the one after the is evaluated Eg these are equivalent

x boo() hoo()

if(x)

boo()

else

hoo()

4 Logical and Bitwise Operators

41 Logical

Quite often we will want to perform some action if two things are true and we can achieve this using nested if statements eg

if(onething == true)

if(secondthing == true)

do something

In C++ we can achieve the same result through the use of the l ogical And operator - ampamp

if(onething == true ampamp secondthing == true)

do something

ampamp is a binary operator ndash meaning that it takes two arguments (nothing to do with base 2) eg Op1 ampamp Op2 The expressions Op1 and Op2 must be capable of evaluating to t rue or false (false in C++ has the value 0 whilst any other value is considered true) and both Op1 and Op2 have to be true in order to have the conditional part execute eg if(x ampamp y) Z = 10 Here both x and y must have non-zero values in order for z to be assigned the value 10 Note again that this is equivalent to

36

if(x)

if(y)

z = 10

The truth table for logical And is as follows ndash note that both Op1 AND Op2 have to be true for the result to be true

Logical And

Op1 Op2 Result

True True True

True False False

False True False

False False False

We also have a Logical Or operator (||) in C++ and its truth table looks like this ndash note that its one OR the other that has to be true in order for the result to be true here

Logical Or

Op1 Op2 Result

True True True

True False True

False True True

False False False

The remaining logical operator we have is the unary Logical Not (the exclamation mark is used for this)

Logical Not

Op1 Result

True False

False True

Logical ampamp and Logical || short-circuit ie for ampamp if the expression on the left-hand side is found to be false then the expression on the right is never evaluated as the whole will evaluate to false (because to be true both sides have to be true and we know that the first one is false at this point)

37

The same is true for logical || in that the right-hand expression is not evaluated if the left is found to be true (the whole will evaluate to true because the left is true so there is no need to evaluate the right-hand expression)

42 Bitwise

PLUSPLUS Base Two and Bits

We also have bitwise versions of the logical operators ndash plus some extra ones Bitwise operators work on a variables individual binary bits ndash rather than the value of all the bits taken as a whole For bitwise And we do not use ampamp but use just a single amp The same is true for bitwise Or we just use a single | and not || Bitwise Not is a little different we use ~ (the tilde) for bitwise Not

The additional bitwise operators we have are for bitwise XOr ndash for which we use the ^ symbol and lastly for left and right bit shifting we use ltlt and gtgt

Bitwise operators work on binary bits (1s and 0s) whereas the logical operators work on values equating to either true or false

For example consider the following code

int w = 10 int x = 42

int y = w amp x

int z = w ampamp x

cout ltlt y ltlt endl

cout ltlt z ltlt endl

The base-2 binary representation of 10 is 001010 and for 42 it is 101010 So w amp x means

001010 101010 amp ------ 001010 ------

Remember And is one and the other

Now let us consider w ampamp x Here were not interested in ws or xs bits just whether when taken together they are zero or something else Here both are non-zero so both are considered to be t rue and if we refer to our truth table from earlier on we will see that the result will be t rue When we assign that to an integer like were doing here the value assigned will be 1

38

Shifts

The shift operators shift the binary bits left or right Bits that do not fit fall off the ends and bits are replaced with zeros when shifting left ie bits do not rotate and come back on the other end again When shifting right the sign-bit may be preserved depending upon whether youre using a signed or unsigned integer

Shifts are useful for all sorts of things but one of the obvious uses is to multiply and divide eg x = 2 x = x ltlt 1 shifts the bits in x one place to the left so given that xs value is 00000010 in binary x = x ltlt 1 turns x into 00000100 which is 4 So x = x ltlt 1 is like saying x = x 2 You can of course divide by right shifting

XOr

The rule for XOr is one or the other but not both ie 1 ^ 0 = 1 (just like 1 | 0) but whereas 1 | 1 = 1 with 1 ^ 1 the answer is 0

Note that we do not have a logical XOr operator in C++ as we can just use = (not equal to) ndash see the (demonstrat ion) Logical XOr project

Practising with Logical and Bitwise operators

You will need to use the Precedence and Associativity table in 1216 to complete these tasks

Task 1

Open the Logical project As earlier DO NOT compilerun this yet

You will need to consult the operator precedence table in section 1216

On paper determine the programs output13

Run the program ndash output as expected

Task 2

Open the Bitwise ndash

unsigned project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Unsigned The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

13 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

39

PLUSPLUS Signs and bits

Task 1

This one is tough as you should really know something about Twos Complement arithmetic to complete this

Open the Bitwise ndash s igned

project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Signed The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

5 Introduction to Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine (which will also be a function) Encapsulat ion is data information or detail hiding If youre mathematically minded you may think of a C++ function as being very similar to one in mathematics ie a mechanism for mapping one thing to another

Once a function is written the detail of how it works is not important It is only necessary to understand what if any inputs the function needs (its parameters) and what output is produced (the functions return value)

The use of functions provides several benefits but the main one is that it makes programs significantly easier to understand and maintain The main program function can consist of a series of function calls rather than hundreds of lines of code A second benefit is that well written functions can be reused across multiple programs

You have to tell the compiler about a function before you use it and this is normally done using a prototype early in the program A function prototype consists of the return type a funct ion name and a parameter l is t - indicating the data the function will receive ndash and is terminated using a semicolon Eg

int someFunc(int int)

This tells the compiler that there is a function (somewhere) called someFunc that takes two integers as its input and returns an integer value for its output

40

Using a prototype is a way of telling the compiler the data types of any return value and of any parameters being passed and enables error checking to be done

The function defini t ion consists of the modified prototype and a function body which is a block of code enclosed in parenthesis which does the work Eg

int someFunc(int a int b)

return a + b

Here we have named the two inputs a and b and we can see that the functions job is to add these two value and to return them As this function returns a value (the sum of a and b) it may be used to expressions like this

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

Arguments can be passed to functions in two ways pass-by-value the default is where a copy of the argument value in the main program is made and then passed to the function The copy in the function only exists in memory as long as the function is active When the code within function has been run to completion the memory is released and the value held there is lost Any changes made to the copy passed to the function do not affect the original variable in any way For example if we altered and used someFunc like this

int someFunc(int a int b)

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 20

41

Note that because we passed a copy of b to the function that the line b = b 2 alters the copy (which then isnt used) and not the original

Arguments can also be passed-by-reference When arguments are passed in this way any changes made to the arguments in the function are reflected by corresponding changes to that data variable in the calling part of the program Pass-by-reference is good for performance reasons because it can eliminate the pass-by-value overhead of copying large amounts of data (In later sections we will examine how pointers can be used to fake pass-by-reference) Eg this will alter b now

int someFunc(int a int amp b) Note the amp

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 40

See section 521 for more on this subject

Creating a function

The format of a function prototype is

return_data_type FunctionName ( argument_l ist )

The function CtoF - void CtoF(int temp) - has no return data type (void) its name is CtoF and it accepts a single input argument called temp of type int (integer)

It is not strictly necessary to give the argument a name (temp) in a function prototype you saw this above in int someFunc(int int) However the argument type must be specified The statement void CtoF(int) is therefore an alternative prototype

The following exercise is an introduction to functions You will learn a lot more about functions in later exercises

42

Writing functions

Task 1

Open the project EvenI you created earlier and change the structure of the program to make use of functions

Solution in (exercise solut ion)

EvenI I

Read two integers in to main() and pass them to a function The prototype is void intCalcs(int int)

intCalcs() function should calculate and display the result of the division and modulus of the two variables passed see Figure 3

Read in two doubles to variables in main() Pass the two doubles and the value of one integer to the second function the prototype is int Calcs(double double int)

Within function Calcs() write statements to produce the output as shown in Figure 3 Most of the code already exists within main()

Return the result of the multiplication of one double and an integer cast this value as an integer

Display the returned value within main() as shown in Figure 3

Figure 3

43

Using a struct

Task 1

Open the project Person

Solution in (exercise solut ion)

Person

As you saw during the presentation we can keep related data together using the struct keyword For example say we define a thing as follows

struct thing

int x

string y

double z

Having done this we can now create as many thing objects as we wish ndash simply by declaring them as we would say an integer

thing a

thing b

Each thing object a and b contains its own x y and z member variables eg

ax = 10 thing as x member set to 10

bx = 20 thing bs x member set to 20

cout ltlt ax ltlt endl outputs 10

cout ltlt bx ltlt endl outputs 20

Complete the exercise by creating and populating a struct Person object Once populated amend the printPerson() function so as to output the persons details

44

PLUSPLUS When Things Go Wrong

Going back to Exercise 8 if you havent tried it already enter zero as your second number What happens

C++ contains mechanisms for catching errors in the form of a trycatch mechanism

cin gtgt y Enter zero

try

intResult = x y

catch(myException amp e)

cout ltlt ewhat() ltlt endl

catch()

cout ltlt Generic oops ltlt endl

Modify your code so as to catch the divide by zero

Hopefully try and catch are fairly self-evident try something and catch any error if something goes wrong

There are two catch blocks here One tries to catch a myException object (we cannot see the definition of this classstruct here) and the other tries to catch anything else that is missed by catch(myException amp e) The amp says that the myException object e is being passed to the catch handler by reference Well learn what this means a little later in section 521

So did you see the Generic oops message appear

Your C++ compiler doesnt have to catch the divide by zero error ndash doing such a thing results in undefined behaviour This is because an arithmetic exception is an OS or processor exception - which is not the same as a C++ exception - hence it cannot be caught by a in a try catch block

To catch errors like this we either need extra support from the compiler14 andor operating system or to write some extra code For example we could do this

14 See also C signal handling httpenwikipediaorgwikiC_signal_handling

45

cin gtgt y Enter zero

if(y gt 0)

intResult = x y

However first we have to realise that this is a possible source of a runtime error and secondly we have to write (correctly) the code to handle the condition

Windows has built-in exception handling ndash called Structured Exception Handl ing (SEH) and we can generate code that uses this in support of the try catch structure used earlier

To enable this we need to tell the compiler to generate code that links into the SEH mechanism

To do this open the Project | ltproject namegt Properties hellip dialog box and in the Code Generation section select Yes wi th SEH Exceptions ( EHa) in the Enable C++

Exceptions line See Figure 4

46

Figure 4

The Monty Hall problem

The Monty Hall problem is a probability puzzle loosely based on the American television game show Lets Make a Deal and named after the shows original host Monty Hall

It goes like this

You are on a game show where you are shown three closed doors You are told that behind one of them is a new car and that behind the other two are goats

Two pieces of essential information at this stage 1 your goal is to win the car 2 the game show host knows what is behind each door

Lets walk through a trial game

The game show hosts asks you to choose a door ndash lets say you choose door number 1 (your door remains closed) The host now opens one of the remaining doors to reveal a goat (as there are two goats they can of course always do this) lets say they open door number 3

47

The situation is now as follows you have chosen door number 1 Only door number 3 is open and it reveals a goat The host now asks you if you would like to switch your door to the only other closed door - door number 2 At this stage you must either stick with door number 1 or switch to door number 2 and at that point the host will open the door youve chosen to reveal your prize

The question is when youre offered the chance should you stick or should you swap - will swapping increase your chance of winning the car or is it just 5050 The claim made here is that by swapping doors you will double your chance of winning the car What does your completed project claim

Task 1

Open and complete the incomplete project MontyHal l

The goal of this project to provide a simulation of problem outlined above

The function

int getRandomDoor(int n = 3)

return rand() n + 1

is used to choose a door number between 1 and 3 (inclusive)

Note that it has a default argument ie if it is called without an argument like this int val = getRandomDoor() the argument n is set to 3 by default and val will be set to a value between 1 and 3 However if it is called like this int val = getRandomDoor(10) then n is set to 10 and val will receive a value in the range of 1 to 10

48

More Functions

Task 1

Open the incomplete project IsLeap

The program asks for a year and determines whether the year is or will be a leap year

You need to complete the function IsLeap(int y) to implement the necessary code

Although the program is incomplete the program contains pseudo code for the algorithm required to compute the answer The pseudo is also show opposite

if year modulo 4 is 0

then

if year modulo 100 is 0

then

if year modulo 400 is 0

then

is_leap_year

else

not_leap_year

else

is_leap_year

else

not_leap_year

Figure 5

49

PLUSPLUS IsLeap in a line

Task 1

Extra points for implementing the IsLeap() function in just a single line of code This could be done using ampamp and || or by using the operator (a short form of if then else)

If you completed this step how readable is your code when compared to the if else version on the right

52 Algorithms

Algorithms

An Aside Big-O notation and Algorithm Complexity feel free to jump over this to Task 1

As programmers we usually implement the various parts of any new program in the simplest and most straight-forward way possible Then later if we find parts of our program are slow (causing what are called hot-spots) we will look again at the code to see if there is a better way to do whatever it is that is taking up the time

As a general rule the most optimal algorithms run in the shortest possible constant t ime ndash such algorithms are often symbolised using O(1) whereas the worst run in quadratic cubic exponential or factorial time (you can think of the O [called Big-Oh] as meaning in the Order of for some input n)

Usually were often happy with those running in O(n) (in the order of n) time ie their running time scales linearly with the number of steps or operations they involve Loops invariably signal O(n) parts of any algorithm

This is best explained using an example

50

Task 1 Understanding Gauss algorithm

Q How would you sum the integers from 1 to n where n is say 100

The obvious way is to use a loop

int tot = 0

for(int i = 1 n = 100 i lt= n ++i)

tot += i

This is fine for small values of n but not so good for very large ones

Interestingly it is said that this self-same problem was once given to a class of children which included one Carl Friedrich Gauss (presumably the teacher wanted to keep his charges occupied for a time) While most of the children started working at the problem (using the loop approach above) Gauss thought about it for a moment and then wrote down the solution 5050

The algorithm Gauss used may be easily demonstrated using the values 1 ndash 10

Gauss realised that if he wrote out the values twice (whether on paper or just in his head) once forward and once in reverse that he could sum each column formed to 11

1 2 3 4 5 6 7 8 9 10

10 9 8 7 6 5 4 3 2 1

1+10 2+9 3+8 4+7 5+6 6+5 7+4 8+3 9+2 10+1

=11 =11 =11 =11 =11 =11 =11 =11 =11 =11

Then sum of 1 ndash 10 is then 11 10 (columns) = 110 2 = 55 (we divided by two because we used each value twice)

Coming back to algorithm runtimes you can see that when using a loop summing 1 ndash 1000 will take ten times longer than summing 1 ndash 100 which will take ten times longer than summing 1 - 10 However by using Gauss approach we can arrive at the answer for any range of values in the same time this is what we mean by a constant time algorithm

51

Task 2

Open the incomplete project SumIntSeries

Complete the project so as to implement Gauss algorithm for any continuous range of integers

The solution project is (exercise solut ion)

SumIntSer ies

The general formula required is

((119948 minus 119947) + 120783)(119947 + 119948)

120784

Or in a more code form

Sum = ((k - j) + 1) (j + k) 2

Where j and k are the starting and ending values in the range respectively (both inclusive)

Functions and Pass by Reference

In the previous section when working with functions all arguments passed to the functions were copies of variable values from main() The arguments were passed by their value

Pass by Value is the default argument passing mechanism for C++ (and the C language)

In pass by value when a function is passed an argument it receives a copy of the value from the calling function (main() in previous examples) This copy remains in scope until the called function has completed and returned at which time the copy is destroyed

Therefore a function that takes value-arguments cannot change a passed variables value because any changes only apply to copies and not to the actual callers variables

An alternate passing scheme is called Pass by Reference

Passing variables to functions by reference is very useful when we need to change or update variable(s) via a function (it is also a faster mechanism than pass by value as no copies have to be made)

Under the covers pass by reference involves passing a memory address and not a copy of the data to the function This is usually more efficient than passing by value because there is no requirement to copy memory However this argument passing mechanism enables a function to modify any argument even if its not supposed to To avoid this we usually declare all read-only parameters as const and pass them by reference

The format of a function prototype when using call by reference is

return-data-type funct ion-name (reference parameter) To indicate a reference parameter an ampersand (amp) is written in the function prototype and header after the parameter type name

The statement void squared(int amp) has no return data type (void) its name is squared and it accepts a reference parameter (amp) of type int (integer)

52

The function definition would be something like this

void squared(int amp inVal)

inVal = inVal inVal inVal

The function call to it would look like this

squared(aValue)

As mentioned above pass by reference is normally used for one of two reasons 1 Because we want to be able to change a passed variable inside a called function 2 Because we want the speed associated with a pass by reference

In 2 we will normally protect our argument by using const in the called function Eg say we want to pass the double argument x to a function f() and take the least possible time about doing it (and given that function f() shouldnt alter x) we would use the following code

void f(const double x)

Use x in some calculation Note that if

x appears on the left hand side of an assignment operator

that it will result in a compilation error

Pass arguments by reference

Task 1

Open the project (demonstrat ion) FunctionRef

Compile and run the program The output should be the same as shown in Figure 6

53

Figure 6

Examine the function prototype

void squared(int amp)

This shows the function squared accepts a reference

parameter of type int The reference parameter is ndash under the covers - the memory address of the argument passed to the function

The function uses this address to both get and set the value stored in variable a (value 21) in main() A reference to this address is passed to the function with the function call squared(a)

Examine the function void squared(int amp x)

Under the covers references to x refer to the address of the variable a in main (that holds the value 21) Ie x and a reference the same piece of memory (the word object was deliberately not used there) So we can think of x and a as two names for the same item

Returning values from functions

In previous programs we have most often produced output (using cout) from within the functions However to be of most use and general utility functions should return resultsinformation rather than output it

Functions may return results in one of two ways 1 via a return value or 2 via arguments ndash either passed as references or via pointer (address)

Non void Functions return a single value ndash if you will they evaluate to this value As such non-void functions may be used in expressions Eg

54

w = x sqrt(y) z

The function sqrt() is replaced with the value of whatever the square root of y happens to be For example if y has the value 4 then to evaluate x sqrt(y) z fully the sqrt() function has to be called ndash where it returns 2 This value is then substituted into the expression for further evaluation ie it becomes w = x 2 z

The second way for functions to return results is via its parameters ndash if they are references or passed via memory addresses Eg

void doubleIt(int amp n)

return n 2 Error The void means doesnt return a value

doubleIt() is a void function ndash so it cannot contain a return statement ndash so it cannot evaluate to anything ndash so it cannot be used in an expression

x = doubleIt(y) error

However the function is still able to return a result (modify something outside of itself is perhaps a better way of putting it)

void doubleIt(int amp n) using amp - a reference

n = n 2

55

doubleIt() cannot (still) be used in an expression but it can change things

int x = 10

doubleIt(x)

cout ltlt x Outputs 20

Why would you use references like this Well references are mainly used for speed (by passing an actual external entity a copy does not have to be made) but they are also useful when multiple values (entities) might best be updated via a single operation (function call)

int x y z

x = y = z = 10

doubleAll(x y z)

void doubleAll(int amp a int amp b int amp c)

a = a 2 b = b 2 c = c 2

Side effects

Going back to w = x sqrt(y) z

Lets replace sqrt() with our own function and cause some havoc

double havoc(double amp d)

++x

d = sqrt(d)

return d

x = 3

w = x havoc(y) z

56

Here the value of y has been changed (yet it is not clear that could happen from the functions call site ndash where it was called from) and so has x Also what value for x will be used in x havoc(y) z Will it be 3 or 4 These sorts of issues are called side-effects

This is one problem (or advantage) with reference arguments ndash and that is that they can cause a change in a variable outside of the function being called

One way to protect against this is to use const references eg

double havoc(const double amp d)

++x

d = sqrt(d) Compilation error here

return d

57

Returning a value from a function

Task 1

Open the TempConver t

project

Run the program The output should be the same as shown in Figure 7

Examine the function prototype

double convert(double temp int mode)

This function prototype has a return type of double When the function is called and calculations are completed a double value is returned to the caller

Examine the function definition The function definition matches the prototype indicating a double and an integer are being passed to the function and a double is being returned

Examine the function body The two statements below convert the temperature input The conversion type required is identified using the user input mode and a switch selection

The statement (temp - 32) 5 9 is used to calculate the temp in Centigrade

The statement 18 temp + 32 is used to calculate the temp in Fahrenheit

Figure 7

58

PLUSPLUS Arithmetic Bases

Task 2

Open compile and run the partially complete Bases project

Note that the project isnt complete

The program uses intrinsic functionality to output values in hexadecimal and octal ndash base 16 and base 8 Both these bases are useful in programming its all to do with binary and the size of a byte

Note that there isnt a bin equivalent to hex and oct and that we have instead written a function called bin1() to convert a value into its binary (base 2) representation

Understanding how bin1() works

bin1 uses the modulus operator () and the right shift operator (gtgt) to work eg 42 in binary is 101010

25 24 23 22 21 20

32 16 8 4 2 1

----------------------

1 0 1 0 1 0

----------------------

1 32 + 0 16 + 1 8 + 0 4 + 1 2 + 0 1 = 42

The function progresses like this

42 2 has remainder zero (false as evaluated in the if) If the if test is true we store a 1 else we store a 0 We then divide 42 by 2 by right shifting it one place ndash but just replace that with n = 42 2 if you prefer We then loop while we have a non-zero value in n to operate on hellip

42 2 = 210 42 2 = 0 if(42 2) = false string value = 0

21 2 = 105 21 2 = 1 if(21 2) = true string value = 1

10 2 = 50 10 2 = 0 if(10 2) = false string value = 0

5 2 = 25 5 2 = 1 if(5 2) = true string value = 1

2 2 = 10 2 2 = 0 if(2 2) = false string value = 0

1 2 = 05 1 2 = 1 if(1 2) = true string value = 1

59

Task 3

The project needs completing specifically it needs the function bin2() writing

We could write such a function as bin1 in a variety of ways and wed like you to write a new function called bin2() that produces the same output as bin1() here

Heres a step by step algorithm for implementing bin2()

Youll use either gtgt or and the bitwise And (amp) operator

Take the functions input (the number to convert) in as a parameter called n To keep it as simple as possible for now you could use plain int types rather than the unsigned long long type we used so the functions signature would look like string bin2(int n)

1 In the function create an integer called i and initialise it to 1

2 Realise that if you left shift the single bit in i (use ltlt or multiply it by 2) it will take on the values 2 4 8 16 32 hellip until it eventually goes to 0 ndash as you shift the bit off of the end

3 Recognise that you could compare your shifting bit with one in the same position in n using bitwise And Ie if((n amp i) == 1) then you know youll need a 1 in your output string for the bit position in n (2 4 8 ) given by is value at this point

4 Build up your result string as you proceed

Change your int n and int i to unsigned long long int and re-run

Try using other integer types ndash signed and unsigned

Lastly examine the solution project in (exercise

solut ion) Bases

60

Figure 8

61

Searching for Sequences

Task 1

Open and modify the incomplete project called called HeadsOrTai ls

When all completed the output should be similar to that shown in

Figure 9

This is the (exercise

solut ion) HeadsOrTai ls project

The programs purpose is to look for a sequence of simulated coin tosses ndash a series consisting of Hs and Ts

The program is complete (as in it runs) but it has some issues At first test it using quite short sequences

The timing information displayed by the application is included simply to demonstrate a timing mechanism that can be used to test the efficiency of the code

The first problem is that the user can currently enter characters other than H or T (h and t are ok as the input is converted to uppercase ndash note the string is passed by reference to toupper() which uses a pointer (which well cover later) to process the string

The second problem is that as it stands the algorithm isnt very optimal if we do not find our pattern we add the result of another coin toss to the current sequence and then re-check the sequence in its entirety

For example if were looking for HHTHH and the generated sequence is currently HTTHHHTTHTHHTTH we will fail to find HHTHH and then proceed to add another coin-toss result at the end ndash HTTHHHTTHTHHTTHH We will then scan this for HHTHH However as we know that we failed to find HHTHH before we added the extra coin-toss re-checking the previously checked sequence is pointless and very time consuming (think how this would (or wouldnt) scale) Your task here is to think of and implement another more optimal approach

62

Figure 9

Task 2

Open the HTTvsHTH project you will find that the project will compile correctly but displays an incorrect result

When completed the program can be used to check how many coin-tosses are required on average to see a particular sequence

Why should that be of interest Because sometimes its rather surprising For example test how many tosses are needed to see say HTH and then HTT

When the program is corrected the output should be as shown in Figure 10

63

Figure 10

PLUSPLUS Optimising Searching for Sequences

Task 1

As it stands the program (yours and ours) encodes a coin toss as a character ndasheither an H or a T Each character is encoded using at least 8-bits and so checking whether a generated sequence is the sequence were looking for means performing a string comparison which is costly in terms of clock-cycles Of course generating and storing the new coin toss also requires the use of these costly string operations

As we have just two tokens as an alternative to generating and storing characters and performing string operations we could encode a sequence as a series of bits For example the sequence HTH could be encoded as 101 in binary (5 in decimal) You can set the corresponding individual bits in an int using the bitwise Or operator | (a vertical bar) eg int n = 0 n = n | i which youd most likely do as a result of scanning the users entered search-sequence string a character at a time In this way you could encode the sequence HTHHTHHTHHTHHTHH in a single sixteen bit unsigned int

Additional operators needed to implement sequence checking and H or T bit manipulation are bitwise And (amp) and the left shift operator (ltlt)

You will find more information on some of these operators just a little below

64

Evolving Searching for Sequences

Task 1

Looking for sequences in stringssequences is an interesting and complex problem in computing and also in genetics where the string being searched could be a DNA sequence and pattern could represent a gene perhaps with a snip (a modificationmutation)

Modify your HeadsOrTai ls program (or our solution) so that instead of Hs and Ts it generates and searches for Gs As Ts and Cs instead

Randomly generate a GCTA sequence and a similar pattern to find within the sequence

How much more time and variation is required in this slightly more complex situation

Conduct a few experiments and using Excel graph your results (copy and paste some data highlight it and then select Excels line graph ndash Excel should then automatically plot your data)

Extrapolate The human genome is how long A gene might contain how many bases How difficult is the task of finding interesting sequences in the human genome How about checking for the odd mutation (insertion transposition deletion) ndash fuzzy matching

A solution for this problem can be found in the (demonstrat ion) GATTACA project

6 Classes and Objects In the previous section we have been working with simple programs that display messages to the user store data input as different data types manipulate the data in some way and output the results to screen

We will now start to look at C++ objects and classes

In the real world there are objects everywhere students staff cars birds houses and many more All objects have at tr ibutes these are similar to the variables created in previous tasks Some attributes of a student may be height weight race course of study etc All objects exhibit behaviours or operations cars accelerate and decelerate students matriculate enrol on courses and leave university

65

Now what is the relationship between a class and an object A good analogy would be from an architects blueprint for a house it would be possible to build many houses Similarly from a class in C++ it would be possible to build many objects

If we had a student class we could create many objects from the student class to represent the many students enrolling Each of these objects would be uniquely identified They would share common attributes and exhibit common behaviours If we wanted an object to perform some task we would call the appropriate member function allowing an operationaction to take place changing the behaviour of that object

Member functions are different from the functions you have created so far Member functions are always associated with objects and are usually called or invoked using a dot notation object member funct ionname() An example is student1getName() The object instance is student1 and the member function is getName()

Member functions contain the detail of how the technical aspects of some operation will be processed When member functions are invoked these technical issues are hidden from the end user When the member function is asked to do some operation a message is sent (a member-function call) telling the member function of that object to perform the operation detailed in the function

Functions are not completely new we have had a brief introduction and you have already created some of your own Note also that main() is a function that is called automatically when you run your program However it is not a member function as there is no object associated with it

Creating your first class

Creating a class

Task 1

Open the project called StudentUG

Compile and run the program It should look like Figure 11

66

Figure 11

Before you can create the object myName it is necessary to define the class from which the object will be created The class definition is shown below

class StudentUG Start of class definition

public

void displayName() Start of member function

cout ltlt My name is Michael Cain ltlt endl

Note a semicolon is required at the end of the class definition

Within main() the statement StudentUG myName creates the object myName of class StudentUG In effect StudentUG is a new type

The statement myNamedisplayName() is used to call the member function displayName() of object myName

As we have seen previously the function main() is called automatically when our programs are executed However member functions (displayname() is one we could have many) must be called in this way objectInstanceNamefunctionName() when dealing with an

67

object directly and like this objectInstanceName-gtfunctionName() if working through a pointer to an object (more on pointers later)

The member function displayName() is preceded by the word void All functions can return values this one does not The word void preceding the function name indicates nothing is being returned If this function returned an integer the definition would be int displayName()

When you use functions it is common to pass data (called parameters) to the function The function then manipulates the data before displaying an output andor returning a value

To pass a parameter to the function in the studentUG class the calling statement in main() would be

myNamedisplayName(name) where name is a string (a series of characters) that contains a value read in from the keyboard

In order for the function displayName() to recognise the parameter being passed the function declaration is changed to include the parameter (name) and type (string) as shown in below

void displayName(string name)

cout ltlt My name is ltlt name ltlt endl

Figure 12

Member functions and Passing parameters

Passing parameters

Task 1

Modify StudentUG to read in a student name The name should be passed to a member function The parameter should be output from within the function to welcome the user to C++ programming

68

Task 2

Modify the program in the above task to read in two more names Each name will be for a different student and you will need to create additional objects (instances) of the class

Data Members

In most of the programs written so far the variables have been declared inside the main() function Variables declared inside a function are local to that function and cannot be accessed from outside that function

You have created a student class and it would be reasonable to assume that a student would be following a particular course So courseName might be one of several attributes of a StudentUG object Attributes are represented as variables in a class defini t ion These variables are called data members and must be declared inside a class definition When you create an object of a StudentUG class each object has a unique memory location for its data members

Figure 13 shows data member name declared in the class definition The access specifier private means that only member functions of the class in which the attribute was declared can use this data member

private string name

Figure 13

When data members are declared as private the data is hidden This is called encapsulat ion and means the attributes of the object are hidden and can only be accessed via member functions

As there is no direct way to change a data member you will also need to create a member

funct ion to set the data member to a value and create a second member funct ion to output the value held there

Data members can also be declared public A data member that is declared public can be accessed from any (non-member) function

A protected data member can only be accessed by member functions of its own class and by member functions of classes derived from this class We will learn more about derived classes and inheritance later

69

Using data members

Task 1

Open the project called StudentCoursesln

Compile and run the program it should look like Figure 14

Figure 14

Task 2

Examine the member function getCourse() shown in Figure 15

string getCourse()

return course

Figure 15

Task 3

Modify the StudentCourse source file to enable the user to add a student name enrolment date and number of years of course Once entered this data should be output to screen You will need to create additional data members and member funct ions to achieve this

70

More Objects

Task 1

So far you have created one StudentCourse object It is about time we had a second student on the course Create a second object of the class StudentCourse You will need to add the second statement shown in Figure 16 to add the new object student2 Call the member functions passing parameters as necessary

Figure 16

Constructors

When you create objects from the StudentCourse class it is necessary to give initial values to all the data members If we were entering data for five people and they were all following the same course of study it would make sense to initialise the course data member (it is possible to initialise some or all of the data members) when each object is created

A constructor is a special kind of function that must have the same name as the class Constructors are normally defined to be publ ic and never have a return type They can be used to automatically initialise data members

In previous programs you have written a defaul t constructor has been provided by the compiler However it is not possible to pass parameters to a default constructor function so the data members in the programs created so far have not been automatically

71

initialised To initialise these data members you created member functions that assigned values to data members

Although a default constructor is provided at compilation time it is a good idea to create your own so that the data members can be initialised

It is worth noting here that functions (constructors are functions) can be over loaded This means it is possible to have more than one function with the same name Note that overloaded functions (functions with the same name) must have different types of or number of arguments

Constructors (functions) can also be overloaded with more than one function with the same name but different types or number of parameters Fortunately for us the compiler automatically calls the correct function whose parameters match the arguments used in the function call

Using constructors

Task 1

Open the project called Constructorss ln

Compile and run the program it should look like Figure 17

Figure 17

72

Task 2

In the constructor shown in Figure 18 what is the purpose behind course = Note that as the string parameter name has the same name as the class variable that we use the hidden this pointer to access the class variable in the assignment If we didnt do this and simply used name = name instead then all we would be doing is assigning the value in the parameter back to the parameter

StudentCourse(string name)

this -gt name = name

course =

Figure 18

Task 3

Create a third constructor that will take an argument enrolment_date

Add a third object call it student3

Write code that will test this additional constructor

Solution in (exercise

solut ion) Constructors

If time allows add other useful properties (data members) access methods (functions) and constructors

Separating use from declaration and definition

C++ is all about objects and any decent project will usually make use of a number of application or domain specific classes

To keeps things maintainable and to promote code reuse C++ projects usually contain a number of cpp and h files where each h files will usually contain a declaration of a class (sometimes called an interface) Note though that the definition of the class (sometimes called the implementation) ndash the code that implements it ndash will be absent from the h file and will instead reside in an accompanying cpp file

Aside from allowing different teams to more easily work on separate parts of the program one of the main reasons for separating definition from declaration is to enforce abstraction which is a programming (and design) technique that relies on the separation of declaration and implementation For example lets say that your team needs a class that acts a bit like a stack (a last-in first-out or LIFO structure) and as this is required

73

urgently you decide to implement it using a simple array You would then only want to give your team what is absolutely necessary to use this class a single h file for your team members to include in their cpp files If they look in the h file they will only see information on how to use the class but how it does what it does is kept elsewhere in the cpp and that youve withheld Consumers shouldnt need to know how a thing works in order to use it

An obvious advantage to this is that there is no danger in you changing how it works Perhaps you later decide to use a vector instead of the array You go ahead and alter the implementation and your team members are none the wiser ndash after all the interface hasnt altered just the implementation

So how does the project get built Of course the implementation of this class will be required at compile time and you can either do that by including the cpp file directly (which will give away the implementation details of course) or by including it as object code ie compiled C++ code (binary machine code) This is how valuable commercial source code is kept in-house while the binary implementation complete with a h file is provided to customers (you will see an example of this just below in Using external

l ibrar ies and thi rd par ty header f i les )

Any discussion on separating use from declaration and definition should include something on namespaces You introduce a namespace by simply using the keyword and braces Anything entered inside these braces is inside the namespace eg

namespace securityModule class Encryptor using namespace std using namespace securityModule int main() Encryptor e Without the using we would have had to use securityModuleEncryptor e securityModuleEncryptor e2

See the (demonstrat ion) Namespaces project for more on this

74

Separating declaration and definition

Using a header and source file to separate class declaration from definition

Task 1

Open and modify the partially complete skeleton project called Precis ionTimers

Like HeadsOrTai ls this project makes use of the Windows operating system to very precisely measure elapsed time However unlike HeadsOrTai ls we have separated the stopWatch class interface from its implementation

As weve previously mentioned Gauss and algorithm efficiency we could test our theory that summing in a loop is O(n) ie that the time taken scales with n

Examine the project files hrTimercpp and hrTimerh noting that the h file contains just enough information for someone to use the declared class stopWatch whilst htTimercpp contains the implementation of the class

Now look in PrecisionTimerscpp You will see that an instance of the stopWatch class is declared Also note that we include hrTimerh but make no reference to hrTimercpp

As it stands the code calls two functions to calculate the sum of a range of integers sumGauss() and sumLoop() The program outputs the clock-ticks used and time taken in seconds

Note that sumLoop() is incomplete

Complete the sumLoop() function and then choosing suitable values for the ranges upper-bound carry out a few experiments to test if the loop is really O(n)

What is this used to do in hrTimerh15

ifndef HRTIMER

define HRTIMER

endif

15 You should also see pragma once as this is rapidly becoming the alternate way to do this ndash whatever this is of course

75

PLUSPLUS Providing object code only

Task 2

We have provided a separate demonstration project that takes the discussion on this one step further (demonstrat ion)

Separat ingThings

In its current form the project wont compile To compile the project in the Solution Explorer add the existing carcpp file to the source files list that just contains SeparatingThingscpp and recompile carcpp is in the same folder as SeparatingThingscpp

Once youve done that right-click on carcpp in the Solution Explorer and select Remove Very importantly when youre prompted for confirmation choose Remove do not choose Delete Now recompile once more youll see that the project fails to compile as the definition of car has been removed

76

But hold on we created carobj - the compiled object-code version of carcpp during our previous compilation so we could tell the linker about that and all should be well (this more or less duplicates the scene whereby you do not provide source code but provide only object code)

The carobj file will be located somewhere like

CUsersDesktopCourse(demonstration) Separating Things(demonstration) Separating Thingsbincarobj

To add this to your project go to Project | Properties | Configuration Properties | Linker | Input

77

In the right-hand window select Additional Dependencies drop down the list and select ltEdit gt

In the dialog that appears add the full path to carobj (see earlier in Step 2) and press Ok

Lastly recompile the code once more It should compile and run At this point you could if you wanted to delete carcpp altogether

One last thing

If you look in the comments in SeparatingThingscpp you will find a discussion that goes into the advanced topic of hiding things even further This includes a brief discussion of the the so called pimpl pattern (pronounced Pimple this stands for Pointer to Implementation16)

16 httpenwikipediaorgwikiOpaque_pointer

78

PLUSPLUS Using external libraries and third party

header files

Task 3

Open and modify the project called Lot to

Examine the projects comments to understand the programs function Run the program ndash does it work

It is supposed to compute the odds of winning the UKs lottery httpwwwnational-lotterycouk (try as we might we couldnt find the odds on their own website)

The program uses the recursive factorial function used earlier in the course (with bigint being typedef ed as unsigned long long int)

Factorial function using recursion

bigint recur_factorial(bigint n)

return n lt 1 1 n recur_factorial(n - 1)

There is a problem here however in that to compute the odds we must compute some significant factorials ie

49 = 608281864034267560872252163321295376887552831379210240000000000

and

6 (49 - 6) = 43498989405629161658895695089330078205230448640000000000

Sadly our bigint (unsigned long long) can hold a maximum value of 2^64 ndash 1 = 18446744073709551615 ie not hardly big enough

Fortunately in C++ we can define new types like an arbitrarily sized integer (outside of the scope of this course but see the (demonstrat ion) newINT project for a small taste) However this is object orientation ndash surely we can just use an existing already defined arbitrarily sized integer class

79

Task 4

The good news is that in this class you can You can use LEDA (The L ibrary of

Eff ic ient Data types and Algor i thms ) a professional class library of advanced numerical functionality

You will need to download the program called

LEDA-63 i386 msc 10 ( NET 2010) 32 bi t

or

LEDA-63 i386 msc 10 ( NET 2010) 64 bi t

Go to wwwalgorithmic-solutionsinfofreeindexphp Accept the licence terms and download the appropriate version (usually the 64 bit version)

The LEDA installation program will install additional numerical libraries and header files from the Algorithmic Solutions company

Once the setup is complete modify the Lotto program

In the Solut ion Explorer right-click on your project (Lot to ) and left-click on Proper t ies A dialog-box appears

Under the CC++ section

1 Click on General Choose Addi t ional include di rec tor ies and enter the directory CAlgor i thmic Solut ions LEDA-63- free-win-msc10-

s td incl

2 Click on Preprocessor and add LEDA_DLL to the end of Preprocessor

Defini t ions Note the semicolon is required

3 Click on Code Generat ion and check that Runtime Library is set to Mult i - threaded Debug DLL ( MDd)

Under the Linker section

4 Click on General

5 Choose Addi t ional l ibrary di rector ies and enter the directory CAlgor i thmic Solut ionsLEDA-63- free-win-msc10-s td

6 Click on Input and add l ibGeoW_mdd_dl l l ib leda_mddl ib to the end of Addi t ional Dependencies Again the semicolon is significant

You may now close Properties dialog-box

7 Modify your code Add the following under include ltiostreamgt

include ltLEDAnumbersintegerhgt using ledainteger using namespace std

80

Then modify the recur_factorial() function so that it accepts and returns a type called simply integer rather than bigint

Save the project and exit Visual Studio

In order to build and execute Lottoexe Windows needs to have l eda_mdddl l in its search path for DLLs Therefore we need to add the path to the folder containing leda_mdddll to the PATH environment variable

8 In Windows Explorer navigate to My Computer then right-click on it and select Propert ies

9 Click on the Advanced tab and then on the Environment Var iables button

10 In the bottom section (System var iables ) of the dialog box highlight Path and then click the Edi t button

At the end of the existing path add -

11 CAlgor i thmic Solut ions LEDA-63- free-win-msc10-s td

Once more note the leading semicolon is significant

81

12 Restart Visual Studio and re-open Lot to Build and run the application as normal

It might seem that this was a lot of work for such an apparently trivial result but the fact is that you now have access to (and have seen how to use) an advanced numerical library of functionality And anyway when all is said and done you must admit that at least you got a return here ndash which is more than you should reasonably expect from the lottery

Figure 19

Task 5

Explore the LEDA samples and documentation ndash if you installed it there should be a shortcut in your start menu to LEDA-63-free-win-msc10-s td

Task 6

Modify the Lotto program to see how the odds change when there are more balls andor when more balls need to be matched (you might also display more of the intermediate results of calculations ndash like 49)

Destructors

Both constructors and destructors are special class methods We have seen how a constructor is called whenever an object is defined

A destructor has the class name prefixed by a tilde ~ Like constructors destructors cannot return values and therefore they have no return type specified but unlike constructors destructors have no arguments and thus cannot be overloaded

An objects destructor is called whenever an object goes out of scope The purpose of the destructor is to clean up eg to free any dynamically allocated memory that the object was using and release other system resources such as files and database connections etc

In the examples used so far no destructor has been provided for any class created In these programs it has been unnecessary If the programmer does not explicitly provide a

82

destructor the compiler will create an empty destructor in the same way that an empty constructor is created if one is not explicitly created

When classes are created any objects instantiated from them that contain dynamically allocated memory will need destructor methods added to implicitly free any dynamically allocated memory when the object goes out of scope

In the class example shown below the destructor function is ~StudentCourse()

~StudentCourse()

cout ltlt Im being destroyed

7 Arrays vectors lists and hash-tables Arrays vectors and lists are all types of data structures Data structures are areas of memory where collections of the same data type are held The main difference between arrays vectors and lists is that arrays stay the same size throughout the program execution whereas vectors and lists can grow automatically

Arrays consist of a series of elements (variables) all of the same type placed consecutively in memory Each of the elements can be individually referenced by adding an index to the arrays name We saw this type of notation earlier when using arrays

Eg

int examMarks[10]

This declares an array of ten scores score 1 is accessed via an index of zero ndash examMarks[0] and score 10 is access through an index of nine ndash examMarks[9] Very important note that indexes start at zero

The advantage of using arrays compared to using discrete variables (the way we have stored values so far) is it is possible to store any number of values of the same type in an array using the same identifier

With arrays it is possible to store 100 student exam marks or 100 student names with using one unique identifier

Vectors and lists are container classes which were originally part of the Standard

Template Library (STL) The STL evolved into C++ Standard Library ndash which includes iostream etc This is the general-purpose C++ library of functions algorithms and data structures that we can use in our programs While some aspects of the library are very complex it can often be applied in a very straightforward way that allows reuse of sophisticated data structures and algorithms

There are many container classes in the library ndash note that C++ now also provides such a class for the more primitive array

ltarraygt

New in C++11 and TR1 (Technical Report One)

83

A container for a fixed sized array

ltbitsetgt

A bit array

ltdequegt

A double-ended queue

ltforward_listgt

New in C++11 and TR1 A singly linked list

ltlistgt

A doubly linked list

ltmapgt

Sorted associative array and multi-map

ltqueuegt

A single-ended queue

ltsetgt

Sorted associative containers or sets

ltstackgt

A stack

ltunordered_mapgt

New in C++11 and TR1 Hash tables

ltunordered_setgt

An unordered_set unordered_multiset

ltvectorgt

A dynamic array

As with an array vector and l is t can hold objects of various types However unlike arrays vectors and lists can resize shrink and grow as elements are added or removed

The standard library provides access via iterators or subscripting Iterators are classes that are abstractions of pointers (more on pointers later) They provide access to container classes using pointer-like syntax and have other useful methods as well

The use of vectors lists and iterators is preferred to arrays and pointers By using containers common problems involving accessing past the bounds of an array are avoided Additionally the C++ standard library includes generic algorithms (an algorithm is a set of instructions on how to perform a task) that can be applied to vectors lists and other container classes

Declaring and using arrays

Arrays are declared indicating the type and number of elements in the following way

type ar rayName[arraySize]

84

Examples are

int inNumbers[20] an array called i nNumbers of 20 in tegers

char inName [20] an array called i nName of 20 characters

float ExamMarks[5] = 0 an array called ExamMarks of 5 floats with all elements explicitly initialised to zero

const int size = 5 declaring a constant variable size

float ExamMarks[size] When the constant variable size is applied to the array declaration the number of elements is set to 5 This cannot be changed during runtime of the program However it is handy when the number of array elements needs to be changed Changing the constant value size changes the number of elements wherever the ExamMarks array is used in the program

int numArray [2][3] is a multidimensional array with 2 rows and 3 columns

Note Arrays have been used in C++ for many years and there will be code you work with that was written before vectors became available Vectors are are usually preferred to using arrays and pointers Common problems involving accessing past the bounds of an array are avoided when using vectors

Creating an array to hold exam results

Task 1

Open the project Array s ln

Compile and run the program

Run the program adding five exam results The output should be similar to Figure 20

Figure 20

85

Examine the following statements

double ExamMarks[5] = 0 This statement declares the array setting its size to 5 elements and explicitly initialising all elements to zero

cout ltlt Enter Exam Mark ltlt i + 1 ltlt This statement prompts the user to enter an Exam mark into the array at element i + 1

Using the notation i + 1 indicates to the user to enter Exam Mark 1 not exam mark 0 which would be less intuitive

Array elements are numbered from 0 to n - 1 So an array that holds 20 integers will be addressed from element 0 to 19

ExamMarks[0] -ExamMarks[19]

The first number will be entered into element [0 ] The last into element [19]

cin gtgt ExamMarks[i]

This statement reads in the user input and stores the values in the array elements of ExamMarks[i] i is incremented within the for loop and starts at 0

Task 2

As it stands the program could be generally improved ndash see the notes in the code and consider how you might make such improvements

Next modify the program to output the highest and lowest marks entered

Task 3

Modify the program so that the number of marks may be easily changed (at compile time)

86

Task 4

Modify the program so as to break out the part that calculates the average and put it into a separate function

Write another function that given an array of this sort returns the mode mean and median values ndash you will need to pass in references as the function will need to return three values

Lastly put your two new functions into a separate cpp (you will also have to create a h file for Arraycpp to use ndash this will contain the new functions prototypes)

87

Searching Arrays with Linear Search

Linear search allows the user to search the array and establish whether the array contains a value that matches a search criteria defined by the user

The search compares each element of the array with the user input The array is not sorted and this method of searching works well for small arrays For large arrays linear searching is inefficient and it is necessary to use other forms of array searching after the array has been sorted

Linear Search

Task 1

Open the project LinearSearch

Compile and run the program - choose a number between 1 and 100 The output should be similar to Figure 21

Figure 21

88

Examine the following statements

myArray[i] = (1 + rand() 100) This statement uses the rand function part of the ltstdlibhgt header file (included via iostream being included) 1 + rand() 100 produces integers in the range 0 to 99

The function l inearSearch takes three arguments The array name the size of the array the third argument is the search value

if(theArray[j] == value)

return j

This selection statement compares each element to the search value If the search value is in the array the element number is returned to main() otherwise -1 is returned

The if selection statement if(containingElement = -1) in main() is used select the output indicating a successful or unsuccessful search

Task 2

Currently the program searches for the first occurrence the search value only

Modify the program so that it outputs al l matching element locations

This function can be used for turning an int value into a string See also the comment below about C++11s to_string() functions

string convertInt(int number)

stringstream ss

ss ltlt number

return ssstr()

Youll need to include ltsstreamgt to use the stringstream class

89

Task 3

Modify the program so that repeated searches may be carried out

See Figure 22

If using C++11 or later you can also use the to_string() helper functions of the string class eg to_string(10) yields 10

Figure 22

PLUSPLUS Debugging Linear Search

Task 1

For debugging purposes modify the program so as to output the contents of the array

Open and run (exercise solution) LinearSearch to see what this might look like You might want to use the modulus operator () to work out when to neatly break a line

You may or may not like to have the program generate varying sets of random numbers To facilitate this youll need to seed the random number generator by inserting a line of code like this

srand((unsigned)time(NULL))

Note the use of the cast

To use srand() include timeh at the top of your program

90

Sorting Arrays with Insertion Sort

When working with large quantities of data in an array you will need to sort the data at some point This makes searching for information quicker and there are many algorithms available that can be used In the following exercise you will learn how to sort numbers stored in an array in ascending order

SortingSearching an array

Task 1

Open the project Sorts

Run the program and examine the code

The program currently uses a class (sorts) which is defined in sortsh to implement one popular sorting algorithm called Inser t ion Sor t

For details on this algorithm see

httpenwikipediaorgwikiInsertion_sort

91

Task 2

Add a new sort to the sorts class

The text file quicksor t txt (in the Sorts folder) contains the C++ code required to implement another popular sorting algorithm called Quicksor t17

For details on this algorithm see

httpenwikipediaorgwikiQuicksort

Add the quicksort code found in quicksor t tx t to the sorts class - considering what parts of it need to be publicprivate

quicksort tx t is in the same folder as the Sortss ln project file

Step 2

Test the quicksort implementation on a range of values

Alter the quicksort implementation so as to have it sort in descending order

Following on from Step 3 parameterise the quickSort() function so as to add an option to have the array sorted in either ascending or descending order

17 Invented by C A R Hoare ndash Sir Tony Hoare with Christopher Strachey the most distinguished computer scientists Oxfords ever produced

92

Figure 23

93

PLUSPLUS Binary Search (Binary Chop)

Task 1

Now that the array is sorted we can implement a very efficient searching algorithm usually called either binary search or binary chop search

See Figure 24

Modify your project to allow the sorted array to be searched for a value using the binary chop algorithm See opposite

The algorithm for binary chop is quite straight forward

1 Look at the value of the middle element of the array If the value = target then youre done

2 If the value is lt than target discard the lower half of the array treating the upper half as though it were the complete array

If the value found is gt than target you obviously want to look in the lower half

3 Repeat step 1 until the item is found or else the index value becomes invalid

Pseudo code for this algorithm is here

first integer = 0

mid integer = 0

last integer = NumberOfItems

while first ltgt last

begin

mid = first + last 2

if List[mid] = target

exit while Found item

If List[mid]gt target

last = mid In the first half

else

first = mid + 1 In the last half

end

found boolean = List[mid] = target

94

Figure 24

Multidimensional Arrays

Multidimensional arrays with two dimensions (arrays can have more than two dimensions) may be thought of as consisting of data arranged in rows and columns see Table 3

Each element in the array is identified by using two subscripts as shown in Table 3 The first subscript identifies the element row and the second identifies the element column a[0] [1] identifies a value in Row 0 Column 1

The array in Table 3 contains two rows and three columns and can be called a 2 by 3 array

Column 0 Column 1 Column 2

Row 0 a[0] [0] a[0] [1] a[0] [2]

Row 1 a[1] [0] a[1] [1] a[1] [2]

Table 3 ndash Array Layout

A multidimensional (2 by 3) array of doubles is shown in Table 4

Column 0 Column 1 Column 2

Row 0 2367 6792 8557

Row 1 1276 9132 2789

Table 4 ndash Array Values

95

Creating a multidimensional array

Task 1

Open the Mult iDimArray

project

Compile and run the program adding 2 exam results for each of the two students The output should be similar to Figure 25

Figure 25

96

Task 2

Examine the code used to write values to and read from a multidimensional array

Examine the following code segments

double ExamMarks[2][2] = 0 This statement creates a two-dimensional array having two rows and two columns and initialises the elements to 0

Every element in the array is identified by an element name in the form a[x] [y] where a is the name of the array and x and y are the subscripts that uniquely identify each element in a Notice that the names of the elements in row 0 all have a first subscript of 0 see Table 5 The names of the elements in column 1 all have a second subscript of 1

Note multidimensional arrays can have two or more dimensions (subscripts) Three-dimensional arrays are uncommon

Column 0 Column 1

Row 0

a[0] [0] a[0] [1]

Row 1

a[1] [0] a[1] [1]

Table 5 ndash Array Indexing

97

Examine the following code segment used to read values in to the array

for(int row = 0 row lt 2 ++row)

for(int col = 0 col lt 2 ++col)

cout ltlt Enter Exam Mark No

ltlt col + 1

ltlt for student No

ltlt row + 1 ltlt

cin gtgt ExamMarks[row][col]

cout ltlt endl

The two for loops work taking one row at a time (the outer for loop) and looping through the columns in that row (the inner for loop) When the marks have been entered for all the columns in row 0 row 1 is selected and values entered for each column cell in row 1

Table 6 shows how four results would be allocated in a 2 x 2 multidimensional array

Exam mark 1 Exam mark 2

Student 1 67 71

Student 2 61 58

Table 6 ndash Populated Array

98

Examine the following code segment used to calculate the total of each students marks

if(row == 0)

r1total += ExamMarks[row][col]

else

r2total += ExamMarks[row][col]

r1total is a variable to hold the sum of values in column 0 and 1 for row 0 (Stud1) r2total sums the values in the columns for row 1 (Stud 2)

Selection for each row is made with if(row == 0) this is Stud1 If row is not 0 then row must be 1 and the mark can be added to r2total If three exam marks were input per student the code for selecting the marks would need to change

Task 3

Modify the program to read in four exam marks for f ive students

Establish the highest and average mark for each student Output the results

One way to do this is to keep a separate array to record the students statistics An alternative would be to extend the existing arrays row so that it may hold the necessary student data

99

Declaring and using vectors

Vectors are declared indicating the type and number of elements in the following way

vectorlttypegtvectorName

vectorlttypegtvectorName(initialSize)

vectorlttypegtvectorName(initialSize elementValues)

Examples

A vector called i nNumbers with no initial size to hold doubles

vectorltdoublegt inNumbers

A vector called Name with an initial size 20 to hold characters

vectorltchargt Name(20)

A vector called ExamMarks holding integers with initial size of 4 elements each with the value 6

vectorltintgt ExamMarks(46)

Note In previous exercises you have created your own member functions In the following exercises you will use some of the vector class member functions Some of these are begin() end() erase() and size() See section 12115 for more detail

The standard library also includes a large collection of algor i thms that manipulate the data stored in containers (vectors are one of several types of container)

You can sort the order of elements in a vector (vec) for example by using the sort algorithm

sort(vecbegin() vecend()) C++11 sort(begin(vec) end(vec))

You can find a value (69) in a vector by using the find algorithm

ptr = find(vecbegin() vecend() 69) See C++ note above

100

ptr is an iterator to store the memory location of the element found

You can reverse the order of elements in a vector for example by using the reverse algorithm

reverse(vecbegin() vecend()) See C++ note above

There are two important points to notice about the call to reverse First it is a global

function (as are find and sort) not a member function Second it takes two arguments rather than one and operates on a range of elements rather than on the container (vector container in this case)

With the above examples the range is the entire container from begin() to end() (vecbegin() to vecend()) reverse like the other standard algorithms is decoupled from the libraries container classes The reverse algorithm can be used to reverse elements in vectors in lists (another container) and even elements in C arrays

int myArray[] = 1 6 20 4

reverse(myArray myArray + 4)

for(int i = 0 i lt 4 ++i) Lets see the reversed array

cout ltlt Array[ ltlt i ltlt ] = ltlt myArray[i]

In the above example the first argument to reverse is a pointer (pointers are covered in Section 8 but for now we can say the first argument points to the address in memory that is the start of the vector ) to the beginning of the range and the second argument points one element past the end of the range This range is denoted (myArray myArray + 4)

Arguments to reverse are i terators which are a generalization of pointers which is why it is possible to reverse the elements of a C array using the array address and pointer notation

Creating a vector to hold exam results

Task 1

Open the Vector project

Compile and run the program adding five exam results The output should be similar to Figure 26

101

Figure 26

Examine the following statements

include ltvectorgt This statement includes the header file vector enabling the program to use the class template vector (templates allow the use of generic functions that admit any data type as parameters and return a value more on this later)

vectorltdoublegt ExamMarks(5) This statement declares the vector to hold doubles and sets the initial size to 5 elements

Note Although vectors can grow to any size it is good practice and more efficient to specify the size when this is known When no size is given and the contiguous memory spaces have been exhausted the elements must be copied to a larger memory space to increase the size of the vector

cin gtgt ExamMarks[i] This statement reads in the user input and stores the values in the vector slot i of ExamMarks[i] i is incremented within the for loop Note that we the same indexingsubscripting syntax as we used previously with arrays ie[ ]

102

Task 2

Modify the code so as to accommodate the adding of an extra exam mark

Note this should not be done (simply) as part of the loop but as a separate action later and you should use the vectors push_back() method to facilitate this

push_back() is a member function of the vector class that adds an additional vector element at the end

After adding the extra mark you will need to generate a new set of statistics ie the average will have changed now To do this separate out the statistical code and place it in a separate function so that you may re-use later (after the new data has been entered)

size() is a member function (method) of the vector class It can be used to establish the size of a vector

The statement for(int i = 0 i lt ExamMarkssize() i++) uses the vector member function size() available to the vector ExamMarks to obtain the size (number of elements) in the vector The size of the vector is used to identify a terminating value that ends iteration of the for loop

Task 3

Open VectorSor t

You will see three TODO sections in the code which need completing

1 Populate a vector with 100 randomly generated numbers

2 Sort the vector

3 Reverse the vector

For sortingreversing you will can use the algorithms sort() and reverse()

Heres a useful link hellip

httpwwwcpluspluscomreferencealgorithm

103

Using insert() and iterators

Task 1

Open and modify the skeleton project called Inser t

Important areas of the program are explained in the steps opposite

Examine the code

vectorltintgtiterator it

This statement creates an iterator that is used to access members of the vector

Iterators are used to access members of the container classes (the container type vector in this case) and can be used in a similar manner to pointers

In the example iterator it is used with the insert() function to place the value (200) at the beginning of the vector nums

it = numsbegin()

This statement uses the vector member function begin() to initialise the iterator it with the address of the start of the vector

it = numsinsert(it 200)

This statement uses the member function insert() and iterator it to insert 200 at the beginning of the vector (it)

Note that an iterator is returned by the function insert() that points to the newly inserted element

104

numsinsert(it + 1 numsTwobegin()

numsTwoend())

This version of the insert() function takes 3 arguments and is used for copying in part or full another collection This may be a vector a plain C++ array or some other collection that is accessed using pointersiterators

This statement inserts a second vector (numsTwo) into nums The three parameters are (copy to nums+1 from star t of numsTwo to end of numsTwo)

it = numsinsert(it + 2 696 )

This version of the insert() function takes 2 arguments The iterator it + 2 points to element number three it points to the beginning of the vector and the 2 moves two elements in The value 696 is inserted at that element

void display(vectorltintgt amp vec)

cout ltlt Vector contains

for(

unsigned int i = 0

i lt vecsize()

++i

)

cout ltlt vecat(i) ltlt

Function display() is passed a reference to a vector and outputs the vector contents used throughout program

105

Task 2

Add the code shown in Figure 27 to the program and using the insert() member function add the array to the nums vector at position two (in the vector) Output the contents of the nums vector to screen

int myArray[] = 5 6 3 4

Figure 27

stdarray

C++11 Introduced a new template array type called stdarray

stdvector is a template class that encapsulates a dynamic array that is stored on the heap and that grows and shrinks automatically if elements are added or removed It provides all the hooks (begin() end() i terators etc) that make it work fine with the rest of the STL It also has several useful methods that let you perform operations that on a normal array would be cumbersome like inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes) Since it stores the elements in memory allocated on the heap it has some overhead in respect to static arrays

stdarray is a template class that encapsulates a static array that is stored inside the object itself which means that if you instantiate the class on the stack the static array will be on the stack Its size has to be known at compile time (it is passed as a template parameter) and it cannot grow or shrink

It is more limited than stdvector but it is often more efficient especially for small sizes because in practice it is mostly a lightweight wrapper around a C-style array However it is more secure since the implicit conversion to a pointer is disabled and it provides much of the STL-related functionality of stdvector and of the other containers so you can use it easily with STL algor i thms

Here is a small example demonstrating the template and some other C++11 extras such as auto and a ranged-based for loop

106

include ltstringgt include ltiteratorgt include ltiostreamgt include ltarraygt using namespace std template ltsize_t N class Tgt arrayltT Ngt make_array(const T amp v) arrayltT Ngt ret retfill(v) return ret int main() The char here can be inferred and so is optional auto a = make_arraylt10 chargt(1) for (const auto amp s a) stdcout ltlt s ltlt system(pause) return 0

1 1 1 1 1 1 1 1 1 1 Press any key to continue

Declaring and using lists

Lists are a kind of sequence container similar to vectors The elements of a list are ordered following a linear sequence with storage handled automatically by the class

List containers are implemented as doubly-linked lists and it is worth noting that elements may be in different and unrelated storage locations

Ordering of a list is kept by a relationship to each element of a link to the element preceding it and a link to the element following it

Because linking information is associated with each element (possibly to different and unrelated storage locations) extra memory may be used to keep the linking This may be important when using a large list

l is ts tend to perform better than vectors at inserting extracting and moving elements in any position within the container but lack direct access to the elements by their position and because of this have a slower access time than vectors Access to an element has to be via a known position (the beginning or the end) and there is a time cost in linking between the known position and the element to be accessed

107

lists are declared indicating the type and number of elements in the following way

listlttypegt listName

listlttypegt listName(initialSize)

listlttypegt listName(initialSize elementValues)

Examples

A list called inNumbers with no initial size to hold doubles

listltdoublegt inNumbers

A list called Name with an initial size 20 to hold characters

listltchargt Name(20)

A list called ExamMarks holding integers with initial size of 4 elements each with the value 6

listltintgt ExamMarks(46)

72 Hash Tables and Cached Calculations

This section has ultimately really been about introducing you to templates and algorithms and well mix both now in a final example

From the binary chop exercise earlier we have seen that sorted arrays provide a very efficient means of storing data for later look-up However we have to bear in mind the algorithmic cost of sorting the array in the first place ie if we have a million unsorted items in our list and we want to find a single item (only) is it better to sort the entire list first and then find the item or is it better to simply walk through the array from the beginning ndash after all we could safely assume that weve a 5050 chance of finding it in the first half of the array Of course as were sorting we could keep an eye open for our item ie we could combine a (partial) sort with look-up operation ndash over time if we repeat this procedure looking for other items we will ultimately sort our array as a side -effect of the look-up operations

But lets move on a little and just consider the fastest look-up method we know so far that carried out on a sorted array using binary chop and think about our programs overall performance when we need to insert additional items into the array When considering problems like this we always think of the worst case hellip despite their often being fans of

108

Monty Python Computer Scientists rarely look on the bright side of life The worst case here is that we need to insert an item into array position zero

Eg say we have this sorted array (look-up operations average O log2 N = fast)

15 24 25 31 78 250 255 262 277

We now have to insert the value 5 into this array Using normal array indexing methods how many operations will this take

5 15 24 25 31 78 250 255 262 277

Each item needs to be shuffled up one position to the right and if weve millions of items that is rather costly especially if the next thing were likely to do is to insert another item

So weve seen that accessing sorted data is very useful and weve also seen that sorting and especially inserting items can be costly The big question is then is there a way we can make both just as efficient - finding andor inserting an item in Olog2N or O(1) (constant time)

Hash Tables

A hash-table is a data structure designed to allow for both rapid insertion and look-up

Although any specific hash-table is implementation specific (there are very many different types of hash-table) well quickly go through the basics

The storage medium well use for our hash-table is an array of strings and we will say that this array has just 10 elements It looks like this

string myhash[10]

Well use this hash-table to store words and well determine the array index for any specific word using a hash- funct ion ndash something that will take a word as its input and return an array index as its output

109

unsigned hashfunc(string s)

unsigned result = 0

for(unsigned i = 0 i lt slength() ++i)

result = result + s[i]

return result 10

hashfunc() iterates through s keeping a running total of the sum of the ASCII codes for each of the characters eg hashfunc(hash-table) computes

h + a + s + h + - + t + a + b + l + e

where the characters ASCII values are

104 + 97 + 115 + 104 + 45 + 116 + 97 + 98 + 108 + 101

The total = 985 and 985 modulus 10 = 5

The final computed value will be used as an index into the array The modulus value used is the size of the hash-table and we use it so as to ensure that resultant computed index value cannot be greater than 9 (remember our arrays indexes are 0 ndash 9)

We can now store words in the myhash array like this

string myhash[10]

string s = hash-table

index = hashfunc(s)

if(myhash[index] = )

myhash[index] = s

else

The complex part is what to do if we have what is called a collision ndash when we find that myhash[index] is already occupied Youll probably have already thought of what value hashfunc(elbat-hsah) will have

One way to help avoid collisions to use a better hash-function and a larger array However in real life collisions are practically impossible to avoid and the only other option to deal with them is to allow more than one string to inhabit an array slot in some way ndash perhaps by having each of the original array slots contain an array ndash rather than an individual string Of course in this case we would also need some way to determine which of the n colliding entries is the one were interested in ndash is it elbat-hsah or hash-table

110

Well briefly leave our examination of hash-tables at this point and instead look at Fibonacci numbers Do not worry we will return to hash-tables very soon

Fibonacci numbers are the numbers in the following integer sequence

0 1 1 2 3 5 8 13 21 34 55 89

By definition the first two numbers in the Fibonacci sequence are 0 and 1 and each subsequent number is the sum of the previous two More formally that is

119865119899 ∶= 119865(119899) ∶=

0 119894119891 119899 = 0 1 119894119891 119899 = 1

119865(119899 minus 1) + 119865 (119899 minus 2) 119894119891 119899 gt 1

Computing Fibonacci Numbers

Task 1

Open Cached_fibonacci

Compile and run the program as is

Examine main() and the calcfib() functions

bigint calcfib(bigint n)

if(n == 1 || n == 0)

return n

else

return calcfib(n - 1) + calcfib(n - 2)

bigint is defined as a unsigned long long int and we have used typedef to save some typing

NOTE The method used to calculate Fibonacci numbers here has been selected because it is perhaps the most obvious way to turn the formal definition into code If you are interested please see the separate Fibonacci project for two other examples of how to calculate Fibonacci numbers

111

Modify the beginning of the calcfib() code

bigint calcfib(bigint n) cout ltlt calcfib was passed ltlt n ltlt endl

Modify main() to set max = 5 and re-run the program

calcfib was passed 0 Fibonacci number 0 is 0 calcfib was passed 1 Fibonacci number 1 is 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 2 is 1 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 Fibonacci number 3 is 2 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 4 is 3 calcfib was passed 5 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1

Fibonacci number 5 is 5

112

Note that to calculate Fibonacci number 5 we calculate Fibonacci number 4 and Fibonacci number 3 - even though weve previously calculated Fibonacci number 3 in order to calculate Fibonacci number 4

To fully appreciate the growth of this process re-run the program adding 10 to max for each subsequent run You maymay not like to comment out the line you inserted in Step 2

Task 2

Getting back to Hash Tables Using a hash-table to store previously computed Fibonacci numbers

As it stands the incomplete solution declares a template hash-table called fibs of the type unordered_map

Read the comments in the function fibCache() and modify the code to as to use the fibs hash-table to store previously computed Fibonacci numbers

fibs[n] = f stores f the n-th Fibonacci number in the n-th slot of fibs (which as you can see you may treat as an array for indexing into)

8 Pointers In C++ programming data (variables) can be referenced via the memory address of the variable This is done using a pointer var iable

A pointer var iable contains the address (location in memory) of a data variable

There are also functional pointers ie those that point to code rather than data and these are briefly explored later

Pointers can be particularly useful when interacting with the operating system andor when working with arrays - as the elements in an array will always occupy consecutive memory places Incrementing the pointer variable by one addresses the next array element

Lastly pointers are also used to fake pass by reference

Declarat ions

int n This is a standard variable declaration n that contains a value as yet unknown of type int

int p This is a pointer p that can hold (point to) an address that contains a variable of type int The type of p is int

Each variable declared as a pointer must be preceded by an asterisk () This modifies the type of the object being declared from thing of type to pointer to thing of type Eg int n means n is an int whereas int n says that n is a pointer to an int

113

int age height age is a pointer to an int height is an int value

double far cent are both pointers to doubles

Pointers can be initialised when they are declared or set using an assignment It is common to initialise pointers to a memory address but they can also be initialised to the predefined constant NULL ndash meaning that they do not (as yet) hold (point to) a valid memory location NULL is defined in the standard library such a pointer is called a nul l pointer

When is used in a variable declaration it indicates the variable being declared is a pointer and not a value

But do beware as is used elsewhere with pointers when the appears before a previously declared pointer variable elsewhere in the program it is said to dereference the pointer and so is used to access data stored at the address which is stored in the pointer A dereferenced pointer is essentially the variable to which the pointer was originally set to point

To complicate matters further using the pointer name without the dereference operator references whatever is stored in the pointer variable itself ndash this is the address of the object it references in memory (which maybe NULL of course)

As we have seen using can mean two things that something is being declared as a pointer or that a previously declared pointer is being dereferenced Experienced programmers sometimes enter the two usages differently ndash a notation we would highly recommend ie

int n n is an object that can hold the address of an int

int k = 0 k is an int holding the value zero

n = ampk n is set to hold ks address amp is explained below

n = 1 k (yes k) is set to hold the value 1

Note the space used in the different usages - int n vs no space in n

Initialising pointers

Pointers can be initialised in two ways

int x = 16 y = 69 variable declaration and initialisation int x_ptr = ampx pointer declaration and initialisation x_ptr holds the address of x int y_ptr pointer declaration yptr is a pointer

y_ptr = ampy pointer assignment yptr holds the address of y

Once declared a pointer variable can be assigned the address of another variable using the amp the addressof operator

114

Note the variable name should not be prefixed by the in the assignment statement unless the pointer is initialised immediately in the variable declaration

We also use pointers when creating objects on the Heap for example we can create and initialise a string object like this string pstring = new string(Hi there) Such objects are not normally tidied away as are the objects created on the stack - objects simply declared in a functionmethod and so they should explicitly be tidied away using delete eg delete pstring For more on this subject see section 9

Using pointers

Task 1

Open the project Pointers

Compile and run the program The output should be as shown in Figure 28

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int x_ptr = ampx This is x_ptr pointer declaration and initialisation

int y_ptr Declaring another pointer y_ptr

y_ptr = ampy Initialising y_ptr

y_ptr = x_ptr Assigning x_ptr contents to y_ptr Both pointers are pointing to variable x (16)

y_ptr = ampy Assigning the address of y back to pointer y_ptr

y_ptr = 170 Assign 170 to the variable at memory location of y_ptr y_ptr points to variable y so 170 has been assigned to y

115

Figure 28

Pointer Arithmetic and Arrays

We have seen that once a pointer is initialised it has a memory address and this address can be reassigned another address It is also possible to change an address using standard arithmetic

The ++ and -- increment and decrement operators can be used to move the pointer along to the next or back to the previous memory address To jump more than one memory address you would have to use the assignment operators += and -=

When using arrays and pointers the array name is the address of the first element in the array

int intArray[] = 1 2 3 4 5

int int_ptr = intArray Same as int int_ptr = ampintArray[0]

The pointer has been declared and initialised with the statement int int_ptr =

intArray Note there is no need to use the address of operator amp when initialising arrays as the array name is the address of the beginning of the array

When working with arrays each element of the array will be the type and size at declaration When an array is declared to hold integers each element will usually be 4 bytes in size An array of doubles will have element sizes of 8 bytes Note ndash these sizes are actually down to the compiler being used and are usually in turn dependent upon the operating system being used

It is not important to know how many bytes make up each element Moving the pointer through the array with the assignment operator x_ptr += 2 will move two elements further through the memory allocated for the array or 16 bytes for an array of doubles

116

Pointers and Arrays

Task 1

Open the project PointerAr i thmetic

Compile and run the program The output should be the same as Figure 29

Examine the program carefully

You may not fully follow the program at first glance as it employees a few potentially new constructs (it depends how far weve got through the lectures)

One slightly truncated new construct is

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

A struct in C++ is just like a class except that the default public and private sections are reversed By default everything in a struct is public

typedef in C++ allows the definition of our own types based on other existing data types

typedef exist ing_type new_type_name

where exist ing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining For example

117

typedef unsigned int WORD

typedef char pChar

You may also remember initialiser lists from earlier eg

s_thing(int a) a(a) b(sqrt((double)a))

If we re-write this

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

We quickly see that a(a) and b() are initialising the a and b struct members const int a and const double b

118

Remember that as these are const we cannot use assignment

typedef struct s_thing

const int a

const double b

s_thing(int a)

Error ndash a and b are const

this -gt a = a

this -gt b = sqrt(a)

thing

Lastly when dealing with pointers to compound types one may access the members of the type via dereferencing or via the so called crows foot operator

(t) dereferences t giving us a thing which was pointed to by t Then we use the dot operator to access the member (t)a

We have to parenthesiset otherwise the would bind to t first ie it would be as though we had done this (ta) which would be an error

The crows foot saves us the dereference t-gta is just like (t)a

119

Figure 29

PLUSPLUS Pointers and Arrays

Task 1

Open and modify the skeleton project called ReverseArray

In main() create an array of 10 integers Fill the array with random numbers between 0 ndash 100

Write a helper function called to output the contents of the array to the console A suitable prototype for this would be void dumpArray(int array[] int size)

Write a helper function to reverse the contents of the array Use a temporary variable as an aid A suitable prototype for this function would be void reverseArray(int array[] int size)

Reverse the values in the array using only pointers

120

Reverse the array without using a temporary variable You should use the XOR operator ^ to achieve this

Pseudo code for an XOR swap is

X = X XOR Y

Y = X XOR Y

X = X XOR Y

The completed program should look like Figure 30

Figure 30

Task 2

Reverse the array using a vector and the standard function template stdreverse()

We can also have pointers to functions in C++ (and C)

The name of a function resolves to be its address in memory (somewhat similar to the case where we use the name of an array) When we call a function we use this name to retrieve the functions address and then use the function invocation operator to execute it The function invocation operator is the set of brackets you use eg

Lets take an example

121

include ltiostreamgt

using namespace std

int lue() life the universe and everything

return 42

int main()

cout ltlt The address of the function lue is

ltlt lue

ltlt invoking it yields

ltlt lue()

ltlt endl

system(pause)

return 0

Typical output is shown in Figure 31

Figure 31

122

We can also store addresses of functions in variables (theyre just numbers) and the type system allows for us to describe and declare scalar variable types for function pointers eg this modified code fragment would produce the same output as that show above

fp is a pointer to a function taking

no arguments and returning an int

int (fp)()

fp = lue

cout ltlt The address of the function lue is

ltlt fp

ltlt invoking it yields

ltlt fp()

ltlt endl

fp is a funct ion pointer var iable so it may be used to point to any other function having the correct signature at runtime

PLUSPLUS Function pointers

Task 1

Open the project Calculator

Compile and run the program The output should be as shown in Figure 32

123

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int (fp)(int int) This is the function pointer declaration It may point to functions that take two integers and return an integer

Like all automatic storage class variables fp will currently be pointing at a random location What happens if you run the program without setting fp to point to an actual function Comment out the switch to find out

switch (Operator)

case 0 fp = Add break

case 1 fp = Subtract break

case 2 fp = Multiply break

The code could do with improving

Modify it to allow for multiple trials eg add the necessary logic to loop and perform multiple calculations ndash youll need to add some way to end the program too therefore

Modify it so that the operator may be inputted as an operator character eg + - etc Allow X x and for multiplication and add for division

All three pieces of information could be entered on a single line eg 6 x 7ltentergt Using cin to read that data just requires you to use three cin statements

cin gtgt X

cin gtgt Operator

cin gtgt Y

Lastly modify the program to that it uses floating point arithmetic

124

Figure 32

9 APIs New Delete and Dynamic Memory As has been stated earlier pointers are useful in a variety of situations However because they are easy to get wrong ndash and when they go wrong everything goes very wrong indeed ndash languages like C++ have tried to make their use the exception rather than the norm For example without reference arguments (eg void someFunc(int amp)) we would have to use pointers to achieve the same functionality and performance

On the whole the underlying philosophy when it comes to pointers is to try to avoid using them whenever possible You can get a real feel for this subject by Googling for smart pointers c++ and from Wikipedia httpenwikipediaorgwikiSmart_pointer

Two areas where we absolutely need pointers are when calling into an external API (Appl icat ion Programming Interface ) and when allocating memory for our own purposes ndash the latter case is also eased by advances in the library support in C++

Using an API

An Appl icat ion Programming Inter face is functionality provided by some third party The most obvious API whether it is Windows Linux or OSX is that exposed by an operating system

If your application needs to interact with the user in any non-portable way you will need to call into your OSs API For example if you want to display a dialog box you will need to access the OSs functionality to do so (perhaps indirectly through a framework like Nokias Qt - httpsenwikipediaorgwikiQt_(framework)) In summary if you ever want to go outside of the standard libraries andor writing consoleterminal applications you will need to call into your operating systems API

When it comes to calling into operating systems pointers are used extensively As an example 1 Google for Linux API 2 Find any website that lists the API functions and then 3 click-through to any function The odds are that the function prototype you see will contain asterisks (pointers)

125

Dynamic Memory Management

The second area where you simply must know something about pointers is when it comes to using the heap

The heap is an area of memory available to your programs You may allocate and use the heap as you wish

Why would you want to do this Normally its to create variable length arrays or to model and use an advanced data structure of some sort a self-balancing red black tree perhaps (httpenwikipediaorgwikiRedAndblack_tree) Of course the more esoteric the data structure and less likely it is that it will be incorporated into the C++ standard library (although the library does contain most of the generally useful and popular ones like doubly l inked l is ts )

To allocate memory from the heap in C++ you use the new keyword and to return it you use the delete eg

int nSize = 12

note nSize does not need to be constant

int pArray = new int[nSize]

pArray[4] = 7

delete [] pArray

10 More on Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine Encapsulation is data information or detail hiding

Once a function is written the detail of how it works is not important to the end user The user needs to understand what data to input and what output will be produced

One of the most important aspects of writing programs using functions is that the functions can be reused from one project to the next Think about the standard functions youve seen already eg the square root function sqrt() Libraries contain atomic generally useful functionality that is likely to be of use at some future time It is useful to bear this thought in mind whenever we build new programs ie we should be on the lookout for generally useful functionality (given our domain) that we should consider coding as functions for later reuse The same goes for classes of course

Probably the most important function in your program in main() ndash without it you do not have a program at all

main() is your programs entry point and as such it may be used in such a way as to inform the rest of your program as to the actions required

126

main() and command-line arguments

Task 1

Open a Command Prompt or PowerShell Prompt and enter the following

dirltreturngt

di r Odltreturngt

t ree ltreturngt

t ree altreturngt

dir and t ree etc are like mini-programs They have default functionality which may be altered by providing additional command-line arguments eg for the dir command dir L N 4 TC

Command-line arguments are passed to your programs by optional parameters eg

int main(int argc char argv[])

Where argc is a count of the number of arguments and argv is an array of pointers to arrays of character (C strings) for each argument being passed Note that argc is always at least 1 and so argv always contains at least one entry ndash this is the name of the program being run

Task 2

Open (demonstrat ion)

CommandLineArgs and Build and run the program

Examine the code

The programs configuration is Debug

In the projects Project | Debugging | Command

Arguments you will see where the programs default command-line arguments are set for debugging purposes

Using the command prompt you opened earlier navigate to your where CommandLineArgsexe is located

CommandLineArgs debug

Run the program by entering its name followed by a variety of arguments eg

gtCommandLineAgs one two threelte ntergt

127

Task 3

Open the project UserPrompter project

Run the program and then examine its code

We will modify this program to use a command-line argument However before doing that its worth pointing out that the primary purpose of this program is to demonstrate the separation of a class declarat ion with its implementat ion (the mechanismfunctionality of class prompter is defined in promptercpp but its capabilities are declared in prompter h )

Its also interesting to note that the optimal strategy is to use an algorithm called binary search or binary chop (we saw this earlier in the course) with each guess you reduce the number of possible solutions by a half This sort of algorithms Big Oh is Log n (where log is base-two logs)

httpenwikipediaorgwikiBig_O_notation

Task 4

Modify the program so that the upper range for the max value is given as a command-line argument

The UserPrompter cpp is the file youll need to modify

Test your program via the setting the projects Command Arguments as detailed above -or- by running the application standalone in a command prompt after building (also as detailed above)

See Figure 33

To convert a string into a number (weve seen one other way of doing this earlier) we can use

include ltcstdlibgt

and the function atoi() eg

atoi(argv[1])

128

Figure 33

EncryptDecrypt a file

Task 1

Open compile and run the EncodeDecode project

Complete the program so that it may be run outside of the IDE and process a file for encryptiondecryption

This is actually quite a simple task as youll only need to add a couple of lines of code However the project also demonstrates how to use the Debug and Release modes to influence the way a program runs ie that in its Debug configuration the program automatically runs through a test

Other things to note include using bitwise XOr to perform the encoding and the use of the C standard library functions putchar() and printf() to perform some of the output eg putchar() is used to output a CR to the console window (CR = char 13)

129

Figure 34

Multiple arguments overloading and default values

In C++ we can over load functions ndash meaning that we can provide different versions of the same function (the different versions must differ by the number andor type of the parameters they take) For example

130

void foo(double d) 1

cout ltlt In void foo(double d)nn

void foo(long int n) 2

cout ltlt In void foo(long int n)nn

void foo(int n) 3

cout ltlt In void foo(int n)nn

double dtest = 0

long int ltest = 0

int ntest = 0

foo(dtest) Calls 1

foo(ltest) Calls 2

foo(ntest) Calls 3

In the above the compiler works out which version of the foo() to call based upon the argument type it is given

We can also overload functions if the number of arguments differ eg

131

void bar(double d)

void bar(double d double t)

We would use a feature like this if sometimes we needed to use extra information ndash in the shape of passing in t in the above eg we would most likely implement void bar(double d) as

void bar(double d)

bar(d 25) Call bar(double d double t)

What were really saying above is that in most cases the implicit double second parameters value is normally 25 ndash perhaps its a standard discount percentage ndash and only occasionally we will need to change that value in which case wed call bar(double d double t) directly and not by going through bar(double d)

Lastly C++ has one extra feature that can make this simpler ndash defaul t arguments

Rewriting bar using this feature we get

void bar(double d double t = 25)

Note that we now only have one bar function now and that we may call it like this

bar(x)

Or like this

132

bar(x y)

In the case of bar(x) the second parameter is omitted and so will receive the default value of 25 in the second example t will receive ys value

Although outside the scope of this class for more on overloading see the (demonstrat ion) Operator Over loading project This shows how to overload the ++ pre and post increment operators overload and provide your own ltlt stream insertion operator (and one use of a friend function) and using an enum with a typedef

Passing Arrays to Functions

To pass an array to a function it is only necessary to pass the array name and the number of elements in the array

The array name is the position (address) in memory of the first element The number of elements is passed to enable the function to establish the array size

An array declared as double somearray[10] would require a function call somefunction(somearray 10)

Passing Arrays to functions

Task 1

Open and modify the skeleton project called the project called ArrayReturnValue

Pass an array to a function to read in five numbers

Pass the array to another function to calculate the average value in the array return this to main() and output to screen

Lastly at the end of the program output the values in the array from within main() The finished program should look something that that in Figure 35

Create two function prototypes

void enterMarks(double ExamMarks[] int num)

double calcAverage(double ExamMarks[] int num)

ExamMarks[] is the array to be passed As with passing variables it is not strictly necessary to give the argument a name in the prototype just its type This could have been written as calcAverage(double [] int) However it is sometimes useful to include this information as it might help explain the functions operation

It is also necessary to pass the size of the array num is the number of elements in the array its size

Within main() declare the array and initialise the elements to zero with the following statement double ExamMarks[5] = 0

This declaration explicitly initialises the first element to zero and implicitly initialises the remaining four to zero

133

Create both functions

enterMarks to read in the values and calcAverage to calculate the average (you will need a for loop in each function)

Return the average value from calcAverage to main() and output the value using cout

Call the functions from within main() with the following statements

enterMarks(ExamMarks 5)

average = calcAverage(ExamMarks 5)

You may output the average directly of course ie without first storing the value in average

At the end of main() add the statements

for(int i = 0 i lt 5 ++i)

cout ltlt Exam Mark Number

ltlt i + 1

ltlt is

ltlt ExamMarks[i]

ltlt endl

ltlt endl

134

Explain how it is possible at the end of the program to output from within main() all the values in the array entered within the function

Modify the program so that the number of exam marks (5) appears only once

In previous exercises when parameters (variables) were passed to functions the function received a value When a value is used in a function a copy is stored in a part of memory that only exists from the time the function is called to when it ends After this the memory and any value in it are lost

However the array in this exercise was initialised in main() with zeros and then passed to the function Data was then added to the array and calculations done At the end of main() the values in the array elements are output The array contains values input from within the function

The name of the array is the address of the first element of the array in the machines memory As the starting address is passed (the name of the array) the called function knows where the array is stored in memory

Because we are working with memory addresses (references ) any changes made to array elements in the function affect the memory location set up in main() for the array

C++ passes arrays to functions by reference (to the memory location of the first element) In previous exercises functions were passed values copies of the variables in main()

135

Figure 35

Passing Two-dimensional Arrays to Functions

It is common to want to store numbers in a two dimensional layout of rows and columns as shown in Table 7

187645 783473 298372

871223 629399 561201

Table 7

This arrangement is known as a two-dimensional array or matrix

C++ uses an array with two subscripts to store a two dimensional array

double Balance[2][3]

When we specify a one-dimensional array the number of elements must be given

When a two-dimensional array is specified it is necessary to specify the array elements in both dimensions We therefore specify the number of rows and columns

The Balance array in the statement above has two rows and three columns

11 Inheritance and (not presented) Polymorphism

111 Inheritance

In Object Oriented languages like C++ inheritance describes a relationship between classes of objects and which usually implies some sort of a sub-division of labour

For example lets say that we want to build an IT system that has something to do with the members of the university

136

In an OO world the first question usually is how would we categorise our significant entities and that always means naming things what names would we use to categorise university members When modelling (for that is what were going to be doing) real-world objects its sensible to use proper names So heres an attempt ndash to broadly categorise university membership

Members are members of the sets

Students

Staff

Other

What is other though

The Bodleian and the card-office issue Readers cards ndash so is a Reader a university members or are they something else And if they are something else does our system really want to concern itself them Or more broadly does our system really want to concern itself with holders of cards issued by the card-office

Are all students really the same

What sort of students do we have at Oxford (and do we want a system ndash either now or in the future ndash that might be interested in recording the differences) Lets see we have undergraduates and graduates We also have Rhodes scholars ndash but are these sorts of student that are distinct (or should be in our system) from our underpost-graduates categories And how about graduates would we want to have some sort of sub-groups Masters students MScMBAMPhil or Doctoral students DPhilDScDLitt etc Perhaps wed like to know something about how theyre being funded ndash and we might want that piece of functionality shared by our undergraduates

We can of course go through the same process when thinking about members of staff (university staff departmental staff members of congregation academic staff fulltimepart-time staff casual staff ndash and how about staff that are sometimes (or also) students) We can go on thinking about this sort of thing for a very long time and we should as its important and when its important it has a name ndash Object Oriented Design or OOD

One of the things wed hope to see appear as part of the OOD phase is the relationship between entities For example if we were to say that a common property of all university members is that they have a date-of-birth we wouldnt want to have our Student and Staff C++ objects contain this information directly by way of some datastate class member (which might seem a little odd at first) But think about it If we performed some validation on the members DoB (perhaps when its being set) we would need to include this in both Student and Staff classes Or as an alternative we would capture the validation in some external function ndash which we would call from the separate classes (if we remember) No its messy and it would be much better if we thought of things this way that all university members are people and that people all have dates of birth

To put it another way we would say that studentsstaffother are just specialisations of people ndash they are people but with a bit of extra something tagged on to them ndash like a bod card number

Now if we also had some way of capturing people stuff in say a basic Person class and could somehow use that automatically ndash perhaps by deriving a Member class from it and then doing the same from Member to both Staff and Student classes from Member One thing though ndash we wouldnt want someone to be able to instantiate a Member object

137

perhaps ie in our system Member is an abstract class Imagine a generic Car vs a Renault Clio ndash it makes no sense to create a Car object ndash there are no generic cars on the road they are all specific cars Similarly we wouldnt want a generic Member wandering around our system (if you remain unconvinced well see why later)

Modelling a student - a first attempt

Please note that in this Introduction to C++ we do not expect you to complete an exercise that requires coding from now on Please just look through the code and follow along with the discussion

Base classes

Task 1

Open the project UnivMember1

Examine the program carefully

The project contains three classes Person Member Student In main() we create a Student and then attempt to output the students name ndash which fails

name is in the protected section of Person ndash which means only Person methods or methods in derived-from-Person classes can access it

Add a public section to the Person class and relocate the name there

Eg

public

string name

Any better now

The problem now is that Student only by default inherits the private side of Person

Change class Student so that we also inherit the public members of Person hellip

class Student public Person

138

Before we tackle further problems with name lets bring in the Member class (left doing nothing until now)

We really want Student to inherit from Member and not Person Change the code to reflect this

People have dates-of-birth and Members have bod cards Add a string member dateOfBirth to Person and move the bodCardNumber member out of Student and into Member ndash make them both strings

Change the code in main() to set these extra pieces of data

If you havent done it already Persons dateOfBirth and Members bodCardNumber should be set via constructors

139

Task 2

Open and examine the project called UnivMember2

UnivMember2 is a copy of the (exercise solut ion)

UnivMember1 solution

One of the problems we have in UnivMember1 is that too much of it is public eg given Student object s we can change name to simply by using assignment eg sname =

We should protect data members at each level using the maximum level of protection we can ie private

However if we do that then cout ltlt sname will no longer work and so well need to provide access methods to the data members Eg heres a modified Member class showing the basic scheme

class Member public Person

public

Member(string bodCardNumber)

this-gtbodCardNumber = bodCardNumber

string getBodCardNumber() For access

return bodCardNumber

private

string bodCardNumber

140

Another problem is that wed really like to not use assignment at all Eg in the above ctor snippet

this -gt bodCardNumber = bodCardNumber

is using assignment

Change string bodCardNumber to const string bodCardNumber Youll see now that assignment wont now work (you have to initialise constants)

What wed really like (most likely) is to use in i t ial isat ion

We can do this via initialiser lists Ie we could change the above to the following

class Member public Person

public

Member(string bodCardNumber)

bodCardNumber(bodCardNumber)

const string getBodCardNumber()

return bodCardNumber

private

const string bodCardNumber

The initialiser list is read thus

bodCardNumber(bodCardNumber)

^^member^^ ^^parameter^^

Note that weve also modified getBodCardNumber() to show that it returns a const string

141

Modify all three classes to use initialiser lists private const data members and use access functions (getBlah() etc)

Task 3

Open and examine the project called UnivMember3

UnivMember3 is a copy of the (exercise solut ion)

UnivMember2 solution

We will now finish this project to the level of an introductory course

Things to note

The main problem with the solution as it stands is that one may create a Member object

Remember that this is analogous to being able to create a generic Car object ndash we should not be allowed to create one

Going right back to UnivMember1 you may remember a comment in there about a protected constructor

protected Protected ctor Person()

At that point in your project we were thinking two things 1) we wont want to create a generic person and 2) a protected constructor will facilitate this

And we were wrong to think both thoughts

1) A properly thought through Person class would be perfectly good to model generic people But although this is true one question here ndash would we ever want just a generic person

2) A protected constructor in a (more) base class doesnt prevent a derived class from creating a base object So what about the Member class ndash would it be ok to instantiate that

The proper means to prevent a Member being created would be to use what is called a pure v i r tual funct ion as part of its definition (such a function is one that must be overridden in a derived class) But what function

142

If you look at the classes derived from Member ndash you can take it from us that one might want to interrogate at runtime ndash to ask them what they are

So a suitable member function to declare in Member would be something like string getRole() A function that does return Student for a student and return Staff for a Staff object

If its pure virtual in in Member wed best define it in our derived classes

class Member public Person

public

virtual const string getRole() = 0

class Student public Member

public

const string getRole() return Student

143

1 Why did we want duplicate (named) functions in Member Student and Staff 2 And what does virtual really mean

We require both 1 and 2 so that we can provide specific responses when being asked the same question and all when being treated in a rather basic way

Being asked the same question means having a method invoked eg getRole() and in a rather basic way means treating us all Students and Staff (etc) as Persons and Members

112 Polymorphism

Polymorphism comes in a few forms

Ad-hoc Polymorphism via function overloading

Parametric Polymorphism or Compile-Time Polymorphism via templates

Subtype Polymorphism or Runtime Polymorphism via virtual functions and

Coercion Polymorphism via casting

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class (after all a derived from base must have or contain all that a base has) Polymorphism is the art of taking advantage of this simple but powerful and versatile feature

One way Subtype Polymorphism is applied is to use a base reference to access a collection of instances of different types that are derived from a common base ndash one way to paraphrase that is to say that related (derived from a common class) objects respond according to their type rather than according to the type of the reference one uses to access them (a base class pointer type) That is the dynamic type of the object is used instead of its static type

All of this is best demonstrated via an example of course

144

PLUSPLUS Polymorphism

Task 1

Open and examine the project called (exercise

solut ion) UnivMember3

Run the program the output should be the same as shown in Figure 36

The crucial code here is as follows

Member arr[6]

Student studs1()

Student studs2()

Staff staff1()

Student studs3()

Staff staff2()

Student studs4()

arr[0] = ampstuds1

arr[1] = ampstaff1

arr[2] = ampstuds2

arr[3] = ampstaff2

arr[4] = ampstuds3

arr[5] = ampstuds4

for(int i = 0 i lt ++i)

cout ltlt arr[i]

ltlt i ltlt s name is

ltlt arr[i]-gtgetName()

ltlt t Their role is

ltlt arr[i]-gtgetRole()

ltlt endl

Weve created an array of Members (it isnt important that weve used pointers) and note that we have set some of the members of this to be pointers to Student and Staff objects We are allowed to do this as both Student and Staff are derived from Member

However when and if we invoke member functions on these objects wed really like it if they responded as what they really are ndash Student and Staff objects

145

From the output below you can see that they indeed do respond accordingly

Figure 36

The mechanism behind allowing this is the virtualisation of the getRole() member function Remember that this was declared and made virtual in the Member class

Play about with the code eg change

Member arr[6] to Person arr[6] Everything still ok How about not using pointers here ndash easy to do

146

Lastly weve implemented (for no good reason but to show you how its done) some instance counting in all three classes Have a look for the static members and the inserted lines immediately below the class definitions that look like this int PersonCount = 0

The End Thank you for coming and we hope that you enjoyed the class

Oh and please Please PLEASE fill out the feedback form email when it arrives

147

12 Appendices

Arithmetical Operators

Operator Operation

+ Addition

- Subtraction

Multiplication

Division

Modulus

++ Increment

-- Decrement

Table 8 ndash Arithmetical Operators

Assignment Operators

Operator Example Equivalent

= a = b a = b

+= a += b a = a + b

-= a -= b a = a - b

= a = b a = a b

= a = b a = a b

= a = b a = a b

Table 9 ndash Assignment Operators

148

Assignment and Arithmetic examples

The assignment operator in C++ is =

The format is var iable = expression this can be read as assign to the var iable the value of the expression

An example to calculate the number of pence in a value in pounds would be

pence = pounds 100

Note it is easy to confuse the assignment operator = with the equals notation used in mathematics The equals notation in C++ is ==

Incrementing a var iable

month = month + 1 adds the value one to the variable month This can be written as

month++

Decrementing a var iable

month = month - 1 deducts the value one from the variable month This can be written as month--

Note that ++ and ndash can be used before or after the thing being modified eg ++x x++ --y y-- However there are some subtle differences which will be explained in the lectures

In C++ it is also possible to combine arithmetic and assignment operations

To add 2 to a variable total

total = total + 2 or total +=2

To subtract 2 from to tal

total = total - 2 or total -=2

To multiply total by 2

total = total 2 or total =2

Relational and Equality Operators

The equality operator is used to compare two operands (a == b) and returns 1 (t rue) if both are equal otherwise 0 (false ) is returned

The inequality operator (=) returns 1 (t rue) if both are NOT equal otherwise 0 (false) is returned

Both the above operators are commonly used to test the state of two variables to perform conditional branching

The relational operators also return either true or false (a gt= b) returns 1 (t rue ) if a is greater than or equal to b otherwise 0 (false ) is returned

149

Standard algebraic equality or relational

operator

C++ equality or relational operator

Sample C++ condition

Meaning of C++ condition

Relational operators

gt gt a gt b a is greater than b

lt lt a lt b a is less than b

gt= a gt= b a is greater than or equal to b

lt= a lt= b a is less than or equal to b

Equality operators

= == a == b a is equal to b

= a = b a is not equal to b

Table 10 ndash Relational Operators

Logical Operators

When using i f selection statements it is common to use the relational operators as part of the test if(num gt 5) if(size lt= 14) if(Char == A) These are fine for testing one condition

To test multiple conditions it is possible to nest i f statements but this can be a bit cumbersome

Logical Operators can be used to form more complex conditions by combining simple conditions

Logical AND (ampamp) Operator allows a test to see if two conditions are true

if(leaveBooked gt LeaveLeft ampamp staffCover == false)

cout ltlt Take your holidays sometime else

Logical OR (||) Operator allows a test to see if either or both of the conditions are true

if(Temperature lt 16 || windspeed gt 15)

cout ltlt Too cold or windy to sunbath today then

Logical Negation ( ) Operator reverses the meaning of a condition

if((windspeed == 20))

150

cout ltlt The wind speed is not 20 its ltlt windspeed

This could be written equally as well with the equality operator

if(windspeed = 20)

cout ltlt The wind speed is not 20 its ltlt windspeed

Precedence and Associativity Table

Precedence Operator Description Associativity

1 Scope resolution Left-to-right

2

++ -- Suffixpostfix increment and decrement

() Function call

[] Array subscripting

Element selection by reference

-gt Element selection through pointer

typeid() Run-time type information (see typeid)

const_cast Type cast (see const_cast)

dynamic_cast Type cast (see dynamic_cast)

reinterpret_cast Type cast (see reinterpret_cast)

static_cast Type cast (see static_cast)

3

++ -- Prefix increment and decrement Right-to-left

+ - Unary plus and minus

~ Logical NOT and bitwise NOT

(type) Type cast

Indirection (dereference)

amp Address-of

sizeof Size-of

new new[] Dynamic memory allocation

delete delete[] Dynamic memory deallocation

151

4 -gt Pointer to member Left-to-right

5 Multiplication division and remainder

6 + - Addition and subtraction

7 ltlt gtgt Bitwise left shift and right shift

8 lt lt= For relational operators lt and le respectively

gt gt= For relational operators gt and ge respectively

9 == = For relational = and ne respectively

10 amp Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 ampamp Logical AND

14 || Logical OR

15 Ternary conditional Right-to-Left

16

= Direct assignment (provided by default for C++ classes)

+= -= Assignment by sum and difference

= = = Assignment by product quotient and remainder

ltlt= gtgt= Assignment by bitwise left shift and right shift

amp= ^= |= Assignment by bitwise AND XOR and OR

17 throw Throw operator (exceptions throwing)

18 Comma Left-to-right

Table 11 ndash Precedence and Associativity Table

Escape Sequences

Escape Sequence

Description

n Newline Position the screen cursor at the beginning of the next line

152

t Horizontal tab Move the cursor to the next tab stop

r Carriage return Position the cursor at the beginning of the current line

a Alert Sound the system bell

Backslash used to print a backslash

Single quote Use to print a single quote character

Double quote Used to print a double quote character

Table 12 ndash Escape Sequences

Cast Operator

Is where the programmer explicitly asks for a change in data type It may be that the result of a calculation is a double and the user wants it to be of type integer

A double can be cast to an integer in the following way

double aNum = 237

int anInt = 0

anInt = static_castltintgt(aNum)

A C style cast may also be used eg

anInt = (int)aNum OR anInt = int(aNum)

Formatted Output

When several numbers are displayed each is printed with the minimum number of digits needed to show the value This can yield some unexpected output

The width of an output field can be set using a stream manipulator To set the next number to be printed to a width of 5 digits use cout ltlt setw(5) This command does not produce any output it manipulates the stream to change the output format of the next value Note setw() must be specified for every item output

To use any stream manipulators you must include the header include ltiomanipgt

setprecision is another manipulator and is used to set the precision of the next floating point number Note setprecis ion only has to be set once as the stream remembers the formatting directive and does not affect integer fields The format is cout ltlt

setprecision(3)

To set precision for trailing zeros (0100 will appear as 01) it is necessary to use the fixed format The notation is cout ltlt fixed Note f ixed only has to be set once

The three manipulators can be combined to achieve the required precision and field width when used in this way

153

cout ltlt fixed ltlt setprecision(3) ltlt setw(5) ltlt myDouble

Alternatively as fixed and setprecision only have to be set once this statement could be written as

cout ltlt fixed ltlt setprecision(3)

cout ltlt setw(5) ltlt myDouble

Header Files

Every program that you create will have at least one header file If you use input or output you will have to include the iostream header

If you use mathematical functions you will need cmath It can be difficult to know which header files to use for each function Some of the common header files used together with some of the older ones you may find with inherited code are shown below It is a good idea to use the help if you are unsure which header files are associated with particular functions

Standard C++ header Old header

iostream iostreamh

iomanip iomaniph

fstream fstreamh

cmath mathh

cstdlib stdlibh

string No equivalent

vector vectorh

Table 13 ndash Header Files Old and New

Matrix Libraries

The STL does not contain a Matrix type and so we must look elsewhere for a suitable implementation that suits the individuals needs

The table below lists the third party libraries that we are aware of

Some Linear AlgebraMatrix Libraries

Armadillo Blitz++ Boost

CPPLapack CPPScaLapack CVM Class Library

Eigen Elemental FLENS

Gmm++ GNU Scientific Library (GSL) HSL

154

IML++ IT++ LA library

Lapack++ LinBox Matrix Template Library (MTL)

MV++ Newmat PETSc

RNM Seldon SimuNova

SL++ (Scientific Library)

SparseLib++ SuiteSparse

TCBI (Temporary Base Class Idiom)

Template Numerical Toolkit (TNT)

Trilinos

uBlas ViennaCL

Table 14 ndash Matrix Libraries

Scope

The portion of a program where an identifier can be used is known as its scope

An identifier declared outside any function or class has f i le scope This type of identifier is known by all functions Global variables and function prototypes all have file scope

Identifiers declared inside a block of code have block scope This type of scope begins at the identifiers declaration and ends at the termination right brace ( ) of the block in which the identifier is declared

Any block can contain local variable declarations If blocks are nested it is possible to declare variables with the same name in each nested block The variable in the outer block is hidden while the inner block is being executed

Enumerating constants

The enum keyword provides a handy way to create a sequence of integer constants An example of enumeration is shown below

enum Months JAN = 1 FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC

Each of the constants will have a default value 1 greater than the constants that it follows in the list The first value in the enumeration above is explicitly set to 1 and the remaining values increment by 1 The values assigned from JAN to DEC will be 1 to 12

The statement cout ltlt DECEMBER is month number ltlt DEC ltlt endl would be output as DECEMBER is month number 12

Constants

Data that will not change during the execution of a program should be stored in a constant container rather than a variable If the program attempts to change the value stored in a constant the compiler will report an error and compilation will fail

Constant can be created for any data type by prefixing the declaration with const keyword followed by a space Note Constants must always be initialised at declaration

The following declaration declares a constant for the speed of sound at sea level ms

155

const double SpeedOfSound = 34029

Vector member functions

Some commonly used member functions of the vector class are

Vector member Functions Effect

at(element number) Gets the value contained in the specified element

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

push_back(value) Adds an element to the end of the vector containing the specified value

size() Gets the number of elements

Table 15 ndash Vector Member Functions

Global functions

Global functions are not member functions They take more than one argument and operate on a range of elements rather than on the vector container ie they can be used on other types of containers

Vector global Functions Effect

find()

ptr = find(vbegin() vend() 67)

Finds the element in the vector containing number 67 Needs iterator (ptr) to store location of element

reverse()

reverse(vbegin() vend()) Reverses the values in a vector (v)

sort()

sort(vbegin() vend()) Sorts the vector (v)

Table 16 ndash Vector Global Functions

156

list member functions

Some commonly used member functions of the list class are

List member Functions Effect

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

pop_front Removes the first element

push_back(value) Adds an element to the end of the vector containing the specified value

sort() Sorts the elements in the container from lower to higher

size() Gets the number of elements

swap() Exchanges the content of the list

Table 17 ndash List class Member Functions

cmath functions

Function Argument Result Returned Value Example Result

ceil(x) double double Smallest integer ge x

ceil(21) 30

cos(x) double double Cosine of x radians cos(10) 054

fabs(x) double double Absolute value of x

fabs(-15) 15

floor(x) double double Largest integer le 29

floor(29) 20

157

pow(x y) double double x to the yth power pow(24) 160

sin(x) double double Sine of x radians sin(10) 084

sqrt(x) double double Square root of x sqrt(4) 20

tan(x) double double Tangent of x radians

tan(10) 156

Table 18 ndash cmath Functions

158

String class

The string class defines many member funct ions A few of the basic ones are described below

Initialisation - constructors form

A string expression string str2 = str1

A character string literal string Intro = Programming with C++

A substring of another string object

string Intro = Capetown

string Mytown = Boars

string MyTown(Intro 4 5)

starts at character 4 (t)

with a length of 5 (or the rest of the string if shorter)

cout ltlt myTown ltlt endl

will produce an output town

Member Functions

length()

string myName = Sebastion

myNamelength()

will produce an output of 9

insert ()

Inserts a string into the current string starting at the specified position

string myName = Sebastion

string nameAdd = rjio

myNameinsert (2nameAdd)

cout ltlt myName ltlt endl

will produce an output Serjiobastion

erase()

Delete a substring from the current string

string myName = Sebastion

myNameerase (02)

cout ltlt myName ltlt endl

will produce an output bastion

replace()

Delete a substring from the current string and replace it with another string

string myName = Sebastion

string aName = renna

159

Member Functions

myNamereplace(3 6 aName)

cout ltlt myName ltlt endl

will produce an output Sebrenna

find()

Search for the first occurrence of the substring in the current string If the word is found return the position of the first character If not return -1

string sName

string findWord

position = sNamefind(findWord)

substr()

Returns a substring of the current string

string myName = Sebastion

string aName = myNamesubstr(0 3)

cout ltlt aName ltlt endl

will produce an output Seb

Non-member functions

getline()

string name

getline(cin name)

Table 19 ndash String Class Member Functions

160

A number of C++ operators also work with str ing objects

Operator

=

string fString = Hello

string lString

lString = fString

Assign a character (char ) to a str ing object

string aStringC

aStringC = Z

+

Concatenate two str ing objects

string str1 = C++

string str2 = Programming

string str3 = str1 + str2

+

Concatenate a string object and a character string literal

string str = Hello

string str1 = str + there

The same concatenation can be done in this way

str += there

+

Concatenate a string object and a single character

string str = Bye Bye

string strBye = str +

161

ASCII Character set

Decimal Octal Hexadecimal Binary Value Meaning

0 0 0 0 NUL (Null char)

1 1 1 1 SOH (Start of Header)

2 2 2 10 STX (Start of Text)

3 3 3 11 ETX (End of Text)

4 4 4 100 EOT (End of Transmission)

5 5 5 101 ENQ (Enquiry)

6 6 6 110 ACK (Acknowledgment)

7 7 7 111 BEL (Bell)

8 10 8 1000 BS (Backspace)

9 11 9 1001 HT (Horizontal Tab)

10 12 00A 1010 LF (Line Feed)

11 13 00B 1011 VT (Vertical Tab)

12 14 00C 1100 FF (Form Feed)

13 15 00D 1101 CR (Carriage Return)

14 16 00E 1110 SO (Shift Out)

15 17 00F 1111 SI (Shift In)

16 20 10 10000 DLE (Data Link Escape)

162

Decimal Octal Hexadecimal Binary Value Meaning

17 21 11 10001 DC1 (X ON) (Device Control 1)

18 22 12 10010 DC2 (Device Control 2)

19 23 13 10011 DC3 (X OFF)(Device Control 3)

20 24 14 10100 DC4 (Device Control 4)

21 25 15 10101 NAK (Negative Acknowledgement)

22 26 16 10110 SYN (Synchronous Idle)

23 27 17 10111 ETB (End of Trans Block)

24 30 18 11000 CAN (Cancel)

25 31 19 11001 EM (End of Medium)

26 32 01A 11010 SUB (Substitute)

27 33 01B 11011 ESC (Escape)

28 34 01C 11100 FS (File Separator)

29 35 01D 11101 GS (Group Separator)

30 36 01E 11110 RS (Request to Send)(Record Separator)

31 37 01F 11111 US (Unit Separator)

32 40 20 100000 SP (Space)

33 41 21 100001 (exclamation mark)

34 42 22 100010 (double quote)

163

Decimal Octal Hexadecimal Binary Value Meaning

35 43 23 100011 (number sign)

36 44 24 100100 $ (dollar sign)

37 45 25 100101 (percent)

38 46 26 100110 amp (ampersand)

39 47 27 100111 (single quote)

40 50 28 101000 ( (leftopening parenthesis)

41 51 29 101001 ) (rightclosing parenthesis)

42 52 02A 101010 (asterisk)

43 53 02B 101011 + (plus)

44 54 02C 101100 (comma)

45 55 02D 101101 - (minus or dash)

46 56 02E 101110 (dot)

47 57 02F 101111 (forward slash)

48 60 30 110000 0

49 61 31 110001 1

50 62 32 110010 2

51 63 33 110011 3

52 64 34 110100 4

164

Decimal Octal Hexadecimal Binary Value Meaning

53 65 35 110101 5

54 66 36 110110 6

55 67 37 110111 7

56 70 38 111000 8

57 71 39 111001 9

58 72 03A 111010 (colon)

59 73 03B 111011 (semi-colon)

60 74 03C 111100 lt (less than)

61 75 03D 111101 = (equal sign)

62 76 03E 111110 gt (greater than)

63 77 03F 111111 (question mark)

64 100 40 1000000 (AT symbol)

65 101 41 1000001 A

66 102 42 1000010 B

67 103 43 1000011 C

68 104 44 1000100 D

69 105 45 1000101 E

70 106 46 1000110 F

165

Decimal Octal Hexadecimal Binary Value Meaning

71 107 47 1000111 G

72 110 48 1001000 H

73 111 49 1001001 I

74 112 04A 1001010 J

75 113 04B 1001011 K

76 114 04C 1001100 L

77 115 04D 1001101 M

78 116 04E 1001110 N

79 117 04F 1001111 O

80 120 50 1010000 P

81 121 51 1010001 Q

82 122 52 1010010 R

83 123 53 1010011 S

84 124 54 1010100 T

85 125 55 1010101 U

86 126 56 1010110 V

87 127 57 1010111 W

88 130 58 1011000 X

166

Decimal Octal Hexadecimal Binary Value Meaning

89 131 59 1011001 Y

90 132 05A 1011010 Z

91 133 05B 1011011 [ (leftopening bracket)

92 134 05C 1011100 (back slash)

93 135 05D 1011101 ] (rightclosing bracket)

94 136 05E 1011110 ^ (caretcirumflex)

95 137 05F 1011111 _ (underscore)

96 140 60 1100000 `

97 141 61 1100001 a

98 142 62 1100010 b

99 143 63 1100011 c

100 144 64 1100100 d

101 145 65 1100101 e

102 146 66 1100110 f

103 147 67 1100111 g

104 150 68 1101000 h

105 151 69 1101001 i

106 152 06A 1101010 j

167

Decimal Octal Hexadecimal Binary Value Meaning

107 153 06B 1101011 k

108 154 06C 1101100 l

109 155 06D 1101101 m

110 156 06E 1101110 n

111 157 06F 1101111 o

112 160 70 1110000 p

113 161 71 1110001 q

114 162 72 1110010 r

115 163 73 1110011 s

116 164 74 1110100 t

117 165 75 1110101 u

118 166 76 1110110 v

119 167 77 1110111 w

120 170 78 1111000 x

121 171 79 1111001 y

122 172 07A 1111010 z

123 173 07B 1111011 (leftopening brace)

124 174 07C 1111100 | (vertical bar)

168

Decimal Octal Hexadecimal Binary Value Meaning

125 175 07D 1111101 (rightclosing brace)

126 176 07E 1111110 ~ (tilde)

127 177 07F 1111111 DEL (delete)

Table 20 ndash Full ASCII Table

169

Handy IDE Settings

Line Numbers onoff Tools | Options | Text Editor | CC++ | Line Numbers

Auto closing the console Tools | Options | Debugging | Automatically close the console window when debugging stops

Saves having to use system(pause)

170

REMAINING PAGES LEFT BLANK FOR NOTE TAKING

171

172

173

Peet Morris

peetmorrisgmailcom

C++ A Comprehensive Introduction

Arrangements

bull We Startfinish at 915am 500pm

bull Format two lectures per day (ask questions) hands-on at all other times

bull You should have Course book (copy of the slides at the back)

bull The course software is pre-installed on the machines

And also separately available from

The compilerIDE wwwvisualstudiocom

Notesslidesexercise files wwwpeetmcomC++introcoursezip

Your safety is important

Where is the fire exit

Beware of hazards

Tripping over bags and coats

Please tell us if anything does not work

Let us know if you have any other concerns

Your comfort is important

The toilets are along the corridor just outside the teaching rooms

The rest area is where you registered it has vending machines and

a water cooler

The seats are adjustable

You can adjust the monitors for brightness

What we assumehellip

What we assume

Experience of using another programming

language

Comprehensive Lots to get through

C++ and OOP

bull Created in 1985 by Bjarne Stroustrup C++ is a highly efficient

multiplatform low level Object Oriented Programming language

bull Latest version is C++17

stroustrupcom

Standard C++ Library

bull Written in the core language it is a collection of classes

(object definitions) functions and algorithms

See wwwcpluspluscomreference

IDEs amp Compilers

Visual Studio 2017

First Program

First application

include ltiostreamgt

using namespace std

int main()

int aNum = 0 aNum(0) or aNum0

cout ltlt Enter a number-

cin gtgt aNum

cout ltlt You entered ltlt aNum

return 0

hellip hellip

First Program

bull include ltiostreamgt

Adds the contents of the iostream header file into the program (for cout and cin)

bull using namespace std

So we donrsquot have to write stdcout ltlt and stdcin gtgt all of the time

bull cin is the standard input stream object that allows input from the keyboard

bull cout is the standard output stream object that allows output to the screen

bull int main() The programs entry point

Mandatory main function in every C++ program ndash always returns an integer value

First Program

bull int aNum = 0

Variable to hold a value of type integer (piece of machine memory referred to via the name aNum)

bull ltlt stream insertion operator ndash outputs to console

cout ltlt Enter a number-

bull gtgt stream extraction operator ndash waits for keyboard input

cin gtgt aNum

Other Types

Microsoft data types summary httpsdocsmicrosoftcomen-gbcppcppfundamental-types-cpp

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststack

Lots

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

x 1

y 2

x 3

y 4

p1

p2

x

y

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 copies the bit pattern from p1 to p2

x 1

y 2

x 1

y 2

p1

p2

Compound Types

Cannot define operators other than assignment

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 p2 compilation error

x 1

y 2

x 3

y 4

p1

p2

Compound Types

We can arbitrarily further compound things

struct point

int xint y

struct rectangle

point tlpoint br

struct line

point startpoint end

startxy

endxy tlxy

brxy

Compound Types

We can also group things using struct to create compound

types

struct point

int xint y

struct rectangle

point tlpoint br

int main()

rectangle r

rtlx = 1rtly = 2

rbrx = 3rbry = 4

int diff_x = abs(rtopLeftx - rbottomRightx)int diff_y = abs(rtopLefty - rbottomRighty)

cout ltlt area ltlt diff_x diff_y ltlt endl

r

tl

br

x 1

y 2

x 3

y 4

Using a Library Type

include ltstringgt

string s

cout ltlt What is your name

getline(cin s)

cout ltlt s ltlt

ltlt is

ltlt slength() ltlt

ltlt characters long ltlt endl

s

Other Types

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststackcomplex

Lots

8 bit Binary signed unsigned

00000001 1 1

00000010 2 2

00000011 3 3

01111111 127 127

10000000 -128 128

10000001 -127 129

10000010 -126 130

11111101 -3 253

11111110 -2 254

11111111 -1 255

00000000 0 0

00000001 1 1

00000010 2 2

signed vs unsigned ndash its all just 1s and 0s and adding

Adding rules

0 + 0 = 0

1 + 0 = 1

0 + 1 = 1

1 + 1 = 0 (carry 1)

1 + 1 + 1 = 1 (carry 1)

-126 + +3 =

10000010

00000011 +

10000101 = -123

-126 + -3

10000010

11111101 +

01111111 = 127 (why not -129)

Arithmetic Operators

+ Addition

- Subtraction and unary minus

Multiplication

Division

Remainder after division (moduloclock arithmetic)

int j k l = 10

j = l 3 js value will be three

k = l 3 ks value will be 1

Relational Operators

Evaluate to either true or false represented by integer values 1 and 0

== Equal to

= Not equal to

gt Greater than

lt Less than

gt= Greater than or equal to

lt= Less than or equal to

Increment and Decrement Operators

++ Increment

-- Decrement

Can be prefix or postfix

b = 3

a = b++ + 6 Add 6 to b then increment b a is 9 b is 4

b = 3

a = ++b + 6 Increment b then add 6 to b a is 10 b is 4

Assignment Operators

Symbol Operation Long Short

= Assign a = 2 a = 2

+= Assign with add a = a + 2 a += 2

-= Assign with subtract a = a ndash 2 a -= 2

= Assign with multiply a = a 2 a = 2

= Assign with divide a = a 2 a = 2

= Assign with remainder a = a 2 a = 2

Basic Control Flow - if

Sequence

What we have been doing already

Selection

if statement if this then that

if (boolean expression) if (score gt= 50)

statement cout ltlt Passed

Logical Operators

Boolean expressions may be combined using

ampamp And

|| Or

Not

Operands and result resolves being either true or false

if (x ampamp (y || z))

else

Precedence and Associativity table in course book

Logical Operators

a b =

true true true

true false false

false true false

false false false

a b =

true true true

true false true

false true true

false false false

a =

true false

false true

a ampamp b a || b a

Logical Operators

if (x ampamp (y || z))

else

The value 0 (zero) is evaluated to mean false any other value is true

x ampamp (y || z) result

false ampamp (false || false) falsefalse ampamp (false || true ) falsefalse ampamp (true || false) falsefalse ampamp (true || true ) falsetrue ampamp (false || true ) falsetrue ampamp (false || false) truetrue ampamp (true || false) truetrue ampamp (true || true ) true

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp (y | ~z))

else

Bitwise Operators

unsigned int x = 11

unsigned int y = 7

unsigned int z = 25

if (x amp (y | ~z))

else

11 (x) = 000010117 (y) = 0000011125 (z) = 00011001

~z = 11100110 (230 or -26)

y | ~z = 11100111 (231 or -25)

x amp (y | ~z) = 00000011 = 3

Operands and the result resolve to a values

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp 1) x is odd

if (x gt y)

x = x ^ y

y = y ^ x XOr swap

x = x ^ y

Control Flow - if else

Selection

ifelse statements

if (boolean exp) if (score gt= 50)

statement cout ltlt Passed

else else

statement cout ltlt Failed

Control Flow -

Selection

Conditional (or Ternary) Operator

boolean exp true result false result

cout ltlt score gt= 50 Passed Failed

Control Flow

if (x gt= y)

if (y 2)

else

if (x gt= y)

if (y 2)

else

Control Flow ndash else if

if (exp)

else if (exp)

else if (exp)

else catch all remaining

if (aNum == 0)

else if (aNum == 1 || aNum == 2)

else if (aNum == 3)

else catch all remaining

aNum not 0123

Control Flow - switch

Selection

switch multiple selection statements

bull test must be an integral value 1 10 A x eg not 1056

bull case values must be constants

switch (aNum)

case 0

break

case 1 Fall through

case 2

break

default catch all

break

Repetition - while

while (exp)

statements

while (n lt k)

cout ltlt Enter mark

cin gtgt mark

t += mark

n++

Repetition - for

for (init exp inc)

statements

for (t = 0 n lt k n++)

cout ltlt Enter mark

cin gtgt mark

t += mark

Preferable to while if the range is known

Repetition - for

for (init exp inc)

statements

for () infinite loop

break causes loop to exit

Preferable to while if the range is known

Repetition - do

do

statements

while (exp)

do

cout ltlt Continue yn

cin gtgt yn

yn = tolower(yn)

while (yn = y ampamp yn = n)

There are a huge number of exercises and we donrsquot expect you to attempt

them all during this course

bull If yoursquore completely new to programming itrsquos probably best to tackle

them in sequence

bull If yoursquove some programming experience you should read through the

exercise summaries and then start wherever you feel comfortable

Exercises

Exercises

Topics covered in ex1 ndash ex6

Functions = mini programs

bull Used to combine data with operations and through functional

decomposition to promote code re-use

bull Simplifies coding

bull Functions for discrete tasks

bull Not hundreds of lines of code

bull Consumer only needs to know

bull What goes in and what comes out

Functions

Like everything else the compiler needs to have seen a prototype or a

definition of a function before we can use it

Prototypes lets the compiler generate the correct code

int min(int int)

int min(int int int)

void drawLine(point to point from = 00)

int square(int)

int main()

void beep()

string getNextPacket(void)

Return type Function name (Parameter list)

min

int min(int int) min prototypes (forward declarations)int min(int int int)

int main()

Having seen the prototypes the compilerc = min(x y) can generate the required code

int min (int a int b) min function definition 1

return a lt b a b

int min (int a int b int c) min function definition 2

return min(min(a b) c)

inline min

int main()

c = min(x y)

inline int min (int a int b)

return a lt b a b

int main()

c = x lt y x y

inline int min (int a int b)

return a lt b a b

Function Parameters

bull Pass by Value

bull A Copy of the parameter is passed to the called function

bull Pass by Reference

bull The actual parameter is passed to the called function

bull Pass by Memory Address (pointer)

bull Same effect as Pass by Reference (tomorrow)

Pass by value

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

return n_copy n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 10

n_copy 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp x)

x just another name for real_n

return x x

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

x 10

Pass by value (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

n_copy = n_copy n_copy

return n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 100

n_copy 100

Pass by reference (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

real_n = real_n real_n

return real_n

100

100

Mem Addr Contents

0x2786 100

real_n 100

Mem Addr Contents

0x2786 100

real_n 100

const Parameters

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Recursion

unsigned long long int fibonacci(int n)

switch(n)

case 0 Fall through - [[fallthrough]]

case 1

return n

break

default

return fibonacci(n - 1) + fibonacci(n - 2) Very inefficient

Arrays (Part 1)

Data structure containing same type of data (int double string char object)

bull Built in to C++

bull Series of elements each containing one item of data (contiguous memory locations)

Size (number of elements) set at compile time

Arrays (1)

int numbers[10] an array of 10 integers Each box sizeof(int) bytes wide

numbers

index values - 0 to 9

0 1 2 3 4 5 6 7 8 9

Arrays (1)

int numbers[10] an array of 10 integers

int n = 0

cout ltlt numbers ltlt endl address of the first element

cout ltlt numbers[n] ltlt endl contents of the nth element

cout ltlt ampnumbers[n] ltlt endl address of the nth element

cout ltlt numbers + n ltlt endl address of the nth element

0 1 2 3 4 5 6 7 8 9

42 hellip hellip hellip hellip hellip hellip hellip hellip hellip

0x1526

Arrays

char name[5] name - an array of five characters

thing t[5] t - an array of five things

examMarks ndash an array of three doubles initialised to 12 39 95double examMarks[] = 12 39 95 C++11 - double examMarks[] 12 39 95

header ndash an array of fifty unsigned chars (bytes) first three elements set to 0 1 255 and the rest to zerotypedef unsigned char bytebyte header[50] = 0 1 -1

Arrays

Accessing array data

define MARKS 5 or const int MARKS = 5

double examMarks[MARKS]

for(int i = 0 i lt MARKS i++)

cout ltlt Enter Exam Mark

ltlt i + 1 ltlt

cin gtgt examMarks[i]

for(i = 0 i lt MARKS i++)

cout ltlt examMarks[i]

Multidimensional Arrays

Two dimensional array Two subscripts First identifies row second identifies column

const int students = 6 const int marks = 3

double examMarks[students][marks] = 0 set to zero

for (int s = 0 s lt students ++s)

for (int m = 0 m lt marks ++m)

cout ltlt Enter mark ltlt m + 1 ltlt for student ltlt s + 1 ltlt endl

cin gtgt examMarks[s][m]

00 01 02

10 11 12

20 21 22

30 31 32

40 41 42

50 51 52

Memory laid out in row column order (more later)

00 01 02 10 11 12 20 21 22 30 31 32 40 41 42 50 51 52

Matrices

Provider Link

Armadillo armasourceforgenet

Blitz blitzsourceforgenet

Boost boostorg

Eigen eigentuxfamilyorg

Elemental libelementalorg

FLENS apfelmathematikuni-ulmde

HSL hslrlacuk

LEDA algorithmic-solutionscom

PETSc mcsanlgov

SimuNova simunovacom

SuiteSparse facultycsetamuedu

TNT mathnistgov

Trilinos trilinosorg

ViennaCL viennaclsourceforgenet

Exercises

Topics covered in ex7 ndash ex16

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people and dice

Recap Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

1 61 61 61 61 6

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

3 11 24 56 12 3

C++ and OOP

Encapsulation Keeping related stuff together

Member functionsmethods

an objectrsquos capabilities functionality and performable actions

int Throw()

Member variablesproperties

an objectrsquos current state values its dumb data

int sides

Dice throwing 3

struct dice

int sides State

dice(int n) Constructor

sides = n

int Throw() Member function (method)

return (rand() sides) + 1

int main()

Could also use dice d1 = 6 or d16 syntaxdice d1(6) d2(6)

d1sides = 6 d2sides = 10 Allow this

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

struct diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

class diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing ndash professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

diceh my-appcpp

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

dicecpp

Compiler

diceobj my-appobj

Linker

my-appexe

other librarycode objectfiles

Dice throwing - professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Compiler

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

diceobj my-appobj

diceh dicecpp my-appcpp

Linker

my-appexe

other librarycode objectfiles

Only items provided to the end-usercustomer

Classes and Objects

the includeltstringgt header file from the standard library

class string

your cpp source code files

include ltstringgt include information about class string

string Name a class string instance

string Address a class string instance

Classes and Objects

the include carh header file

class car

your cpp source code files

include carh include information about class car

car c a class car instance

Classes and Objects

the include househpp header file

class house

your cpp source code files

include househpp include information about class house

house no1 a class house instance

house no2 a class house instance

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do with it

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

cstart()

cenginestart() Or should cstart() internally use enginestart()

OOD

Time for a break

class student

What properties and methods do we need

class student

public

string name

string DoB

string college

string bodCardNumber

float age()

int main()

student s

sname =

sDoB =

How to guarantee an objectrsquos integrity

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s

sname = Compilation errors

sDoB =

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s( )

cout ltlt sage()

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB Error ndash cant assign to a constant

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_name(name) m_DoB(DoB)

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_namename m_DoBDoB

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Exceptions

class student

int main()

try

student s( )

catch(const char msg)

cout ltlt msg ltlt endl

student initialisation failed

Exceptions

try

catch(const char msg)

cout ltlt msg ltlt endl

catch (const invalid_argument amp e)

cout ltlt ewhat() ltlt endl

catch (exception amp e)

cout ltlt ewhat() ltlt endl

catch ()

cout ltlt Something went wrong ltlt endl

student invalid arg 2

if using C++11 see stdcurrent_exception

Reuse and inheritance

Say we now want to add a new type to our system ndash class academic With what we have seen so far we would proceed something like this

class academic

private

string m_name string m_DoB

Duplicating everything we had in class student

class person (generalisation)

OOP is sometimes called Programming by Describing the differences

student and academic are all specialisations of a more generalised and abstract class ndash person

class student public personpublic

student(string name) person(name)

class academic public personpublic

academic(string name) person(name)

class personprotected

person(string name) m_name(name)

private

string m_name

public

base class derived class

derived class

Specialised State

class student public person

private

const string m_bodCard

public

student(string name string DoB string bc ) person(name DoB) m_bodCard(bc)

Multiple inheritance

class student public person public oxMember

public

student(string name int age string bc) person(name age) oxMember(bc)

class academic public person public oxMember

public

academic(string name int age string bc) person(name age) oxMember(bc)

Destructors

class foo

private

int m_x int m_y

public

foo() foo(0 0)

foo(int x) foo(x 0)

foo(int x int y) m_x(x) m_y(y) only ctor that accesses private state

~foo() any necessary tidy up code

Dice throwing 5

class diceprivate

int sides

public

dice(int n) sides(n)

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

srand((unsigned)time(0)) Happy with this

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 6

class diceprivate

int sides

public

dice(int n) sides(n)

classshared state static bool seeded = false

if (seeded)srand((unsigned)time(0))seeded = true

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

3 65 21 44 22 6

Dice throwing 7

class dice private

int sides

public

dice(int n) sides(n)

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

Dice throwing 7

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyesDouble 14 33 5

Dice throwing 8

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6) int t

for(int n = 0 n lt 5 ++n)

cout ltlt (t = d1Throw()) ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp t = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Dice throwing 9

class dice private

int sidesint _lastThrow

public

const int amp lastThrow read-only stateproperty

dice(int n) _lastThrow(-1) lastThrow(_lastThrow) sides(n)

int Throw()

return _lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp d1lastThrow = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Exercises

Topics covered in ex17 ndash ex22

Vectors

Like an array a data structure containing same type of data (int double object)

bull A container class part of the standard library a wrapper similar to arrays

Need to includeltvectorgt

bull Can resize grow shrink as elements are added or removed from the end

bull Algorithms to manipulate data

bull Iterators to cycle through all the elements

Vectors

vectorltchargt name(5) vector of five characters

vectorltthinggt t(5) vector of five things

vectorltdoublegt examMarks 12 39 95 initialised vector of three doubles

typedef unsigned char byte

a vector of fifty bytes first three elements set to 0 1 255 and the rest to zerobyte char b[50] = 0 1 255 fully populate array

calc itemCountint itemCount = sizeof(b) sizeof(b[0])

vectorltbytegt bytes (b ampb[0] + itemCount) then init with vector 50 items

Vectors (iteration 1)

include ltvectorgt

vectorltintgt vec(20) 20 ints

for(int i = 0 i lt vecsize() i++) input values into vec

cin gtgt vec[i]

for(i = 0 i lt vecsize() i++) output vec

cout ltlt vec[i] ltlt

Vectors (iteration 2) (C++11 and later)

for(type identifier container)

statements

vectorltintgt vec(20)

for (int amp i vec)

Vectors

Adding an extra element

cout ltlt Enter an Extra Value

cin gtgt aNum

vecpush_back(aNum)

for (int i = 0 i lt vecsize() i++)

cout ltlt vec[i] ltlt endl

cout ltlt vecat(i) ltlt endl same as above but range checked (ie slowsafe)

Vectors (most of the methods)

docsmicrosoftcomen-uscppstandard-libraryvector-classFull list

Method Purpose

assign Erases a vector and copies the specified elements to the empty vector

at Returns a reference to the element at a specified location in the vector

back Returns a reference to the last element of the vector

begin Returns a random-access iterator to the first element in the vector

capacity Returns the number of elements that the vector could contain without allocating more storage

clear Erases the elements of the vector

C++11 data Returns a pointer to the first element in the vector

C++11 emplace Inserts an element constructed in place into the vector at a specified position

C++11 emplace_back Adds an element constructed in place to the end of the vector

empty Tests if the vector container is empty

end Returns a random-access iterator that points to the end of the vector

erase Removes an element or a range of elements in a vector from specified positions

front Returns a reference to the first element in a vector

insert Inserts an element or a number of elements into the vector at a specified position

max_size Returns the maximum length of the vector

pop_back Deletes the element at the end of the vector

push_back Add an element to the end of the vector

rbegin Returns an iterator to the first element in a reversed vector

rend Returns an iterator to the end of a reversed vector

reserve Reserves a minimum length of storage for a vector object

resize Specifies a new size for a vector

C++11 shrink_to_fit Discards excess capacity

size Returns the number of elements in the vector

swap Exchanges the elements of two vectors

Vectors (iteration 3)

include ltalgorithmgt

vectorltintgt vec

for(int i = 1 i lt= 5 ++i)vecpush_back(i)

1 2 3 4 5

5 4 3 2 1

vectorltintgtiterator it

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Reverse the vectorreverse(vecbegin() vecend())

cout ltlt endl

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Arrays (2) (C++11 and later)

arrayltint 5gt arr Thin veneer over an array ndash so requires fixed size

arrfill(0) int j = 0

for (int amp i arr)

supports latest iteration style

reverse(arrbegin() arrend()) and iterators for use with algorithms

C++11 - Uniform initialisers

C++98

complexltdoublegt c( 271828 314159 )

int a[] = 1 2 3 4

vectorltintgt v

for( int i = 1 i lt= 4 ++i )

vpush_back(i)

C++11

complexltdoublegt c 271828 314159

int a[] 1 2 3 4

vectorltintgt v 1 2 3 4

Pointers ndash What

A pointer is a scalar variable that is used to hold the memory-address of

another variable or function the stored address is said to point to the thing

it holds ndash thus the name

Pointers have a type ndash the type of the thing they point to

int n = 10I (p) am a pointer to an integer and I point to n over thereint p = ampn

Pointers ndash Why

In no particular order

bull Because external libraries and APIs (like the operating system (all of them)) are written using them

bull Create custom data structures like linked-lists trees graphs etc

bull Create tables of functions or single functions for handling events callback or signals

bull Access data on to the heap (allocate memory dynamically)

bull Writecall functions that change their input parameters

1 2

3

4 5 6 nilhead

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

Recap - Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference using Pointers

int main()

int real_n = 10

cout ltlt square(ampreal_n)

cout ltlt real_n

return 0

int square(const int real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x5110 0x2786

real_n 0x2786

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt pcout ltlt pcout ltlt ampxcout ltlt xcout ltlt ampp

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

15438

11

15438

11

17216

Pointers

int main(int argc char argv)

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )(argv + n) ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv + 0 C

argv + 1

argv + 2

argv + 3

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

int main(int argc char argv[])

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )argv[n] ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv[0] C

argv[1]

argv[2]

argv[3]

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

Memory Stack vs Heap

Stack (last in first out - LIFO)

Space automatically allocated

The place where arguments of a function call are stored

The place where local function data is allocated (eg variables)

The place where a function leaves its result (if any)

Heap

Space must be explicitly allocated

A place for allocating memory that is not part of last-in first-out approach

ie dynamically allocated data structures that survive function calls

Stack vs Heap

int stackArray[100] Allocate 100 ints on the stack

stackArray[n] = 0 Do something with it

int heapArray = new int[100] 100 ints on the heap C++

int heapArray = malloc(100 sizeof(int)) 100 ints on the heap C

heapArray[n] = 0 Or (heapArray + n) = 0 Do something with it C++ and C

delete [] heapArray When youre done C++

free(heapArray) When youre done C

Exercises

Topics covered in ex22 onwards

If time allows look through the remaining

exercises and attempt those that fit best

with your requirements

  • C++ Notes TPLO 12-11-2019 Blackbox
  • C++ Slides TPLO 12-11-2019 - Copy

Precedence and Associativity Table 150

Escape Sequences 151

Cast Operator 152

Formatted Output 152

Header Files 153

Matrix Libraries 153

Scope 154

Enumerating constants 154

Constants 154

Vector member functions 155

Global functions 155

list member functions 156

cmath functions 156

String class 158

ASCII Character set 161

Handy IDE Settings 169

Exercises

Exercise 1 (Optional) Creating a first and default program 6

Exercise 2 CreatingModifying additional projects 26

Exercise 3 SearchString 29

Puzzled Programmers 29

The Collatz Conjecture 31

Mixing loops 33

PLUSPLUS Recursion 34

PLUSPLUS Base Two and Bits 37

Practising with Logical and Bitwise operators 38

Writing functions 42

Using a struct 43

PLUSPLUS When Things Go Wrong 44

The Monty Hall problem 46

More Functions 48

PLUSPLUS IsLeap in a line 49

Algorithms 49

Pass arguments by reference 52

Returning a value from a function 57

PLUSPLUS Arithmetic Bases 58

Searching for Sequences 61

PLUSPLUS Optimising Searching for Sequences 63

Evolving Searching for Sequences 64

Creating a class 65

Passing parameters 67

Using data members 69

More Objects 70

Using constructors 71

Separating declaration and definition 74

PLUSPLUS Using external libraries and third party header files 78

Creating an array to hold exam results 84

Linear Search 87

PLUSPLUS Debugging Linear Search 89

SortingSearching an array 90

PLUSPLUS Binary Search (Binary Chop) 93

Creating a multidimensional array 95

Creating a vector to hold exam results 100

Using insert() and iterators 103

Computing Fibonacci Numbers 110

Using pointers 114

Pointers and Arrays 116

PLUSPLUS Pointers and Arrays 119

PLUSPLUS Function pointers 122

main() and command-line arguments 126

EncryptDecrypt a file 128

Passing Arrays to functions 132

Base classes 137

PLUSPLUS Polymorphism 144

The PowerPoint slides entitled Exercises show the inclusive fromto exercise numbers which cover the topics discussed in the previous section It is not at all necessary to attempt to work through the entire quoted range variety is the spice of life ndash just choose those that appeal

1

1 Introduction Welcome to C++ A Comprehensive Introduction

These notes accompany the course delivered by Oxfords IT Services IT Learning Programme

If at any time you are not clear about any aspect of the course please make sure you ask your lecturer or demonstrator for some help If you are away from the class you can get help by email from your lecturer or from helpitoxacuk

Please also note that the university subscribes to Lyndacom ndash please check there for other C++ resources

11 What you should already know

The prerequisite for this course says that Either experience in another programming language or attendance on one of the PHP JavaScript or Python Kick-Start courses Is required

The more programming knowledge you have the better That said the documentation and lectures are structured such that those with very little knowledge should still be able to work through the course at their own pace

12 What you will learn

We will cover the following topics

Working with Microsofts Visual Studio Fundamental data types

Control Flow amp Iteration Header Files

Strings Functions

Arrays and Vectors Classes and Objects

Constructors and Destructors Member functions

Pointers And much more

13 Where can I get a copy of the softwaretools used

wwwvisualstudiocom (Microsofts C++ Compiler IDE and tools)

wwwpeetmcomC++introcoursezip (latest course code notes slides etc)

2 Things to understand

21 Compilers new and old

Students on this course often have to work with enhance or bug-fix existing code This sub-section is primarily for their consideration (it assumes some prior C++ knowledge)

2

Not all C++ compilers comply with the latest official ISO C++ standard (C++17) which was finally approved in December 20171

What does this mean It means that the code you write compile and run on one machine may not compile on the next machine if you are using a different compiler (even if it is using the same operating system) In this course you will be using Microsofts C++ Compiler (part of Visual Studio 2019)

Some older header files you may see with inherited C++ code are

include ltiostreamhgt have a h extension The C++ standard for this header file is include ltiostreamgt Your program may run correctly by adding a h but simply adding a h suffix will not work for all included files

include ltstringhgt has been replaced with include ltstringgt The stringh header file does not include C++ strings it includes C strings

include ltmathhgt has been replaced with include ltmathgt

The lesson to be learnt here is that a lot of C++ code you come across will have been created using older compilers Some of the header file and other code will not be recognised and may cause compilation errors when compiled on a machine which is more compliant with the C++ standard

If you are using the Gnu Compiler Collection (gcc g++ etc) you can specify standards compliancy via the ndashstd option eg -std=c++17 (other options are C++98

C++11 C++14)

Visual Studio can also be configured to use LLVM and clang Please see the relevant online documentation of how to install and use these if you wish to use them httpsllvmorgdocsGettingStartedVShtml

22 The C++ Standard Template Library (STL)

enwikipediaorgwikiStandard_Template_Library

The C++ programs you write will consist of the classes and functions that you write or modify (we provide partial solutions to every exercise)

However we will also look at what is still commonly referred to as the STL (now just part of the C++ Standard Library ) which holds a collection of existing classes functions and algorithms that you can use in the programs you will be creating

Some of the classes and template classes we will be looking at are

The string class The vector container template

The sort algorithm The list container template

The find algorithm

In addition you should also look at and be aware of another powerful library called Boost (parts of the STL come directly from the Boost library) wwwboostorg

The Boost library is easy to install (on any platform) as most Boost libraries are what is called header-only ie they consist entirely of header files containing templates and inline

1 A draft of this is included with your course files (n4660pdf) Its worth mentioning that this draft is in effect the published C++17 standard

3

functions and require no separately-compiled library binaries or special treatment when linking

23 Visual Studio 2019

What is Visual Studio (VS) VS is Microsofts freely available integrated development environment (IDE) and comes complete with optional compilerstools for a variety of languages We have only installed the IDE and the C++ compi ler (clexe etc) for this course

So what is a compiler

A compiler is a computer program that allows us to write programs in some specially defined language (unfortunately not English yet) in our case C++ (a so called high- level

language ) As you heard earlier the tex t we write in C++ is called source-code it is just simple text that one could write in Notepadexe for example

Sadly source-code is not directly understood by operat ing systems such as Windows Linux and macOS etc and it is the compilers job to convert our source-code into the terse concise and highly optimised machine-code that computers understand directly

Machine-code is often called executable or object-code and the compiled version of the source code is really just a file that contains numbers ndash a series of 8-bit bytes each holding a value between 0 and 255 The numbers either encode l ow-level instruct ions (code) or data that working together define the program Because these numbers may not encode displayable characters (see the ASCII table in the appendices to see a mapping between the numbers and the displayable characters) opening such a file an exe file in something like Windows notepad application would result in something like this being displayed (just the beginning shown)

However if we open this same executable file in a program that simply displays the files content as numbers and not what characters if any are represented by those numbers as Notepad is doing) we see this (the numbers are shown in base-16 or hexadecimal format)

4

The first two numbers 4D and 5A can be displayed as the text M and Z2 (see the first two characters at the top left in the previous notepad view of this file) 4D in base 10 is 77 and 5A is 90 ie the ASCII values for M amp Z (you can look these up in the ASCII table in the back of your course book)

Also take note of the line sequence starting 55 8B EC Then read on

2 MZ (0x4D5A) at the beginning of a file is an example of whats known as a magic number these are often used to identify a file type ndash in this case an MS-DOS executable file Trivia MZ are the initials of Mark Zbikowski the designer of the MS-DOS executable file format

5

If we have Visual Studio we can open the same file to see how such numbers translate into instructions and data

55 8B EC is the real beginning of our program In the above we see the numbers on the left and on the right what they actually mean Eg the first number 55 means push ebp which is an Intel CPU instruction Likewise 8B and EC together mean mov ebp esp The next line 81 EC C0 00 00 00 combines instructions and data and translate into sub esp 0C0h (subtract from esp the value C0 or 192 in base-10)

This is the entire program really the extra data shown in the previous views are for housekeeping

What does this program actually do then

Well youre about to find out ndash youre optionally now going to recreate it in Exercise 1

6

Creating your first program in Visual Studio 2019

Exercise 1 (Optional) Creating a first and default program

IMPORTANT

This exercise starts with a walk-through of using Visual Studio to create a new solution which you then go on to modify You should have already seen the steps needed to create a new solution in class so if youd rather just get on with the modification part simply open the (exercise solut ion)

f i rs t folder (in the Course folder) and double click the f i rs t s ln file If you choose to do this you can skip over the next few pages to the Explanation section (232) or even jump further on to Task 1 on page 14

Note You will not need to create any completely new programs during the course so even if you didnt fully follow the steps you can still safely move on to the modification part However if you really want to walk it through for yourself

Start the Visual Studio 2019 Integrated Development Environment (IDE) and create a new C++ Console application project You should have a shortcut to Visual Studio on your desktop failing that look for it on the Start menu

If they appear follow the prompts as shown below (if youre asked about keyboard mappings or Develop options select the C++ option)

7

Click Create a new project

Select Console App and click Next

8

Well locate the first project in a folder called first in your C drives Temp folder If the folder doesnt exist it will be created for you Click Create

Something like the above should appear (if you dont see the Solution Explorer panel open it via the View menu)

9

Alter the code adding the lines in bold as show here

include ltiostreamgt using namespace std int main() stdcout ltlt Hello Worldn system(pause)

Build and run the project by pressing the green arrow or by pressing F5

10

Explanation

Disclaimer at this stage you do not need to fully follow all of this just now

include ltiostreamgt

iostream is a standard C++ library file Files of this type are called header files They are text files usually containing C++ declarations definitions and code

Including iostream allows us to use some pre-defined objects to output messages to a console window This file must be included for any program that outputs data to the screen - or inputs data from the keyboard for that matter

The C++ compiler operates in passes through our code In the first pass ndash called the pre-processing pass ndash include directives are processed which are really text-substitution directives To be precise what include ltiostreamgt says is ldquoGo and find the text file called iostream and replace the directive with the contents of that filerdquo

The file name following a include directive can be enclosed in double quotes or chevrons ie include iostream or include ltiostreamgt The meaning of each is defined by the implementation (Microsofts C++ compiler in our case)

However it is common practice that if file name is in quotes it will be looked for locally first - in the same folder as the cpp file containing it and before being sought elsewhere Conversely if it is in chevrons the compiler will usually look for the file in a central include folder that was installed with the compiler ndash this folder is usually reserved for include files that come with the compiler as opposed to those that you might write yourself eg standard includes (like iostream) We therefore usually use quotes when we want to include our own custom project specific include files and chevrons when wanting to use include files that come with the compiler

You may also see that the filename sometimes has a h file extension This typically means that the header file being used is a C language header file and not a C++ one There are other variations (you are welcome to use your own) for example you might also see the occasional hxx file extension or something else entirely

using namespace std

The using namespace std code above doesnt actually appear in the automatically generated code In our project and solution files we will add it just after any include directives

namespaces in summary are very simple Everything within a namespace has a unique name and so theyre often used to help divide larger projects into more manageable chunks and to avoid name clashes

Standard C++ places a lot of its routines and functionality within a namespace call std Wed like to use this functionality and so we say we want to use all of the std namespace In the real world this isnt terribly good practice

11

However by declaring that were using namespace std throughout we can access members of this namespace without having to say exactly where they are (in which namespace) or worry about name clashes - where two objects in different files have been given the same name

The members of std that we will be using throughout are

cin (Console In) and cout (Console Out) and we must use include ltiostreamgt in order to use them

endl - is a stream manipulator that writes a new line to output endl stands for end

of l ine and is pronounced end all

If we dont declare that we were using the std namespace (which is the case in the automatically generated code) we have to prefix any use of cin cout and endl with std eg stdcin stdcout stdendl If youve added the using namespace std directive you may now remove the std in front of the stdcout ltlt Hello Worldn line

int main()

This is the entry point to our program ndash every C++ program must have this same entry point defined main() is a function the body of a function is defined within the opening and closing braces that come after its name The int to the left of main() says that this function returns (or resolves to beevaluates to) an integer value Returning a value requires you to use a return statement However as it is normal practice to simply return the value zero if you omit the return statement a value of zero is returned for you (only where main is concerned) If you want to explicitly return the value yourself you could modify the code to read

int main() stdcout ltlt Hello Worldn system(pause) return 0

So why return a value anyway Our added line return 0 means in this case that our main doing whatever it does as part of its function eventually resolves to the value 0 The value is returned to whatever called our programs entry point in this case and as usually that is the operating system ndash which has been waiting for us to return a value at this point However the operating system will simply ignore whatever value we ultimately return Why do it then

12

Consider the case when one of your programs needs to run another program to perform a part of its entire function Your main program needs to start this other program and wait until it completes successfully before continuing See the description of the system(pause) code line below

stdcout ltlt Hello Worldn

cout is an object declared in iostream ndash think of its name meaning console out Anything sent to cout using the double chevron operator ltlt appears on the console the

The n in the text means that cout should also output a carriage-return linefeed sequence (terms taken from the days of typewriters and telex machines) basically it means start any new output on a newline underneath the current line An alternative to using n is to use endl eg stdcout ltlt Hello World ltlt endl endl does more or less the same thing as n

system(pause)

system() is a standard function that is used to run an external program (here thats a standard Windows program called pauseexe) The system() function waits for the pause program to complete before continuing Going back to the discussion on return 0 earlier this is an example of one program starting another ndash here thats our program starting the pause program The pause program returns a value as part of its completion and we can examine that if we want Programs usually return 0 for success or some other integer value that means something went wrong ndash the value returned indicates what went wrong Ie a returned value of say 42 might mean that we cant answer the ultimate question with this computer3

So what is pause pauseexe is a standard Windows program that simply outputs the message Press any key to continue and then waits for a key to be pressed before exiting We use that facility here so that our program doesnt simply shutdown and disappear as it falls off the end of main()s closing or encounters a return statement If we did allow it to exit we would hardly have time to examine our programs output before it disappeared off the screen Try that and see (comment out the line using a double-slash like this system(pause))

If you run any of the course code on Linux or a Mac youll need to change this line to something like cinget()

3 An unashamed reference to the Hitch Hikers Guide to the Galaxy and the Deep Thought computer

13

Your projects default code template

In the course exercises when it comes to you writing code we will always ask you to open and then modify a partially complete projectsolution so you wont have to fiddle with projects and boilerplate code like this again

Nevertheless should you wish to start from scratch or simply experiment with Visual Studio we recommend using the code below as a starting point

include ltiostreamgt using namespace std int main() Start coding after here system(pause) return 0

14

Task 1

Immediately above system(pause) Replace the stdcout ltlt Hello Worldn line with the code shown here

int anum = 0

cout ltlt Enter a number

cin gtgt anum

cout ltlt The number you entered is

ltlt anum

ltlt endl

Test your modified program Tip remember you may hit the F5 key to build and then run your program

Try entering some text instead of a number Did it work

Alter the spacing (use of spaces and tab characters) in your code ndash does the C++ compiler care about this so called whi tespace

The statement int anum = 0 defines a variable (a memory location) which we will refer to in our code as anum to store a number of type int to hold an in teger (ie 1 -4 27) The memory location is being initialised with a value of 0 here It is good practice to initialise variables when you define them In C++11 a new type of uniform initialisation syntax was introduced and also encouraged eg int anum 0

cout ltlt Enter a number cout is a name that belongs to the namespace std The ltlt is called the stream insert ion operator When the program executes the value to the right of the operator (Enter a number) is inserted in the output stream and ultimately output to console window

cin gtgt anum cin is the input stream object of the namespace std gtgt is called the stream extract ion operator and is used here to read a number from the keyboard

cout ltlt The number you entered is ltlt anum ltlt endl This statement concatenates the output by using multiple stream insertion operators ltlt endl is the stream manipulator that adds a new line

The next Exercise starts on page 26 The pages between here and page 26 contain

code that you may like to try out by further modifying this project if not just read through the textcode until you get to page 26

15

Arithmetic Operators

Most computer programs perform arithmetic calculations Table 1 summarises the standard C++ arithmetic operators When working with integer division where both the numerator and denominator are integer the expression 15 6 evaluates to 2 To get the remainder after integer division you would use the modulus operator Note the modulus operator can only be used with integer operands

To establish the complete result of the following integer division 156 requires two operations

15 6 = 2

15 6 = 3

The result being 2 remainder 3

C++ Operation C++

arithmetic operator

Algebraic expression C++ expression

Addition + y + 6 y + 6

Subtraction - a - b a - b

Multiplication c times d or cd c d

Division xy or y

x or yx x y

Modulus p mod q p q

Table 1 - C++ arithmetic operators

Other fundamental data types Table 2 shows how you would declare and initialise four other data types for use in programs (there are more data types available)

16

Data type Example

Float float aFloat = 1234

Double (the precision of a Float) double aDouble = 123456

Char char aChar = A

Bool bool aBoolean = true

Table 2 - C++ numerical types4

Characters

Characters are normally stored in variables of type char but can also be stored as in t(eger) data types Characters are represented as single byte integers in the computer so it is possible to output a character as an integer or as a character

All characters have a numerical representation in the computer and the ASCII (American Standard Code for Information Interchange) character set shows each character and its decimal equivalent (also note that a combination of characters may be used to form more complex Unicode characters) See appendix 111

Characters can be read in with the following statements

char aChar declares a variable (aChar) of type char

cin gtgt aChar this statement is used to read a character into the variable aChar

Note After entering a character the ltENTERgtkey must be pressed before the character is read by the program

The following four statements correctly declare a variable of type char output a user prompt then read a character and store it in the variable aChar

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar

4 See httpencppreferencecomwcpplanguagetypes for a complete list (or the official ISO standard of course)

17

Header (include) Files

So far weve seen that to use certain functionality we had to include ltiostreamgt We have to do similar to use other functionality which is not part of the code C++ language ie we will need to include anything that comes as part of the standard library

In its current form Visual Studio comes with the following include files (most of which are standard files)

h files (95 C language files)

agentsh agileh ammintrinh amph amprth amprt_exceptionsh amp_graphicsh amp_mathh amp_short_vectorsh armintrh arm_neonh cfguardh collectionh comdefh comdefsph comiph comutilh concrth concrtrmh ConcurrencySalh concurrent_priority_queueh concurrent_queueh concurrent_unordered_maph concurrent_unordered_seth concurrent_vectorh crtdefsh crtversionh delayimph dloadsuph dvech ehh emmintrinh excpth fvech gcrooth immintrinh internal_concurrent_hashh internal_split_ordered_listh intrinh intrin0h invkprxyh iso646h ivech limitsh mm3dnowh mmintrinh nmmintrinh omph pgobootrunh pmmintrinh pplh pplawaith pplcancellation_tokenh pplinterfaceh ppltasksh ppltaskschedulerh pplwinh rtcapih salh setjmph setjmpexh smmintrinh srvh stdargh stdboolh stdexcpth stdinth tmmintrinh typeinfoh use_ansih vadefsh varargsh vcclrh vccorlibh vcruntimeh vcruntime_exceptionh vcruntime_newh vcruntime_new_debugh vcruntime_startuph vcruntime_stringh vcruntime_typeinfoh wmmintrinh xatomich xatomic0h xkeycheckh xlocinfoh xmmintrinh xsmf_controlh xstring_inserth xtgmathh xxamph xxamp_inlh ymathh yvalsh zmmintrinh

115 C++ files

algorithm allocators any array atomic bitset cassert ccomplex cctype cerrno cfenv cfloat chrono cinttypes ciso646 cliext climits clocale cmath CodeAnalysis codecvt complex condition_variable csetjmp csignal cstdalign cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cuchar cvt cwchar cwctype deque exception experimental filesystem forward_list fstream functional future hash_map hash_set initializer_list iomanip ios iosfwd iostream istream iterator limits list locale Manifest

18

map memory msclr mutex new numeric optional ostream queue random ratio regex scoped_allocator set shared_mutex sstream stack stdexcept streambuf string string_view strstream system_error thr thread tuple typeindex typeinfo type_traits unordered_map unordered_set utility valarray variant vector xcomplex xfacet xfunctional xhash xiosbase xlocale xlocbuf xlocinfo xlocmes xlocmon xlocnum xloctime xmemory xmemory0 xstddef xstring xtr1common xtree xutility xxatomic

Strings

Next to numbers strings are the most commonly used data type in programming

A string is both a datatype (string) and also literal character data ie a sequence of characters such as Oxford or StAndrews In C++ string literals are enclosed in quotes The quotes are not part of the string they identify the data type as a string

Actually this isnt quite true the double quoted strings are a sequence of characters and are taken from the C programming language The things declared of the string type are C++ string objects ndash which may be initialised using the C language literal

C++ strings can be declared and initialised in this way

string institution = Oxford

string name = Peet

To use the string type in your programs add the header file include ltstringgt at the top of your program This allows the use of part of the C++ library of classes called the string class (and its member functionsmethods explanations will follow soon)

Of course strings are normally used when requesting an input Consider this code

string aName aDept Two string objects

cout ltlt Enter your full name

cin gtgt aName

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

19

If in answer to the first prompt we were to enter say Fred Brooks 5 the interaction and output of our program would immediately result in this

Enter your full name Fred Brooks

Enter your department Fred is associated with Brooks

Why When reading in a string with a space such as FredltspgtBrooks only the first part Fred is read into aName ndash and the input is said to be space delimited by cin ndash and consists of two separate inputs (so the Brooks parts is read into the aDept string variable)

We could use multiple prompts to read in a name of course but this is inconvenient

To handle this situation we can use the standard getline(cin aName) function to read in a name instead of using cin gtgt aName This reads all key-strokes into aName until the ltENTERgt key is pressed at which point it returns a string containing all of the characters from the input

cout ltlt Enter your full name

getline(cin aName)

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

The string class has many useful functions you can use to manipulate strings An example is the length() member functionmethod

string aName = Fred Brooks

cout ltlt The length of the string aName is ltlt aNamelength() ltlt endl

This statement will output - The length of the str ing aName is 11

See section 12119 for more information on the string class and its member functions

5 Fred Brooks is a real person and a legendary computer scientist httpenwikipediaorgwikiFred_Brooks

20

The LF (Line Feed) Problem and Reading Keys

Continuing on consider the following code

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

string aName

cout ltlt Enter your full name

getline(cin aName)

cout ltlt You entered ltlt aName ltlt endl

system(pause)

The intent here is to first ask for a character and then to use getline() to ask for a name

If only things were that simple

If we were to enter say a Z to satisfy the first prompt the program would immediately output

Enter a character Z

You entered Z

Enter your full name You entered

Press any key to continue

The problem here is that being a keyboard key theltENTERgt key is itself being seen as a valid input so when we enter Z followed by the ltENTERgt key were actually entering two keys ndash Z and the ltENTERgt key The first keys placed into aChar whilst the enter key is left in the keyboards buffer This is quite reasonable if you think about it you entered two keys (Z and ltENTERgt) but provided a home for just one of them in aChar

Ok so whats the problem Well the problem is that we really need to use something like getline() to read text that contains spaces and it just so happens that getline() given this scenario will see the residual ltENTERgt key left in the buffer and it will assume that you didnt enter anything you just hit the enter key

This problem - that of having a mischievous ltENTERgt key waiting to surprise us ndash will occur whenever you read a key from the keyboard using cin Luckily theres an easy fix as we can use another input function to read and then discard the waiting ltENTERgt key Its called cinget() Here is a modified version of the code above that fixes the problem

21

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

cinget() REMOVE THE ENTER KEY discarding the got character

string aName

cout ltlt Enter your full name

getline(cin aName)

Used like this cinget() reads and discards a character from the input stream You can do the same using cinignore() cinget extracts a single character from the stream and returns it cinignore() extracts any number of characters and discards them (the details are specified via passed parameters to the function) or a single character if no arguments to the function are provided

You can easily use cinignore() to ignore a number of characters or until a certain token (character) is met eg the following code reads in a users first and last names and then outputs their initials

22

char first last Two 8-bit characters

cout ltlt Please enter your first name followed by your surname

first = cinget() Get one character

The first parameter is the maximum number of characters to

extract (and ignore) The second parameter is a

delimiting character The function stops extracting characters

as soon as an extracted character matches this one

cinignore(2566 ) Ignore until a space is seen

last = cinget() Get one character

cout ltlt Your initials are ltlt first ltlt last ltlt endl

Casts

On occasions in your programs you may want to store a value in a variable of a different type (when there is a danger of a loss of information the compiler will issue a warning for example when storing a double in an int) If you store a double as an integer you lose information in two ways

any mantissa (fractional part) will be lost

the magnitude of the double being stored may be too large to fit into the integer

Eg it is not possible7 to store 6678 x 10000 as a 16-bit unsigned integer because 667800 is 10000010011011100 in binary (17-bits) and is therefore larger than the maximum storable value of 65535 (1111111111111111) However you can store 1230 as an integer8

When you need to represent a value as a different type you can use the static_cast notation as shown here to change a double to an integer

6 If this is exactly numeric_limitsltstreamsizegtmax() there is no limit As many characters are extracted as needed until delim (or the end-of-file) is found

7 Actually the result of attempting to store 66780 in a 16-bit unsigned integer will be 10011011100 or 1244 Do you see how this value comes about

8 Also see the (demonst rat ion) L imi ts project

23

int anInt

anInt = static_castltintgt(doResult) where dResult is a double

You may also use the following historic classic C-style9 notation to cast to different data types

anInt = (int)dResult

Eg to change an integer to a character

char aChar

aChar = static_castltchargt(bInt) where bInt is an integer

You may also combine this using the

object-constructionfunction-call syntax of C++ eg

double d = 314157

int n = (int)d Convert ds value to an integer

int j = int(d) Ditto

9 C-style casts are usually considered to be too powerful ndash in that they indiscriminately allow unsafe and downright dangerous conversions C++ casts were introduced to solve this problem

24

Other Cast Types

Although outside the scope of this introductory course for reference here is a summary of the cast types in C++ (feel free to skip this for now and come back to it at a later time)

static_castlttypegt(object)

The type parameter must be a data type for which there is a known method for converting object to whether this be a built-in or through a casting function (constructor) All types of conversions that are well-defined and allowed by the compiler are done using static_cast

The static_cast operator may be used for operations such as converting a pointer of a base class to a pointer of a derived class converting numeric data types such as enums to ints or ints to floats However static_cast conversions are not necessarily safe as no run-time type check is done which can cause casting between incompatible data types for example initialised pointers However this is checked at compile time to prevent casting obvious incompatibles Also be aware that a static_cast between pointer of base to pointer of derived may produce an erroneous result (where the actual object pointed to is of type base not derived)

dynamic_castlttypegt(object)

In the C++ programming language the dynamic_cast operator is a part of the run-time type information (RTTI) system that performs a typecast Unlike the static_cast the target of the dynamic_cast must be pointer or reference to class Unlike static_cast and C-style typecast (where a type check is made during compilation) a type safety check is performed at runtime If the types are not compatible an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers)

reinterpret_castlttypegt(object)

Allows any pointer to be converted into any other pointer type Also allows any integral type to be converted into any pointer type and vice versa

The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument (unlike static_cast but like const_cast the reinterpret_cast expression does not compile to any CPU instructions It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type)

You cannot cast away a const or volatile qualification You can explicitly perform the following conversions

const_castlttypegt(object) A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is

25

identical except for the const and volatile qualifiers For pointers and references the result will refer to the original object For pointers to data members the result will refer to the same member as the original (uncast) pointer to data member Depending on the type of the referenced object a write operation through the resulting pointer reference or pointer to data member may produce undefined behaviour

26

Exercise 2 CreatingModifying additional projects

Examine how comments look in a program

Examine the use of some fundamental data types

Using different data types

Using the cast operator

Using the string class

Task 1

Open the skeleton project called EvenI

The project folder is

EvenIEvenI s ln

Modify the projects code in to prompt for two numbers of type double and two numbers of type integer

The program should output the sum the product and the difference of the double numbers Also output the quotient and the fractional part of the two integers10

Youll need something along the lines of hellip

double aDouble double bDouble

etc

To read a number into aDouble you could use

cin gtgt aDouble

Task 2

Modify your EvenI program to read in two characters Enter the characters a and Z

Output the two characters with the character case changed ie a becomes A and Z becomes z

You will need to look online or at in 12120 to establish the ASCII integer values of each character hellip you can alter a characters case by treating it as an integer and

To convert integers (or the results of evaluating integer expressions) to say characters we need to use a cast Eg

int i = 65

cout ltlt static_castltchargt(i + 32)

10 Trivia quotient comes from the Latin quotiens for how many times For example when dividing twenty by three the quotient is six and two thirds You can use a modulus b to get the fractional part

27

then by addingsubtracting tofrom it

Task 3

Open the skeleton project called Address and modify it so that it can be used to collect some user data

Output this collected data to screen as shown in Figure 1

Note that youll have to have include ltstringgt in order to use getline()

Figure 1

Visual Studio builds projects in one of two different modes ndash Debug or Release we will always use the Debug mode (a Release build is normally only used when a product is being beta tested ie late in the cycle)

When using Visual Studio (or most other IDEs for that matter) we normally do not have to concern ourselves with the location of the executable that is built by the program ndash because we normally run it from within Visual Studio itself However and just for your information really the exe for a debug build will always be located in the Debug folder immediately below the projects root folder ie for this project Addressexe is located in the (exercise solut ion) Address Debug folder whilst a version built in Release mode would be in the (exercise solut ion) Address Release folder

Debug builds contain extra diagnostic code that is automatically inserted by the compiler

28

3 Basic Control Flow The programs you have created so far are limited in that they run through a sequence of instructions once and then stop Most computer programs will make decisions and carry out different actions determined by the user input

C++ has three kinds of control structures

Sequence statement - the computer executes the statements one after another All the programs you have written so far use sequence statements

Select ion statements - if ifelse switch

The if selection statement selects an action if a condition is true or skips the action if the condition is false

The ifelse selection statement selects an action if a condition is true or performs a different action if the condition is false

The switch multiple selection statement can be used to perform many different actions based on a character or integer value

Repeti t ion statements - while for do while

The while and for statements perform actions within their bodies zero or more times If the loop condition test is initially false no actions will occur

The dowhile statement will perform the actions in the body at least once (the test ndash as to whether to continue - is at the end)

Selection - ifhellipelse statement

The if selection structure is used to choose among alternative courses of action The structure of the statement is

if(mark gt= 50)

cout ltlt Passed

else

cout ltlt Failed

If the condition (mark gt= 50) is t rue the statement following it is executed cout ltlt Passed

If the condition is false the statement is ignored and control is passed to the else part of the selection and statement following else is then executed cout ltlt Failed

ifelse selection statements can also be nested within other ifelse selection statements

29

Exercise 3 SearchString

Task 4

Open the skeleton project called SearchStr ing

You will need to include ltstringgt at the top of the code to complete this exercise See page 158 for more on the string class functionality

Modify the program to display a string of text to the user

The user should then be prompted to select a word from the sentence and input a replacement word Your program should replace one with the other You will want to See section 12119 on string functionality

The prompting string should be shown both before and after the update

Tips

Given a string s initialised to

string s = C++ at the University of Oxford

string t

int i = sfind(U)

cout ltlt i ltlt endl 11

t = ssubstr(0 i) bit before U in t

t = t + ancient + + ssubstr(i) +

Outputs C++ at the ancient University of Oxford

cout ltlt t ltlt endl

Puzzled Programmers

Using if if else nested ifs switch and the conditional operator -

Task 1

Solving puzzles

Open the I fp project and WITHOUT compilingrunning it determine its output

You will need to consult the operator precedence table in section 1216

You shouldnt compile or run the program to start with ndash the idea here is for you to determine its output on paper11

Tip you might want to consider tidying up the codes layout before attempting to solve it

void out(int n) is a function We havent covered functions yet but it makes sense to use one here and so we have Suffice to say for now that using out(some value) will output the value to the console window

11 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

30

Functions will be explained fully soon

Compile and run the program ndash if your workings from Step 1 differ from the output you should determine where you went wrong

Selection - switch multiple selection statement

The switch multiple selection statement can be used to perform many different actions based only on a single integer value Note however the switch statement can only be applied in narrow circumstances The tests must be constants and be integers Lets compare the two statements

int num switch(num) case 1 cout ltlt num = one

double num switch(num) case 11 cout ltlt num = 11

OK ndash Test is 1 a constant and an integer NOT OK ndash Test is not constant integer

Repetition ndash while dohellipwhile and for loops

The while statement is commonly used to carry out repeated steps perhaps reading in values before doing a calculation on values read in The format of the code is

while(condition)

statement

This can be read as whi le the condition is t rue continue to do the statements until the condition is false

31

The Collatz Conjecture

Win a million dollars

Task 1

Open and complete the project called Col latz (use a while() loop)

Given any positive integer if the number is even divide it by two else treble it and then add one If the result is one stop else repeat the process

The Collatz conjecture says that given any starting value the process above will eventually hal t (goes to one and stops)

Eg setting n to 9 as a starting point successive values would be

28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is not known whether the Collatz conjecture is true Fame and fortune await anyone who can prove it httpenwikipediaorgwikiCollatz_conjecture

A Collatz tree as visualised by Edmund Harriss

32

This image is a sample from the colouring book Visions of the Universe by Alex Bellos and Edmund Harriss

Get your own hi-res version for colouring-in here and see here for an explanation

33

Task 2

Re-implement your code so as to use a for() loop (this will be a lot easier than you might first think)

Not essential for this task but as we mention for loops you might like to look at the for project to see how a for loop can be animated to show how the three sections of it work in order

Mixing loops

Task 1

Open and modify the skeleton project called Factor ial

Modify it to use different repetition statements to calculate and display the factorial of a value entered by the user (they should enter a value between 1 and 10 inclusive)

Example use a while loop to prompt for an input value (between 1 and 10) and a for loop to calculate the factorial result

The output should be like that shown in Figure 2 below

Factorials12

The factorial of 5 (usually written as 5) is

1 x 2 x 3 x 4 x 5 = 120

If factorials are new to you think of them as defining the number of ways to arrange n items

To avoid displaying results in scient i f ic notat ion use

cout ltlt setprecision(0) ltlt fixed

setprecision() requires include ltiomanipgt

12 0 Is defined to be 1

34

Figure 2

PLUSPLUS Recursion

Come back to this after weve covered functions

Note that our solution optionally also uses a function and recursion to find the same factorial If you open it you will see that just after where we perform the output above we have commented out an extra line of code (uncomment and rebuild to see it in action)

We havent covered recursion in this C++ course yet but its basically the process of solving a problem in terms of smaller versions of the same problem Since the problem gets smaller each time the process eventually terminates in a problem (the base case) that can be solved directly When defining a recursive function be sure of three things 1 The problem gets smaller each time 2 Include a solution for the base case And 3 Each case is handled correctly

The recursive function looks like this ndash add then test it in your own solution

Factorial function using recursion

long long int recur_factorial(long long int n)

return n lt 1 1 n recur_factorial(n - 1)

The question mark is the conditional operator and is used with the colon to form the functional equivalent of an if then else

35

If the expression before the is true then the expressionstatement to the left of the is evaluated otherwise the one after the is evaluated Eg these are equivalent

x boo() hoo()

if(x)

boo()

else

hoo()

4 Logical and Bitwise Operators

41 Logical

Quite often we will want to perform some action if two things are true and we can achieve this using nested if statements eg

if(onething == true)

if(secondthing == true)

do something

In C++ we can achieve the same result through the use of the l ogical And operator - ampamp

if(onething == true ampamp secondthing == true)

do something

ampamp is a binary operator ndash meaning that it takes two arguments (nothing to do with base 2) eg Op1 ampamp Op2 The expressions Op1 and Op2 must be capable of evaluating to t rue or false (false in C++ has the value 0 whilst any other value is considered true) and both Op1 and Op2 have to be true in order to have the conditional part execute eg if(x ampamp y) Z = 10 Here both x and y must have non-zero values in order for z to be assigned the value 10 Note again that this is equivalent to

36

if(x)

if(y)

z = 10

The truth table for logical And is as follows ndash note that both Op1 AND Op2 have to be true for the result to be true

Logical And

Op1 Op2 Result

True True True

True False False

False True False

False False False

We also have a Logical Or operator (||) in C++ and its truth table looks like this ndash note that its one OR the other that has to be true in order for the result to be true here

Logical Or

Op1 Op2 Result

True True True

True False True

False True True

False False False

The remaining logical operator we have is the unary Logical Not (the exclamation mark is used for this)

Logical Not

Op1 Result

True False

False True

Logical ampamp and Logical || short-circuit ie for ampamp if the expression on the left-hand side is found to be false then the expression on the right is never evaluated as the whole will evaluate to false (because to be true both sides have to be true and we know that the first one is false at this point)

37

The same is true for logical || in that the right-hand expression is not evaluated if the left is found to be true (the whole will evaluate to true because the left is true so there is no need to evaluate the right-hand expression)

42 Bitwise

PLUSPLUS Base Two and Bits

We also have bitwise versions of the logical operators ndash plus some extra ones Bitwise operators work on a variables individual binary bits ndash rather than the value of all the bits taken as a whole For bitwise And we do not use ampamp but use just a single amp The same is true for bitwise Or we just use a single | and not || Bitwise Not is a little different we use ~ (the tilde) for bitwise Not

The additional bitwise operators we have are for bitwise XOr ndash for which we use the ^ symbol and lastly for left and right bit shifting we use ltlt and gtgt

Bitwise operators work on binary bits (1s and 0s) whereas the logical operators work on values equating to either true or false

For example consider the following code

int w = 10 int x = 42

int y = w amp x

int z = w ampamp x

cout ltlt y ltlt endl

cout ltlt z ltlt endl

The base-2 binary representation of 10 is 001010 and for 42 it is 101010 So w amp x means

001010 101010 amp ------ 001010 ------

Remember And is one and the other

Now let us consider w ampamp x Here were not interested in ws or xs bits just whether when taken together they are zero or something else Here both are non-zero so both are considered to be t rue and if we refer to our truth table from earlier on we will see that the result will be t rue When we assign that to an integer like were doing here the value assigned will be 1

38

Shifts

The shift operators shift the binary bits left or right Bits that do not fit fall off the ends and bits are replaced with zeros when shifting left ie bits do not rotate and come back on the other end again When shifting right the sign-bit may be preserved depending upon whether youre using a signed or unsigned integer

Shifts are useful for all sorts of things but one of the obvious uses is to multiply and divide eg x = 2 x = x ltlt 1 shifts the bits in x one place to the left so given that xs value is 00000010 in binary x = x ltlt 1 turns x into 00000100 which is 4 So x = x ltlt 1 is like saying x = x 2 You can of course divide by right shifting

XOr

The rule for XOr is one or the other but not both ie 1 ^ 0 = 1 (just like 1 | 0) but whereas 1 | 1 = 1 with 1 ^ 1 the answer is 0

Note that we do not have a logical XOr operator in C++ as we can just use = (not equal to) ndash see the (demonstrat ion) Logical XOr project

Practising with Logical and Bitwise operators

You will need to use the Precedence and Associativity table in 1216 to complete these tasks

Task 1

Open the Logical project As earlier DO NOT compilerun this yet

You will need to consult the operator precedence table in section 1216

On paper determine the programs output13

Run the program ndash output as expected

Task 2

Open the Bitwise ndash

unsigned project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Unsigned The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

13 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

39

PLUSPLUS Signs and bits

Task 1

This one is tough as you should really know something about Twos Complement arithmetic to complete this

Open the Bitwise ndash s igned

project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Signed The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

5 Introduction to Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine (which will also be a function) Encapsulat ion is data information or detail hiding If youre mathematically minded you may think of a C++ function as being very similar to one in mathematics ie a mechanism for mapping one thing to another

Once a function is written the detail of how it works is not important It is only necessary to understand what if any inputs the function needs (its parameters) and what output is produced (the functions return value)

The use of functions provides several benefits but the main one is that it makes programs significantly easier to understand and maintain The main program function can consist of a series of function calls rather than hundreds of lines of code A second benefit is that well written functions can be reused across multiple programs

You have to tell the compiler about a function before you use it and this is normally done using a prototype early in the program A function prototype consists of the return type a funct ion name and a parameter l is t - indicating the data the function will receive ndash and is terminated using a semicolon Eg

int someFunc(int int)

This tells the compiler that there is a function (somewhere) called someFunc that takes two integers as its input and returns an integer value for its output

40

Using a prototype is a way of telling the compiler the data types of any return value and of any parameters being passed and enables error checking to be done

The function defini t ion consists of the modified prototype and a function body which is a block of code enclosed in parenthesis which does the work Eg

int someFunc(int a int b)

return a + b

Here we have named the two inputs a and b and we can see that the functions job is to add these two value and to return them As this function returns a value (the sum of a and b) it may be used to expressions like this

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

Arguments can be passed to functions in two ways pass-by-value the default is where a copy of the argument value in the main program is made and then passed to the function The copy in the function only exists in memory as long as the function is active When the code within function has been run to completion the memory is released and the value held there is lost Any changes made to the copy passed to the function do not affect the original variable in any way For example if we altered and used someFunc like this

int someFunc(int a int b)

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 20

41

Note that because we passed a copy of b to the function that the line b = b 2 alters the copy (which then isnt used) and not the original

Arguments can also be passed-by-reference When arguments are passed in this way any changes made to the arguments in the function are reflected by corresponding changes to that data variable in the calling part of the program Pass-by-reference is good for performance reasons because it can eliminate the pass-by-value overhead of copying large amounts of data (In later sections we will examine how pointers can be used to fake pass-by-reference) Eg this will alter b now

int someFunc(int a int amp b) Note the amp

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 40

See section 521 for more on this subject

Creating a function

The format of a function prototype is

return_data_type FunctionName ( argument_l ist )

The function CtoF - void CtoF(int temp) - has no return data type (void) its name is CtoF and it accepts a single input argument called temp of type int (integer)

It is not strictly necessary to give the argument a name (temp) in a function prototype you saw this above in int someFunc(int int) However the argument type must be specified The statement void CtoF(int) is therefore an alternative prototype

The following exercise is an introduction to functions You will learn a lot more about functions in later exercises

42

Writing functions

Task 1

Open the project EvenI you created earlier and change the structure of the program to make use of functions

Solution in (exercise solut ion)

EvenI I

Read two integers in to main() and pass them to a function The prototype is void intCalcs(int int)

intCalcs() function should calculate and display the result of the division and modulus of the two variables passed see Figure 3

Read in two doubles to variables in main() Pass the two doubles and the value of one integer to the second function the prototype is int Calcs(double double int)

Within function Calcs() write statements to produce the output as shown in Figure 3 Most of the code already exists within main()

Return the result of the multiplication of one double and an integer cast this value as an integer

Display the returned value within main() as shown in Figure 3

Figure 3

43

Using a struct

Task 1

Open the project Person

Solution in (exercise solut ion)

Person

As you saw during the presentation we can keep related data together using the struct keyword For example say we define a thing as follows

struct thing

int x

string y

double z

Having done this we can now create as many thing objects as we wish ndash simply by declaring them as we would say an integer

thing a

thing b

Each thing object a and b contains its own x y and z member variables eg

ax = 10 thing as x member set to 10

bx = 20 thing bs x member set to 20

cout ltlt ax ltlt endl outputs 10

cout ltlt bx ltlt endl outputs 20

Complete the exercise by creating and populating a struct Person object Once populated amend the printPerson() function so as to output the persons details

44

PLUSPLUS When Things Go Wrong

Going back to Exercise 8 if you havent tried it already enter zero as your second number What happens

C++ contains mechanisms for catching errors in the form of a trycatch mechanism

cin gtgt y Enter zero

try

intResult = x y

catch(myException amp e)

cout ltlt ewhat() ltlt endl

catch()

cout ltlt Generic oops ltlt endl

Modify your code so as to catch the divide by zero

Hopefully try and catch are fairly self-evident try something and catch any error if something goes wrong

There are two catch blocks here One tries to catch a myException object (we cannot see the definition of this classstruct here) and the other tries to catch anything else that is missed by catch(myException amp e) The amp says that the myException object e is being passed to the catch handler by reference Well learn what this means a little later in section 521

So did you see the Generic oops message appear

Your C++ compiler doesnt have to catch the divide by zero error ndash doing such a thing results in undefined behaviour This is because an arithmetic exception is an OS or processor exception - which is not the same as a C++ exception - hence it cannot be caught by a in a try catch block

To catch errors like this we either need extra support from the compiler14 andor operating system or to write some extra code For example we could do this

14 See also C signal handling httpenwikipediaorgwikiC_signal_handling

45

cin gtgt y Enter zero

if(y gt 0)

intResult = x y

However first we have to realise that this is a possible source of a runtime error and secondly we have to write (correctly) the code to handle the condition

Windows has built-in exception handling ndash called Structured Exception Handl ing (SEH) and we can generate code that uses this in support of the try catch structure used earlier

To enable this we need to tell the compiler to generate code that links into the SEH mechanism

To do this open the Project | ltproject namegt Properties hellip dialog box and in the Code Generation section select Yes wi th SEH Exceptions ( EHa) in the Enable C++

Exceptions line See Figure 4

46

Figure 4

The Monty Hall problem

The Monty Hall problem is a probability puzzle loosely based on the American television game show Lets Make a Deal and named after the shows original host Monty Hall

It goes like this

You are on a game show where you are shown three closed doors You are told that behind one of them is a new car and that behind the other two are goats

Two pieces of essential information at this stage 1 your goal is to win the car 2 the game show host knows what is behind each door

Lets walk through a trial game

The game show hosts asks you to choose a door ndash lets say you choose door number 1 (your door remains closed) The host now opens one of the remaining doors to reveal a goat (as there are two goats they can of course always do this) lets say they open door number 3

47

The situation is now as follows you have chosen door number 1 Only door number 3 is open and it reveals a goat The host now asks you if you would like to switch your door to the only other closed door - door number 2 At this stage you must either stick with door number 1 or switch to door number 2 and at that point the host will open the door youve chosen to reveal your prize

The question is when youre offered the chance should you stick or should you swap - will swapping increase your chance of winning the car or is it just 5050 The claim made here is that by swapping doors you will double your chance of winning the car What does your completed project claim

Task 1

Open and complete the incomplete project MontyHal l

The goal of this project to provide a simulation of problem outlined above

The function

int getRandomDoor(int n = 3)

return rand() n + 1

is used to choose a door number between 1 and 3 (inclusive)

Note that it has a default argument ie if it is called without an argument like this int val = getRandomDoor() the argument n is set to 3 by default and val will be set to a value between 1 and 3 However if it is called like this int val = getRandomDoor(10) then n is set to 10 and val will receive a value in the range of 1 to 10

48

More Functions

Task 1

Open the incomplete project IsLeap

The program asks for a year and determines whether the year is or will be a leap year

You need to complete the function IsLeap(int y) to implement the necessary code

Although the program is incomplete the program contains pseudo code for the algorithm required to compute the answer The pseudo is also show opposite

if year modulo 4 is 0

then

if year modulo 100 is 0

then

if year modulo 400 is 0

then

is_leap_year

else

not_leap_year

else

is_leap_year

else

not_leap_year

Figure 5

49

PLUSPLUS IsLeap in a line

Task 1

Extra points for implementing the IsLeap() function in just a single line of code This could be done using ampamp and || or by using the operator (a short form of if then else)

If you completed this step how readable is your code when compared to the if else version on the right

52 Algorithms

Algorithms

An Aside Big-O notation and Algorithm Complexity feel free to jump over this to Task 1

As programmers we usually implement the various parts of any new program in the simplest and most straight-forward way possible Then later if we find parts of our program are slow (causing what are called hot-spots) we will look again at the code to see if there is a better way to do whatever it is that is taking up the time

As a general rule the most optimal algorithms run in the shortest possible constant t ime ndash such algorithms are often symbolised using O(1) whereas the worst run in quadratic cubic exponential or factorial time (you can think of the O [called Big-Oh] as meaning in the Order of for some input n)

Usually were often happy with those running in O(n) (in the order of n) time ie their running time scales linearly with the number of steps or operations they involve Loops invariably signal O(n) parts of any algorithm

This is best explained using an example

50

Task 1 Understanding Gauss algorithm

Q How would you sum the integers from 1 to n where n is say 100

The obvious way is to use a loop

int tot = 0

for(int i = 1 n = 100 i lt= n ++i)

tot += i

This is fine for small values of n but not so good for very large ones

Interestingly it is said that this self-same problem was once given to a class of children which included one Carl Friedrich Gauss (presumably the teacher wanted to keep his charges occupied for a time) While most of the children started working at the problem (using the loop approach above) Gauss thought about it for a moment and then wrote down the solution 5050

The algorithm Gauss used may be easily demonstrated using the values 1 ndash 10

Gauss realised that if he wrote out the values twice (whether on paper or just in his head) once forward and once in reverse that he could sum each column formed to 11

1 2 3 4 5 6 7 8 9 10

10 9 8 7 6 5 4 3 2 1

1+10 2+9 3+8 4+7 5+6 6+5 7+4 8+3 9+2 10+1

=11 =11 =11 =11 =11 =11 =11 =11 =11 =11

Then sum of 1 ndash 10 is then 11 10 (columns) = 110 2 = 55 (we divided by two because we used each value twice)

Coming back to algorithm runtimes you can see that when using a loop summing 1 ndash 1000 will take ten times longer than summing 1 ndash 100 which will take ten times longer than summing 1 - 10 However by using Gauss approach we can arrive at the answer for any range of values in the same time this is what we mean by a constant time algorithm

51

Task 2

Open the incomplete project SumIntSeries

Complete the project so as to implement Gauss algorithm for any continuous range of integers

The solution project is (exercise solut ion)

SumIntSer ies

The general formula required is

((119948 minus 119947) + 120783)(119947 + 119948)

120784

Or in a more code form

Sum = ((k - j) + 1) (j + k) 2

Where j and k are the starting and ending values in the range respectively (both inclusive)

Functions and Pass by Reference

In the previous section when working with functions all arguments passed to the functions were copies of variable values from main() The arguments were passed by their value

Pass by Value is the default argument passing mechanism for C++ (and the C language)

In pass by value when a function is passed an argument it receives a copy of the value from the calling function (main() in previous examples) This copy remains in scope until the called function has completed and returned at which time the copy is destroyed

Therefore a function that takes value-arguments cannot change a passed variables value because any changes only apply to copies and not to the actual callers variables

An alternate passing scheme is called Pass by Reference

Passing variables to functions by reference is very useful when we need to change or update variable(s) via a function (it is also a faster mechanism than pass by value as no copies have to be made)

Under the covers pass by reference involves passing a memory address and not a copy of the data to the function This is usually more efficient than passing by value because there is no requirement to copy memory However this argument passing mechanism enables a function to modify any argument even if its not supposed to To avoid this we usually declare all read-only parameters as const and pass them by reference

The format of a function prototype when using call by reference is

return-data-type funct ion-name (reference parameter) To indicate a reference parameter an ampersand (amp) is written in the function prototype and header after the parameter type name

The statement void squared(int amp) has no return data type (void) its name is squared and it accepts a reference parameter (amp) of type int (integer)

52

The function definition would be something like this

void squared(int amp inVal)

inVal = inVal inVal inVal

The function call to it would look like this

squared(aValue)

As mentioned above pass by reference is normally used for one of two reasons 1 Because we want to be able to change a passed variable inside a called function 2 Because we want the speed associated with a pass by reference

In 2 we will normally protect our argument by using const in the called function Eg say we want to pass the double argument x to a function f() and take the least possible time about doing it (and given that function f() shouldnt alter x) we would use the following code

void f(const double x)

Use x in some calculation Note that if

x appears on the left hand side of an assignment operator

that it will result in a compilation error

Pass arguments by reference

Task 1

Open the project (demonstrat ion) FunctionRef

Compile and run the program The output should be the same as shown in Figure 6

53

Figure 6

Examine the function prototype

void squared(int amp)

This shows the function squared accepts a reference

parameter of type int The reference parameter is ndash under the covers - the memory address of the argument passed to the function

The function uses this address to both get and set the value stored in variable a (value 21) in main() A reference to this address is passed to the function with the function call squared(a)

Examine the function void squared(int amp x)

Under the covers references to x refer to the address of the variable a in main (that holds the value 21) Ie x and a reference the same piece of memory (the word object was deliberately not used there) So we can think of x and a as two names for the same item

Returning values from functions

In previous programs we have most often produced output (using cout) from within the functions However to be of most use and general utility functions should return resultsinformation rather than output it

Functions may return results in one of two ways 1 via a return value or 2 via arguments ndash either passed as references or via pointer (address)

Non void Functions return a single value ndash if you will they evaluate to this value As such non-void functions may be used in expressions Eg

54

w = x sqrt(y) z

The function sqrt() is replaced with the value of whatever the square root of y happens to be For example if y has the value 4 then to evaluate x sqrt(y) z fully the sqrt() function has to be called ndash where it returns 2 This value is then substituted into the expression for further evaluation ie it becomes w = x 2 z

The second way for functions to return results is via its parameters ndash if they are references or passed via memory addresses Eg

void doubleIt(int amp n)

return n 2 Error The void means doesnt return a value

doubleIt() is a void function ndash so it cannot contain a return statement ndash so it cannot evaluate to anything ndash so it cannot be used in an expression

x = doubleIt(y) error

However the function is still able to return a result (modify something outside of itself is perhaps a better way of putting it)

void doubleIt(int amp n) using amp - a reference

n = n 2

55

doubleIt() cannot (still) be used in an expression but it can change things

int x = 10

doubleIt(x)

cout ltlt x Outputs 20

Why would you use references like this Well references are mainly used for speed (by passing an actual external entity a copy does not have to be made) but they are also useful when multiple values (entities) might best be updated via a single operation (function call)

int x y z

x = y = z = 10

doubleAll(x y z)

void doubleAll(int amp a int amp b int amp c)

a = a 2 b = b 2 c = c 2

Side effects

Going back to w = x sqrt(y) z

Lets replace sqrt() with our own function and cause some havoc

double havoc(double amp d)

++x

d = sqrt(d)

return d

x = 3

w = x havoc(y) z

56

Here the value of y has been changed (yet it is not clear that could happen from the functions call site ndash where it was called from) and so has x Also what value for x will be used in x havoc(y) z Will it be 3 or 4 These sorts of issues are called side-effects

This is one problem (or advantage) with reference arguments ndash and that is that they can cause a change in a variable outside of the function being called

One way to protect against this is to use const references eg

double havoc(const double amp d)

++x

d = sqrt(d) Compilation error here

return d

57

Returning a value from a function

Task 1

Open the TempConver t

project

Run the program The output should be the same as shown in Figure 7

Examine the function prototype

double convert(double temp int mode)

This function prototype has a return type of double When the function is called and calculations are completed a double value is returned to the caller

Examine the function definition The function definition matches the prototype indicating a double and an integer are being passed to the function and a double is being returned

Examine the function body The two statements below convert the temperature input The conversion type required is identified using the user input mode and a switch selection

The statement (temp - 32) 5 9 is used to calculate the temp in Centigrade

The statement 18 temp + 32 is used to calculate the temp in Fahrenheit

Figure 7

58

PLUSPLUS Arithmetic Bases

Task 2

Open compile and run the partially complete Bases project

Note that the project isnt complete

The program uses intrinsic functionality to output values in hexadecimal and octal ndash base 16 and base 8 Both these bases are useful in programming its all to do with binary and the size of a byte

Note that there isnt a bin equivalent to hex and oct and that we have instead written a function called bin1() to convert a value into its binary (base 2) representation

Understanding how bin1() works

bin1 uses the modulus operator () and the right shift operator (gtgt) to work eg 42 in binary is 101010

25 24 23 22 21 20

32 16 8 4 2 1

----------------------

1 0 1 0 1 0

----------------------

1 32 + 0 16 + 1 8 + 0 4 + 1 2 + 0 1 = 42

The function progresses like this

42 2 has remainder zero (false as evaluated in the if) If the if test is true we store a 1 else we store a 0 We then divide 42 by 2 by right shifting it one place ndash but just replace that with n = 42 2 if you prefer We then loop while we have a non-zero value in n to operate on hellip

42 2 = 210 42 2 = 0 if(42 2) = false string value = 0

21 2 = 105 21 2 = 1 if(21 2) = true string value = 1

10 2 = 50 10 2 = 0 if(10 2) = false string value = 0

5 2 = 25 5 2 = 1 if(5 2) = true string value = 1

2 2 = 10 2 2 = 0 if(2 2) = false string value = 0

1 2 = 05 1 2 = 1 if(1 2) = true string value = 1

59

Task 3

The project needs completing specifically it needs the function bin2() writing

We could write such a function as bin1 in a variety of ways and wed like you to write a new function called bin2() that produces the same output as bin1() here

Heres a step by step algorithm for implementing bin2()

Youll use either gtgt or and the bitwise And (amp) operator

Take the functions input (the number to convert) in as a parameter called n To keep it as simple as possible for now you could use plain int types rather than the unsigned long long type we used so the functions signature would look like string bin2(int n)

1 In the function create an integer called i and initialise it to 1

2 Realise that if you left shift the single bit in i (use ltlt or multiply it by 2) it will take on the values 2 4 8 16 32 hellip until it eventually goes to 0 ndash as you shift the bit off of the end

3 Recognise that you could compare your shifting bit with one in the same position in n using bitwise And Ie if((n amp i) == 1) then you know youll need a 1 in your output string for the bit position in n (2 4 8 ) given by is value at this point

4 Build up your result string as you proceed

Change your int n and int i to unsigned long long int and re-run

Try using other integer types ndash signed and unsigned

Lastly examine the solution project in (exercise

solut ion) Bases

60

Figure 8

61

Searching for Sequences

Task 1

Open and modify the incomplete project called called HeadsOrTai ls

When all completed the output should be similar to that shown in

Figure 9

This is the (exercise

solut ion) HeadsOrTai ls project

The programs purpose is to look for a sequence of simulated coin tosses ndash a series consisting of Hs and Ts

The program is complete (as in it runs) but it has some issues At first test it using quite short sequences

The timing information displayed by the application is included simply to demonstrate a timing mechanism that can be used to test the efficiency of the code

The first problem is that the user can currently enter characters other than H or T (h and t are ok as the input is converted to uppercase ndash note the string is passed by reference to toupper() which uses a pointer (which well cover later) to process the string

The second problem is that as it stands the algorithm isnt very optimal if we do not find our pattern we add the result of another coin toss to the current sequence and then re-check the sequence in its entirety

For example if were looking for HHTHH and the generated sequence is currently HTTHHHTTHTHHTTH we will fail to find HHTHH and then proceed to add another coin-toss result at the end ndash HTTHHHTTHTHHTTHH We will then scan this for HHTHH However as we know that we failed to find HHTHH before we added the extra coin-toss re-checking the previously checked sequence is pointless and very time consuming (think how this would (or wouldnt) scale) Your task here is to think of and implement another more optimal approach

62

Figure 9

Task 2

Open the HTTvsHTH project you will find that the project will compile correctly but displays an incorrect result

When completed the program can be used to check how many coin-tosses are required on average to see a particular sequence

Why should that be of interest Because sometimes its rather surprising For example test how many tosses are needed to see say HTH and then HTT

When the program is corrected the output should be as shown in Figure 10

63

Figure 10

PLUSPLUS Optimising Searching for Sequences

Task 1

As it stands the program (yours and ours) encodes a coin toss as a character ndasheither an H or a T Each character is encoded using at least 8-bits and so checking whether a generated sequence is the sequence were looking for means performing a string comparison which is costly in terms of clock-cycles Of course generating and storing the new coin toss also requires the use of these costly string operations

As we have just two tokens as an alternative to generating and storing characters and performing string operations we could encode a sequence as a series of bits For example the sequence HTH could be encoded as 101 in binary (5 in decimal) You can set the corresponding individual bits in an int using the bitwise Or operator | (a vertical bar) eg int n = 0 n = n | i which youd most likely do as a result of scanning the users entered search-sequence string a character at a time In this way you could encode the sequence HTHHTHHTHHTHHTHH in a single sixteen bit unsigned int

Additional operators needed to implement sequence checking and H or T bit manipulation are bitwise And (amp) and the left shift operator (ltlt)

You will find more information on some of these operators just a little below

64

Evolving Searching for Sequences

Task 1

Looking for sequences in stringssequences is an interesting and complex problem in computing and also in genetics where the string being searched could be a DNA sequence and pattern could represent a gene perhaps with a snip (a modificationmutation)

Modify your HeadsOrTai ls program (or our solution) so that instead of Hs and Ts it generates and searches for Gs As Ts and Cs instead

Randomly generate a GCTA sequence and a similar pattern to find within the sequence

How much more time and variation is required in this slightly more complex situation

Conduct a few experiments and using Excel graph your results (copy and paste some data highlight it and then select Excels line graph ndash Excel should then automatically plot your data)

Extrapolate The human genome is how long A gene might contain how many bases How difficult is the task of finding interesting sequences in the human genome How about checking for the odd mutation (insertion transposition deletion) ndash fuzzy matching

A solution for this problem can be found in the (demonstrat ion) GATTACA project

6 Classes and Objects In the previous section we have been working with simple programs that display messages to the user store data input as different data types manipulate the data in some way and output the results to screen

We will now start to look at C++ objects and classes

In the real world there are objects everywhere students staff cars birds houses and many more All objects have at tr ibutes these are similar to the variables created in previous tasks Some attributes of a student may be height weight race course of study etc All objects exhibit behaviours or operations cars accelerate and decelerate students matriculate enrol on courses and leave university

65

Now what is the relationship between a class and an object A good analogy would be from an architects blueprint for a house it would be possible to build many houses Similarly from a class in C++ it would be possible to build many objects

If we had a student class we could create many objects from the student class to represent the many students enrolling Each of these objects would be uniquely identified They would share common attributes and exhibit common behaviours If we wanted an object to perform some task we would call the appropriate member function allowing an operationaction to take place changing the behaviour of that object

Member functions are different from the functions you have created so far Member functions are always associated with objects and are usually called or invoked using a dot notation object member funct ionname() An example is student1getName() The object instance is student1 and the member function is getName()

Member functions contain the detail of how the technical aspects of some operation will be processed When member functions are invoked these technical issues are hidden from the end user When the member function is asked to do some operation a message is sent (a member-function call) telling the member function of that object to perform the operation detailed in the function

Functions are not completely new we have had a brief introduction and you have already created some of your own Note also that main() is a function that is called automatically when you run your program However it is not a member function as there is no object associated with it

Creating your first class

Creating a class

Task 1

Open the project called StudentUG

Compile and run the program It should look like Figure 11

66

Figure 11

Before you can create the object myName it is necessary to define the class from which the object will be created The class definition is shown below

class StudentUG Start of class definition

public

void displayName() Start of member function

cout ltlt My name is Michael Cain ltlt endl

Note a semicolon is required at the end of the class definition

Within main() the statement StudentUG myName creates the object myName of class StudentUG In effect StudentUG is a new type

The statement myNamedisplayName() is used to call the member function displayName() of object myName

As we have seen previously the function main() is called automatically when our programs are executed However member functions (displayname() is one we could have many) must be called in this way objectInstanceNamefunctionName() when dealing with an

67

object directly and like this objectInstanceName-gtfunctionName() if working through a pointer to an object (more on pointers later)

The member function displayName() is preceded by the word void All functions can return values this one does not The word void preceding the function name indicates nothing is being returned If this function returned an integer the definition would be int displayName()

When you use functions it is common to pass data (called parameters) to the function The function then manipulates the data before displaying an output andor returning a value

To pass a parameter to the function in the studentUG class the calling statement in main() would be

myNamedisplayName(name) where name is a string (a series of characters) that contains a value read in from the keyboard

In order for the function displayName() to recognise the parameter being passed the function declaration is changed to include the parameter (name) and type (string) as shown in below

void displayName(string name)

cout ltlt My name is ltlt name ltlt endl

Figure 12

Member functions and Passing parameters

Passing parameters

Task 1

Modify StudentUG to read in a student name The name should be passed to a member function The parameter should be output from within the function to welcome the user to C++ programming

68

Task 2

Modify the program in the above task to read in two more names Each name will be for a different student and you will need to create additional objects (instances) of the class

Data Members

In most of the programs written so far the variables have been declared inside the main() function Variables declared inside a function are local to that function and cannot be accessed from outside that function

You have created a student class and it would be reasonable to assume that a student would be following a particular course So courseName might be one of several attributes of a StudentUG object Attributes are represented as variables in a class defini t ion These variables are called data members and must be declared inside a class definition When you create an object of a StudentUG class each object has a unique memory location for its data members

Figure 13 shows data member name declared in the class definition The access specifier private means that only member functions of the class in which the attribute was declared can use this data member

private string name

Figure 13

When data members are declared as private the data is hidden This is called encapsulat ion and means the attributes of the object are hidden and can only be accessed via member functions

As there is no direct way to change a data member you will also need to create a member

funct ion to set the data member to a value and create a second member funct ion to output the value held there

Data members can also be declared public A data member that is declared public can be accessed from any (non-member) function

A protected data member can only be accessed by member functions of its own class and by member functions of classes derived from this class We will learn more about derived classes and inheritance later

69

Using data members

Task 1

Open the project called StudentCoursesln

Compile and run the program it should look like Figure 14

Figure 14

Task 2

Examine the member function getCourse() shown in Figure 15

string getCourse()

return course

Figure 15

Task 3

Modify the StudentCourse source file to enable the user to add a student name enrolment date and number of years of course Once entered this data should be output to screen You will need to create additional data members and member funct ions to achieve this

70

More Objects

Task 1

So far you have created one StudentCourse object It is about time we had a second student on the course Create a second object of the class StudentCourse You will need to add the second statement shown in Figure 16 to add the new object student2 Call the member functions passing parameters as necessary

Figure 16

Constructors

When you create objects from the StudentCourse class it is necessary to give initial values to all the data members If we were entering data for five people and they were all following the same course of study it would make sense to initialise the course data member (it is possible to initialise some or all of the data members) when each object is created

A constructor is a special kind of function that must have the same name as the class Constructors are normally defined to be publ ic and never have a return type They can be used to automatically initialise data members

In previous programs you have written a defaul t constructor has been provided by the compiler However it is not possible to pass parameters to a default constructor function so the data members in the programs created so far have not been automatically

71

initialised To initialise these data members you created member functions that assigned values to data members

Although a default constructor is provided at compilation time it is a good idea to create your own so that the data members can be initialised

It is worth noting here that functions (constructors are functions) can be over loaded This means it is possible to have more than one function with the same name Note that overloaded functions (functions with the same name) must have different types of or number of arguments

Constructors (functions) can also be overloaded with more than one function with the same name but different types or number of parameters Fortunately for us the compiler automatically calls the correct function whose parameters match the arguments used in the function call

Using constructors

Task 1

Open the project called Constructorss ln

Compile and run the program it should look like Figure 17

Figure 17

72

Task 2

In the constructor shown in Figure 18 what is the purpose behind course = Note that as the string parameter name has the same name as the class variable that we use the hidden this pointer to access the class variable in the assignment If we didnt do this and simply used name = name instead then all we would be doing is assigning the value in the parameter back to the parameter

StudentCourse(string name)

this -gt name = name

course =

Figure 18

Task 3

Create a third constructor that will take an argument enrolment_date

Add a third object call it student3

Write code that will test this additional constructor

Solution in (exercise

solut ion) Constructors

If time allows add other useful properties (data members) access methods (functions) and constructors

Separating use from declaration and definition

C++ is all about objects and any decent project will usually make use of a number of application or domain specific classes

To keeps things maintainable and to promote code reuse C++ projects usually contain a number of cpp and h files where each h files will usually contain a declaration of a class (sometimes called an interface) Note though that the definition of the class (sometimes called the implementation) ndash the code that implements it ndash will be absent from the h file and will instead reside in an accompanying cpp file

Aside from allowing different teams to more easily work on separate parts of the program one of the main reasons for separating definition from declaration is to enforce abstraction which is a programming (and design) technique that relies on the separation of declaration and implementation For example lets say that your team needs a class that acts a bit like a stack (a last-in first-out or LIFO structure) and as this is required

73

urgently you decide to implement it using a simple array You would then only want to give your team what is absolutely necessary to use this class a single h file for your team members to include in their cpp files If they look in the h file they will only see information on how to use the class but how it does what it does is kept elsewhere in the cpp and that youve withheld Consumers shouldnt need to know how a thing works in order to use it

An obvious advantage to this is that there is no danger in you changing how it works Perhaps you later decide to use a vector instead of the array You go ahead and alter the implementation and your team members are none the wiser ndash after all the interface hasnt altered just the implementation

So how does the project get built Of course the implementation of this class will be required at compile time and you can either do that by including the cpp file directly (which will give away the implementation details of course) or by including it as object code ie compiled C++ code (binary machine code) This is how valuable commercial source code is kept in-house while the binary implementation complete with a h file is provided to customers (you will see an example of this just below in Using external

l ibrar ies and thi rd par ty header f i les )

Any discussion on separating use from declaration and definition should include something on namespaces You introduce a namespace by simply using the keyword and braces Anything entered inside these braces is inside the namespace eg

namespace securityModule class Encryptor using namespace std using namespace securityModule int main() Encryptor e Without the using we would have had to use securityModuleEncryptor e securityModuleEncryptor e2

See the (demonstrat ion) Namespaces project for more on this

74

Separating declaration and definition

Using a header and source file to separate class declaration from definition

Task 1

Open and modify the partially complete skeleton project called Precis ionTimers

Like HeadsOrTai ls this project makes use of the Windows operating system to very precisely measure elapsed time However unlike HeadsOrTai ls we have separated the stopWatch class interface from its implementation

As weve previously mentioned Gauss and algorithm efficiency we could test our theory that summing in a loop is O(n) ie that the time taken scales with n

Examine the project files hrTimercpp and hrTimerh noting that the h file contains just enough information for someone to use the declared class stopWatch whilst htTimercpp contains the implementation of the class

Now look in PrecisionTimerscpp You will see that an instance of the stopWatch class is declared Also note that we include hrTimerh but make no reference to hrTimercpp

As it stands the code calls two functions to calculate the sum of a range of integers sumGauss() and sumLoop() The program outputs the clock-ticks used and time taken in seconds

Note that sumLoop() is incomplete

Complete the sumLoop() function and then choosing suitable values for the ranges upper-bound carry out a few experiments to test if the loop is really O(n)

What is this used to do in hrTimerh15

ifndef HRTIMER

define HRTIMER

endif

15 You should also see pragma once as this is rapidly becoming the alternate way to do this ndash whatever this is of course

75

PLUSPLUS Providing object code only

Task 2

We have provided a separate demonstration project that takes the discussion on this one step further (demonstrat ion)

Separat ingThings

In its current form the project wont compile To compile the project in the Solution Explorer add the existing carcpp file to the source files list that just contains SeparatingThingscpp and recompile carcpp is in the same folder as SeparatingThingscpp

Once youve done that right-click on carcpp in the Solution Explorer and select Remove Very importantly when youre prompted for confirmation choose Remove do not choose Delete Now recompile once more youll see that the project fails to compile as the definition of car has been removed

76

But hold on we created carobj - the compiled object-code version of carcpp during our previous compilation so we could tell the linker about that and all should be well (this more or less duplicates the scene whereby you do not provide source code but provide only object code)

The carobj file will be located somewhere like

CUsersDesktopCourse(demonstration) Separating Things(demonstration) Separating Thingsbincarobj

To add this to your project go to Project | Properties | Configuration Properties | Linker | Input

77

In the right-hand window select Additional Dependencies drop down the list and select ltEdit gt

In the dialog that appears add the full path to carobj (see earlier in Step 2) and press Ok

Lastly recompile the code once more It should compile and run At this point you could if you wanted to delete carcpp altogether

One last thing

If you look in the comments in SeparatingThingscpp you will find a discussion that goes into the advanced topic of hiding things even further This includes a brief discussion of the the so called pimpl pattern (pronounced Pimple this stands for Pointer to Implementation16)

16 httpenwikipediaorgwikiOpaque_pointer

78

PLUSPLUS Using external libraries and third party

header files

Task 3

Open and modify the project called Lot to

Examine the projects comments to understand the programs function Run the program ndash does it work

It is supposed to compute the odds of winning the UKs lottery httpwwwnational-lotterycouk (try as we might we couldnt find the odds on their own website)

The program uses the recursive factorial function used earlier in the course (with bigint being typedef ed as unsigned long long int)

Factorial function using recursion

bigint recur_factorial(bigint n)

return n lt 1 1 n recur_factorial(n - 1)

There is a problem here however in that to compute the odds we must compute some significant factorials ie

49 = 608281864034267560872252163321295376887552831379210240000000000

and

6 (49 - 6) = 43498989405629161658895695089330078205230448640000000000

Sadly our bigint (unsigned long long) can hold a maximum value of 2^64 ndash 1 = 18446744073709551615 ie not hardly big enough

Fortunately in C++ we can define new types like an arbitrarily sized integer (outside of the scope of this course but see the (demonstrat ion) newINT project for a small taste) However this is object orientation ndash surely we can just use an existing already defined arbitrarily sized integer class

79

Task 4

The good news is that in this class you can You can use LEDA (The L ibrary of

Eff ic ient Data types and Algor i thms ) a professional class library of advanced numerical functionality

You will need to download the program called

LEDA-63 i386 msc 10 ( NET 2010) 32 bi t

or

LEDA-63 i386 msc 10 ( NET 2010) 64 bi t

Go to wwwalgorithmic-solutionsinfofreeindexphp Accept the licence terms and download the appropriate version (usually the 64 bit version)

The LEDA installation program will install additional numerical libraries and header files from the Algorithmic Solutions company

Once the setup is complete modify the Lotto program

In the Solut ion Explorer right-click on your project (Lot to ) and left-click on Proper t ies A dialog-box appears

Under the CC++ section

1 Click on General Choose Addi t ional include di rec tor ies and enter the directory CAlgor i thmic Solut ions LEDA-63- free-win-msc10-

s td incl

2 Click on Preprocessor and add LEDA_DLL to the end of Preprocessor

Defini t ions Note the semicolon is required

3 Click on Code Generat ion and check that Runtime Library is set to Mult i - threaded Debug DLL ( MDd)

Under the Linker section

4 Click on General

5 Choose Addi t ional l ibrary di rector ies and enter the directory CAlgor i thmic Solut ionsLEDA-63- free-win-msc10-s td

6 Click on Input and add l ibGeoW_mdd_dl l l ib leda_mddl ib to the end of Addi t ional Dependencies Again the semicolon is significant

You may now close Properties dialog-box

7 Modify your code Add the following under include ltiostreamgt

include ltLEDAnumbersintegerhgt using ledainteger using namespace std

80

Then modify the recur_factorial() function so that it accepts and returns a type called simply integer rather than bigint

Save the project and exit Visual Studio

In order to build and execute Lottoexe Windows needs to have l eda_mdddl l in its search path for DLLs Therefore we need to add the path to the folder containing leda_mdddll to the PATH environment variable

8 In Windows Explorer navigate to My Computer then right-click on it and select Propert ies

9 Click on the Advanced tab and then on the Environment Var iables button

10 In the bottom section (System var iables ) of the dialog box highlight Path and then click the Edi t button

At the end of the existing path add -

11 CAlgor i thmic Solut ions LEDA-63- free-win-msc10-s td

Once more note the leading semicolon is significant

81

12 Restart Visual Studio and re-open Lot to Build and run the application as normal

It might seem that this was a lot of work for such an apparently trivial result but the fact is that you now have access to (and have seen how to use) an advanced numerical library of functionality And anyway when all is said and done you must admit that at least you got a return here ndash which is more than you should reasonably expect from the lottery

Figure 19

Task 5

Explore the LEDA samples and documentation ndash if you installed it there should be a shortcut in your start menu to LEDA-63-free-win-msc10-s td

Task 6

Modify the Lotto program to see how the odds change when there are more balls andor when more balls need to be matched (you might also display more of the intermediate results of calculations ndash like 49)

Destructors

Both constructors and destructors are special class methods We have seen how a constructor is called whenever an object is defined

A destructor has the class name prefixed by a tilde ~ Like constructors destructors cannot return values and therefore they have no return type specified but unlike constructors destructors have no arguments and thus cannot be overloaded

An objects destructor is called whenever an object goes out of scope The purpose of the destructor is to clean up eg to free any dynamically allocated memory that the object was using and release other system resources such as files and database connections etc

In the examples used so far no destructor has been provided for any class created In these programs it has been unnecessary If the programmer does not explicitly provide a

82

destructor the compiler will create an empty destructor in the same way that an empty constructor is created if one is not explicitly created

When classes are created any objects instantiated from them that contain dynamically allocated memory will need destructor methods added to implicitly free any dynamically allocated memory when the object goes out of scope

In the class example shown below the destructor function is ~StudentCourse()

~StudentCourse()

cout ltlt Im being destroyed

7 Arrays vectors lists and hash-tables Arrays vectors and lists are all types of data structures Data structures are areas of memory where collections of the same data type are held The main difference between arrays vectors and lists is that arrays stay the same size throughout the program execution whereas vectors and lists can grow automatically

Arrays consist of a series of elements (variables) all of the same type placed consecutively in memory Each of the elements can be individually referenced by adding an index to the arrays name We saw this type of notation earlier when using arrays

Eg

int examMarks[10]

This declares an array of ten scores score 1 is accessed via an index of zero ndash examMarks[0] and score 10 is access through an index of nine ndash examMarks[9] Very important note that indexes start at zero

The advantage of using arrays compared to using discrete variables (the way we have stored values so far) is it is possible to store any number of values of the same type in an array using the same identifier

With arrays it is possible to store 100 student exam marks or 100 student names with using one unique identifier

Vectors and lists are container classes which were originally part of the Standard

Template Library (STL) The STL evolved into C++ Standard Library ndash which includes iostream etc This is the general-purpose C++ library of functions algorithms and data structures that we can use in our programs While some aspects of the library are very complex it can often be applied in a very straightforward way that allows reuse of sophisticated data structures and algorithms

There are many container classes in the library ndash note that C++ now also provides such a class for the more primitive array

ltarraygt

New in C++11 and TR1 (Technical Report One)

83

A container for a fixed sized array

ltbitsetgt

A bit array

ltdequegt

A double-ended queue

ltforward_listgt

New in C++11 and TR1 A singly linked list

ltlistgt

A doubly linked list

ltmapgt

Sorted associative array and multi-map

ltqueuegt

A single-ended queue

ltsetgt

Sorted associative containers or sets

ltstackgt

A stack

ltunordered_mapgt

New in C++11 and TR1 Hash tables

ltunordered_setgt

An unordered_set unordered_multiset

ltvectorgt

A dynamic array

As with an array vector and l is t can hold objects of various types However unlike arrays vectors and lists can resize shrink and grow as elements are added or removed

The standard library provides access via iterators or subscripting Iterators are classes that are abstractions of pointers (more on pointers later) They provide access to container classes using pointer-like syntax and have other useful methods as well

The use of vectors lists and iterators is preferred to arrays and pointers By using containers common problems involving accessing past the bounds of an array are avoided Additionally the C++ standard library includes generic algorithms (an algorithm is a set of instructions on how to perform a task) that can be applied to vectors lists and other container classes

Declaring and using arrays

Arrays are declared indicating the type and number of elements in the following way

type ar rayName[arraySize]

84

Examples are

int inNumbers[20] an array called i nNumbers of 20 in tegers

char inName [20] an array called i nName of 20 characters

float ExamMarks[5] = 0 an array called ExamMarks of 5 floats with all elements explicitly initialised to zero

const int size = 5 declaring a constant variable size

float ExamMarks[size] When the constant variable size is applied to the array declaration the number of elements is set to 5 This cannot be changed during runtime of the program However it is handy when the number of array elements needs to be changed Changing the constant value size changes the number of elements wherever the ExamMarks array is used in the program

int numArray [2][3] is a multidimensional array with 2 rows and 3 columns

Note Arrays have been used in C++ for many years and there will be code you work with that was written before vectors became available Vectors are are usually preferred to using arrays and pointers Common problems involving accessing past the bounds of an array are avoided when using vectors

Creating an array to hold exam results

Task 1

Open the project Array s ln

Compile and run the program

Run the program adding five exam results The output should be similar to Figure 20

Figure 20

85

Examine the following statements

double ExamMarks[5] = 0 This statement declares the array setting its size to 5 elements and explicitly initialising all elements to zero

cout ltlt Enter Exam Mark ltlt i + 1 ltlt This statement prompts the user to enter an Exam mark into the array at element i + 1

Using the notation i + 1 indicates to the user to enter Exam Mark 1 not exam mark 0 which would be less intuitive

Array elements are numbered from 0 to n - 1 So an array that holds 20 integers will be addressed from element 0 to 19

ExamMarks[0] -ExamMarks[19]

The first number will be entered into element [0 ] The last into element [19]

cin gtgt ExamMarks[i]

This statement reads in the user input and stores the values in the array elements of ExamMarks[i] i is incremented within the for loop and starts at 0

Task 2

As it stands the program could be generally improved ndash see the notes in the code and consider how you might make such improvements

Next modify the program to output the highest and lowest marks entered

Task 3

Modify the program so that the number of marks may be easily changed (at compile time)

86

Task 4

Modify the program so as to break out the part that calculates the average and put it into a separate function

Write another function that given an array of this sort returns the mode mean and median values ndash you will need to pass in references as the function will need to return three values

Lastly put your two new functions into a separate cpp (you will also have to create a h file for Arraycpp to use ndash this will contain the new functions prototypes)

87

Searching Arrays with Linear Search

Linear search allows the user to search the array and establish whether the array contains a value that matches a search criteria defined by the user

The search compares each element of the array with the user input The array is not sorted and this method of searching works well for small arrays For large arrays linear searching is inefficient and it is necessary to use other forms of array searching after the array has been sorted

Linear Search

Task 1

Open the project LinearSearch

Compile and run the program - choose a number between 1 and 100 The output should be similar to Figure 21

Figure 21

88

Examine the following statements

myArray[i] = (1 + rand() 100) This statement uses the rand function part of the ltstdlibhgt header file (included via iostream being included) 1 + rand() 100 produces integers in the range 0 to 99

The function l inearSearch takes three arguments The array name the size of the array the third argument is the search value

if(theArray[j] == value)

return j

This selection statement compares each element to the search value If the search value is in the array the element number is returned to main() otherwise -1 is returned

The if selection statement if(containingElement = -1) in main() is used select the output indicating a successful or unsuccessful search

Task 2

Currently the program searches for the first occurrence the search value only

Modify the program so that it outputs al l matching element locations

This function can be used for turning an int value into a string See also the comment below about C++11s to_string() functions

string convertInt(int number)

stringstream ss

ss ltlt number

return ssstr()

Youll need to include ltsstreamgt to use the stringstream class

89

Task 3

Modify the program so that repeated searches may be carried out

See Figure 22

If using C++11 or later you can also use the to_string() helper functions of the string class eg to_string(10) yields 10

Figure 22

PLUSPLUS Debugging Linear Search

Task 1

For debugging purposes modify the program so as to output the contents of the array

Open and run (exercise solution) LinearSearch to see what this might look like You might want to use the modulus operator () to work out when to neatly break a line

You may or may not like to have the program generate varying sets of random numbers To facilitate this youll need to seed the random number generator by inserting a line of code like this

srand((unsigned)time(NULL))

Note the use of the cast

To use srand() include timeh at the top of your program

90

Sorting Arrays with Insertion Sort

When working with large quantities of data in an array you will need to sort the data at some point This makes searching for information quicker and there are many algorithms available that can be used In the following exercise you will learn how to sort numbers stored in an array in ascending order

SortingSearching an array

Task 1

Open the project Sorts

Run the program and examine the code

The program currently uses a class (sorts) which is defined in sortsh to implement one popular sorting algorithm called Inser t ion Sor t

For details on this algorithm see

httpenwikipediaorgwikiInsertion_sort

91

Task 2

Add a new sort to the sorts class

The text file quicksor t txt (in the Sorts folder) contains the C++ code required to implement another popular sorting algorithm called Quicksor t17

For details on this algorithm see

httpenwikipediaorgwikiQuicksort

Add the quicksort code found in quicksor t tx t to the sorts class - considering what parts of it need to be publicprivate

quicksort tx t is in the same folder as the Sortss ln project file

Step 2

Test the quicksort implementation on a range of values

Alter the quicksort implementation so as to have it sort in descending order

Following on from Step 3 parameterise the quickSort() function so as to add an option to have the array sorted in either ascending or descending order

17 Invented by C A R Hoare ndash Sir Tony Hoare with Christopher Strachey the most distinguished computer scientists Oxfords ever produced

92

Figure 23

93

PLUSPLUS Binary Search (Binary Chop)

Task 1

Now that the array is sorted we can implement a very efficient searching algorithm usually called either binary search or binary chop search

See Figure 24

Modify your project to allow the sorted array to be searched for a value using the binary chop algorithm See opposite

The algorithm for binary chop is quite straight forward

1 Look at the value of the middle element of the array If the value = target then youre done

2 If the value is lt than target discard the lower half of the array treating the upper half as though it were the complete array

If the value found is gt than target you obviously want to look in the lower half

3 Repeat step 1 until the item is found or else the index value becomes invalid

Pseudo code for this algorithm is here

first integer = 0

mid integer = 0

last integer = NumberOfItems

while first ltgt last

begin

mid = first + last 2

if List[mid] = target

exit while Found item

If List[mid]gt target

last = mid In the first half

else

first = mid + 1 In the last half

end

found boolean = List[mid] = target

94

Figure 24

Multidimensional Arrays

Multidimensional arrays with two dimensions (arrays can have more than two dimensions) may be thought of as consisting of data arranged in rows and columns see Table 3

Each element in the array is identified by using two subscripts as shown in Table 3 The first subscript identifies the element row and the second identifies the element column a[0] [1] identifies a value in Row 0 Column 1

The array in Table 3 contains two rows and three columns and can be called a 2 by 3 array

Column 0 Column 1 Column 2

Row 0 a[0] [0] a[0] [1] a[0] [2]

Row 1 a[1] [0] a[1] [1] a[1] [2]

Table 3 ndash Array Layout

A multidimensional (2 by 3) array of doubles is shown in Table 4

Column 0 Column 1 Column 2

Row 0 2367 6792 8557

Row 1 1276 9132 2789

Table 4 ndash Array Values

95

Creating a multidimensional array

Task 1

Open the Mult iDimArray

project

Compile and run the program adding 2 exam results for each of the two students The output should be similar to Figure 25

Figure 25

96

Task 2

Examine the code used to write values to and read from a multidimensional array

Examine the following code segments

double ExamMarks[2][2] = 0 This statement creates a two-dimensional array having two rows and two columns and initialises the elements to 0

Every element in the array is identified by an element name in the form a[x] [y] where a is the name of the array and x and y are the subscripts that uniquely identify each element in a Notice that the names of the elements in row 0 all have a first subscript of 0 see Table 5 The names of the elements in column 1 all have a second subscript of 1

Note multidimensional arrays can have two or more dimensions (subscripts) Three-dimensional arrays are uncommon

Column 0 Column 1

Row 0

a[0] [0] a[0] [1]

Row 1

a[1] [0] a[1] [1]

Table 5 ndash Array Indexing

97

Examine the following code segment used to read values in to the array

for(int row = 0 row lt 2 ++row)

for(int col = 0 col lt 2 ++col)

cout ltlt Enter Exam Mark No

ltlt col + 1

ltlt for student No

ltlt row + 1 ltlt

cin gtgt ExamMarks[row][col]

cout ltlt endl

The two for loops work taking one row at a time (the outer for loop) and looping through the columns in that row (the inner for loop) When the marks have been entered for all the columns in row 0 row 1 is selected and values entered for each column cell in row 1

Table 6 shows how four results would be allocated in a 2 x 2 multidimensional array

Exam mark 1 Exam mark 2

Student 1 67 71

Student 2 61 58

Table 6 ndash Populated Array

98

Examine the following code segment used to calculate the total of each students marks

if(row == 0)

r1total += ExamMarks[row][col]

else

r2total += ExamMarks[row][col]

r1total is a variable to hold the sum of values in column 0 and 1 for row 0 (Stud1) r2total sums the values in the columns for row 1 (Stud 2)

Selection for each row is made with if(row == 0) this is Stud1 If row is not 0 then row must be 1 and the mark can be added to r2total If three exam marks were input per student the code for selecting the marks would need to change

Task 3

Modify the program to read in four exam marks for f ive students

Establish the highest and average mark for each student Output the results

One way to do this is to keep a separate array to record the students statistics An alternative would be to extend the existing arrays row so that it may hold the necessary student data

99

Declaring and using vectors

Vectors are declared indicating the type and number of elements in the following way

vectorlttypegtvectorName

vectorlttypegtvectorName(initialSize)

vectorlttypegtvectorName(initialSize elementValues)

Examples

A vector called i nNumbers with no initial size to hold doubles

vectorltdoublegt inNumbers

A vector called Name with an initial size 20 to hold characters

vectorltchargt Name(20)

A vector called ExamMarks holding integers with initial size of 4 elements each with the value 6

vectorltintgt ExamMarks(46)

Note In previous exercises you have created your own member functions In the following exercises you will use some of the vector class member functions Some of these are begin() end() erase() and size() See section 12115 for more detail

The standard library also includes a large collection of algor i thms that manipulate the data stored in containers (vectors are one of several types of container)

You can sort the order of elements in a vector (vec) for example by using the sort algorithm

sort(vecbegin() vecend()) C++11 sort(begin(vec) end(vec))

You can find a value (69) in a vector by using the find algorithm

ptr = find(vecbegin() vecend() 69) See C++ note above

100

ptr is an iterator to store the memory location of the element found

You can reverse the order of elements in a vector for example by using the reverse algorithm

reverse(vecbegin() vecend()) See C++ note above

There are two important points to notice about the call to reverse First it is a global

function (as are find and sort) not a member function Second it takes two arguments rather than one and operates on a range of elements rather than on the container (vector container in this case)

With the above examples the range is the entire container from begin() to end() (vecbegin() to vecend()) reverse like the other standard algorithms is decoupled from the libraries container classes The reverse algorithm can be used to reverse elements in vectors in lists (another container) and even elements in C arrays

int myArray[] = 1 6 20 4

reverse(myArray myArray + 4)

for(int i = 0 i lt 4 ++i) Lets see the reversed array

cout ltlt Array[ ltlt i ltlt ] = ltlt myArray[i]

In the above example the first argument to reverse is a pointer (pointers are covered in Section 8 but for now we can say the first argument points to the address in memory that is the start of the vector ) to the beginning of the range and the second argument points one element past the end of the range This range is denoted (myArray myArray + 4)

Arguments to reverse are i terators which are a generalization of pointers which is why it is possible to reverse the elements of a C array using the array address and pointer notation

Creating a vector to hold exam results

Task 1

Open the Vector project

Compile and run the program adding five exam results The output should be similar to Figure 26

101

Figure 26

Examine the following statements

include ltvectorgt This statement includes the header file vector enabling the program to use the class template vector (templates allow the use of generic functions that admit any data type as parameters and return a value more on this later)

vectorltdoublegt ExamMarks(5) This statement declares the vector to hold doubles and sets the initial size to 5 elements

Note Although vectors can grow to any size it is good practice and more efficient to specify the size when this is known When no size is given and the contiguous memory spaces have been exhausted the elements must be copied to a larger memory space to increase the size of the vector

cin gtgt ExamMarks[i] This statement reads in the user input and stores the values in the vector slot i of ExamMarks[i] i is incremented within the for loop Note that we the same indexingsubscripting syntax as we used previously with arrays ie[ ]

102

Task 2

Modify the code so as to accommodate the adding of an extra exam mark

Note this should not be done (simply) as part of the loop but as a separate action later and you should use the vectors push_back() method to facilitate this

push_back() is a member function of the vector class that adds an additional vector element at the end

After adding the extra mark you will need to generate a new set of statistics ie the average will have changed now To do this separate out the statistical code and place it in a separate function so that you may re-use later (after the new data has been entered)

size() is a member function (method) of the vector class It can be used to establish the size of a vector

The statement for(int i = 0 i lt ExamMarkssize() i++) uses the vector member function size() available to the vector ExamMarks to obtain the size (number of elements) in the vector The size of the vector is used to identify a terminating value that ends iteration of the for loop

Task 3

Open VectorSor t

You will see three TODO sections in the code which need completing

1 Populate a vector with 100 randomly generated numbers

2 Sort the vector

3 Reverse the vector

For sortingreversing you will can use the algorithms sort() and reverse()

Heres a useful link hellip

httpwwwcpluspluscomreferencealgorithm

103

Using insert() and iterators

Task 1

Open and modify the skeleton project called Inser t

Important areas of the program are explained in the steps opposite

Examine the code

vectorltintgtiterator it

This statement creates an iterator that is used to access members of the vector

Iterators are used to access members of the container classes (the container type vector in this case) and can be used in a similar manner to pointers

In the example iterator it is used with the insert() function to place the value (200) at the beginning of the vector nums

it = numsbegin()

This statement uses the vector member function begin() to initialise the iterator it with the address of the start of the vector

it = numsinsert(it 200)

This statement uses the member function insert() and iterator it to insert 200 at the beginning of the vector (it)

Note that an iterator is returned by the function insert() that points to the newly inserted element

104

numsinsert(it + 1 numsTwobegin()

numsTwoend())

This version of the insert() function takes 3 arguments and is used for copying in part or full another collection This may be a vector a plain C++ array or some other collection that is accessed using pointersiterators

This statement inserts a second vector (numsTwo) into nums The three parameters are (copy to nums+1 from star t of numsTwo to end of numsTwo)

it = numsinsert(it + 2 696 )

This version of the insert() function takes 2 arguments The iterator it + 2 points to element number three it points to the beginning of the vector and the 2 moves two elements in The value 696 is inserted at that element

void display(vectorltintgt amp vec)

cout ltlt Vector contains

for(

unsigned int i = 0

i lt vecsize()

++i

)

cout ltlt vecat(i) ltlt

Function display() is passed a reference to a vector and outputs the vector contents used throughout program

105

Task 2

Add the code shown in Figure 27 to the program and using the insert() member function add the array to the nums vector at position two (in the vector) Output the contents of the nums vector to screen

int myArray[] = 5 6 3 4

Figure 27

stdarray

C++11 Introduced a new template array type called stdarray

stdvector is a template class that encapsulates a dynamic array that is stored on the heap and that grows and shrinks automatically if elements are added or removed It provides all the hooks (begin() end() i terators etc) that make it work fine with the rest of the STL It also has several useful methods that let you perform operations that on a normal array would be cumbersome like inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes) Since it stores the elements in memory allocated on the heap it has some overhead in respect to static arrays

stdarray is a template class that encapsulates a static array that is stored inside the object itself which means that if you instantiate the class on the stack the static array will be on the stack Its size has to be known at compile time (it is passed as a template parameter) and it cannot grow or shrink

It is more limited than stdvector but it is often more efficient especially for small sizes because in practice it is mostly a lightweight wrapper around a C-style array However it is more secure since the implicit conversion to a pointer is disabled and it provides much of the STL-related functionality of stdvector and of the other containers so you can use it easily with STL algor i thms

Here is a small example demonstrating the template and some other C++11 extras such as auto and a ranged-based for loop

106

include ltstringgt include ltiteratorgt include ltiostreamgt include ltarraygt using namespace std template ltsize_t N class Tgt arrayltT Ngt make_array(const T amp v) arrayltT Ngt ret retfill(v) return ret int main() The char here can be inferred and so is optional auto a = make_arraylt10 chargt(1) for (const auto amp s a) stdcout ltlt s ltlt system(pause) return 0

1 1 1 1 1 1 1 1 1 1 Press any key to continue

Declaring and using lists

Lists are a kind of sequence container similar to vectors The elements of a list are ordered following a linear sequence with storage handled automatically by the class

List containers are implemented as doubly-linked lists and it is worth noting that elements may be in different and unrelated storage locations

Ordering of a list is kept by a relationship to each element of a link to the element preceding it and a link to the element following it

Because linking information is associated with each element (possibly to different and unrelated storage locations) extra memory may be used to keep the linking This may be important when using a large list

l is ts tend to perform better than vectors at inserting extracting and moving elements in any position within the container but lack direct access to the elements by their position and because of this have a slower access time than vectors Access to an element has to be via a known position (the beginning or the end) and there is a time cost in linking between the known position and the element to be accessed

107

lists are declared indicating the type and number of elements in the following way

listlttypegt listName

listlttypegt listName(initialSize)

listlttypegt listName(initialSize elementValues)

Examples

A list called inNumbers with no initial size to hold doubles

listltdoublegt inNumbers

A list called Name with an initial size 20 to hold characters

listltchargt Name(20)

A list called ExamMarks holding integers with initial size of 4 elements each with the value 6

listltintgt ExamMarks(46)

72 Hash Tables and Cached Calculations

This section has ultimately really been about introducing you to templates and algorithms and well mix both now in a final example

From the binary chop exercise earlier we have seen that sorted arrays provide a very efficient means of storing data for later look-up However we have to bear in mind the algorithmic cost of sorting the array in the first place ie if we have a million unsorted items in our list and we want to find a single item (only) is it better to sort the entire list first and then find the item or is it better to simply walk through the array from the beginning ndash after all we could safely assume that weve a 5050 chance of finding it in the first half of the array Of course as were sorting we could keep an eye open for our item ie we could combine a (partial) sort with look-up operation ndash over time if we repeat this procedure looking for other items we will ultimately sort our array as a side -effect of the look-up operations

But lets move on a little and just consider the fastest look-up method we know so far that carried out on a sorted array using binary chop and think about our programs overall performance when we need to insert additional items into the array When considering problems like this we always think of the worst case hellip despite their often being fans of

108

Monty Python Computer Scientists rarely look on the bright side of life The worst case here is that we need to insert an item into array position zero

Eg say we have this sorted array (look-up operations average O log2 N = fast)

15 24 25 31 78 250 255 262 277

We now have to insert the value 5 into this array Using normal array indexing methods how many operations will this take

5 15 24 25 31 78 250 255 262 277

Each item needs to be shuffled up one position to the right and if weve millions of items that is rather costly especially if the next thing were likely to do is to insert another item

So weve seen that accessing sorted data is very useful and weve also seen that sorting and especially inserting items can be costly The big question is then is there a way we can make both just as efficient - finding andor inserting an item in Olog2N or O(1) (constant time)

Hash Tables

A hash-table is a data structure designed to allow for both rapid insertion and look-up

Although any specific hash-table is implementation specific (there are very many different types of hash-table) well quickly go through the basics

The storage medium well use for our hash-table is an array of strings and we will say that this array has just 10 elements It looks like this

string myhash[10]

Well use this hash-table to store words and well determine the array index for any specific word using a hash- funct ion ndash something that will take a word as its input and return an array index as its output

109

unsigned hashfunc(string s)

unsigned result = 0

for(unsigned i = 0 i lt slength() ++i)

result = result + s[i]

return result 10

hashfunc() iterates through s keeping a running total of the sum of the ASCII codes for each of the characters eg hashfunc(hash-table) computes

h + a + s + h + - + t + a + b + l + e

where the characters ASCII values are

104 + 97 + 115 + 104 + 45 + 116 + 97 + 98 + 108 + 101

The total = 985 and 985 modulus 10 = 5

The final computed value will be used as an index into the array The modulus value used is the size of the hash-table and we use it so as to ensure that resultant computed index value cannot be greater than 9 (remember our arrays indexes are 0 ndash 9)

We can now store words in the myhash array like this

string myhash[10]

string s = hash-table

index = hashfunc(s)

if(myhash[index] = )

myhash[index] = s

else

The complex part is what to do if we have what is called a collision ndash when we find that myhash[index] is already occupied Youll probably have already thought of what value hashfunc(elbat-hsah) will have

One way to help avoid collisions to use a better hash-function and a larger array However in real life collisions are practically impossible to avoid and the only other option to deal with them is to allow more than one string to inhabit an array slot in some way ndash perhaps by having each of the original array slots contain an array ndash rather than an individual string Of course in this case we would also need some way to determine which of the n colliding entries is the one were interested in ndash is it elbat-hsah or hash-table

110

Well briefly leave our examination of hash-tables at this point and instead look at Fibonacci numbers Do not worry we will return to hash-tables very soon

Fibonacci numbers are the numbers in the following integer sequence

0 1 1 2 3 5 8 13 21 34 55 89

By definition the first two numbers in the Fibonacci sequence are 0 and 1 and each subsequent number is the sum of the previous two More formally that is

119865119899 ∶= 119865(119899) ∶=

0 119894119891 119899 = 0 1 119894119891 119899 = 1

119865(119899 minus 1) + 119865 (119899 minus 2) 119894119891 119899 gt 1

Computing Fibonacci Numbers

Task 1

Open Cached_fibonacci

Compile and run the program as is

Examine main() and the calcfib() functions

bigint calcfib(bigint n)

if(n == 1 || n == 0)

return n

else

return calcfib(n - 1) + calcfib(n - 2)

bigint is defined as a unsigned long long int and we have used typedef to save some typing

NOTE The method used to calculate Fibonacci numbers here has been selected because it is perhaps the most obvious way to turn the formal definition into code If you are interested please see the separate Fibonacci project for two other examples of how to calculate Fibonacci numbers

111

Modify the beginning of the calcfib() code

bigint calcfib(bigint n) cout ltlt calcfib was passed ltlt n ltlt endl

Modify main() to set max = 5 and re-run the program

calcfib was passed 0 Fibonacci number 0 is 0 calcfib was passed 1 Fibonacci number 1 is 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 2 is 1 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 Fibonacci number 3 is 2 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 4 is 3 calcfib was passed 5 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1

Fibonacci number 5 is 5

112

Note that to calculate Fibonacci number 5 we calculate Fibonacci number 4 and Fibonacci number 3 - even though weve previously calculated Fibonacci number 3 in order to calculate Fibonacci number 4

To fully appreciate the growth of this process re-run the program adding 10 to max for each subsequent run You maymay not like to comment out the line you inserted in Step 2

Task 2

Getting back to Hash Tables Using a hash-table to store previously computed Fibonacci numbers

As it stands the incomplete solution declares a template hash-table called fibs of the type unordered_map

Read the comments in the function fibCache() and modify the code to as to use the fibs hash-table to store previously computed Fibonacci numbers

fibs[n] = f stores f the n-th Fibonacci number in the n-th slot of fibs (which as you can see you may treat as an array for indexing into)

8 Pointers In C++ programming data (variables) can be referenced via the memory address of the variable This is done using a pointer var iable

A pointer var iable contains the address (location in memory) of a data variable

There are also functional pointers ie those that point to code rather than data and these are briefly explored later

Pointers can be particularly useful when interacting with the operating system andor when working with arrays - as the elements in an array will always occupy consecutive memory places Incrementing the pointer variable by one addresses the next array element

Lastly pointers are also used to fake pass by reference

Declarat ions

int n This is a standard variable declaration n that contains a value as yet unknown of type int

int p This is a pointer p that can hold (point to) an address that contains a variable of type int The type of p is int

Each variable declared as a pointer must be preceded by an asterisk () This modifies the type of the object being declared from thing of type to pointer to thing of type Eg int n means n is an int whereas int n says that n is a pointer to an int

113

int age height age is a pointer to an int height is an int value

double far cent are both pointers to doubles

Pointers can be initialised when they are declared or set using an assignment It is common to initialise pointers to a memory address but they can also be initialised to the predefined constant NULL ndash meaning that they do not (as yet) hold (point to) a valid memory location NULL is defined in the standard library such a pointer is called a nul l pointer

When is used in a variable declaration it indicates the variable being declared is a pointer and not a value

But do beware as is used elsewhere with pointers when the appears before a previously declared pointer variable elsewhere in the program it is said to dereference the pointer and so is used to access data stored at the address which is stored in the pointer A dereferenced pointer is essentially the variable to which the pointer was originally set to point

To complicate matters further using the pointer name without the dereference operator references whatever is stored in the pointer variable itself ndash this is the address of the object it references in memory (which maybe NULL of course)

As we have seen using can mean two things that something is being declared as a pointer or that a previously declared pointer is being dereferenced Experienced programmers sometimes enter the two usages differently ndash a notation we would highly recommend ie

int n n is an object that can hold the address of an int

int k = 0 k is an int holding the value zero

n = ampk n is set to hold ks address amp is explained below

n = 1 k (yes k) is set to hold the value 1

Note the space used in the different usages - int n vs no space in n

Initialising pointers

Pointers can be initialised in two ways

int x = 16 y = 69 variable declaration and initialisation int x_ptr = ampx pointer declaration and initialisation x_ptr holds the address of x int y_ptr pointer declaration yptr is a pointer

y_ptr = ampy pointer assignment yptr holds the address of y

Once declared a pointer variable can be assigned the address of another variable using the amp the addressof operator

114

Note the variable name should not be prefixed by the in the assignment statement unless the pointer is initialised immediately in the variable declaration

We also use pointers when creating objects on the Heap for example we can create and initialise a string object like this string pstring = new string(Hi there) Such objects are not normally tidied away as are the objects created on the stack - objects simply declared in a functionmethod and so they should explicitly be tidied away using delete eg delete pstring For more on this subject see section 9

Using pointers

Task 1

Open the project Pointers

Compile and run the program The output should be as shown in Figure 28

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int x_ptr = ampx This is x_ptr pointer declaration and initialisation

int y_ptr Declaring another pointer y_ptr

y_ptr = ampy Initialising y_ptr

y_ptr = x_ptr Assigning x_ptr contents to y_ptr Both pointers are pointing to variable x (16)

y_ptr = ampy Assigning the address of y back to pointer y_ptr

y_ptr = 170 Assign 170 to the variable at memory location of y_ptr y_ptr points to variable y so 170 has been assigned to y

115

Figure 28

Pointer Arithmetic and Arrays

We have seen that once a pointer is initialised it has a memory address and this address can be reassigned another address It is also possible to change an address using standard arithmetic

The ++ and -- increment and decrement operators can be used to move the pointer along to the next or back to the previous memory address To jump more than one memory address you would have to use the assignment operators += and -=

When using arrays and pointers the array name is the address of the first element in the array

int intArray[] = 1 2 3 4 5

int int_ptr = intArray Same as int int_ptr = ampintArray[0]

The pointer has been declared and initialised with the statement int int_ptr =

intArray Note there is no need to use the address of operator amp when initialising arrays as the array name is the address of the beginning of the array

When working with arrays each element of the array will be the type and size at declaration When an array is declared to hold integers each element will usually be 4 bytes in size An array of doubles will have element sizes of 8 bytes Note ndash these sizes are actually down to the compiler being used and are usually in turn dependent upon the operating system being used

It is not important to know how many bytes make up each element Moving the pointer through the array with the assignment operator x_ptr += 2 will move two elements further through the memory allocated for the array or 16 bytes for an array of doubles

116

Pointers and Arrays

Task 1

Open the project PointerAr i thmetic

Compile and run the program The output should be the same as Figure 29

Examine the program carefully

You may not fully follow the program at first glance as it employees a few potentially new constructs (it depends how far weve got through the lectures)

One slightly truncated new construct is

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

A struct in C++ is just like a class except that the default public and private sections are reversed By default everything in a struct is public

typedef in C++ allows the definition of our own types based on other existing data types

typedef exist ing_type new_type_name

where exist ing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining For example

117

typedef unsigned int WORD

typedef char pChar

You may also remember initialiser lists from earlier eg

s_thing(int a) a(a) b(sqrt((double)a))

If we re-write this

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

We quickly see that a(a) and b() are initialising the a and b struct members const int a and const double b

118

Remember that as these are const we cannot use assignment

typedef struct s_thing

const int a

const double b

s_thing(int a)

Error ndash a and b are const

this -gt a = a

this -gt b = sqrt(a)

thing

Lastly when dealing with pointers to compound types one may access the members of the type via dereferencing or via the so called crows foot operator

(t) dereferences t giving us a thing which was pointed to by t Then we use the dot operator to access the member (t)a

We have to parenthesiset otherwise the would bind to t first ie it would be as though we had done this (ta) which would be an error

The crows foot saves us the dereference t-gta is just like (t)a

119

Figure 29

PLUSPLUS Pointers and Arrays

Task 1

Open and modify the skeleton project called ReverseArray

In main() create an array of 10 integers Fill the array with random numbers between 0 ndash 100

Write a helper function called to output the contents of the array to the console A suitable prototype for this would be void dumpArray(int array[] int size)

Write a helper function to reverse the contents of the array Use a temporary variable as an aid A suitable prototype for this function would be void reverseArray(int array[] int size)

Reverse the values in the array using only pointers

120

Reverse the array without using a temporary variable You should use the XOR operator ^ to achieve this

Pseudo code for an XOR swap is

X = X XOR Y

Y = X XOR Y

X = X XOR Y

The completed program should look like Figure 30

Figure 30

Task 2

Reverse the array using a vector and the standard function template stdreverse()

We can also have pointers to functions in C++ (and C)

The name of a function resolves to be its address in memory (somewhat similar to the case where we use the name of an array) When we call a function we use this name to retrieve the functions address and then use the function invocation operator to execute it The function invocation operator is the set of brackets you use eg

Lets take an example

121

include ltiostreamgt

using namespace std

int lue() life the universe and everything

return 42

int main()

cout ltlt The address of the function lue is

ltlt lue

ltlt invoking it yields

ltlt lue()

ltlt endl

system(pause)

return 0

Typical output is shown in Figure 31

Figure 31

122

We can also store addresses of functions in variables (theyre just numbers) and the type system allows for us to describe and declare scalar variable types for function pointers eg this modified code fragment would produce the same output as that show above

fp is a pointer to a function taking

no arguments and returning an int

int (fp)()

fp = lue

cout ltlt The address of the function lue is

ltlt fp

ltlt invoking it yields

ltlt fp()

ltlt endl

fp is a funct ion pointer var iable so it may be used to point to any other function having the correct signature at runtime

PLUSPLUS Function pointers

Task 1

Open the project Calculator

Compile and run the program The output should be as shown in Figure 32

123

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int (fp)(int int) This is the function pointer declaration It may point to functions that take two integers and return an integer

Like all automatic storage class variables fp will currently be pointing at a random location What happens if you run the program without setting fp to point to an actual function Comment out the switch to find out

switch (Operator)

case 0 fp = Add break

case 1 fp = Subtract break

case 2 fp = Multiply break

The code could do with improving

Modify it to allow for multiple trials eg add the necessary logic to loop and perform multiple calculations ndash youll need to add some way to end the program too therefore

Modify it so that the operator may be inputted as an operator character eg + - etc Allow X x and for multiplication and add for division

All three pieces of information could be entered on a single line eg 6 x 7ltentergt Using cin to read that data just requires you to use three cin statements

cin gtgt X

cin gtgt Operator

cin gtgt Y

Lastly modify the program to that it uses floating point arithmetic

124

Figure 32

9 APIs New Delete and Dynamic Memory As has been stated earlier pointers are useful in a variety of situations However because they are easy to get wrong ndash and when they go wrong everything goes very wrong indeed ndash languages like C++ have tried to make their use the exception rather than the norm For example without reference arguments (eg void someFunc(int amp)) we would have to use pointers to achieve the same functionality and performance

On the whole the underlying philosophy when it comes to pointers is to try to avoid using them whenever possible You can get a real feel for this subject by Googling for smart pointers c++ and from Wikipedia httpenwikipediaorgwikiSmart_pointer

Two areas where we absolutely need pointers are when calling into an external API (Appl icat ion Programming Interface ) and when allocating memory for our own purposes ndash the latter case is also eased by advances in the library support in C++

Using an API

An Appl icat ion Programming Inter face is functionality provided by some third party The most obvious API whether it is Windows Linux or OSX is that exposed by an operating system

If your application needs to interact with the user in any non-portable way you will need to call into your OSs API For example if you want to display a dialog box you will need to access the OSs functionality to do so (perhaps indirectly through a framework like Nokias Qt - httpsenwikipediaorgwikiQt_(framework)) In summary if you ever want to go outside of the standard libraries andor writing consoleterminal applications you will need to call into your operating systems API

When it comes to calling into operating systems pointers are used extensively As an example 1 Google for Linux API 2 Find any website that lists the API functions and then 3 click-through to any function The odds are that the function prototype you see will contain asterisks (pointers)

125

Dynamic Memory Management

The second area where you simply must know something about pointers is when it comes to using the heap

The heap is an area of memory available to your programs You may allocate and use the heap as you wish

Why would you want to do this Normally its to create variable length arrays or to model and use an advanced data structure of some sort a self-balancing red black tree perhaps (httpenwikipediaorgwikiRedAndblack_tree) Of course the more esoteric the data structure and less likely it is that it will be incorporated into the C++ standard library (although the library does contain most of the generally useful and popular ones like doubly l inked l is ts )

To allocate memory from the heap in C++ you use the new keyword and to return it you use the delete eg

int nSize = 12

note nSize does not need to be constant

int pArray = new int[nSize]

pArray[4] = 7

delete [] pArray

10 More on Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine Encapsulation is data information or detail hiding

Once a function is written the detail of how it works is not important to the end user The user needs to understand what data to input and what output will be produced

One of the most important aspects of writing programs using functions is that the functions can be reused from one project to the next Think about the standard functions youve seen already eg the square root function sqrt() Libraries contain atomic generally useful functionality that is likely to be of use at some future time It is useful to bear this thought in mind whenever we build new programs ie we should be on the lookout for generally useful functionality (given our domain) that we should consider coding as functions for later reuse The same goes for classes of course

Probably the most important function in your program in main() ndash without it you do not have a program at all

main() is your programs entry point and as such it may be used in such a way as to inform the rest of your program as to the actions required

126

main() and command-line arguments

Task 1

Open a Command Prompt or PowerShell Prompt and enter the following

dirltreturngt

di r Odltreturngt

t ree ltreturngt

t ree altreturngt

dir and t ree etc are like mini-programs They have default functionality which may be altered by providing additional command-line arguments eg for the dir command dir L N 4 TC

Command-line arguments are passed to your programs by optional parameters eg

int main(int argc char argv[])

Where argc is a count of the number of arguments and argv is an array of pointers to arrays of character (C strings) for each argument being passed Note that argc is always at least 1 and so argv always contains at least one entry ndash this is the name of the program being run

Task 2

Open (demonstrat ion)

CommandLineArgs and Build and run the program

Examine the code

The programs configuration is Debug

In the projects Project | Debugging | Command

Arguments you will see where the programs default command-line arguments are set for debugging purposes

Using the command prompt you opened earlier navigate to your where CommandLineArgsexe is located

CommandLineArgs debug

Run the program by entering its name followed by a variety of arguments eg

gtCommandLineAgs one two threelte ntergt

127

Task 3

Open the project UserPrompter project

Run the program and then examine its code

We will modify this program to use a command-line argument However before doing that its worth pointing out that the primary purpose of this program is to demonstrate the separation of a class declarat ion with its implementat ion (the mechanismfunctionality of class prompter is defined in promptercpp but its capabilities are declared in prompter h )

Its also interesting to note that the optimal strategy is to use an algorithm called binary search or binary chop (we saw this earlier in the course) with each guess you reduce the number of possible solutions by a half This sort of algorithms Big Oh is Log n (where log is base-two logs)

httpenwikipediaorgwikiBig_O_notation

Task 4

Modify the program so that the upper range for the max value is given as a command-line argument

The UserPrompter cpp is the file youll need to modify

Test your program via the setting the projects Command Arguments as detailed above -or- by running the application standalone in a command prompt after building (also as detailed above)

See Figure 33

To convert a string into a number (weve seen one other way of doing this earlier) we can use

include ltcstdlibgt

and the function atoi() eg

atoi(argv[1])

128

Figure 33

EncryptDecrypt a file

Task 1

Open compile and run the EncodeDecode project

Complete the program so that it may be run outside of the IDE and process a file for encryptiondecryption

This is actually quite a simple task as youll only need to add a couple of lines of code However the project also demonstrates how to use the Debug and Release modes to influence the way a program runs ie that in its Debug configuration the program automatically runs through a test

Other things to note include using bitwise XOr to perform the encoding and the use of the C standard library functions putchar() and printf() to perform some of the output eg putchar() is used to output a CR to the console window (CR = char 13)

129

Figure 34

Multiple arguments overloading and default values

In C++ we can over load functions ndash meaning that we can provide different versions of the same function (the different versions must differ by the number andor type of the parameters they take) For example

130

void foo(double d) 1

cout ltlt In void foo(double d)nn

void foo(long int n) 2

cout ltlt In void foo(long int n)nn

void foo(int n) 3

cout ltlt In void foo(int n)nn

double dtest = 0

long int ltest = 0

int ntest = 0

foo(dtest) Calls 1

foo(ltest) Calls 2

foo(ntest) Calls 3

In the above the compiler works out which version of the foo() to call based upon the argument type it is given

We can also overload functions if the number of arguments differ eg

131

void bar(double d)

void bar(double d double t)

We would use a feature like this if sometimes we needed to use extra information ndash in the shape of passing in t in the above eg we would most likely implement void bar(double d) as

void bar(double d)

bar(d 25) Call bar(double d double t)

What were really saying above is that in most cases the implicit double second parameters value is normally 25 ndash perhaps its a standard discount percentage ndash and only occasionally we will need to change that value in which case wed call bar(double d double t) directly and not by going through bar(double d)

Lastly C++ has one extra feature that can make this simpler ndash defaul t arguments

Rewriting bar using this feature we get

void bar(double d double t = 25)

Note that we now only have one bar function now and that we may call it like this

bar(x)

Or like this

132

bar(x y)

In the case of bar(x) the second parameter is omitted and so will receive the default value of 25 in the second example t will receive ys value

Although outside the scope of this class for more on overloading see the (demonstrat ion) Operator Over loading project This shows how to overload the ++ pre and post increment operators overload and provide your own ltlt stream insertion operator (and one use of a friend function) and using an enum with a typedef

Passing Arrays to Functions

To pass an array to a function it is only necessary to pass the array name and the number of elements in the array

The array name is the position (address) in memory of the first element The number of elements is passed to enable the function to establish the array size

An array declared as double somearray[10] would require a function call somefunction(somearray 10)

Passing Arrays to functions

Task 1

Open and modify the skeleton project called the project called ArrayReturnValue

Pass an array to a function to read in five numbers

Pass the array to another function to calculate the average value in the array return this to main() and output to screen

Lastly at the end of the program output the values in the array from within main() The finished program should look something that that in Figure 35

Create two function prototypes

void enterMarks(double ExamMarks[] int num)

double calcAverage(double ExamMarks[] int num)

ExamMarks[] is the array to be passed As with passing variables it is not strictly necessary to give the argument a name in the prototype just its type This could have been written as calcAverage(double [] int) However it is sometimes useful to include this information as it might help explain the functions operation

It is also necessary to pass the size of the array num is the number of elements in the array its size

Within main() declare the array and initialise the elements to zero with the following statement double ExamMarks[5] = 0

This declaration explicitly initialises the first element to zero and implicitly initialises the remaining four to zero

133

Create both functions

enterMarks to read in the values and calcAverage to calculate the average (you will need a for loop in each function)

Return the average value from calcAverage to main() and output the value using cout

Call the functions from within main() with the following statements

enterMarks(ExamMarks 5)

average = calcAverage(ExamMarks 5)

You may output the average directly of course ie without first storing the value in average

At the end of main() add the statements

for(int i = 0 i lt 5 ++i)

cout ltlt Exam Mark Number

ltlt i + 1

ltlt is

ltlt ExamMarks[i]

ltlt endl

ltlt endl

134

Explain how it is possible at the end of the program to output from within main() all the values in the array entered within the function

Modify the program so that the number of exam marks (5) appears only once

In previous exercises when parameters (variables) were passed to functions the function received a value When a value is used in a function a copy is stored in a part of memory that only exists from the time the function is called to when it ends After this the memory and any value in it are lost

However the array in this exercise was initialised in main() with zeros and then passed to the function Data was then added to the array and calculations done At the end of main() the values in the array elements are output The array contains values input from within the function

The name of the array is the address of the first element of the array in the machines memory As the starting address is passed (the name of the array) the called function knows where the array is stored in memory

Because we are working with memory addresses (references ) any changes made to array elements in the function affect the memory location set up in main() for the array

C++ passes arrays to functions by reference (to the memory location of the first element) In previous exercises functions were passed values copies of the variables in main()

135

Figure 35

Passing Two-dimensional Arrays to Functions

It is common to want to store numbers in a two dimensional layout of rows and columns as shown in Table 7

187645 783473 298372

871223 629399 561201

Table 7

This arrangement is known as a two-dimensional array or matrix

C++ uses an array with two subscripts to store a two dimensional array

double Balance[2][3]

When we specify a one-dimensional array the number of elements must be given

When a two-dimensional array is specified it is necessary to specify the array elements in both dimensions We therefore specify the number of rows and columns

The Balance array in the statement above has two rows and three columns

11 Inheritance and (not presented) Polymorphism

111 Inheritance

In Object Oriented languages like C++ inheritance describes a relationship between classes of objects and which usually implies some sort of a sub-division of labour

For example lets say that we want to build an IT system that has something to do with the members of the university

136

In an OO world the first question usually is how would we categorise our significant entities and that always means naming things what names would we use to categorise university members When modelling (for that is what were going to be doing) real-world objects its sensible to use proper names So heres an attempt ndash to broadly categorise university membership

Members are members of the sets

Students

Staff

Other

What is other though

The Bodleian and the card-office issue Readers cards ndash so is a Reader a university members or are they something else And if they are something else does our system really want to concern itself them Or more broadly does our system really want to concern itself with holders of cards issued by the card-office

Are all students really the same

What sort of students do we have at Oxford (and do we want a system ndash either now or in the future ndash that might be interested in recording the differences) Lets see we have undergraduates and graduates We also have Rhodes scholars ndash but are these sorts of student that are distinct (or should be in our system) from our underpost-graduates categories And how about graduates would we want to have some sort of sub-groups Masters students MScMBAMPhil or Doctoral students DPhilDScDLitt etc Perhaps wed like to know something about how theyre being funded ndash and we might want that piece of functionality shared by our undergraduates

We can of course go through the same process when thinking about members of staff (university staff departmental staff members of congregation academic staff fulltimepart-time staff casual staff ndash and how about staff that are sometimes (or also) students) We can go on thinking about this sort of thing for a very long time and we should as its important and when its important it has a name ndash Object Oriented Design or OOD

One of the things wed hope to see appear as part of the OOD phase is the relationship between entities For example if we were to say that a common property of all university members is that they have a date-of-birth we wouldnt want to have our Student and Staff C++ objects contain this information directly by way of some datastate class member (which might seem a little odd at first) But think about it If we performed some validation on the members DoB (perhaps when its being set) we would need to include this in both Student and Staff classes Or as an alternative we would capture the validation in some external function ndash which we would call from the separate classes (if we remember) No its messy and it would be much better if we thought of things this way that all university members are people and that people all have dates of birth

To put it another way we would say that studentsstaffother are just specialisations of people ndash they are people but with a bit of extra something tagged on to them ndash like a bod card number

Now if we also had some way of capturing people stuff in say a basic Person class and could somehow use that automatically ndash perhaps by deriving a Member class from it and then doing the same from Member to both Staff and Student classes from Member One thing though ndash we wouldnt want someone to be able to instantiate a Member object

137

perhaps ie in our system Member is an abstract class Imagine a generic Car vs a Renault Clio ndash it makes no sense to create a Car object ndash there are no generic cars on the road they are all specific cars Similarly we wouldnt want a generic Member wandering around our system (if you remain unconvinced well see why later)

Modelling a student - a first attempt

Please note that in this Introduction to C++ we do not expect you to complete an exercise that requires coding from now on Please just look through the code and follow along with the discussion

Base classes

Task 1

Open the project UnivMember1

Examine the program carefully

The project contains three classes Person Member Student In main() we create a Student and then attempt to output the students name ndash which fails

name is in the protected section of Person ndash which means only Person methods or methods in derived-from-Person classes can access it

Add a public section to the Person class and relocate the name there

Eg

public

string name

Any better now

The problem now is that Student only by default inherits the private side of Person

Change class Student so that we also inherit the public members of Person hellip

class Student public Person

138

Before we tackle further problems with name lets bring in the Member class (left doing nothing until now)

We really want Student to inherit from Member and not Person Change the code to reflect this

People have dates-of-birth and Members have bod cards Add a string member dateOfBirth to Person and move the bodCardNumber member out of Student and into Member ndash make them both strings

Change the code in main() to set these extra pieces of data

If you havent done it already Persons dateOfBirth and Members bodCardNumber should be set via constructors

139

Task 2

Open and examine the project called UnivMember2

UnivMember2 is a copy of the (exercise solut ion)

UnivMember1 solution

One of the problems we have in UnivMember1 is that too much of it is public eg given Student object s we can change name to simply by using assignment eg sname =

We should protect data members at each level using the maximum level of protection we can ie private

However if we do that then cout ltlt sname will no longer work and so well need to provide access methods to the data members Eg heres a modified Member class showing the basic scheme

class Member public Person

public

Member(string bodCardNumber)

this-gtbodCardNumber = bodCardNumber

string getBodCardNumber() For access

return bodCardNumber

private

string bodCardNumber

140

Another problem is that wed really like to not use assignment at all Eg in the above ctor snippet

this -gt bodCardNumber = bodCardNumber

is using assignment

Change string bodCardNumber to const string bodCardNumber Youll see now that assignment wont now work (you have to initialise constants)

What wed really like (most likely) is to use in i t ial isat ion

We can do this via initialiser lists Ie we could change the above to the following

class Member public Person

public

Member(string bodCardNumber)

bodCardNumber(bodCardNumber)

const string getBodCardNumber()

return bodCardNumber

private

const string bodCardNumber

The initialiser list is read thus

bodCardNumber(bodCardNumber)

^^member^^ ^^parameter^^

Note that weve also modified getBodCardNumber() to show that it returns a const string

141

Modify all three classes to use initialiser lists private const data members and use access functions (getBlah() etc)

Task 3

Open and examine the project called UnivMember3

UnivMember3 is a copy of the (exercise solut ion)

UnivMember2 solution

We will now finish this project to the level of an introductory course

Things to note

The main problem with the solution as it stands is that one may create a Member object

Remember that this is analogous to being able to create a generic Car object ndash we should not be allowed to create one

Going right back to UnivMember1 you may remember a comment in there about a protected constructor

protected Protected ctor Person()

At that point in your project we were thinking two things 1) we wont want to create a generic person and 2) a protected constructor will facilitate this

And we were wrong to think both thoughts

1) A properly thought through Person class would be perfectly good to model generic people But although this is true one question here ndash would we ever want just a generic person

2) A protected constructor in a (more) base class doesnt prevent a derived class from creating a base object So what about the Member class ndash would it be ok to instantiate that

The proper means to prevent a Member being created would be to use what is called a pure v i r tual funct ion as part of its definition (such a function is one that must be overridden in a derived class) But what function

142

If you look at the classes derived from Member ndash you can take it from us that one might want to interrogate at runtime ndash to ask them what they are

So a suitable member function to declare in Member would be something like string getRole() A function that does return Student for a student and return Staff for a Staff object

If its pure virtual in in Member wed best define it in our derived classes

class Member public Person

public

virtual const string getRole() = 0

class Student public Member

public

const string getRole() return Student

143

1 Why did we want duplicate (named) functions in Member Student and Staff 2 And what does virtual really mean

We require both 1 and 2 so that we can provide specific responses when being asked the same question and all when being treated in a rather basic way

Being asked the same question means having a method invoked eg getRole() and in a rather basic way means treating us all Students and Staff (etc) as Persons and Members

112 Polymorphism

Polymorphism comes in a few forms

Ad-hoc Polymorphism via function overloading

Parametric Polymorphism or Compile-Time Polymorphism via templates

Subtype Polymorphism or Runtime Polymorphism via virtual functions and

Coercion Polymorphism via casting

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class (after all a derived from base must have or contain all that a base has) Polymorphism is the art of taking advantage of this simple but powerful and versatile feature

One way Subtype Polymorphism is applied is to use a base reference to access a collection of instances of different types that are derived from a common base ndash one way to paraphrase that is to say that related (derived from a common class) objects respond according to their type rather than according to the type of the reference one uses to access them (a base class pointer type) That is the dynamic type of the object is used instead of its static type

All of this is best demonstrated via an example of course

144

PLUSPLUS Polymorphism

Task 1

Open and examine the project called (exercise

solut ion) UnivMember3

Run the program the output should be the same as shown in Figure 36

The crucial code here is as follows

Member arr[6]

Student studs1()

Student studs2()

Staff staff1()

Student studs3()

Staff staff2()

Student studs4()

arr[0] = ampstuds1

arr[1] = ampstaff1

arr[2] = ampstuds2

arr[3] = ampstaff2

arr[4] = ampstuds3

arr[5] = ampstuds4

for(int i = 0 i lt ++i)

cout ltlt arr[i]

ltlt i ltlt s name is

ltlt arr[i]-gtgetName()

ltlt t Their role is

ltlt arr[i]-gtgetRole()

ltlt endl

Weve created an array of Members (it isnt important that weve used pointers) and note that we have set some of the members of this to be pointers to Student and Staff objects We are allowed to do this as both Student and Staff are derived from Member

However when and if we invoke member functions on these objects wed really like it if they responded as what they really are ndash Student and Staff objects

145

From the output below you can see that they indeed do respond accordingly

Figure 36

The mechanism behind allowing this is the virtualisation of the getRole() member function Remember that this was declared and made virtual in the Member class

Play about with the code eg change

Member arr[6] to Person arr[6] Everything still ok How about not using pointers here ndash easy to do

146

Lastly weve implemented (for no good reason but to show you how its done) some instance counting in all three classes Have a look for the static members and the inserted lines immediately below the class definitions that look like this int PersonCount = 0

The End Thank you for coming and we hope that you enjoyed the class

Oh and please Please PLEASE fill out the feedback form email when it arrives

147

12 Appendices

Arithmetical Operators

Operator Operation

+ Addition

- Subtraction

Multiplication

Division

Modulus

++ Increment

-- Decrement

Table 8 ndash Arithmetical Operators

Assignment Operators

Operator Example Equivalent

= a = b a = b

+= a += b a = a + b

-= a -= b a = a - b

= a = b a = a b

= a = b a = a b

= a = b a = a b

Table 9 ndash Assignment Operators

148

Assignment and Arithmetic examples

The assignment operator in C++ is =

The format is var iable = expression this can be read as assign to the var iable the value of the expression

An example to calculate the number of pence in a value in pounds would be

pence = pounds 100

Note it is easy to confuse the assignment operator = with the equals notation used in mathematics The equals notation in C++ is ==

Incrementing a var iable

month = month + 1 adds the value one to the variable month This can be written as

month++

Decrementing a var iable

month = month - 1 deducts the value one from the variable month This can be written as month--

Note that ++ and ndash can be used before or after the thing being modified eg ++x x++ --y y-- However there are some subtle differences which will be explained in the lectures

In C++ it is also possible to combine arithmetic and assignment operations

To add 2 to a variable total

total = total + 2 or total +=2

To subtract 2 from to tal

total = total - 2 or total -=2

To multiply total by 2

total = total 2 or total =2

Relational and Equality Operators

The equality operator is used to compare two operands (a == b) and returns 1 (t rue) if both are equal otherwise 0 (false ) is returned

The inequality operator (=) returns 1 (t rue) if both are NOT equal otherwise 0 (false) is returned

Both the above operators are commonly used to test the state of two variables to perform conditional branching

The relational operators also return either true or false (a gt= b) returns 1 (t rue ) if a is greater than or equal to b otherwise 0 (false ) is returned

149

Standard algebraic equality or relational

operator

C++ equality or relational operator

Sample C++ condition

Meaning of C++ condition

Relational operators

gt gt a gt b a is greater than b

lt lt a lt b a is less than b

gt= a gt= b a is greater than or equal to b

lt= a lt= b a is less than or equal to b

Equality operators

= == a == b a is equal to b

= a = b a is not equal to b

Table 10 ndash Relational Operators

Logical Operators

When using i f selection statements it is common to use the relational operators as part of the test if(num gt 5) if(size lt= 14) if(Char == A) These are fine for testing one condition

To test multiple conditions it is possible to nest i f statements but this can be a bit cumbersome

Logical Operators can be used to form more complex conditions by combining simple conditions

Logical AND (ampamp) Operator allows a test to see if two conditions are true

if(leaveBooked gt LeaveLeft ampamp staffCover == false)

cout ltlt Take your holidays sometime else

Logical OR (||) Operator allows a test to see if either or both of the conditions are true

if(Temperature lt 16 || windspeed gt 15)

cout ltlt Too cold or windy to sunbath today then

Logical Negation ( ) Operator reverses the meaning of a condition

if((windspeed == 20))

150

cout ltlt The wind speed is not 20 its ltlt windspeed

This could be written equally as well with the equality operator

if(windspeed = 20)

cout ltlt The wind speed is not 20 its ltlt windspeed

Precedence and Associativity Table

Precedence Operator Description Associativity

1 Scope resolution Left-to-right

2

++ -- Suffixpostfix increment and decrement

() Function call

[] Array subscripting

Element selection by reference

-gt Element selection through pointer

typeid() Run-time type information (see typeid)

const_cast Type cast (see const_cast)

dynamic_cast Type cast (see dynamic_cast)

reinterpret_cast Type cast (see reinterpret_cast)

static_cast Type cast (see static_cast)

3

++ -- Prefix increment and decrement Right-to-left

+ - Unary plus and minus

~ Logical NOT and bitwise NOT

(type) Type cast

Indirection (dereference)

amp Address-of

sizeof Size-of

new new[] Dynamic memory allocation

delete delete[] Dynamic memory deallocation

151

4 -gt Pointer to member Left-to-right

5 Multiplication division and remainder

6 + - Addition and subtraction

7 ltlt gtgt Bitwise left shift and right shift

8 lt lt= For relational operators lt and le respectively

gt gt= For relational operators gt and ge respectively

9 == = For relational = and ne respectively

10 amp Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 ampamp Logical AND

14 || Logical OR

15 Ternary conditional Right-to-Left

16

= Direct assignment (provided by default for C++ classes)

+= -= Assignment by sum and difference

= = = Assignment by product quotient and remainder

ltlt= gtgt= Assignment by bitwise left shift and right shift

amp= ^= |= Assignment by bitwise AND XOR and OR

17 throw Throw operator (exceptions throwing)

18 Comma Left-to-right

Table 11 ndash Precedence and Associativity Table

Escape Sequences

Escape Sequence

Description

n Newline Position the screen cursor at the beginning of the next line

152

t Horizontal tab Move the cursor to the next tab stop

r Carriage return Position the cursor at the beginning of the current line

a Alert Sound the system bell

Backslash used to print a backslash

Single quote Use to print a single quote character

Double quote Used to print a double quote character

Table 12 ndash Escape Sequences

Cast Operator

Is where the programmer explicitly asks for a change in data type It may be that the result of a calculation is a double and the user wants it to be of type integer

A double can be cast to an integer in the following way

double aNum = 237

int anInt = 0

anInt = static_castltintgt(aNum)

A C style cast may also be used eg

anInt = (int)aNum OR anInt = int(aNum)

Formatted Output

When several numbers are displayed each is printed with the minimum number of digits needed to show the value This can yield some unexpected output

The width of an output field can be set using a stream manipulator To set the next number to be printed to a width of 5 digits use cout ltlt setw(5) This command does not produce any output it manipulates the stream to change the output format of the next value Note setw() must be specified for every item output

To use any stream manipulators you must include the header include ltiomanipgt

setprecision is another manipulator and is used to set the precision of the next floating point number Note setprecis ion only has to be set once as the stream remembers the formatting directive and does not affect integer fields The format is cout ltlt

setprecision(3)

To set precision for trailing zeros (0100 will appear as 01) it is necessary to use the fixed format The notation is cout ltlt fixed Note f ixed only has to be set once

The three manipulators can be combined to achieve the required precision and field width when used in this way

153

cout ltlt fixed ltlt setprecision(3) ltlt setw(5) ltlt myDouble

Alternatively as fixed and setprecision only have to be set once this statement could be written as

cout ltlt fixed ltlt setprecision(3)

cout ltlt setw(5) ltlt myDouble

Header Files

Every program that you create will have at least one header file If you use input or output you will have to include the iostream header

If you use mathematical functions you will need cmath It can be difficult to know which header files to use for each function Some of the common header files used together with some of the older ones you may find with inherited code are shown below It is a good idea to use the help if you are unsure which header files are associated with particular functions

Standard C++ header Old header

iostream iostreamh

iomanip iomaniph

fstream fstreamh

cmath mathh

cstdlib stdlibh

string No equivalent

vector vectorh

Table 13 ndash Header Files Old and New

Matrix Libraries

The STL does not contain a Matrix type and so we must look elsewhere for a suitable implementation that suits the individuals needs

The table below lists the third party libraries that we are aware of

Some Linear AlgebraMatrix Libraries

Armadillo Blitz++ Boost

CPPLapack CPPScaLapack CVM Class Library

Eigen Elemental FLENS

Gmm++ GNU Scientific Library (GSL) HSL

154

IML++ IT++ LA library

Lapack++ LinBox Matrix Template Library (MTL)

MV++ Newmat PETSc

RNM Seldon SimuNova

SL++ (Scientific Library)

SparseLib++ SuiteSparse

TCBI (Temporary Base Class Idiom)

Template Numerical Toolkit (TNT)

Trilinos

uBlas ViennaCL

Table 14 ndash Matrix Libraries

Scope

The portion of a program where an identifier can be used is known as its scope

An identifier declared outside any function or class has f i le scope This type of identifier is known by all functions Global variables and function prototypes all have file scope

Identifiers declared inside a block of code have block scope This type of scope begins at the identifiers declaration and ends at the termination right brace ( ) of the block in which the identifier is declared

Any block can contain local variable declarations If blocks are nested it is possible to declare variables with the same name in each nested block The variable in the outer block is hidden while the inner block is being executed

Enumerating constants

The enum keyword provides a handy way to create a sequence of integer constants An example of enumeration is shown below

enum Months JAN = 1 FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC

Each of the constants will have a default value 1 greater than the constants that it follows in the list The first value in the enumeration above is explicitly set to 1 and the remaining values increment by 1 The values assigned from JAN to DEC will be 1 to 12

The statement cout ltlt DECEMBER is month number ltlt DEC ltlt endl would be output as DECEMBER is month number 12

Constants

Data that will not change during the execution of a program should be stored in a constant container rather than a variable If the program attempts to change the value stored in a constant the compiler will report an error and compilation will fail

Constant can be created for any data type by prefixing the declaration with const keyword followed by a space Note Constants must always be initialised at declaration

The following declaration declares a constant for the speed of sound at sea level ms

155

const double SpeedOfSound = 34029

Vector member functions

Some commonly used member functions of the vector class are

Vector member Functions Effect

at(element number) Gets the value contained in the specified element

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

push_back(value) Adds an element to the end of the vector containing the specified value

size() Gets the number of elements

Table 15 ndash Vector Member Functions

Global functions

Global functions are not member functions They take more than one argument and operate on a range of elements rather than on the vector container ie they can be used on other types of containers

Vector global Functions Effect

find()

ptr = find(vbegin() vend() 67)

Finds the element in the vector containing number 67 Needs iterator (ptr) to store location of element

reverse()

reverse(vbegin() vend()) Reverses the values in a vector (v)

sort()

sort(vbegin() vend()) Sorts the vector (v)

Table 16 ndash Vector Global Functions

156

list member functions

Some commonly used member functions of the list class are

List member Functions Effect

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

pop_front Removes the first element

push_back(value) Adds an element to the end of the vector containing the specified value

sort() Sorts the elements in the container from lower to higher

size() Gets the number of elements

swap() Exchanges the content of the list

Table 17 ndash List class Member Functions

cmath functions

Function Argument Result Returned Value Example Result

ceil(x) double double Smallest integer ge x

ceil(21) 30

cos(x) double double Cosine of x radians cos(10) 054

fabs(x) double double Absolute value of x

fabs(-15) 15

floor(x) double double Largest integer le 29

floor(29) 20

157

pow(x y) double double x to the yth power pow(24) 160

sin(x) double double Sine of x radians sin(10) 084

sqrt(x) double double Square root of x sqrt(4) 20

tan(x) double double Tangent of x radians

tan(10) 156

Table 18 ndash cmath Functions

158

String class

The string class defines many member funct ions A few of the basic ones are described below

Initialisation - constructors form

A string expression string str2 = str1

A character string literal string Intro = Programming with C++

A substring of another string object

string Intro = Capetown

string Mytown = Boars

string MyTown(Intro 4 5)

starts at character 4 (t)

with a length of 5 (or the rest of the string if shorter)

cout ltlt myTown ltlt endl

will produce an output town

Member Functions

length()

string myName = Sebastion

myNamelength()

will produce an output of 9

insert ()

Inserts a string into the current string starting at the specified position

string myName = Sebastion

string nameAdd = rjio

myNameinsert (2nameAdd)

cout ltlt myName ltlt endl

will produce an output Serjiobastion

erase()

Delete a substring from the current string

string myName = Sebastion

myNameerase (02)

cout ltlt myName ltlt endl

will produce an output bastion

replace()

Delete a substring from the current string and replace it with another string

string myName = Sebastion

string aName = renna

159

Member Functions

myNamereplace(3 6 aName)

cout ltlt myName ltlt endl

will produce an output Sebrenna

find()

Search for the first occurrence of the substring in the current string If the word is found return the position of the first character If not return -1

string sName

string findWord

position = sNamefind(findWord)

substr()

Returns a substring of the current string

string myName = Sebastion

string aName = myNamesubstr(0 3)

cout ltlt aName ltlt endl

will produce an output Seb

Non-member functions

getline()

string name

getline(cin name)

Table 19 ndash String Class Member Functions

160

A number of C++ operators also work with str ing objects

Operator

=

string fString = Hello

string lString

lString = fString

Assign a character (char ) to a str ing object

string aStringC

aStringC = Z

+

Concatenate two str ing objects

string str1 = C++

string str2 = Programming

string str3 = str1 + str2

+

Concatenate a string object and a character string literal

string str = Hello

string str1 = str + there

The same concatenation can be done in this way

str += there

+

Concatenate a string object and a single character

string str = Bye Bye

string strBye = str +

161

ASCII Character set

Decimal Octal Hexadecimal Binary Value Meaning

0 0 0 0 NUL (Null char)

1 1 1 1 SOH (Start of Header)

2 2 2 10 STX (Start of Text)

3 3 3 11 ETX (End of Text)

4 4 4 100 EOT (End of Transmission)

5 5 5 101 ENQ (Enquiry)

6 6 6 110 ACK (Acknowledgment)

7 7 7 111 BEL (Bell)

8 10 8 1000 BS (Backspace)

9 11 9 1001 HT (Horizontal Tab)

10 12 00A 1010 LF (Line Feed)

11 13 00B 1011 VT (Vertical Tab)

12 14 00C 1100 FF (Form Feed)

13 15 00D 1101 CR (Carriage Return)

14 16 00E 1110 SO (Shift Out)

15 17 00F 1111 SI (Shift In)

16 20 10 10000 DLE (Data Link Escape)

162

Decimal Octal Hexadecimal Binary Value Meaning

17 21 11 10001 DC1 (X ON) (Device Control 1)

18 22 12 10010 DC2 (Device Control 2)

19 23 13 10011 DC3 (X OFF)(Device Control 3)

20 24 14 10100 DC4 (Device Control 4)

21 25 15 10101 NAK (Negative Acknowledgement)

22 26 16 10110 SYN (Synchronous Idle)

23 27 17 10111 ETB (End of Trans Block)

24 30 18 11000 CAN (Cancel)

25 31 19 11001 EM (End of Medium)

26 32 01A 11010 SUB (Substitute)

27 33 01B 11011 ESC (Escape)

28 34 01C 11100 FS (File Separator)

29 35 01D 11101 GS (Group Separator)

30 36 01E 11110 RS (Request to Send)(Record Separator)

31 37 01F 11111 US (Unit Separator)

32 40 20 100000 SP (Space)

33 41 21 100001 (exclamation mark)

34 42 22 100010 (double quote)

163

Decimal Octal Hexadecimal Binary Value Meaning

35 43 23 100011 (number sign)

36 44 24 100100 $ (dollar sign)

37 45 25 100101 (percent)

38 46 26 100110 amp (ampersand)

39 47 27 100111 (single quote)

40 50 28 101000 ( (leftopening parenthesis)

41 51 29 101001 ) (rightclosing parenthesis)

42 52 02A 101010 (asterisk)

43 53 02B 101011 + (plus)

44 54 02C 101100 (comma)

45 55 02D 101101 - (minus or dash)

46 56 02E 101110 (dot)

47 57 02F 101111 (forward slash)

48 60 30 110000 0

49 61 31 110001 1

50 62 32 110010 2

51 63 33 110011 3

52 64 34 110100 4

164

Decimal Octal Hexadecimal Binary Value Meaning

53 65 35 110101 5

54 66 36 110110 6

55 67 37 110111 7

56 70 38 111000 8

57 71 39 111001 9

58 72 03A 111010 (colon)

59 73 03B 111011 (semi-colon)

60 74 03C 111100 lt (less than)

61 75 03D 111101 = (equal sign)

62 76 03E 111110 gt (greater than)

63 77 03F 111111 (question mark)

64 100 40 1000000 (AT symbol)

65 101 41 1000001 A

66 102 42 1000010 B

67 103 43 1000011 C

68 104 44 1000100 D

69 105 45 1000101 E

70 106 46 1000110 F

165

Decimal Octal Hexadecimal Binary Value Meaning

71 107 47 1000111 G

72 110 48 1001000 H

73 111 49 1001001 I

74 112 04A 1001010 J

75 113 04B 1001011 K

76 114 04C 1001100 L

77 115 04D 1001101 M

78 116 04E 1001110 N

79 117 04F 1001111 O

80 120 50 1010000 P

81 121 51 1010001 Q

82 122 52 1010010 R

83 123 53 1010011 S

84 124 54 1010100 T

85 125 55 1010101 U

86 126 56 1010110 V

87 127 57 1010111 W

88 130 58 1011000 X

166

Decimal Octal Hexadecimal Binary Value Meaning

89 131 59 1011001 Y

90 132 05A 1011010 Z

91 133 05B 1011011 [ (leftopening bracket)

92 134 05C 1011100 (back slash)

93 135 05D 1011101 ] (rightclosing bracket)

94 136 05E 1011110 ^ (caretcirumflex)

95 137 05F 1011111 _ (underscore)

96 140 60 1100000 `

97 141 61 1100001 a

98 142 62 1100010 b

99 143 63 1100011 c

100 144 64 1100100 d

101 145 65 1100101 e

102 146 66 1100110 f

103 147 67 1100111 g

104 150 68 1101000 h

105 151 69 1101001 i

106 152 06A 1101010 j

167

Decimal Octal Hexadecimal Binary Value Meaning

107 153 06B 1101011 k

108 154 06C 1101100 l

109 155 06D 1101101 m

110 156 06E 1101110 n

111 157 06F 1101111 o

112 160 70 1110000 p

113 161 71 1110001 q

114 162 72 1110010 r

115 163 73 1110011 s

116 164 74 1110100 t

117 165 75 1110101 u

118 166 76 1110110 v

119 167 77 1110111 w

120 170 78 1111000 x

121 171 79 1111001 y

122 172 07A 1111010 z

123 173 07B 1111011 (leftopening brace)

124 174 07C 1111100 | (vertical bar)

168

Decimal Octal Hexadecimal Binary Value Meaning

125 175 07D 1111101 (rightclosing brace)

126 176 07E 1111110 ~ (tilde)

127 177 07F 1111111 DEL (delete)

Table 20 ndash Full ASCII Table

169

Handy IDE Settings

Line Numbers onoff Tools | Options | Text Editor | CC++ | Line Numbers

Auto closing the console Tools | Options | Debugging | Automatically close the console window when debugging stops

Saves having to use system(pause)

170

REMAINING PAGES LEFT BLANK FOR NOTE TAKING

171

172

173

Peet Morris

peetmorrisgmailcom

C++ A Comprehensive Introduction

Arrangements

bull We Startfinish at 915am 500pm

bull Format two lectures per day (ask questions) hands-on at all other times

bull You should have Course book (copy of the slides at the back)

bull The course software is pre-installed on the machines

And also separately available from

The compilerIDE wwwvisualstudiocom

Notesslidesexercise files wwwpeetmcomC++introcoursezip

Your safety is important

Where is the fire exit

Beware of hazards

Tripping over bags and coats

Please tell us if anything does not work

Let us know if you have any other concerns

Your comfort is important

The toilets are along the corridor just outside the teaching rooms

The rest area is where you registered it has vending machines and

a water cooler

The seats are adjustable

You can adjust the monitors for brightness

What we assumehellip

What we assume

Experience of using another programming

language

Comprehensive Lots to get through

C++ and OOP

bull Created in 1985 by Bjarne Stroustrup C++ is a highly efficient

multiplatform low level Object Oriented Programming language

bull Latest version is C++17

stroustrupcom

Standard C++ Library

bull Written in the core language it is a collection of classes

(object definitions) functions and algorithms

See wwwcpluspluscomreference

IDEs amp Compilers

Visual Studio 2017

First Program

First application

include ltiostreamgt

using namespace std

int main()

int aNum = 0 aNum(0) or aNum0

cout ltlt Enter a number-

cin gtgt aNum

cout ltlt You entered ltlt aNum

return 0

hellip hellip

First Program

bull include ltiostreamgt

Adds the contents of the iostream header file into the program (for cout and cin)

bull using namespace std

So we donrsquot have to write stdcout ltlt and stdcin gtgt all of the time

bull cin is the standard input stream object that allows input from the keyboard

bull cout is the standard output stream object that allows output to the screen

bull int main() The programs entry point

Mandatory main function in every C++ program ndash always returns an integer value

First Program

bull int aNum = 0

Variable to hold a value of type integer (piece of machine memory referred to via the name aNum)

bull ltlt stream insertion operator ndash outputs to console

cout ltlt Enter a number-

bull gtgt stream extraction operator ndash waits for keyboard input

cin gtgt aNum

Other Types

Microsoft data types summary httpsdocsmicrosoftcomen-gbcppcppfundamental-types-cpp

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststack

Lots

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

x 1

y 2

x 3

y 4

p1

p2

x

y

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 copies the bit pattern from p1 to p2

x 1

y 2

x 1

y 2

p1

p2

Compound Types

Cannot define operators other than assignment

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 p2 compilation error

x 1

y 2

x 3

y 4

p1

p2

Compound Types

We can arbitrarily further compound things

struct point

int xint y

struct rectangle

point tlpoint br

struct line

point startpoint end

startxy

endxy tlxy

brxy

Compound Types

We can also group things using struct to create compound

types

struct point

int xint y

struct rectangle

point tlpoint br

int main()

rectangle r

rtlx = 1rtly = 2

rbrx = 3rbry = 4

int diff_x = abs(rtopLeftx - rbottomRightx)int diff_y = abs(rtopLefty - rbottomRighty)

cout ltlt area ltlt diff_x diff_y ltlt endl

r

tl

br

x 1

y 2

x 3

y 4

Using a Library Type

include ltstringgt

string s

cout ltlt What is your name

getline(cin s)

cout ltlt s ltlt

ltlt is

ltlt slength() ltlt

ltlt characters long ltlt endl

s

Other Types

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststackcomplex

Lots

8 bit Binary signed unsigned

00000001 1 1

00000010 2 2

00000011 3 3

01111111 127 127

10000000 -128 128

10000001 -127 129

10000010 -126 130

11111101 -3 253

11111110 -2 254

11111111 -1 255

00000000 0 0

00000001 1 1

00000010 2 2

signed vs unsigned ndash its all just 1s and 0s and adding

Adding rules

0 + 0 = 0

1 + 0 = 1

0 + 1 = 1

1 + 1 = 0 (carry 1)

1 + 1 + 1 = 1 (carry 1)

-126 + +3 =

10000010

00000011 +

10000101 = -123

-126 + -3

10000010

11111101 +

01111111 = 127 (why not -129)

Arithmetic Operators

+ Addition

- Subtraction and unary minus

Multiplication

Division

Remainder after division (moduloclock arithmetic)

int j k l = 10

j = l 3 js value will be three

k = l 3 ks value will be 1

Relational Operators

Evaluate to either true or false represented by integer values 1 and 0

== Equal to

= Not equal to

gt Greater than

lt Less than

gt= Greater than or equal to

lt= Less than or equal to

Increment and Decrement Operators

++ Increment

-- Decrement

Can be prefix or postfix

b = 3

a = b++ + 6 Add 6 to b then increment b a is 9 b is 4

b = 3

a = ++b + 6 Increment b then add 6 to b a is 10 b is 4

Assignment Operators

Symbol Operation Long Short

= Assign a = 2 a = 2

+= Assign with add a = a + 2 a += 2

-= Assign with subtract a = a ndash 2 a -= 2

= Assign with multiply a = a 2 a = 2

= Assign with divide a = a 2 a = 2

= Assign with remainder a = a 2 a = 2

Basic Control Flow - if

Sequence

What we have been doing already

Selection

if statement if this then that

if (boolean expression) if (score gt= 50)

statement cout ltlt Passed

Logical Operators

Boolean expressions may be combined using

ampamp And

|| Or

Not

Operands and result resolves being either true or false

if (x ampamp (y || z))

else

Precedence and Associativity table in course book

Logical Operators

a b =

true true true

true false false

false true false

false false false

a b =

true true true

true false true

false true true

false false false

a =

true false

false true

a ampamp b a || b a

Logical Operators

if (x ampamp (y || z))

else

The value 0 (zero) is evaluated to mean false any other value is true

x ampamp (y || z) result

false ampamp (false || false) falsefalse ampamp (false || true ) falsefalse ampamp (true || false) falsefalse ampamp (true || true ) falsetrue ampamp (false || true ) falsetrue ampamp (false || false) truetrue ampamp (true || false) truetrue ampamp (true || true ) true

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp (y | ~z))

else

Bitwise Operators

unsigned int x = 11

unsigned int y = 7

unsigned int z = 25

if (x amp (y | ~z))

else

11 (x) = 000010117 (y) = 0000011125 (z) = 00011001

~z = 11100110 (230 or -26)

y | ~z = 11100111 (231 or -25)

x amp (y | ~z) = 00000011 = 3

Operands and the result resolve to a values

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp 1) x is odd

if (x gt y)

x = x ^ y

y = y ^ x XOr swap

x = x ^ y

Control Flow - if else

Selection

ifelse statements

if (boolean exp) if (score gt= 50)

statement cout ltlt Passed

else else

statement cout ltlt Failed

Control Flow -

Selection

Conditional (or Ternary) Operator

boolean exp true result false result

cout ltlt score gt= 50 Passed Failed

Control Flow

if (x gt= y)

if (y 2)

else

if (x gt= y)

if (y 2)

else

Control Flow ndash else if

if (exp)

else if (exp)

else if (exp)

else catch all remaining

if (aNum == 0)

else if (aNum == 1 || aNum == 2)

else if (aNum == 3)

else catch all remaining

aNum not 0123

Control Flow - switch

Selection

switch multiple selection statements

bull test must be an integral value 1 10 A x eg not 1056

bull case values must be constants

switch (aNum)

case 0

break

case 1 Fall through

case 2

break

default catch all

break

Repetition - while

while (exp)

statements

while (n lt k)

cout ltlt Enter mark

cin gtgt mark

t += mark

n++

Repetition - for

for (init exp inc)

statements

for (t = 0 n lt k n++)

cout ltlt Enter mark

cin gtgt mark

t += mark

Preferable to while if the range is known

Repetition - for

for (init exp inc)

statements

for () infinite loop

break causes loop to exit

Preferable to while if the range is known

Repetition - do

do

statements

while (exp)

do

cout ltlt Continue yn

cin gtgt yn

yn = tolower(yn)

while (yn = y ampamp yn = n)

There are a huge number of exercises and we donrsquot expect you to attempt

them all during this course

bull If yoursquore completely new to programming itrsquos probably best to tackle

them in sequence

bull If yoursquove some programming experience you should read through the

exercise summaries and then start wherever you feel comfortable

Exercises

Exercises

Topics covered in ex1 ndash ex6

Functions = mini programs

bull Used to combine data with operations and through functional

decomposition to promote code re-use

bull Simplifies coding

bull Functions for discrete tasks

bull Not hundreds of lines of code

bull Consumer only needs to know

bull What goes in and what comes out

Functions

Like everything else the compiler needs to have seen a prototype or a

definition of a function before we can use it

Prototypes lets the compiler generate the correct code

int min(int int)

int min(int int int)

void drawLine(point to point from = 00)

int square(int)

int main()

void beep()

string getNextPacket(void)

Return type Function name (Parameter list)

min

int min(int int) min prototypes (forward declarations)int min(int int int)

int main()

Having seen the prototypes the compilerc = min(x y) can generate the required code

int min (int a int b) min function definition 1

return a lt b a b

int min (int a int b int c) min function definition 2

return min(min(a b) c)

inline min

int main()

c = min(x y)

inline int min (int a int b)

return a lt b a b

int main()

c = x lt y x y

inline int min (int a int b)

return a lt b a b

Function Parameters

bull Pass by Value

bull A Copy of the parameter is passed to the called function

bull Pass by Reference

bull The actual parameter is passed to the called function

bull Pass by Memory Address (pointer)

bull Same effect as Pass by Reference (tomorrow)

Pass by value

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

return n_copy n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 10

n_copy 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp x)

x just another name for real_n

return x x

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

x 10

Pass by value (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

n_copy = n_copy n_copy

return n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 100

n_copy 100

Pass by reference (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

real_n = real_n real_n

return real_n

100

100

Mem Addr Contents

0x2786 100

real_n 100

Mem Addr Contents

0x2786 100

real_n 100

const Parameters

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Recursion

unsigned long long int fibonacci(int n)

switch(n)

case 0 Fall through - [[fallthrough]]

case 1

return n

break

default

return fibonacci(n - 1) + fibonacci(n - 2) Very inefficient

Arrays (Part 1)

Data structure containing same type of data (int double string char object)

bull Built in to C++

bull Series of elements each containing one item of data (contiguous memory locations)

Size (number of elements) set at compile time

Arrays (1)

int numbers[10] an array of 10 integers Each box sizeof(int) bytes wide

numbers

index values - 0 to 9

0 1 2 3 4 5 6 7 8 9

Arrays (1)

int numbers[10] an array of 10 integers

int n = 0

cout ltlt numbers ltlt endl address of the first element

cout ltlt numbers[n] ltlt endl contents of the nth element

cout ltlt ampnumbers[n] ltlt endl address of the nth element

cout ltlt numbers + n ltlt endl address of the nth element

0 1 2 3 4 5 6 7 8 9

42 hellip hellip hellip hellip hellip hellip hellip hellip hellip

0x1526

Arrays

char name[5] name - an array of five characters

thing t[5] t - an array of five things

examMarks ndash an array of three doubles initialised to 12 39 95double examMarks[] = 12 39 95 C++11 - double examMarks[] 12 39 95

header ndash an array of fifty unsigned chars (bytes) first three elements set to 0 1 255 and the rest to zerotypedef unsigned char bytebyte header[50] = 0 1 -1

Arrays

Accessing array data

define MARKS 5 or const int MARKS = 5

double examMarks[MARKS]

for(int i = 0 i lt MARKS i++)

cout ltlt Enter Exam Mark

ltlt i + 1 ltlt

cin gtgt examMarks[i]

for(i = 0 i lt MARKS i++)

cout ltlt examMarks[i]

Multidimensional Arrays

Two dimensional array Two subscripts First identifies row second identifies column

const int students = 6 const int marks = 3

double examMarks[students][marks] = 0 set to zero

for (int s = 0 s lt students ++s)

for (int m = 0 m lt marks ++m)

cout ltlt Enter mark ltlt m + 1 ltlt for student ltlt s + 1 ltlt endl

cin gtgt examMarks[s][m]

00 01 02

10 11 12

20 21 22

30 31 32

40 41 42

50 51 52

Memory laid out in row column order (more later)

00 01 02 10 11 12 20 21 22 30 31 32 40 41 42 50 51 52

Matrices

Provider Link

Armadillo armasourceforgenet

Blitz blitzsourceforgenet

Boost boostorg

Eigen eigentuxfamilyorg

Elemental libelementalorg

FLENS apfelmathematikuni-ulmde

HSL hslrlacuk

LEDA algorithmic-solutionscom

PETSc mcsanlgov

SimuNova simunovacom

SuiteSparse facultycsetamuedu

TNT mathnistgov

Trilinos trilinosorg

ViennaCL viennaclsourceforgenet

Exercises

Topics covered in ex7 ndash ex16

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people and dice

Recap Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

1 61 61 61 61 6

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

3 11 24 56 12 3

C++ and OOP

Encapsulation Keeping related stuff together

Member functionsmethods

an objectrsquos capabilities functionality and performable actions

int Throw()

Member variablesproperties

an objectrsquos current state values its dumb data

int sides

Dice throwing 3

struct dice

int sides State

dice(int n) Constructor

sides = n

int Throw() Member function (method)

return (rand() sides) + 1

int main()

Could also use dice d1 = 6 or d16 syntaxdice d1(6) d2(6)

d1sides = 6 d2sides = 10 Allow this

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

struct diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

class diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing ndash professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

diceh my-appcpp

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

dicecpp

Compiler

diceobj my-appobj

Linker

my-appexe

other librarycode objectfiles

Dice throwing - professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Compiler

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

diceobj my-appobj

diceh dicecpp my-appcpp

Linker

my-appexe

other librarycode objectfiles

Only items provided to the end-usercustomer

Classes and Objects

the includeltstringgt header file from the standard library

class string

your cpp source code files

include ltstringgt include information about class string

string Name a class string instance

string Address a class string instance

Classes and Objects

the include carh header file

class car

your cpp source code files

include carh include information about class car

car c a class car instance

Classes and Objects

the include househpp header file

class house

your cpp source code files

include househpp include information about class house

house no1 a class house instance

house no2 a class house instance

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do with it

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

cstart()

cenginestart() Or should cstart() internally use enginestart()

OOD

Time for a break

class student

What properties and methods do we need

class student

public

string name

string DoB

string college

string bodCardNumber

float age()

int main()

student s

sname =

sDoB =

How to guarantee an objectrsquos integrity

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s

sname = Compilation errors

sDoB =

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s( )

cout ltlt sage()

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB Error ndash cant assign to a constant

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_name(name) m_DoB(DoB)

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_namename m_DoBDoB

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Exceptions

class student

int main()

try

student s( )

catch(const char msg)

cout ltlt msg ltlt endl

student initialisation failed

Exceptions

try

catch(const char msg)

cout ltlt msg ltlt endl

catch (const invalid_argument amp e)

cout ltlt ewhat() ltlt endl

catch (exception amp e)

cout ltlt ewhat() ltlt endl

catch ()

cout ltlt Something went wrong ltlt endl

student invalid arg 2

if using C++11 see stdcurrent_exception

Reuse and inheritance

Say we now want to add a new type to our system ndash class academic With what we have seen so far we would proceed something like this

class academic

private

string m_name string m_DoB

Duplicating everything we had in class student

class person (generalisation)

OOP is sometimes called Programming by Describing the differences

student and academic are all specialisations of a more generalised and abstract class ndash person

class student public personpublic

student(string name) person(name)

class academic public personpublic

academic(string name) person(name)

class personprotected

person(string name) m_name(name)

private

string m_name

public

base class derived class

derived class

Specialised State

class student public person

private

const string m_bodCard

public

student(string name string DoB string bc ) person(name DoB) m_bodCard(bc)

Multiple inheritance

class student public person public oxMember

public

student(string name int age string bc) person(name age) oxMember(bc)

class academic public person public oxMember

public

academic(string name int age string bc) person(name age) oxMember(bc)

Destructors

class foo

private

int m_x int m_y

public

foo() foo(0 0)

foo(int x) foo(x 0)

foo(int x int y) m_x(x) m_y(y) only ctor that accesses private state

~foo() any necessary tidy up code

Dice throwing 5

class diceprivate

int sides

public

dice(int n) sides(n)

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

srand((unsigned)time(0)) Happy with this

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 6

class diceprivate

int sides

public

dice(int n) sides(n)

classshared state static bool seeded = false

if (seeded)srand((unsigned)time(0))seeded = true

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

3 65 21 44 22 6

Dice throwing 7

class dice private

int sides

public

dice(int n) sides(n)

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

Dice throwing 7

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyesDouble 14 33 5

Dice throwing 8

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6) int t

for(int n = 0 n lt 5 ++n)

cout ltlt (t = d1Throw()) ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp t = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Dice throwing 9

class dice private

int sidesint _lastThrow

public

const int amp lastThrow read-only stateproperty

dice(int n) _lastThrow(-1) lastThrow(_lastThrow) sides(n)

int Throw()

return _lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp d1lastThrow = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Exercises

Topics covered in ex17 ndash ex22

Vectors

Like an array a data structure containing same type of data (int double object)

bull A container class part of the standard library a wrapper similar to arrays

Need to includeltvectorgt

bull Can resize grow shrink as elements are added or removed from the end

bull Algorithms to manipulate data

bull Iterators to cycle through all the elements

Vectors

vectorltchargt name(5) vector of five characters

vectorltthinggt t(5) vector of five things

vectorltdoublegt examMarks 12 39 95 initialised vector of three doubles

typedef unsigned char byte

a vector of fifty bytes first three elements set to 0 1 255 and the rest to zerobyte char b[50] = 0 1 255 fully populate array

calc itemCountint itemCount = sizeof(b) sizeof(b[0])

vectorltbytegt bytes (b ampb[0] + itemCount) then init with vector 50 items

Vectors (iteration 1)

include ltvectorgt

vectorltintgt vec(20) 20 ints

for(int i = 0 i lt vecsize() i++) input values into vec

cin gtgt vec[i]

for(i = 0 i lt vecsize() i++) output vec

cout ltlt vec[i] ltlt

Vectors (iteration 2) (C++11 and later)

for(type identifier container)

statements

vectorltintgt vec(20)

for (int amp i vec)

Vectors

Adding an extra element

cout ltlt Enter an Extra Value

cin gtgt aNum

vecpush_back(aNum)

for (int i = 0 i lt vecsize() i++)

cout ltlt vec[i] ltlt endl

cout ltlt vecat(i) ltlt endl same as above but range checked (ie slowsafe)

Vectors (most of the methods)

docsmicrosoftcomen-uscppstandard-libraryvector-classFull list

Method Purpose

assign Erases a vector and copies the specified elements to the empty vector

at Returns a reference to the element at a specified location in the vector

back Returns a reference to the last element of the vector

begin Returns a random-access iterator to the first element in the vector

capacity Returns the number of elements that the vector could contain without allocating more storage

clear Erases the elements of the vector

C++11 data Returns a pointer to the first element in the vector

C++11 emplace Inserts an element constructed in place into the vector at a specified position

C++11 emplace_back Adds an element constructed in place to the end of the vector

empty Tests if the vector container is empty

end Returns a random-access iterator that points to the end of the vector

erase Removes an element or a range of elements in a vector from specified positions

front Returns a reference to the first element in a vector

insert Inserts an element or a number of elements into the vector at a specified position

max_size Returns the maximum length of the vector

pop_back Deletes the element at the end of the vector

push_back Add an element to the end of the vector

rbegin Returns an iterator to the first element in a reversed vector

rend Returns an iterator to the end of a reversed vector

reserve Reserves a minimum length of storage for a vector object

resize Specifies a new size for a vector

C++11 shrink_to_fit Discards excess capacity

size Returns the number of elements in the vector

swap Exchanges the elements of two vectors

Vectors (iteration 3)

include ltalgorithmgt

vectorltintgt vec

for(int i = 1 i lt= 5 ++i)vecpush_back(i)

1 2 3 4 5

5 4 3 2 1

vectorltintgtiterator it

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Reverse the vectorreverse(vecbegin() vecend())

cout ltlt endl

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Arrays (2) (C++11 and later)

arrayltint 5gt arr Thin veneer over an array ndash so requires fixed size

arrfill(0) int j = 0

for (int amp i arr)

supports latest iteration style

reverse(arrbegin() arrend()) and iterators for use with algorithms

C++11 - Uniform initialisers

C++98

complexltdoublegt c( 271828 314159 )

int a[] = 1 2 3 4

vectorltintgt v

for( int i = 1 i lt= 4 ++i )

vpush_back(i)

C++11

complexltdoublegt c 271828 314159

int a[] 1 2 3 4

vectorltintgt v 1 2 3 4

Pointers ndash What

A pointer is a scalar variable that is used to hold the memory-address of

another variable or function the stored address is said to point to the thing

it holds ndash thus the name

Pointers have a type ndash the type of the thing they point to

int n = 10I (p) am a pointer to an integer and I point to n over thereint p = ampn

Pointers ndash Why

In no particular order

bull Because external libraries and APIs (like the operating system (all of them)) are written using them

bull Create custom data structures like linked-lists trees graphs etc

bull Create tables of functions or single functions for handling events callback or signals

bull Access data on to the heap (allocate memory dynamically)

bull Writecall functions that change their input parameters

1 2

3

4 5 6 nilhead

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

Recap - Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference using Pointers

int main()

int real_n = 10

cout ltlt square(ampreal_n)

cout ltlt real_n

return 0

int square(const int real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x5110 0x2786

real_n 0x2786

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt pcout ltlt pcout ltlt ampxcout ltlt xcout ltlt ampp

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

15438

11

15438

11

17216

Pointers

int main(int argc char argv)

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )(argv + n) ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv + 0 C

argv + 1

argv + 2

argv + 3

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

int main(int argc char argv[])

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )argv[n] ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv[0] C

argv[1]

argv[2]

argv[3]

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

Memory Stack vs Heap

Stack (last in first out - LIFO)

Space automatically allocated

The place where arguments of a function call are stored

The place where local function data is allocated (eg variables)

The place where a function leaves its result (if any)

Heap

Space must be explicitly allocated

A place for allocating memory that is not part of last-in first-out approach

ie dynamically allocated data structures that survive function calls

Stack vs Heap

int stackArray[100] Allocate 100 ints on the stack

stackArray[n] = 0 Do something with it

int heapArray = new int[100] 100 ints on the heap C++

int heapArray = malloc(100 sizeof(int)) 100 ints on the heap C

heapArray[n] = 0 Or (heapArray + n) = 0 Do something with it C++ and C

delete [] heapArray When youre done C++

free(heapArray) When youre done C

Exercises

Topics covered in ex22 onwards

If time allows look through the remaining

exercises and attempt those that fit best

with your requirements

  • C++ Notes TPLO 12-11-2019 Blackbox
  • C++ Slides TPLO 12-11-2019 - Copy

Exercises

Exercise 1 (Optional) Creating a first and default program 6

Exercise 2 CreatingModifying additional projects 26

Exercise 3 SearchString 29

Puzzled Programmers 29

The Collatz Conjecture 31

Mixing loops 33

PLUSPLUS Recursion 34

PLUSPLUS Base Two and Bits 37

Practising with Logical and Bitwise operators 38

Writing functions 42

Using a struct 43

PLUSPLUS When Things Go Wrong 44

The Monty Hall problem 46

More Functions 48

PLUSPLUS IsLeap in a line 49

Algorithms 49

Pass arguments by reference 52

Returning a value from a function 57

PLUSPLUS Arithmetic Bases 58

Searching for Sequences 61

PLUSPLUS Optimising Searching for Sequences 63

Evolving Searching for Sequences 64

Creating a class 65

Passing parameters 67

Using data members 69

More Objects 70

Using constructors 71

Separating declaration and definition 74

PLUSPLUS Using external libraries and third party header files 78

Creating an array to hold exam results 84

Linear Search 87

PLUSPLUS Debugging Linear Search 89

SortingSearching an array 90

PLUSPLUS Binary Search (Binary Chop) 93

Creating a multidimensional array 95

Creating a vector to hold exam results 100

Using insert() and iterators 103

Computing Fibonacci Numbers 110

Using pointers 114

Pointers and Arrays 116

PLUSPLUS Pointers and Arrays 119

PLUSPLUS Function pointers 122

main() and command-line arguments 126

EncryptDecrypt a file 128

Passing Arrays to functions 132

Base classes 137

PLUSPLUS Polymorphism 144

The PowerPoint slides entitled Exercises show the inclusive fromto exercise numbers which cover the topics discussed in the previous section It is not at all necessary to attempt to work through the entire quoted range variety is the spice of life ndash just choose those that appeal

1

1 Introduction Welcome to C++ A Comprehensive Introduction

These notes accompany the course delivered by Oxfords IT Services IT Learning Programme

If at any time you are not clear about any aspect of the course please make sure you ask your lecturer or demonstrator for some help If you are away from the class you can get help by email from your lecturer or from helpitoxacuk

Please also note that the university subscribes to Lyndacom ndash please check there for other C++ resources

11 What you should already know

The prerequisite for this course says that Either experience in another programming language or attendance on one of the PHP JavaScript or Python Kick-Start courses Is required

The more programming knowledge you have the better That said the documentation and lectures are structured such that those with very little knowledge should still be able to work through the course at their own pace

12 What you will learn

We will cover the following topics

Working with Microsofts Visual Studio Fundamental data types

Control Flow amp Iteration Header Files

Strings Functions

Arrays and Vectors Classes and Objects

Constructors and Destructors Member functions

Pointers And much more

13 Where can I get a copy of the softwaretools used

wwwvisualstudiocom (Microsofts C++ Compiler IDE and tools)

wwwpeetmcomC++introcoursezip (latest course code notes slides etc)

2 Things to understand

21 Compilers new and old

Students on this course often have to work with enhance or bug-fix existing code This sub-section is primarily for their consideration (it assumes some prior C++ knowledge)

2

Not all C++ compilers comply with the latest official ISO C++ standard (C++17) which was finally approved in December 20171

What does this mean It means that the code you write compile and run on one machine may not compile on the next machine if you are using a different compiler (even if it is using the same operating system) In this course you will be using Microsofts C++ Compiler (part of Visual Studio 2019)

Some older header files you may see with inherited C++ code are

include ltiostreamhgt have a h extension The C++ standard for this header file is include ltiostreamgt Your program may run correctly by adding a h but simply adding a h suffix will not work for all included files

include ltstringhgt has been replaced with include ltstringgt The stringh header file does not include C++ strings it includes C strings

include ltmathhgt has been replaced with include ltmathgt

The lesson to be learnt here is that a lot of C++ code you come across will have been created using older compilers Some of the header file and other code will not be recognised and may cause compilation errors when compiled on a machine which is more compliant with the C++ standard

If you are using the Gnu Compiler Collection (gcc g++ etc) you can specify standards compliancy via the ndashstd option eg -std=c++17 (other options are C++98

C++11 C++14)

Visual Studio can also be configured to use LLVM and clang Please see the relevant online documentation of how to install and use these if you wish to use them httpsllvmorgdocsGettingStartedVShtml

22 The C++ Standard Template Library (STL)

enwikipediaorgwikiStandard_Template_Library

The C++ programs you write will consist of the classes and functions that you write or modify (we provide partial solutions to every exercise)

However we will also look at what is still commonly referred to as the STL (now just part of the C++ Standard Library ) which holds a collection of existing classes functions and algorithms that you can use in the programs you will be creating

Some of the classes and template classes we will be looking at are

The string class The vector container template

The sort algorithm The list container template

The find algorithm

In addition you should also look at and be aware of another powerful library called Boost (parts of the STL come directly from the Boost library) wwwboostorg

The Boost library is easy to install (on any platform) as most Boost libraries are what is called header-only ie they consist entirely of header files containing templates and inline

1 A draft of this is included with your course files (n4660pdf) Its worth mentioning that this draft is in effect the published C++17 standard

3

functions and require no separately-compiled library binaries or special treatment when linking

23 Visual Studio 2019

What is Visual Studio (VS) VS is Microsofts freely available integrated development environment (IDE) and comes complete with optional compilerstools for a variety of languages We have only installed the IDE and the C++ compi ler (clexe etc) for this course

So what is a compiler

A compiler is a computer program that allows us to write programs in some specially defined language (unfortunately not English yet) in our case C++ (a so called high- level

language ) As you heard earlier the tex t we write in C++ is called source-code it is just simple text that one could write in Notepadexe for example

Sadly source-code is not directly understood by operat ing systems such as Windows Linux and macOS etc and it is the compilers job to convert our source-code into the terse concise and highly optimised machine-code that computers understand directly

Machine-code is often called executable or object-code and the compiled version of the source code is really just a file that contains numbers ndash a series of 8-bit bytes each holding a value between 0 and 255 The numbers either encode l ow-level instruct ions (code) or data that working together define the program Because these numbers may not encode displayable characters (see the ASCII table in the appendices to see a mapping between the numbers and the displayable characters) opening such a file an exe file in something like Windows notepad application would result in something like this being displayed (just the beginning shown)

However if we open this same executable file in a program that simply displays the files content as numbers and not what characters if any are represented by those numbers as Notepad is doing) we see this (the numbers are shown in base-16 or hexadecimal format)

4

The first two numbers 4D and 5A can be displayed as the text M and Z2 (see the first two characters at the top left in the previous notepad view of this file) 4D in base 10 is 77 and 5A is 90 ie the ASCII values for M amp Z (you can look these up in the ASCII table in the back of your course book)

Also take note of the line sequence starting 55 8B EC Then read on

2 MZ (0x4D5A) at the beginning of a file is an example of whats known as a magic number these are often used to identify a file type ndash in this case an MS-DOS executable file Trivia MZ are the initials of Mark Zbikowski the designer of the MS-DOS executable file format

5

If we have Visual Studio we can open the same file to see how such numbers translate into instructions and data

55 8B EC is the real beginning of our program In the above we see the numbers on the left and on the right what they actually mean Eg the first number 55 means push ebp which is an Intel CPU instruction Likewise 8B and EC together mean mov ebp esp The next line 81 EC C0 00 00 00 combines instructions and data and translate into sub esp 0C0h (subtract from esp the value C0 or 192 in base-10)

This is the entire program really the extra data shown in the previous views are for housekeeping

What does this program actually do then

Well youre about to find out ndash youre optionally now going to recreate it in Exercise 1

6

Creating your first program in Visual Studio 2019

Exercise 1 (Optional) Creating a first and default program

IMPORTANT

This exercise starts with a walk-through of using Visual Studio to create a new solution which you then go on to modify You should have already seen the steps needed to create a new solution in class so if youd rather just get on with the modification part simply open the (exercise solut ion)

f i rs t folder (in the Course folder) and double click the f i rs t s ln file If you choose to do this you can skip over the next few pages to the Explanation section (232) or even jump further on to Task 1 on page 14

Note You will not need to create any completely new programs during the course so even if you didnt fully follow the steps you can still safely move on to the modification part However if you really want to walk it through for yourself

Start the Visual Studio 2019 Integrated Development Environment (IDE) and create a new C++ Console application project You should have a shortcut to Visual Studio on your desktop failing that look for it on the Start menu

If they appear follow the prompts as shown below (if youre asked about keyboard mappings or Develop options select the C++ option)

7

Click Create a new project

Select Console App and click Next

8

Well locate the first project in a folder called first in your C drives Temp folder If the folder doesnt exist it will be created for you Click Create

Something like the above should appear (if you dont see the Solution Explorer panel open it via the View menu)

9

Alter the code adding the lines in bold as show here

include ltiostreamgt using namespace std int main() stdcout ltlt Hello Worldn system(pause)

Build and run the project by pressing the green arrow or by pressing F5

10

Explanation

Disclaimer at this stage you do not need to fully follow all of this just now

include ltiostreamgt

iostream is a standard C++ library file Files of this type are called header files They are text files usually containing C++ declarations definitions and code

Including iostream allows us to use some pre-defined objects to output messages to a console window This file must be included for any program that outputs data to the screen - or inputs data from the keyboard for that matter

The C++ compiler operates in passes through our code In the first pass ndash called the pre-processing pass ndash include directives are processed which are really text-substitution directives To be precise what include ltiostreamgt says is ldquoGo and find the text file called iostream and replace the directive with the contents of that filerdquo

The file name following a include directive can be enclosed in double quotes or chevrons ie include iostream or include ltiostreamgt The meaning of each is defined by the implementation (Microsofts C++ compiler in our case)

However it is common practice that if file name is in quotes it will be looked for locally first - in the same folder as the cpp file containing it and before being sought elsewhere Conversely if it is in chevrons the compiler will usually look for the file in a central include folder that was installed with the compiler ndash this folder is usually reserved for include files that come with the compiler as opposed to those that you might write yourself eg standard includes (like iostream) We therefore usually use quotes when we want to include our own custom project specific include files and chevrons when wanting to use include files that come with the compiler

You may also see that the filename sometimes has a h file extension This typically means that the header file being used is a C language header file and not a C++ one There are other variations (you are welcome to use your own) for example you might also see the occasional hxx file extension or something else entirely

using namespace std

The using namespace std code above doesnt actually appear in the automatically generated code In our project and solution files we will add it just after any include directives

namespaces in summary are very simple Everything within a namespace has a unique name and so theyre often used to help divide larger projects into more manageable chunks and to avoid name clashes

Standard C++ places a lot of its routines and functionality within a namespace call std Wed like to use this functionality and so we say we want to use all of the std namespace In the real world this isnt terribly good practice

11

However by declaring that were using namespace std throughout we can access members of this namespace without having to say exactly where they are (in which namespace) or worry about name clashes - where two objects in different files have been given the same name

The members of std that we will be using throughout are

cin (Console In) and cout (Console Out) and we must use include ltiostreamgt in order to use them

endl - is a stream manipulator that writes a new line to output endl stands for end

of l ine and is pronounced end all

If we dont declare that we were using the std namespace (which is the case in the automatically generated code) we have to prefix any use of cin cout and endl with std eg stdcin stdcout stdendl If youve added the using namespace std directive you may now remove the std in front of the stdcout ltlt Hello Worldn line

int main()

This is the entry point to our program ndash every C++ program must have this same entry point defined main() is a function the body of a function is defined within the opening and closing braces that come after its name The int to the left of main() says that this function returns (or resolves to beevaluates to) an integer value Returning a value requires you to use a return statement However as it is normal practice to simply return the value zero if you omit the return statement a value of zero is returned for you (only where main is concerned) If you want to explicitly return the value yourself you could modify the code to read

int main() stdcout ltlt Hello Worldn system(pause) return 0

So why return a value anyway Our added line return 0 means in this case that our main doing whatever it does as part of its function eventually resolves to the value 0 The value is returned to whatever called our programs entry point in this case and as usually that is the operating system ndash which has been waiting for us to return a value at this point However the operating system will simply ignore whatever value we ultimately return Why do it then

12

Consider the case when one of your programs needs to run another program to perform a part of its entire function Your main program needs to start this other program and wait until it completes successfully before continuing See the description of the system(pause) code line below

stdcout ltlt Hello Worldn

cout is an object declared in iostream ndash think of its name meaning console out Anything sent to cout using the double chevron operator ltlt appears on the console the

The n in the text means that cout should also output a carriage-return linefeed sequence (terms taken from the days of typewriters and telex machines) basically it means start any new output on a newline underneath the current line An alternative to using n is to use endl eg stdcout ltlt Hello World ltlt endl endl does more or less the same thing as n

system(pause)

system() is a standard function that is used to run an external program (here thats a standard Windows program called pauseexe) The system() function waits for the pause program to complete before continuing Going back to the discussion on return 0 earlier this is an example of one program starting another ndash here thats our program starting the pause program The pause program returns a value as part of its completion and we can examine that if we want Programs usually return 0 for success or some other integer value that means something went wrong ndash the value returned indicates what went wrong Ie a returned value of say 42 might mean that we cant answer the ultimate question with this computer3

So what is pause pauseexe is a standard Windows program that simply outputs the message Press any key to continue and then waits for a key to be pressed before exiting We use that facility here so that our program doesnt simply shutdown and disappear as it falls off the end of main()s closing or encounters a return statement If we did allow it to exit we would hardly have time to examine our programs output before it disappeared off the screen Try that and see (comment out the line using a double-slash like this system(pause))

If you run any of the course code on Linux or a Mac youll need to change this line to something like cinget()

3 An unashamed reference to the Hitch Hikers Guide to the Galaxy and the Deep Thought computer

13

Your projects default code template

In the course exercises when it comes to you writing code we will always ask you to open and then modify a partially complete projectsolution so you wont have to fiddle with projects and boilerplate code like this again

Nevertheless should you wish to start from scratch or simply experiment with Visual Studio we recommend using the code below as a starting point

include ltiostreamgt using namespace std int main() Start coding after here system(pause) return 0

14

Task 1

Immediately above system(pause) Replace the stdcout ltlt Hello Worldn line with the code shown here

int anum = 0

cout ltlt Enter a number

cin gtgt anum

cout ltlt The number you entered is

ltlt anum

ltlt endl

Test your modified program Tip remember you may hit the F5 key to build and then run your program

Try entering some text instead of a number Did it work

Alter the spacing (use of spaces and tab characters) in your code ndash does the C++ compiler care about this so called whi tespace

The statement int anum = 0 defines a variable (a memory location) which we will refer to in our code as anum to store a number of type int to hold an in teger (ie 1 -4 27) The memory location is being initialised with a value of 0 here It is good practice to initialise variables when you define them In C++11 a new type of uniform initialisation syntax was introduced and also encouraged eg int anum 0

cout ltlt Enter a number cout is a name that belongs to the namespace std The ltlt is called the stream insert ion operator When the program executes the value to the right of the operator (Enter a number) is inserted in the output stream and ultimately output to console window

cin gtgt anum cin is the input stream object of the namespace std gtgt is called the stream extract ion operator and is used here to read a number from the keyboard

cout ltlt The number you entered is ltlt anum ltlt endl This statement concatenates the output by using multiple stream insertion operators ltlt endl is the stream manipulator that adds a new line

The next Exercise starts on page 26 The pages between here and page 26 contain

code that you may like to try out by further modifying this project if not just read through the textcode until you get to page 26

15

Arithmetic Operators

Most computer programs perform arithmetic calculations Table 1 summarises the standard C++ arithmetic operators When working with integer division where both the numerator and denominator are integer the expression 15 6 evaluates to 2 To get the remainder after integer division you would use the modulus operator Note the modulus operator can only be used with integer operands

To establish the complete result of the following integer division 156 requires two operations

15 6 = 2

15 6 = 3

The result being 2 remainder 3

C++ Operation C++

arithmetic operator

Algebraic expression C++ expression

Addition + y + 6 y + 6

Subtraction - a - b a - b

Multiplication c times d or cd c d

Division xy or y

x or yx x y

Modulus p mod q p q

Table 1 - C++ arithmetic operators

Other fundamental data types Table 2 shows how you would declare and initialise four other data types for use in programs (there are more data types available)

16

Data type Example

Float float aFloat = 1234

Double (the precision of a Float) double aDouble = 123456

Char char aChar = A

Bool bool aBoolean = true

Table 2 - C++ numerical types4

Characters

Characters are normally stored in variables of type char but can also be stored as in t(eger) data types Characters are represented as single byte integers in the computer so it is possible to output a character as an integer or as a character

All characters have a numerical representation in the computer and the ASCII (American Standard Code for Information Interchange) character set shows each character and its decimal equivalent (also note that a combination of characters may be used to form more complex Unicode characters) See appendix 111

Characters can be read in with the following statements

char aChar declares a variable (aChar) of type char

cin gtgt aChar this statement is used to read a character into the variable aChar

Note After entering a character the ltENTERgtkey must be pressed before the character is read by the program

The following four statements correctly declare a variable of type char output a user prompt then read a character and store it in the variable aChar

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar

4 See httpencppreferencecomwcpplanguagetypes for a complete list (or the official ISO standard of course)

17

Header (include) Files

So far weve seen that to use certain functionality we had to include ltiostreamgt We have to do similar to use other functionality which is not part of the code C++ language ie we will need to include anything that comes as part of the standard library

In its current form Visual Studio comes with the following include files (most of which are standard files)

h files (95 C language files)

agentsh agileh ammintrinh amph amprth amprt_exceptionsh amp_graphicsh amp_mathh amp_short_vectorsh armintrh arm_neonh cfguardh collectionh comdefh comdefsph comiph comutilh concrth concrtrmh ConcurrencySalh concurrent_priority_queueh concurrent_queueh concurrent_unordered_maph concurrent_unordered_seth concurrent_vectorh crtdefsh crtversionh delayimph dloadsuph dvech ehh emmintrinh excpth fvech gcrooth immintrinh internal_concurrent_hashh internal_split_ordered_listh intrinh intrin0h invkprxyh iso646h ivech limitsh mm3dnowh mmintrinh nmmintrinh omph pgobootrunh pmmintrinh pplh pplawaith pplcancellation_tokenh pplinterfaceh ppltasksh ppltaskschedulerh pplwinh rtcapih salh setjmph setjmpexh smmintrinh srvh stdargh stdboolh stdexcpth stdinth tmmintrinh typeinfoh use_ansih vadefsh varargsh vcclrh vccorlibh vcruntimeh vcruntime_exceptionh vcruntime_newh vcruntime_new_debugh vcruntime_startuph vcruntime_stringh vcruntime_typeinfoh wmmintrinh xatomich xatomic0h xkeycheckh xlocinfoh xmmintrinh xsmf_controlh xstring_inserth xtgmathh xxamph xxamp_inlh ymathh yvalsh zmmintrinh

115 C++ files

algorithm allocators any array atomic bitset cassert ccomplex cctype cerrno cfenv cfloat chrono cinttypes ciso646 cliext climits clocale cmath CodeAnalysis codecvt complex condition_variable csetjmp csignal cstdalign cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cuchar cvt cwchar cwctype deque exception experimental filesystem forward_list fstream functional future hash_map hash_set initializer_list iomanip ios iosfwd iostream istream iterator limits list locale Manifest

18

map memory msclr mutex new numeric optional ostream queue random ratio regex scoped_allocator set shared_mutex sstream stack stdexcept streambuf string string_view strstream system_error thr thread tuple typeindex typeinfo type_traits unordered_map unordered_set utility valarray variant vector xcomplex xfacet xfunctional xhash xiosbase xlocale xlocbuf xlocinfo xlocmes xlocmon xlocnum xloctime xmemory xmemory0 xstddef xstring xtr1common xtree xutility xxatomic

Strings

Next to numbers strings are the most commonly used data type in programming

A string is both a datatype (string) and also literal character data ie a sequence of characters such as Oxford or StAndrews In C++ string literals are enclosed in quotes The quotes are not part of the string they identify the data type as a string

Actually this isnt quite true the double quoted strings are a sequence of characters and are taken from the C programming language The things declared of the string type are C++ string objects ndash which may be initialised using the C language literal

C++ strings can be declared and initialised in this way

string institution = Oxford

string name = Peet

To use the string type in your programs add the header file include ltstringgt at the top of your program This allows the use of part of the C++ library of classes called the string class (and its member functionsmethods explanations will follow soon)

Of course strings are normally used when requesting an input Consider this code

string aName aDept Two string objects

cout ltlt Enter your full name

cin gtgt aName

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

19

If in answer to the first prompt we were to enter say Fred Brooks 5 the interaction and output of our program would immediately result in this

Enter your full name Fred Brooks

Enter your department Fred is associated with Brooks

Why When reading in a string with a space such as FredltspgtBrooks only the first part Fred is read into aName ndash and the input is said to be space delimited by cin ndash and consists of two separate inputs (so the Brooks parts is read into the aDept string variable)

We could use multiple prompts to read in a name of course but this is inconvenient

To handle this situation we can use the standard getline(cin aName) function to read in a name instead of using cin gtgt aName This reads all key-strokes into aName until the ltENTERgt key is pressed at which point it returns a string containing all of the characters from the input

cout ltlt Enter your full name

getline(cin aName)

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

The string class has many useful functions you can use to manipulate strings An example is the length() member functionmethod

string aName = Fred Brooks

cout ltlt The length of the string aName is ltlt aNamelength() ltlt endl

This statement will output - The length of the str ing aName is 11

See section 12119 for more information on the string class and its member functions

5 Fred Brooks is a real person and a legendary computer scientist httpenwikipediaorgwikiFred_Brooks

20

The LF (Line Feed) Problem and Reading Keys

Continuing on consider the following code

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

string aName

cout ltlt Enter your full name

getline(cin aName)

cout ltlt You entered ltlt aName ltlt endl

system(pause)

The intent here is to first ask for a character and then to use getline() to ask for a name

If only things were that simple

If we were to enter say a Z to satisfy the first prompt the program would immediately output

Enter a character Z

You entered Z

Enter your full name You entered

Press any key to continue

The problem here is that being a keyboard key theltENTERgt key is itself being seen as a valid input so when we enter Z followed by the ltENTERgt key were actually entering two keys ndash Z and the ltENTERgt key The first keys placed into aChar whilst the enter key is left in the keyboards buffer This is quite reasonable if you think about it you entered two keys (Z and ltENTERgt) but provided a home for just one of them in aChar

Ok so whats the problem Well the problem is that we really need to use something like getline() to read text that contains spaces and it just so happens that getline() given this scenario will see the residual ltENTERgt key left in the buffer and it will assume that you didnt enter anything you just hit the enter key

This problem - that of having a mischievous ltENTERgt key waiting to surprise us ndash will occur whenever you read a key from the keyboard using cin Luckily theres an easy fix as we can use another input function to read and then discard the waiting ltENTERgt key Its called cinget() Here is a modified version of the code above that fixes the problem

21

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

cinget() REMOVE THE ENTER KEY discarding the got character

string aName

cout ltlt Enter your full name

getline(cin aName)

Used like this cinget() reads and discards a character from the input stream You can do the same using cinignore() cinget extracts a single character from the stream and returns it cinignore() extracts any number of characters and discards them (the details are specified via passed parameters to the function) or a single character if no arguments to the function are provided

You can easily use cinignore() to ignore a number of characters or until a certain token (character) is met eg the following code reads in a users first and last names and then outputs their initials

22

char first last Two 8-bit characters

cout ltlt Please enter your first name followed by your surname

first = cinget() Get one character

The first parameter is the maximum number of characters to

extract (and ignore) The second parameter is a

delimiting character The function stops extracting characters

as soon as an extracted character matches this one

cinignore(2566 ) Ignore until a space is seen

last = cinget() Get one character

cout ltlt Your initials are ltlt first ltlt last ltlt endl

Casts

On occasions in your programs you may want to store a value in a variable of a different type (when there is a danger of a loss of information the compiler will issue a warning for example when storing a double in an int) If you store a double as an integer you lose information in two ways

any mantissa (fractional part) will be lost

the magnitude of the double being stored may be too large to fit into the integer

Eg it is not possible7 to store 6678 x 10000 as a 16-bit unsigned integer because 667800 is 10000010011011100 in binary (17-bits) and is therefore larger than the maximum storable value of 65535 (1111111111111111) However you can store 1230 as an integer8

When you need to represent a value as a different type you can use the static_cast notation as shown here to change a double to an integer

6 If this is exactly numeric_limitsltstreamsizegtmax() there is no limit As many characters are extracted as needed until delim (or the end-of-file) is found

7 Actually the result of attempting to store 66780 in a 16-bit unsigned integer will be 10011011100 or 1244 Do you see how this value comes about

8 Also see the (demonst rat ion) L imi ts project

23

int anInt

anInt = static_castltintgt(doResult) where dResult is a double

You may also use the following historic classic C-style9 notation to cast to different data types

anInt = (int)dResult

Eg to change an integer to a character

char aChar

aChar = static_castltchargt(bInt) where bInt is an integer

You may also combine this using the

object-constructionfunction-call syntax of C++ eg

double d = 314157

int n = (int)d Convert ds value to an integer

int j = int(d) Ditto

9 C-style casts are usually considered to be too powerful ndash in that they indiscriminately allow unsafe and downright dangerous conversions C++ casts were introduced to solve this problem

24

Other Cast Types

Although outside the scope of this introductory course for reference here is a summary of the cast types in C++ (feel free to skip this for now and come back to it at a later time)

static_castlttypegt(object)

The type parameter must be a data type for which there is a known method for converting object to whether this be a built-in or through a casting function (constructor) All types of conversions that are well-defined and allowed by the compiler are done using static_cast

The static_cast operator may be used for operations such as converting a pointer of a base class to a pointer of a derived class converting numeric data types such as enums to ints or ints to floats However static_cast conversions are not necessarily safe as no run-time type check is done which can cause casting between incompatible data types for example initialised pointers However this is checked at compile time to prevent casting obvious incompatibles Also be aware that a static_cast between pointer of base to pointer of derived may produce an erroneous result (where the actual object pointed to is of type base not derived)

dynamic_castlttypegt(object)

In the C++ programming language the dynamic_cast operator is a part of the run-time type information (RTTI) system that performs a typecast Unlike the static_cast the target of the dynamic_cast must be pointer or reference to class Unlike static_cast and C-style typecast (where a type check is made during compilation) a type safety check is performed at runtime If the types are not compatible an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers)

reinterpret_castlttypegt(object)

Allows any pointer to be converted into any other pointer type Also allows any integral type to be converted into any pointer type and vice versa

The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument (unlike static_cast but like const_cast the reinterpret_cast expression does not compile to any CPU instructions It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type)

You cannot cast away a const or volatile qualification You can explicitly perform the following conversions

const_castlttypegt(object) A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is

25

identical except for the const and volatile qualifiers For pointers and references the result will refer to the original object For pointers to data members the result will refer to the same member as the original (uncast) pointer to data member Depending on the type of the referenced object a write operation through the resulting pointer reference or pointer to data member may produce undefined behaviour

26

Exercise 2 CreatingModifying additional projects

Examine how comments look in a program

Examine the use of some fundamental data types

Using different data types

Using the cast operator

Using the string class

Task 1

Open the skeleton project called EvenI

The project folder is

EvenIEvenI s ln

Modify the projects code in to prompt for two numbers of type double and two numbers of type integer

The program should output the sum the product and the difference of the double numbers Also output the quotient and the fractional part of the two integers10

Youll need something along the lines of hellip

double aDouble double bDouble

etc

To read a number into aDouble you could use

cin gtgt aDouble

Task 2

Modify your EvenI program to read in two characters Enter the characters a and Z

Output the two characters with the character case changed ie a becomes A and Z becomes z

You will need to look online or at in 12120 to establish the ASCII integer values of each character hellip you can alter a characters case by treating it as an integer and

To convert integers (or the results of evaluating integer expressions) to say characters we need to use a cast Eg

int i = 65

cout ltlt static_castltchargt(i + 32)

10 Trivia quotient comes from the Latin quotiens for how many times For example when dividing twenty by three the quotient is six and two thirds You can use a modulus b to get the fractional part

27

then by addingsubtracting tofrom it

Task 3

Open the skeleton project called Address and modify it so that it can be used to collect some user data

Output this collected data to screen as shown in Figure 1

Note that youll have to have include ltstringgt in order to use getline()

Figure 1

Visual Studio builds projects in one of two different modes ndash Debug or Release we will always use the Debug mode (a Release build is normally only used when a product is being beta tested ie late in the cycle)

When using Visual Studio (or most other IDEs for that matter) we normally do not have to concern ourselves with the location of the executable that is built by the program ndash because we normally run it from within Visual Studio itself However and just for your information really the exe for a debug build will always be located in the Debug folder immediately below the projects root folder ie for this project Addressexe is located in the (exercise solut ion) Address Debug folder whilst a version built in Release mode would be in the (exercise solut ion) Address Release folder

Debug builds contain extra diagnostic code that is automatically inserted by the compiler

28

3 Basic Control Flow The programs you have created so far are limited in that they run through a sequence of instructions once and then stop Most computer programs will make decisions and carry out different actions determined by the user input

C++ has three kinds of control structures

Sequence statement - the computer executes the statements one after another All the programs you have written so far use sequence statements

Select ion statements - if ifelse switch

The if selection statement selects an action if a condition is true or skips the action if the condition is false

The ifelse selection statement selects an action if a condition is true or performs a different action if the condition is false

The switch multiple selection statement can be used to perform many different actions based on a character or integer value

Repeti t ion statements - while for do while

The while and for statements perform actions within their bodies zero or more times If the loop condition test is initially false no actions will occur

The dowhile statement will perform the actions in the body at least once (the test ndash as to whether to continue - is at the end)

Selection - ifhellipelse statement

The if selection structure is used to choose among alternative courses of action The structure of the statement is

if(mark gt= 50)

cout ltlt Passed

else

cout ltlt Failed

If the condition (mark gt= 50) is t rue the statement following it is executed cout ltlt Passed

If the condition is false the statement is ignored and control is passed to the else part of the selection and statement following else is then executed cout ltlt Failed

ifelse selection statements can also be nested within other ifelse selection statements

29

Exercise 3 SearchString

Task 4

Open the skeleton project called SearchStr ing

You will need to include ltstringgt at the top of the code to complete this exercise See page 158 for more on the string class functionality

Modify the program to display a string of text to the user

The user should then be prompted to select a word from the sentence and input a replacement word Your program should replace one with the other You will want to See section 12119 on string functionality

The prompting string should be shown both before and after the update

Tips

Given a string s initialised to

string s = C++ at the University of Oxford

string t

int i = sfind(U)

cout ltlt i ltlt endl 11

t = ssubstr(0 i) bit before U in t

t = t + ancient + + ssubstr(i) +

Outputs C++ at the ancient University of Oxford

cout ltlt t ltlt endl

Puzzled Programmers

Using if if else nested ifs switch and the conditional operator -

Task 1

Solving puzzles

Open the I fp project and WITHOUT compilingrunning it determine its output

You will need to consult the operator precedence table in section 1216

You shouldnt compile or run the program to start with ndash the idea here is for you to determine its output on paper11

Tip you might want to consider tidying up the codes layout before attempting to solve it

void out(int n) is a function We havent covered functions yet but it makes sense to use one here and so we have Suffice to say for now that using out(some value) will output the value to the console window

11 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

30

Functions will be explained fully soon

Compile and run the program ndash if your workings from Step 1 differ from the output you should determine where you went wrong

Selection - switch multiple selection statement

The switch multiple selection statement can be used to perform many different actions based only on a single integer value Note however the switch statement can only be applied in narrow circumstances The tests must be constants and be integers Lets compare the two statements

int num switch(num) case 1 cout ltlt num = one

double num switch(num) case 11 cout ltlt num = 11

OK ndash Test is 1 a constant and an integer NOT OK ndash Test is not constant integer

Repetition ndash while dohellipwhile and for loops

The while statement is commonly used to carry out repeated steps perhaps reading in values before doing a calculation on values read in The format of the code is

while(condition)

statement

This can be read as whi le the condition is t rue continue to do the statements until the condition is false

31

The Collatz Conjecture

Win a million dollars

Task 1

Open and complete the project called Col latz (use a while() loop)

Given any positive integer if the number is even divide it by two else treble it and then add one If the result is one stop else repeat the process

The Collatz conjecture says that given any starting value the process above will eventually hal t (goes to one and stops)

Eg setting n to 9 as a starting point successive values would be

28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is not known whether the Collatz conjecture is true Fame and fortune await anyone who can prove it httpenwikipediaorgwikiCollatz_conjecture

A Collatz tree as visualised by Edmund Harriss

32

This image is a sample from the colouring book Visions of the Universe by Alex Bellos and Edmund Harriss

Get your own hi-res version for colouring-in here and see here for an explanation

33

Task 2

Re-implement your code so as to use a for() loop (this will be a lot easier than you might first think)

Not essential for this task but as we mention for loops you might like to look at the for project to see how a for loop can be animated to show how the three sections of it work in order

Mixing loops

Task 1

Open and modify the skeleton project called Factor ial

Modify it to use different repetition statements to calculate and display the factorial of a value entered by the user (they should enter a value between 1 and 10 inclusive)

Example use a while loop to prompt for an input value (between 1 and 10) and a for loop to calculate the factorial result

The output should be like that shown in Figure 2 below

Factorials12

The factorial of 5 (usually written as 5) is

1 x 2 x 3 x 4 x 5 = 120

If factorials are new to you think of them as defining the number of ways to arrange n items

To avoid displaying results in scient i f ic notat ion use

cout ltlt setprecision(0) ltlt fixed

setprecision() requires include ltiomanipgt

12 0 Is defined to be 1

34

Figure 2

PLUSPLUS Recursion

Come back to this after weve covered functions

Note that our solution optionally also uses a function and recursion to find the same factorial If you open it you will see that just after where we perform the output above we have commented out an extra line of code (uncomment and rebuild to see it in action)

We havent covered recursion in this C++ course yet but its basically the process of solving a problem in terms of smaller versions of the same problem Since the problem gets smaller each time the process eventually terminates in a problem (the base case) that can be solved directly When defining a recursive function be sure of three things 1 The problem gets smaller each time 2 Include a solution for the base case And 3 Each case is handled correctly

The recursive function looks like this ndash add then test it in your own solution

Factorial function using recursion

long long int recur_factorial(long long int n)

return n lt 1 1 n recur_factorial(n - 1)

The question mark is the conditional operator and is used with the colon to form the functional equivalent of an if then else

35

If the expression before the is true then the expressionstatement to the left of the is evaluated otherwise the one after the is evaluated Eg these are equivalent

x boo() hoo()

if(x)

boo()

else

hoo()

4 Logical and Bitwise Operators

41 Logical

Quite often we will want to perform some action if two things are true and we can achieve this using nested if statements eg

if(onething == true)

if(secondthing == true)

do something

In C++ we can achieve the same result through the use of the l ogical And operator - ampamp

if(onething == true ampamp secondthing == true)

do something

ampamp is a binary operator ndash meaning that it takes two arguments (nothing to do with base 2) eg Op1 ampamp Op2 The expressions Op1 and Op2 must be capable of evaluating to t rue or false (false in C++ has the value 0 whilst any other value is considered true) and both Op1 and Op2 have to be true in order to have the conditional part execute eg if(x ampamp y) Z = 10 Here both x and y must have non-zero values in order for z to be assigned the value 10 Note again that this is equivalent to

36

if(x)

if(y)

z = 10

The truth table for logical And is as follows ndash note that both Op1 AND Op2 have to be true for the result to be true

Logical And

Op1 Op2 Result

True True True

True False False

False True False

False False False

We also have a Logical Or operator (||) in C++ and its truth table looks like this ndash note that its one OR the other that has to be true in order for the result to be true here

Logical Or

Op1 Op2 Result

True True True

True False True

False True True

False False False

The remaining logical operator we have is the unary Logical Not (the exclamation mark is used for this)

Logical Not

Op1 Result

True False

False True

Logical ampamp and Logical || short-circuit ie for ampamp if the expression on the left-hand side is found to be false then the expression on the right is never evaluated as the whole will evaluate to false (because to be true both sides have to be true and we know that the first one is false at this point)

37

The same is true for logical || in that the right-hand expression is not evaluated if the left is found to be true (the whole will evaluate to true because the left is true so there is no need to evaluate the right-hand expression)

42 Bitwise

PLUSPLUS Base Two and Bits

We also have bitwise versions of the logical operators ndash plus some extra ones Bitwise operators work on a variables individual binary bits ndash rather than the value of all the bits taken as a whole For bitwise And we do not use ampamp but use just a single amp The same is true for bitwise Or we just use a single | and not || Bitwise Not is a little different we use ~ (the tilde) for bitwise Not

The additional bitwise operators we have are for bitwise XOr ndash for which we use the ^ symbol and lastly for left and right bit shifting we use ltlt and gtgt

Bitwise operators work on binary bits (1s and 0s) whereas the logical operators work on values equating to either true or false

For example consider the following code

int w = 10 int x = 42

int y = w amp x

int z = w ampamp x

cout ltlt y ltlt endl

cout ltlt z ltlt endl

The base-2 binary representation of 10 is 001010 and for 42 it is 101010 So w amp x means

001010 101010 amp ------ 001010 ------

Remember And is one and the other

Now let us consider w ampamp x Here were not interested in ws or xs bits just whether when taken together they are zero or something else Here both are non-zero so both are considered to be t rue and if we refer to our truth table from earlier on we will see that the result will be t rue When we assign that to an integer like were doing here the value assigned will be 1

38

Shifts

The shift operators shift the binary bits left or right Bits that do not fit fall off the ends and bits are replaced with zeros when shifting left ie bits do not rotate and come back on the other end again When shifting right the sign-bit may be preserved depending upon whether youre using a signed or unsigned integer

Shifts are useful for all sorts of things but one of the obvious uses is to multiply and divide eg x = 2 x = x ltlt 1 shifts the bits in x one place to the left so given that xs value is 00000010 in binary x = x ltlt 1 turns x into 00000100 which is 4 So x = x ltlt 1 is like saying x = x 2 You can of course divide by right shifting

XOr

The rule for XOr is one or the other but not both ie 1 ^ 0 = 1 (just like 1 | 0) but whereas 1 | 1 = 1 with 1 ^ 1 the answer is 0

Note that we do not have a logical XOr operator in C++ as we can just use = (not equal to) ndash see the (demonstrat ion) Logical XOr project

Practising with Logical and Bitwise operators

You will need to use the Precedence and Associativity table in 1216 to complete these tasks

Task 1

Open the Logical project As earlier DO NOT compilerun this yet

You will need to consult the operator precedence table in section 1216

On paper determine the programs output13

Run the program ndash output as expected

Task 2

Open the Bitwise ndash

unsigned project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Unsigned The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

13 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

39

PLUSPLUS Signs and bits

Task 1

This one is tough as you should really know something about Twos Complement arithmetic to complete this

Open the Bitwise ndash s igned

project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Signed The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

5 Introduction to Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine (which will also be a function) Encapsulat ion is data information or detail hiding If youre mathematically minded you may think of a C++ function as being very similar to one in mathematics ie a mechanism for mapping one thing to another

Once a function is written the detail of how it works is not important It is only necessary to understand what if any inputs the function needs (its parameters) and what output is produced (the functions return value)

The use of functions provides several benefits but the main one is that it makes programs significantly easier to understand and maintain The main program function can consist of a series of function calls rather than hundreds of lines of code A second benefit is that well written functions can be reused across multiple programs

You have to tell the compiler about a function before you use it and this is normally done using a prototype early in the program A function prototype consists of the return type a funct ion name and a parameter l is t - indicating the data the function will receive ndash and is terminated using a semicolon Eg

int someFunc(int int)

This tells the compiler that there is a function (somewhere) called someFunc that takes two integers as its input and returns an integer value for its output

40

Using a prototype is a way of telling the compiler the data types of any return value and of any parameters being passed and enables error checking to be done

The function defini t ion consists of the modified prototype and a function body which is a block of code enclosed in parenthesis which does the work Eg

int someFunc(int a int b)

return a + b

Here we have named the two inputs a and b and we can see that the functions job is to add these two value and to return them As this function returns a value (the sum of a and b) it may be used to expressions like this

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

Arguments can be passed to functions in two ways pass-by-value the default is where a copy of the argument value in the main program is made and then passed to the function The copy in the function only exists in memory as long as the function is active When the code within function has been run to completion the memory is released and the value held there is lost Any changes made to the copy passed to the function do not affect the original variable in any way For example if we altered and used someFunc like this

int someFunc(int a int b)

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 20

41

Note that because we passed a copy of b to the function that the line b = b 2 alters the copy (which then isnt used) and not the original

Arguments can also be passed-by-reference When arguments are passed in this way any changes made to the arguments in the function are reflected by corresponding changes to that data variable in the calling part of the program Pass-by-reference is good for performance reasons because it can eliminate the pass-by-value overhead of copying large amounts of data (In later sections we will examine how pointers can be used to fake pass-by-reference) Eg this will alter b now

int someFunc(int a int amp b) Note the amp

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 40

See section 521 for more on this subject

Creating a function

The format of a function prototype is

return_data_type FunctionName ( argument_l ist )

The function CtoF - void CtoF(int temp) - has no return data type (void) its name is CtoF and it accepts a single input argument called temp of type int (integer)

It is not strictly necessary to give the argument a name (temp) in a function prototype you saw this above in int someFunc(int int) However the argument type must be specified The statement void CtoF(int) is therefore an alternative prototype

The following exercise is an introduction to functions You will learn a lot more about functions in later exercises

42

Writing functions

Task 1

Open the project EvenI you created earlier and change the structure of the program to make use of functions

Solution in (exercise solut ion)

EvenI I

Read two integers in to main() and pass them to a function The prototype is void intCalcs(int int)

intCalcs() function should calculate and display the result of the division and modulus of the two variables passed see Figure 3

Read in two doubles to variables in main() Pass the two doubles and the value of one integer to the second function the prototype is int Calcs(double double int)

Within function Calcs() write statements to produce the output as shown in Figure 3 Most of the code already exists within main()

Return the result of the multiplication of one double and an integer cast this value as an integer

Display the returned value within main() as shown in Figure 3

Figure 3

43

Using a struct

Task 1

Open the project Person

Solution in (exercise solut ion)

Person

As you saw during the presentation we can keep related data together using the struct keyword For example say we define a thing as follows

struct thing

int x

string y

double z

Having done this we can now create as many thing objects as we wish ndash simply by declaring them as we would say an integer

thing a

thing b

Each thing object a and b contains its own x y and z member variables eg

ax = 10 thing as x member set to 10

bx = 20 thing bs x member set to 20

cout ltlt ax ltlt endl outputs 10

cout ltlt bx ltlt endl outputs 20

Complete the exercise by creating and populating a struct Person object Once populated amend the printPerson() function so as to output the persons details

44

PLUSPLUS When Things Go Wrong

Going back to Exercise 8 if you havent tried it already enter zero as your second number What happens

C++ contains mechanisms for catching errors in the form of a trycatch mechanism

cin gtgt y Enter zero

try

intResult = x y

catch(myException amp e)

cout ltlt ewhat() ltlt endl

catch()

cout ltlt Generic oops ltlt endl

Modify your code so as to catch the divide by zero

Hopefully try and catch are fairly self-evident try something and catch any error if something goes wrong

There are two catch blocks here One tries to catch a myException object (we cannot see the definition of this classstruct here) and the other tries to catch anything else that is missed by catch(myException amp e) The amp says that the myException object e is being passed to the catch handler by reference Well learn what this means a little later in section 521

So did you see the Generic oops message appear

Your C++ compiler doesnt have to catch the divide by zero error ndash doing such a thing results in undefined behaviour This is because an arithmetic exception is an OS or processor exception - which is not the same as a C++ exception - hence it cannot be caught by a in a try catch block

To catch errors like this we either need extra support from the compiler14 andor operating system or to write some extra code For example we could do this

14 See also C signal handling httpenwikipediaorgwikiC_signal_handling

45

cin gtgt y Enter zero

if(y gt 0)

intResult = x y

However first we have to realise that this is a possible source of a runtime error and secondly we have to write (correctly) the code to handle the condition

Windows has built-in exception handling ndash called Structured Exception Handl ing (SEH) and we can generate code that uses this in support of the try catch structure used earlier

To enable this we need to tell the compiler to generate code that links into the SEH mechanism

To do this open the Project | ltproject namegt Properties hellip dialog box and in the Code Generation section select Yes wi th SEH Exceptions ( EHa) in the Enable C++

Exceptions line See Figure 4

46

Figure 4

The Monty Hall problem

The Monty Hall problem is a probability puzzle loosely based on the American television game show Lets Make a Deal and named after the shows original host Monty Hall

It goes like this

You are on a game show where you are shown three closed doors You are told that behind one of them is a new car and that behind the other two are goats

Two pieces of essential information at this stage 1 your goal is to win the car 2 the game show host knows what is behind each door

Lets walk through a trial game

The game show hosts asks you to choose a door ndash lets say you choose door number 1 (your door remains closed) The host now opens one of the remaining doors to reveal a goat (as there are two goats they can of course always do this) lets say they open door number 3

47

The situation is now as follows you have chosen door number 1 Only door number 3 is open and it reveals a goat The host now asks you if you would like to switch your door to the only other closed door - door number 2 At this stage you must either stick with door number 1 or switch to door number 2 and at that point the host will open the door youve chosen to reveal your prize

The question is when youre offered the chance should you stick or should you swap - will swapping increase your chance of winning the car or is it just 5050 The claim made here is that by swapping doors you will double your chance of winning the car What does your completed project claim

Task 1

Open and complete the incomplete project MontyHal l

The goal of this project to provide a simulation of problem outlined above

The function

int getRandomDoor(int n = 3)

return rand() n + 1

is used to choose a door number between 1 and 3 (inclusive)

Note that it has a default argument ie if it is called without an argument like this int val = getRandomDoor() the argument n is set to 3 by default and val will be set to a value between 1 and 3 However if it is called like this int val = getRandomDoor(10) then n is set to 10 and val will receive a value in the range of 1 to 10

48

More Functions

Task 1

Open the incomplete project IsLeap

The program asks for a year and determines whether the year is or will be a leap year

You need to complete the function IsLeap(int y) to implement the necessary code

Although the program is incomplete the program contains pseudo code for the algorithm required to compute the answer The pseudo is also show opposite

if year modulo 4 is 0

then

if year modulo 100 is 0

then

if year modulo 400 is 0

then

is_leap_year

else

not_leap_year

else

is_leap_year

else

not_leap_year

Figure 5

49

PLUSPLUS IsLeap in a line

Task 1

Extra points for implementing the IsLeap() function in just a single line of code This could be done using ampamp and || or by using the operator (a short form of if then else)

If you completed this step how readable is your code when compared to the if else version on the right

52 Algorithms

Algorithms

An Aside Big-O notation and Algorithm Complexity feel free to jump over this to Task 1

As programmers we usually implement the various parts of any new program in the simplest and most straight-forward way possible Then later if we find parts of our program are slow (causing what are called hot-spots) we will look again at the code to see if there is a better way to do whatever it is that is taking up the time

As a general rule the most optimal algorithms run in the shortest possible constant t ime ndash such algorithms are often symbolised using O(1) whereas the worst run in quadratic cubic exponential or factorial time (you can think of the O [called Big-Oh] as meaning in the Order of for some input n)

Usually were often happy with those running in O(n) (in the order of n) time ie their running time scales linearly with the number of steps or operations they involve Loops invariably signal O(n) parts of any algorithm

This is best explained using an example

50

Task 1 Understanding Gauss algorithm

Q How would you sum the integers from 1 to n where n is say 100

The obvious way is to use a loop

int tot = 0

for(int i = 1 n = 100 i lt= n ++i)

tot += i

This is fine for small values of n but not so good for very large ones

Interestingly it is said that this self-same problem was once given to a class of children which included one Carl Friedrich Gauss (presumably the teacher wanted to keep his charges occupied for a time) While most of the children started working at the problem (using the loop approach above) Gauss thought about it for a moment and then wrote down the solution 5050

The algorithm Gauss used may be easily demonstrated using the values 1 ndash 10

Gauss realised that if he wrote out the values twice (whether on paper or just in his head) once forward and once in reverse that he could sum each column formed to 11

1 2 3 4 5 6 7 8 9 10

10 9 8 7 6 5 4 3 2 1

1+10 2+9 3+8 4+7 5+6 6+5 7+4 8+3 9+2 10+1

=11 =11 =11 =11 =11 =11 =11 =11 =11 =11

Then sum of 1 ndash 10 is then 11 10 (columns) = 110 2 = 55 (we divided by two because we used each value twice)

Coming back to algorithm runtimes you can see that when using a loop summing 1 ndash 1000 will take ten times longer than summing 1 ndash 100 which will take ten times longer than summing 1 - 10 However by using Gauss approach we can arrive at the answer for any range of values in the same time this is what we mean by a constant time algorithm

51

Task 2

Open the incomplete project SumIntSeries

Complete the project so as to implement Gauss algorithm for any continuous range of integers

The solution project is (exercise solut ion)

SumIntSer ies

The general formula required is

((119948 minus 119947) + 120783)(119947 + 119948)

120784

Or in a more code form

Sum = ((k - j) + 1) (j + k) 2

Where j and k are the starting and ending values in the range respectively (both inclusive)

Functions and Pass by Reference

In the previous section when working with functions all arguments passed to the functions were copies of variable values from main() The arguments were passed by their value

Pass by Value is the default argument passing mechanism for C++ (and the C language)

In pass by value when a function is passed an argument it receives a copy of the value from the calling function (main() in previous examples) This copy remains in scope until the called function has completed and returned at which time the copy is destroyed

Therefore a function that takes value-arguments cannot change a passed variables value because any changes only apply to copies and not to the actual callers variables

An alternate passing scheme is called Pass by Reference

Passing variables to functions by reference is very useful when we need to change or update variable(s) via a function (it is also a faster mechanism than pass by value as no copies have to be made)

Under the covers pass by reference involves passing a memory address and not a copy of the data to the function This is usually more efficient than passing by value because there is no requirement to copy memory However this argument passing mechanism enables a function to modify any argument even if its not supposed to To avoid this we usually declare all read-only parameters as const and pass them by reference

The format of a function prototype when using call by reference is

return-data-type funct ion-name (reference parameter) To indicate a reference parameter an ampersand (amp) is written in the function prototype and header after the parameter type name

The statement void squared(int amp) has no return data type (void) its name is squared and it accepts a reference parameter (amp) of type int (integer)

52

The function definition would be something like this

void squared(int amp inVal)

inVal = inVal inVal inVal

The function call to it would look like this

squared(aValue)

As mentioned above pass by reference is normally used for one of two reasons 1 Because we want to be able to change a passed variable inside a called function 2 Because we want the speed associated with a pass by reference

In 2 we will normally protect our argument by using const in the called function Eg say we want to pass the double argument x to a function f() and take the least possible time about doing it (and given that function f() shouldnt alter x) we would use the following code

void f(const double x)

Use x in some calculation Note that if

x appears on the left hand side of an assignment operator

that it will result in a compilation error

Pass arguments by reference

Task 1

Open the project (demonstrat ion) FunctionRef

Compile and run the program The output should be the same as shown in Figure 6

53

Figure 6

Examine the function prototype

void squared(int amp)

This shows the function squared accepts a reference

parameter of type int The reference parameter is ndash under the covers - the memory address of the argument passed to the function

The function uses this address to both get and set the value stored in variable a (value 21) in main() A reference to this address is passed to the function with the function call squared(a)

Examine the function void squared(int amp x)

Under the covers references to x refer to the address of the variable a in main (that holds the value 21) Ie x and a reference the same piece of memory (the word object was deliberately not used there) So we can think of x and a as two names for the same item

Returning values from functions

In previous programs we have most often produced output (using cout) from within the functions However to be of most use and general utility functions should return resultsinformation rather than output it

Functions may return results in one of two ways 1 via a return value or 2 via arguments ndash either passed as references or via pointer (address)

Non void Functions return a single value ndash if you will they evaluate to this value As such non-void functions may be used in expressions Eg

54

w = x sqrt(y) z

The function sqrt() is replaced with the value of whatever the square root of y happens to be For example if y has the value 4 then to evaluate x sqrt(y) z fully the sqrt() function has to be called ndash where it returns 2 This value is then substituted into the expression for further evaluation ie it becomes w = x 2 z

The second way for functions to return results is via its parameters ndash if they are references or passed via memory addresses Eg

void doubleIt(int amp n)

return n 2 Error The void means doesnt return a value

doubleIt() is a void function ndash so it cannot contain a return statement ndash so it cannot evaluate to anything ndash so it cannot be used in an expression

x = doubleIt(y) error

However the function is still able to return a result (modify something outside of itself is perhaps a better way of putting it)

void doubleIt(int amp n) using amp - a reference

n = n 2

55

doubleIt() cannot (still) be used in an expression but it can change things

int x = 10

doubleIt(x)

cout ltlt x Outputs 20

Why would you use references like this Well references are mainly used for speed (by passing an actual external entity a copy does not have to be made) but they are also useful when multiple values (entities) might best be updated via a single operation (function call)

int x y z

x = y = z = 10

doubleAll(x y z)

void doubleAll(int amp a int amp b int amp c)

a = a 2 b = b 2 c = c 2

Side effects

Going back to w = x sqrt(y) z

Lets replace sqrt() with our own function and cause some havoc

double havoc(double amp d)

++x

d = sqrt(d)

return d

x = 3

w = x havoc(y) z

56

Here the value of y has been changed (yet it is not clear that could happen from the functions call site ndash where it was called from) and so has x Also what value for x will be used in x havoc(y) z Will it be 3 or 4 These sorts of issues are called side-effects

This is one problem (or advantage) with reference arguments ndash and that is that they can cause a change in a variable outside of the function being called

One way to protect against this is to use const references eg

double havoc(const double amp d)

++x

d = sqrt(d) Compilation error here

return d

57

Returning a value from a function

Task 1

Open the TempConver t

project

Run the program The output should be the same as shown in Figure 7

Examine the function prototype

double convert(double temp int mode)

This function prototype has a return type of double When the function is called and calculations are completed a double value is returned to the caller

Examine the function definition The function definition matches the prototype indicating a double and an integer are being passed to the function and a double is being returned

Examine the function body The two statements below convert the temperature input The conversion type required is identified using the user input mode and a switch selection

The statement (temp - 32) 5 9 is used to calculate the temp in Centigrade

The statement 18 temp + 32 is used to calculate the temp in Fahrenheit

Figure 7

58

PLUSPLUS Arithmetic Bases

Task 2

Open compile and run the partially complete Bases project

Note that the project isnt complete

The program uses intrinsic functionality to output values in hexadecimal and octal ndash base 16 and base 8 Both these bases are useful in programming its all to do with binary and the size of a byte

Note that there isnt a bin equivalent to hex and oct and that we have instead written a function called bin1() to convert a value into its binary (base 2) representation

Understanding how bin1() works

bin1 uses the modulus operator () and the right shift operator (gtgt) to work eg 42 in binary is 101010

25 24 23 22 21 20

32 16 8 4 2 1

----------------------

1 0 1 0 1 0

----------------------

1 32 + 0 16 + 1 8 + 0 4 + 1 2 + 0 1 = 42

The function progresses like this

42 2 has remainder zero (false as evaluated in the if) If the if test is true we store a 1 else we store a 0 We then divide 42 by 2 by right shifting it one place ndash but just replace that with n = 42 2 if you prefer We then loop while we have a non-zero value in n to operate on hellip

42 2 = 210 42 2 = 0 if(42 2) = false string value = 0

21 2 = 105 21 2 = 1 if(21 2) = true string value = 1

10 2 = 50 10 2 = 0 if(10 2) = false string value = 0

5 2 = 25 5 2 = 1 if(5 2) = true string value = 1

2 2 = 10 2 2 = 0 if(2 2) = false string value = 0

1 2 = 05 1 2 = 1 if(1 2) = true string value = 1

59

Task 3

The project needs completing specifically it needs the function bin2() writing

We could write such a function as bin1 in a variety of ways and wed like you to write a new function called bin2() that produces the same output as bin1() here

Heres a step by step algorithm for implementing bin2()

Youll use either gtgt or and the bitwise And (amp) operator

Take the functions input (the number to convert) in as a parameter called n To keep it as simple as possible for now you could use plain int types rather than the unsigned long long type we used so the functions signature would look like string bin2(int n)

1 In the function create an integer called i and initialise it to 1

2 Realise that if you left shift the single bit in i (use ltlt or multiply it by 2) it will take on the values 2 4 8 16 32 hellip until it eventually goes to 0 ndash as you shift the bit off of the end

3 Recognise that you could compare your shifting bit with one in the same position in n using bitwise And Ie if((n amp i) == 1) then you know youll need a 1 in your output string for the bit position in n (2 4 8 ) given by is value at this point

4 Build up your result string as you proceed

Change your int n and int i to unsigned long long int and re-run

Try using other integer types ndash signed and unsigned

Lastly examine the solution project in (exercise

solut ion) Bases

60

Figure 8

61

Searching for Sequences

Task 1

Open and modify the incomplete project called called HeadsOrTai ls

When all completed the output should be similar to that shown in

Figure 9

This is the (exercise

solut ion) HeadsOrTai ls project

The programs purpose is to look for a sequence of simulated coin tosses ndash a series consisting of Hs and Ts

The program is complete (as in it runs) but it has some issues At first test it using quite short sequences

The timing information displayed by the application is included simply to demonstrate a timing mechanism that can be used to test the efficiency of the code

The first problem is that the user can currently enter characters other than H or T (h and t are ok as the input is converted to uppercase ndash note the string is passed by reference to toupper() which uses a pointer (which well cover later) to process the string

The second problem is that as it stands the algorithm isnt very optimal if we do not find our pattern we add the result of another coin toss to the current sequence and then re-check the sequence in its entirety

For example if were looking for HHTHH and the generated sequence is currently HTTHHHTTHTHHTTH we will fail to find HHTHH and then proceed to add another coin-toss result at the end ndash HTTHHHTTHTHHTTHH We will then scan this for HHTHH However as we know that we failed to find HHTHH before we added the extra coin-toss re-checking the previously checked sequence is pointless and very time consuming (think how this would (or wouldnt) scale) Your task here is to think of and implement another more optimal approach

62

Figure 9

Task 2

Open the HTTvsHTH project you will find that the project will compile correctly but displays an incorrect result

When completed the program can be used to check how many coin-tosses are required on average to see a particular sequence

Why should that be of interest Because sometimes its rather surprising For example test how many tosses are needed to see say HTH and then HTT

When the program is corrected the output should be as shown in Figure 10

63

Figure 10

PLUSPLUS Optimising Searching for Sequences

Task 1

As it stands the program (yours and ours) encodes a coin toss as a character ndasheither an H or a T Each character is encoded using at least 8-bits and so checking whether a generated sequence is the sequence were looking for means performing a string comparison which is costly in terms of clock-cycles Of course generating and storing the new coin toss also requires the use of these costly string operations

As we have just two tokens as an alternative to generating and storing characters and performing string operations we could encode a sequence as a series of bits For example the sequence HTH could be encoded as 101 in binary (5 in decimal) You can set the corresponding individual bits in an int using the bitwise Or operator | (a vertical bar) eg int n = 0 n = n | i which youd most likely do as a result of scanning the users entered search-sequence string a character at a time In this way you could encode the sequence HTHHTHHTHHTHHTHH in a single sixteen bit unsigned int

Additional operators needed to implement sequence checking and H or T bit manipulation are bitwise And (amp) and the left shift operator (ltlt)

You will find more information on some of these operators just a little below

64

Evolving Searching for Sequences

Task 1

Looking for sequences in stringssequences is an interesting and complex problem in computing and also in genetics where the string being searched could be a DNA sequence and pattern could represent a gene perhaps with a snip (a modificationmutation)

Modify your HeadsOrTai ls program (or our solution) so that instead of Hs and Ts it generates and searches for Gs As Ts and Cs instead

Randomly generate a GCTA sequence and a similar pattern to find within the sequence

How much more time and variation is required in this slightly more complex situation

Conduct a few experiments and using Excel graph your results (copy and paste some data highlight it and then select Excels line graph ndash Excel should then automatically plot your data)

Extrapolate The human genome is how long A gene might contain how many bases How difficult is the task of finding interesting sequences in the human genome How about checking for the odd mutation (insertion transposition deletion) ndash fuzzy matching

A solution for this problem can be found in the (demonstrat ion) GATTACA project

6 Classes and Objects In the previous section we have been working with simple programs that display messages to the user store data input as different data types manipulate the data in some way and output the results to screen

We will now start to look at C++ objects and classes

In the real world there are objects everywhere students staff cars birds houses and many more All objects have at tr ibutes these are similar to the variables created in previous tasks Some attributes of a student may be height weight race course of study etc All objects exhibit behaviours or operations cars accelerate and decelerate students matriculate enrol on courses and leave university

65

Now what is the relationship between a class and an object A good analogy would be from an architects blueprint for a house it would be possible to build many houses Similarly from a class in C++ it would be possible to build many objects

If we had a student class we could create many objects from the student class to represent the many students enrolling Each of these objects would be uniquely identified They would share common attributes and exhibit common behaviours If we wanted an object to perform some task we would call the appropriate member function allowing an operationaction to take place changing the behaviour of that object

Member functions are different from the functions you have created so far Member functions are always associated with objects and are usually called or invoked using a dot notation object member funct ionname() An example is student1getName() The object instance is student1 and the member function is getName()

Member functions contain the detail of how the technical aspects of some operation will be processed When member functions are invoked these technical issues are hidden from the end user When the member function is asked to do some operation a message is sent (a member-function call) telling the member function of that object to perform the operation detailed in the function

Functions are not completely new we have had a brief introduction and you have already created some of your own Note also that main() is a function that is called automatically when you run your program However it is not a member function as there is no object associated with it

Creating your first class

Creating a class

Task 1

Open the project called StudentUG

Compile and run the program It should look like Figure 11

66

Figure 11

Before you can create the object myName it is necessary to define the class from which the object will be created The class definition is shown below

class StudentUG Start of class definition

public

void displayName() Start of member function

cout ltlt My name is Michael Cain ltlt endl

Note a semicolon is required at the end of the class definition

Within main() the statement StudentUG myName creates the object myName of class StudentUG In effect StudentUG is a new type

The statement myNamedisplayName() is used to call the member function displayName() of object myName

As we have seen previously the function main() is called automatically when our programs are executed However member functions (displayname() is one we could have many) must be called in this way objectInstanceNamefunctionName() when dealing with an

67

object directly and like this objectInstanceName-gtfunctionName() if working through a pointer to an object (more on pointers later)

The member function displayName() is preceded by the word void All functions can return values this one does not The word void preceding the function name indicates nothing is being returned If this function returned an integer the definition would be int displayName()

When you use functions it is common to pass data (called parameters) to the function The function then manipulates the data before displaying an output andor returning a value

To pass a parameter to the function in the studentUG class the calling statement in main() would be

myNamedisplayName(name) where name is a string (a series of characters) that contains a value read in from the keyboard

In order for the function displayName() to recognise the parameter being passed the function declaration is changed to include the parameter (name) and type (string) as shown in below

void displayName(string name)

cout ltlt My name is ltlt name ltlt endl

Figure 12

Member functions and Passing parameters

Passing parameters

Task 1

Modify StudentUG to read in a student name The name should be passed to a member function The parameter should be output from within the function to welcome the user to C++ programming

68

Task 2

Modify the program in the above task to read in two more names Each name will be for a different student and you will need to create additional objects (instances) of the class

Data Members

In most of the programs written so far the variables have been declared inside the main() function Variables declared inside a function are local to that function and cannot be accessed from outside that function

You have created a student class and it would be reasonable to assume that a student would be following a particular course So courseName might be one of several attributes of a StudentUG object Attributes are represented as variables in a class defini t ion These variables are called data members and must be declared inside a class definition When you create an object of a StudentUG class each object has a unique memory location for its data members

Figure 13 shows data member name declared in the class definition The access specifier private means that only member functions of the class in which the attribute was declared can use this data member

private string name

Figure 13

When data members are declared as private the data is hidden This is called encapsulat ion and means the attributes of the object are hidden and can only be accessed via member functions

As there is no direct way to change a data member you will also need to create a member

funct ion to set the data member to a value and create a second member funct ion to output the value held there

Data members can also be declared public A data member that is declared public can be accessed from any (non-member) function

A protected data member can only be accessed by member functions of its own class and by member functions of classes derived from this class We will learn more about derived classes and inheritance later

69

Using data members

Task 1

Open the project called StudentCoursesln

Compile and run the program it should look like Figure 14

Figure 14

Task 2

Examine the member function getCourse() shown in Figure 15

string getCourse()

return course

Figure 15

Task 3

Modify the StudentCourse source file to enable the user to add a student name enrolment date and number of years of course Once entered this data should be output to screen You will need to create additional data members and member funct ions to achieve this

70

More Objects

Task 1

So far you have created one StudentCourse object It is about time we had a second student on the course Create a second object of the class StudentCourse You will need to add the second statement shown in Figure 16 to add the new object student2 Call the member functions passing parameters as necessary

Figure 16

Constructors

When you create objects from the StudentCourse class it is necessary to give initial values to all the data members If we were entering data for five people and they were all following the same course of study it would make sense to initialise the course data member (it is possible to initialise some or all of the data members) when each object is created

A constructor is a special kind of function that must have the same name as the class Constructors are normally defined to be publ ic and never have a return type They can be used to automatically initialise data members

In previous programs you have written a defaul t constructor has been provided by the compiler However it is not possible to pass parameters to a default constructor function so the data members in the programs created so far have not been automatically

71

initialised To initialise these data members you created member functions that assigned values to data members

Although a default constructor is provided at compilation time it is a good idea to create your own so that the data members can be initialised

It is worth noting here that functions (constructors are functions) can be over loaded This means it is possible to have more than one function with the same name Note that overloaded functions (functions with the same name) must have different types of or number of arguments

Constructors (functions) can also be overloaded with more than one function with the same name but different types or number of parameters Fortunately for us the compiler automatically calls the correct function whose parameters match the arguments used in the function call

Using constructors

Task 1

Open the project called Constructorss ln

Compile and run the program it should look like Figure 17

Figure 17

72

Task 2

In the constructor shown in Figure 18 what is the purpose behind course = Note that as the string parameter name has the same name as the class variable that we use the hidden this pointer to access the class variable in the assignment If we didnt do this and simply used name = name instead then all we would be doing is assigning the value in the parameter back to the parameter

StudentCourse(string name)

this -gt name = name

course =

Figure 18

Task 3

Create a third constructor that will take an argument enrolment_date

Add a third object call it student3

Write code that will test this additional constructor

Solution in (exercise

solut ion) Constructors

If time allows add other useful properties (data members) access methods (functions) and constructors

Separating use from declaration and definition

C++ is all about objects and any decent project will usually make use of a number of application or domain specific classes

To keeps things maintainable and to promote code reuse C++ projects usually contain a number of cpp and h files where each h files will usually contain a declaration of a class (sometimes called an interface) Note though that the definition of the class (sometimes called the implementation) ndash the code that implements it ndash will be absent from the h file and will instead reside in an accompanying cpp file

Aside from allowing different teams to more easily work on separate parts of the program one of the main reasons for separating definition from declaration is to enforce abstraction which is a programming (and design) technique that relies on the separation of declaration and implementation For example lets say that your team needs a class that acts a bit like a stack (a last-in first-out or LIFO structure) and as this is required

73

urgently you decide to implement it using a simple array You would then only want to give your team what is absolutely necessary to use this class a single h file for your team members to include in their cpp files If they look in the h file they will only see information on how to use the class but how it does what it does is kept elsewhere in the cpp and that youve withheld Consumers shouldnt need to know how a thing works in order to use it

An obvious advantage to this is that there is no danger in you changing how it works Perhaps you later decide to use a vector instead of the array You go ahead and alter the implementation and your team members are none the wiser ndash after all the interface hasnt altered just the implementation

So how does the project get built Of course the implementation of this class will be required at compile time and you can either do that by including the cpp file directly (which will give away the implementation details of course) or by including it as object code ie compiled C++ code (binary machine code) This is how valuable commercial source code is kept in-house while the binary implementation complete with a h file is provided to customers (you will see an example of this just below in Using external

l ibrar ies and thi rd par ty header f i les )

Any discussion on separating use from declaration and definition should include something on namespaces You introduce a namespace by simply using the keyword and braces Anything entered inside these braces is inside the namespace eg

namespace securityModule class Encryptor using namespace std using namespace securityModule int main() Encryptor e Without the using we would have had to use securityModuleEncryptor e securityModuleEncryptor e2

See the (demonstrat ion) Namespaces project for more on this

74

Separating declaration and definition

Using a header and source file to separate class declaration from definition

Task 1

Open and modify the partially complete skeleton project called Precis ionTimers

Like HeadsOrTai ls this project makes use of the Windows operating system to very precisely measure elapsed time However unlike HeadsOrTai ls we have separated the stopWatch class interface from its implementation

As weve previously mentioned Gauss and algorithm efficiency we could test our theory that summing in a loop is O(n) ie that the time taken scales with n

Examine the project files hrTimercpp and hrTimerh noting that the h file contains just enough information for someone to use the declared class stopWatch whilst htTimercpp contains the implementation of the class

Now look in PrecisionTimerscpp You will see that an instance of the stopWatch class is declared Also note that we include hrTimerh but make no reference to hrTimercpp

As it stands the code calls two functions to calculate the sum of a range of integers sumGauss() and sumLoop() The program outputs the clock-ticks used and time taken in seconds

Note that sumLoop() is incomplete

Complete the sumLoop() function and then choosing suitable values for the ranges upper-bound carry out a few experiments to test if the loop is really O(n)

What is this used to do in hrTimerh15

ifndef HRTIMER

define HRTIMER

endif

15 You should also see pragma once as this is rapidly becoming the alternate way to do this ndash whatever this is of course

75

PLUSPLUS Providing object code only

Task 2

We have provided a separate demonstration project that takes the discussion on this one step further (demonstrat ion)

Separat ingThings

In its current form the project wont compile To compile the project in the Solution Explorer add the existing carcpp file to the source files list that just contains SeparatingThingscpp and recompile carcpp is in the same folder as SeparatingThingscpp

Once youve done that right-click on carcpp in the Solution Explorer and select Remove Very importantly when youre prompted for confirmation choose Remove do not choose Delete Now recompile once more youll see that the project fails to compile as the definition of car has been removed

76

But hold on we created carobj - the compiled object-code version of carcpp during our previous compilation so we could tell the linker about that and all should be well (this more or less duplicates the scene whereby you do not provide source code but provide only object code)

The carobj file will be located somewhere like

CUsersDesktopCourse(demonstration) Separating Things(demonstration) Separating Thingsbincarobj

To add this to your project go to Project | Properties | Configuration Properties | Linker | Input

77

In the right-hand window select Additional Dependencies drop down the list and select ltEdit gt

In the dialog that appears add the full path to carobj (see earlier in Step 2) and press Ok

Lastly recompile the code once more It should compile and run At this point you could if you wanted to delete carcpp altogether

One last thing

If you look in the comments in SeparatingThingscpp you will find a discussion that goes into the advanced topic of hiding things even further This includes a brief discussion of the the so called pimpl pattern (pronounced Pimple this stands for Pointer to Implementation16)

16 httpenwikipediaorgwikiOpaque_pointer

78

PLUSPLUS Using external libraries and third party

header files

Task 3

Open and modify the project called Lot to

Examine the projects comments to understand the programs function Run the program ndash does it work

It is supposed to compute the odds of winning the UKs lottery httpwwwnational-lotterycouk (try as we might we couldnt find the odds on their own website)

The program uses the recursive factorial function used earlier in the course (with bigint being typedef ed as unsigned long long int)

Factorial function using recursion

bigint recur_factorial(bigint n)

return n lt 1 1 n recur_factorial(n - 1)

There is a problem here however in that to compute the odds we must compute some significant factorials ie

49 = 608281864034267560872252163321295376887552831379210240000000000

and

6 (49 - 6) = 43498989405629161658895695089330078205230448640000000000

Sadly our bigint (unsigned long long) can hold a maximum value of 2^64 ndash 1 = 18446744073709551615 ie not hardly big enough

Fortunately in C++ we can define new types like an arbitrarily sized integer (outside of the scope of this course but see the (demonstrat ion) newINT project for a small taste) However this is object orientation ndash surely we can just use an existing already defined arbitrarily sized integer class

79

Task 4

The good news is that in this class you can You can use LEDA (The L ibrary of

Eff ic ient Data types and Algor i thms ) a professional class library of advanced numerical functionality

You will need to download the program called

LEDA-63 i386 msc 10 ( NET 2010) 32 bi t

or

LEDA-63 i386 msc 10 ( NET 2010) 64 bi t

Go to wwwalgorithmic-solutionsinfofreeindexphp Accept the licence terms and download the appropriate version (usually the 64 bit version)

The LEDA installation program will install additional numerical libraries and header files from the Algorithmic Solutions company

Once the setup is complete modify the Lotto program

In the Solut ion Explorer right-click on your project (Lot to ) and left-click on Proper t ies A dialog-box appears

Under the CC++ section

1 Click on General Choose Addi t ional include di rec tor ies and enter the directory CAlgor i thmic Solut ions LEDA-63- free-win-msc10-

s td incl

2 Click on Preprocessor and add LEDA_DLL to the end of Preprocessor

Defini t ions Note the semicolon is required

3 Click on Code Generat ion and check that Runtime Library is set to Mult i - threaded Debug DLL ( MDd)

Under the Linker section

4 Click on General

5 Choose Addi t ional l ibrary di rector ies and enter the directory CAlgor i thmic Solut ionsLEDA-63- free-win-msc10-s td

6 Click on Input and add l ibGeoW_mdd_dl l l ib leda_mddl ib to the end of Addi t ional Dependencies Again the semicolon is significant

You may now close Properties dialog-box

7 Modify your code Add the following under include ltiostreamgt

include ltLEDAnumbersintegerhgt using ledainteger using namespace std

80

Then modify the recur_factorial() function so that it accepts and returns a type called simply integer rather than bigint

Save the project and exit Visual Studio

In order to build and execute Lottoexe Windows needs to have l eda_mdddl l in its search path for DLLs Therefore we need to add the path to the folder containing leda_mdddll to the PATH environment variable

8 In Windows Explorer navigate to My Computer then right-click on it and select Propert ies

9 Click on the Advanced tab and then on the Environment Var iables button

10 In the bottom section (System var iables ) of the dialog box highlight Path and then click the Edi t button

At the end of the existing path add -

11 CAlgor i thmic Solut ions LEDA-63- free-win-msc10-s td

Once more note the leading semicolon is significant

81

12 Restart Visual Studio and re-open Lot to Build and run the application as normal

It might seem that this was a lot of work for such an apparently trivial result but the fact is that you now have access to (and have seen how to use) an advanced numerical library of functionality And anyway when all is said and done you must admit that at least you got a return here ndash which is more than you should reasonably expect from the lottery

Figure 19

Task 5

Explore the LEDA samples and documentation ndash if you installed it there should be a shortcut in your start menu to LEDA-63-free-win-msc10-s td

Task 6

Modify the Lotto program to see how the odds change when there are more balls andor when more balls need to be matched (you might also display more of the intermediate results of calculations ndash like 49)

Destructors

Both constructors and destructors are special class methods We have seen how a constructor is called whenever an object is defined

A destructor has the class name prefixed by a tilde ~ Like constructors destructors cannot return values and therefore they have no return type specified but unlike constructors destructors have no arguments and thus cannot be overloaded

An objects destructor is called whenever an object goes out of scope The purpose of the destructor is to clean up eg to free any dynamically allocated memory that the object was using and release other system resources such as files and database connections etc

In the examples used so far no destructor has been provided for any class created In these programs it has been unnecessary If the programmer does not explicitly provide a

82

destructor the compiler will create an empty destructor in the same way that an empty constructor is created if one is not explicitly created

When classes are created any objects instantiated from them that contain dynamically allocated memory will need destructor methods added to implicitly free any dynamically allocated memory when the object goes out of scope

In the class example shown below the destructor function is ~StudentCourse()

~StudentCourse()

cout ltlt Im being destroyed

7 Arrays vectors lists and hash-tables Arrays vectors and lists are all types of data structures Data structures are areas of memory where collections of the same data type are held The main difference between arrays vectors and lists is that arrays stay the same size throughout the program execution whereas vectors and lists can grow automatically

Arrays consist of a series of elements (variables) all of the same type placed consecutively in memory Each of the elements can be individually referenced by adding an index to the arrays name We saw this type of notation earlier when using arrays

Eg

int examMarks[10]

This declares an array of ten scores score 1 is accessed via an index of zero ndash examMarks[0] and score 10 is access through an index of nine ndash examMarks[9] Very important note that indexes start at zero

The advantage of using arrays compared to using discrete variables (the way we have stored values so far) is it is possible to store any number of values of the same type in an array using the same identifier

With arrays it is possible to store 100 student exam marks or 100 student names with using one unique identifier

Vectors and lists are container classes which were originally part of the Standard

Template Library (STL) The STL evolved into C++ Standard Library ndash which includes iostream etc This is the general-purpose C++ library of functions algorithms and data structures that we can use in our programs While some aspects of the library are very complex it can often be applied in a very straightforward way that allows reuse of sophisticated data structures and algorithms

There are many container classes in the library ndash note that C++ now also provides such a class for the more primitive array

ltarraygt

New in C++11 and TR1 (Technical Report One)

83

A container for a fixed sized array

ltbitsetgt

A bit array

ltdequegt

A double-ended queue

ltforward_listgt

New in C++11 and TR1 A singly linked list

ltlistgt

A doubly linked list

ltmapgt

Sorted associative array and multi-map

ltqueuegt

A single-ended queue

ltsetgt

Sorted associative containers or sets

ltstackgt

A stack

ltunordered_mapgt

New in C++11 and TR1 Hash tables

ltunordered_setgt

An unordered_set unordered_multiset

ltvectorgt

A dynamic array

As with an array vector and l is t can hold objects of various types However unlike arrays vectors and lists can resize shrink and grow as elements are added or removed

The standard library provides access via iterators or subscripting Iterators are classes that are abstractions of pointers (more on pointers later) They provide access to container classes using pointer-like syntax and have other useful methods as well

The use of vectors lists and iterators is preferred to arrays and pointers By using containers common problems involving accessing past the bounds of an array are avoided Additionally the C++ standard library includes generic algorithms (an algorithm is a set of instructions on how to perform a task) that can be applied to vectors lists and other container classes

Declaring and using arrays

Arrays are declared indicating the type and number of elements in the following way

type ar rayName[arraySize]

84

Examples are

int inNumbers[20] an array called i nNumbers of 20 in tegers

char inName [20] an array called i nName of 20 characters

float ExamMarks[5] = 0 an array called ExamMarks of 5 floats with all elements explicitly initialised to zero

const int size = 5 declaring a constant variable size

float ExamMarks[size] When the constant variable size is applied to the array declaration the number of elements is set to 5 This cannot be changed during runtime of the program However it is handy when the number of array elements needs to be changed Changing the constant value size changes the number of elements wherever the ExamMarks array is used in the program

int numArray [2][3] is a multidimensional array with 2 rows and 3 columns

Note Arrays have been used in C++ for many years and there will be code you work with that was written before vectors became available Vectors are are usually preferred to using arrays and pointers Common problems involving accessing past the bounds of an array are avoided when using vectors

Creating an array to hold exam results

Task 1

Open the project Array s ln

Compile and run the program

Run the program adding five exam results The output should be similar to Figure 20

Figure 20

85

Examine the following statements

double ExamMarks[5] = 0 This statement declares the array setting its size to 5 elements and explicitly initialising all elements to zero

cout ltlt Enter Exam Mark ltlt i + 1 ltlt This statement prompts the user to enter an Exam mark into the array at element i + 1

Using the notation i + 1 indicates to the user to enter Exam Mark 1 not exam mark 0 which would be less intuitive

Array elements are numbered from 0 to n - 1 So an array that holds 20 integers will be addressed from element 0 to 19

ExamMarks[0] -ExamMarks[19]

The first number will be entered into element [0 ] The last into element [19]

cin gtgt ExamMarks[i]

This statement reads in the user input and stores the values in the array elements of ExamMarks[i] i is incremented within the for loop and starts at 0

Task 2

As it stands the program could be generally improved ndash see the notes in the code and consider how you might make such improvements

Next modify the program to output the highest and lowest marks entered

Task 3

Modify the program so that the number of marks may be easily changed (at compile time)

86

Task 4

Modify the program so as to break out the part that calculates the average and put it into a separate function

Write another function that given an array of this sort returns the mode mean and median values ndash you will need to pass in references as the function will need to return three values

Lastly put your two new functions into a separate cpp (you will also have to create a h file for Arraycpp to use ndash this will contain the new functions prototypes)

87

Searching Arrays with Linear Search

Linear search allows the user to search the array and establish whether the array contains a value that matches a search criteria defined by the user

The search compares each element of the array with the user input The array is not sorted and this method of searching works well for small arrays For large arrays linear searching is inefficient and it is necessary to use other forms of array searching after the array has been sorted

Linear Search

Task 1

Open the project LinearSearch

Compile and run the program - choose a number between 1 and 100 The output should be similar to Figure 21

Figure 21

88

Examine the following statements

myArray[i] = (1 + rand() 100) This statement uses the rand function part of the ltstdlibhgt header file (included via iostream being included) 1 + rand() 100 produces integers in the range 0 to 99

The function l inearSearch takes three arguments The array name the size of the array the third argument is the search value

if(theArray[j] == value)

return j

This selection statement compares each element to the search value If the search value is in the array the element number is returned to main() otherwise -1 is returned

The if selection statement if(containingElement = -1) in main() is used select the output indicating a successful or unsuccessful search

Task 2

Currently the program searches for the first occurrence the search value only

Modify the program so that it outputs al l matching element locations

This function can be used for turning an int value into a string See also the comment below about C++11s to_string() functions

string convertInt(int number)

stringstream ss

ss ltlt number

return ssstr()

Youll need to include ltsstreamgt to use the stringstream class

89

Task 3

Modify the program so that repeated searches may be carried out

See Figure 22

If using C++11 or later you can also use the to_string() helper functions of the string class eg to_string(10) yields 10

Figure 22

PLUSPLUS Debugging Linear Search

Task 1

For debugging purposes modify the program so as to output the contents of the array

Open and run (exercise solution) LinearSearch to see what this might look like You might want to use the modulus operator () to work out when to neatly break a line

You may or may not like to have the program generate varying sets of random numbers To facilitate this youll need to seed the random number generator by inserting a line of code like this

srand((unsigned)time(NULL))

Note the use of the cast

To use srand() include timeh at the top of your program

90

Sorting Arrays with Insertion Sort

When working with large quantities of data in an array you will need to sort the data at some point This makes searching for information quicker and there are many algorithms available that can be used In the following exercise you will learn how to sort numbers stored in an array in ascending order

SortingSearching an array

Task 1

Open the project Sorts

Run the program and examine the code

The program currently uses a class (sorts) which is defined in sortsh to implement one popular sorting algorithm called Inser t ion Sor t

For details on this algorithm see

httpenwikipediaorgwikiInsertion_sort

91

Task 2

Add a new sort to the sorts class

The text file quicksor t txt (in the Sorts folder) contains the C++ code required to implement another popular sorting algorithm called Quicksor t17

For details on this algorithm see

httpenwikipediaorgwikiQuicksort

Add the quicksort code found in quicksor t tx t to the sorts class - considering what parts of it need to be publicprivate

quicksort tx t is in the same folder as the Sortss ln project file

Step 2

Test the quicksort implementation on a range of values

Alter the quicksort implementation so as to have it sort in descending order

Following on from Step 3 parameterise the quickSort() function so as to add an option to have the array sorted in either ascending or descending order

17 Invented by C A R Hoare ndash Sir Tony Hoare with Christopher Strachey the most distinguished computer scientists Oxfords ever produced

92

Figure 23

93

PLUSPLUS Binary Search (Binary Chop)

Task 1

Now that the array is sorted we can implement a very efficient searching algorithm usually called either binary search or binary chop search

See Figure 24

Modify your project to allow the sorted array to be searched for a value using the binary chop algorithm See opposite

The algorithm for binary chop is quite straight forward

1 Look at the value of the middle element of the array If the value = target then youre done

2 If the value is lt than target discard the lower half of the array treating the upper half as though it were the complete array

If the value found is gt than target you obviously want to look in the lower half

3 Repeat step 1 until the item is found or else the index value becomes invalid

Pseudo code for this algorithm is here

first integer = 0

mid integer = 0

last integer = NumberOfItems

while first ltgt last

begin

mid = first + last 2

if List[mid] = target

exit while Found item

If List[mid]gt target

last = mid In the first half

else

first = mid + 1 In the last half

end

found boolean = List[mid] = target

94

Figure 24

Multidimensional Arrays

Multidimensional arrays with two dimensions (arrays can have more than two dimensions) may be thought of as consisting of data arranged in rows and columns see Table 3

Each element in the array is identified by using two subscripts as shown in Table 3 The first subscript identifies the element row and the second identifies the element column a[0] [1] identifies a value in Row 0 Column 1

The array in Table 3 contains two rows and three columns and can be called a 2 by 3 array

Column 0 Column 1 Column 2

Row 0 a[0] [0] a[0] [1] a[0] [2]

Row 1 a[1] [0] a[1] [1] a[1] [2]

Table 3 ndash Array Layout

A multidimensional (2 by 3) array of doubles is shown in Table 4

Column 0 Column 1 Column 2

Row 0 2367 6792 8557

Row 1 1276 9132 2789

Table 4 ndash Array Values

95

Creating a multidimensional array

Task 1

Open the Mult iDimArray

project

Compile and run the program adding 2 exam results for each of the two students The output should be similar to Figure 25

Figure 25

96

Task 2

Examine the code used to write values to and read from a multidimensional array

Examine the following code segments

double ExamMarks[2][2] = 0 This statement creates a two-dimensional array having two rows and two columns and initialises the elements to 0

Every element in the array is identified by an element name in the form a[x] [y] where a is the name of the array and x and y are the subscripts that uniquely identify each element in a Notice that the names of the elements in row 0 all have a first subscript of 0 see Table 5 The names of the elements in column 1 all have a second subscript of 1

Note multidimensional arrays can have two or more dimensions (subscripts) Three-dimensional arrays are uncommon

Column 0 Column 1

Row 0

a[0] [0] a[0] [1]

Row 1

a[1] [0] a[1] [1]

Table 5 ndash Array Indexing

97

Examine the following code segment used to read values in to the array

for(int row = 0 row lt 2 ++row)

for(int col = 0 col lt 2 ++col)

cout ltlt Enter Exam Mark No

ltlt col + 1

ltlt for student No

ltlt row + 1 ltlt

cin gtgt ExamMarks[row][col]

cout ltlt endl

The two for loops work taking one row at a time (the outer for loop) and looping through the columns in that row (the inner for loop) When the marks have been entered for all the columns in row 0 row 1 is selected and values entered for each column cell in row 1

Table 6 shows how four results would be allocated in a 2 x 2 multidimensional array

Exam mark 1 Exam mark 2

Student 1 67 71

Student 2 61 58

Table 6 ndash Populated Array

98

Examine the following code segment used to calculate the total of each students marks

if(row == 0)

r1total += ExamMarks[row][col]

else

r2total += ExamMarks[row][col]

r1total is a variable to hold the sum of values in column 0 and 1 for row 0 (Stud1) r2total sums the values in the columns for row 1 (Stud 2)

Selection for each row is made with if(row == 0) this is Stud1 If row is not 0 then row must be 1 and the mark can be added to r2total If three exam marks were input per student the code for selecting the marks would need to change

Task 3

Modify the program to read in four exam marks for f ive students

Establish the highest and average mark for each student Output the results

One way to do this is to keep a separate array to record the students statistics An alternative would be to extend the existing arrays row so that it may hold the necessary student data

99

Declaring and using vectors

Vectors are declared indicating the type and number of elements in the following way

vectorlttypegtvectorName

vectorlttypegtvectorName(initialSize)

vectorlttypegtvectorName(initialSize elementValues)

Examples

A vector called i nNumbers with no initial size to hold doubles

vectorltdoublegt inNumbers

A vector called Name with an initial size 20 to hold characters

vectorltchargt Name(20)

A vector called ExamMarks holding integers with initial size of 4 elements each with the value 6

vectorltintgt ExamMarks(46)

Note In previous exercises you have created your own member functions In the following exercises you will use some of the vector class member functions Some of these are begin() end() erase() and size() See section 12115 for more detail

The standard library also includes a large collection of algor i thms that manipulate the data stored in containers (vectors are one of several types of container)

You can sort the order of elements in a vector (vec) for example by using the sort algorithm

sort(vecbegin() vecend()) C++11 sort(begin(vec) end(vec))

You can find a value (69) in a vector by using the find algorithm

ptr = find(vecbegin() vecend() 69) See C++ note above

100

ptr is an iterator to store the memory location of the element found

You can reverse the order of elements in a vector for example by using the reverse algorithm

reverse(vecbegin() vecend()) See C++ note above

There are two important points to notice about the call to reverse First it is a global

function (as are find and sort) not a member function Second it takes two arguments rather than one and operates on a range of elements rather than on the container (vector container in this case)

With the above examples the range is the entire container from begin() to end() (vecbegin() to vecend()) reverse like the other standard algorithms is decoupled from the libraries container classes The reverse algorithm can be used to reverse elements in vectors in lists (another container) and even elements in C arrays

int myArray[] = 1 6 20 4

reverse(myArray myArray + 4)

for(int i = 0 i lt 4 ++i) Lets see the reversed array

cout ltlt Array[ ltlt i ltlt ] = ltlt myArray[i]

In the above example the first argument to reverse is a pointer (pointers are covered in Section 8 but for now we can say the first argument points to the address in memory that is the start of the vector ) to the beginning of the range and the second argument points one element past the end of the range This range is denoted (myArray myArray + 4)

Arguments to reverse are i terators which are a generalization of pointers which is why it is possible to reverse the elements of a C array using the array address and pointer notation

Creating a vector to hold exam results

Task 1

Open the Vector project

Compile and run the program adding five exam results The output should be similar to Figure 26

101

Figure 26

Examine the following statements

include ltvectorgt This statement includes the header file vector enabling the program to use the class template vector (templates allow the use of generic functions that admit any data type as parameters and return a value more on this later)

vectorltdoublegt ExamMarks(5) This statement declares the vector to hold doubles and sets the initial size to 5 elements

Note Although vectors can grow to any size it is good practice and more efficient to specify the size when this is known When no size is given and the contiguous memory spaces have been exhausted the elements must be copied to a larger memory space to increase the size of the vector

cin gtgt ExamMarks[i] This statement reads in the user input and stores the values in the vector slot i of ExamMarks[i] i is incremented within the for loop Note that we the same indexingsubscripting syntax as we used previously with arrays ie[ ]

102

Task 2

Modify the code so as to accommodate the adding of an extra exam mark

Note this should not be done (simply) as part of the loop but as a separate action later and you should use the vectors push_back() method to facilitate this

push_back() is a member function of the vector class that adds an additional vector element at the end

After adding the extra mark you will need to generate a new set of statistics ie the average will have changed now To do this separate out the statistical code and place it in a separate function so that you may re-use later (after the new data has been entered)

size() is a member function (method) of the vector class It can be used to establish the size of a vector

The statement for(int i = 0 i lt ExamMarkssize() i++) uses the vector member function size() available to the vector ExamMarks to obtain the size (number of elements) in the vector The size of the vector is used to identify a terminating value that ends iteration of the for loop

Task 3

Open VectorSor t

You will see three TODO sections in the code which need completing

1 Populate a vector with 100 randomly generated numbers

2 Sort the vector

3 Reverse the vector

For sortingreversing you will can use the algorithms sort() and reverse()

Heres a useful link hellip

httpwwwcpluspluscomreferencealgorithm

103

Using insert() and iterators

Task 1

Open and modify the skeleton project called Inser t

Important areas of the program are explained in the steps opposite

Examine the code

vectorltintgtiterator it

This statement creates an iterator that is used to access members of the vector

Iterators are used to access members of the container classes (the container type vector in this case) and can be used in a similar manner to pointers

In the example iterator it is used with the insert() function to place the value (200) at the beginning of the vector nums

it = numsbegin()

This statement uses the vector member function begin() to initialise the iterator it with the address of the start of the vector

it = numsinsert(it 200)

This statement uses the member function insert() and iterator it to insert 200 at the beginning of the vector (it)

Note that an iterator is returned by the function insert() that points to the newly inserted element

104

numsinsert(it + 1 numsTwobegin()

numsTwoend())

This version of the insert() function takes 3 arguments and is used for copying in part or full another collection This may be a vector a plain C++ array or some other collection that is accessed using pointersiterators

This statement inserts a second vector (numsTwo) into nums The three parameters are (copy to nums+1 from star t of numsTwo to end of numsTwo)

it = numsinsert(it + 2 696 )

This version of the insert() function takes 2 arguments The iterator it + 2 points to element number three it points to the beginning of the vector and the 2 moves two elements in The value 696 is inserted at that element

void display(vectorltintgt amp vec)

cout ltlt Vector contains

for(

unsigned int i = 0

i lt vecsize()

++i

)

cout ltlt vecat(i) ltlt

Function display() is passed a reference to a vector and outputs the vector contents used throughout program

105

Task 2

Add the code shown in Figure 27 to the program and using the insert() member function add the array to the nums vector at position two (in the vector) Output the contents of the nums vector to screen

int myArray[] = 5 6 3 4

Figure 27

stdarray

C++11 Introduced a new template array type called stdarray

stdvector is a template class that encapsulates a dynamic array that is stored on the heap and that grows and shrinks automatically if elements are added or removed It provides all the hooks (begin() end() i terators etc) that make it work fine with the rest of the STL It also has several useful methods that let you perform operations that on a normal array would be cumbersome like inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes) Since it stores the elements in memory allocated on the heap it has some overhead in respect to static arrays

stdarray is a template class that encapsulates a static array that is stored inside the object itself which means that if you instantiate the class on the stack the static array will be on the stack Its size has to be known at compile time (it is passed as a template parameter) and it cannot grow or shrink

It is more limited than stdvector but it is often more efficient especially for small sizes because in practice it is mostly a lightweight wrapper around a C-style array However it is more secure since the implicit conversion to a pointer is disabled and it provides much of the STL-related functionality of stdvector and of the other containers so you can use it easily with STL algor i thms

Here is a small example demonstrating the template and some other C++11 extras such as auto and a ranged-based for loop

106

include ltstringgt include ltiteratorgt include ltiostreamgt include ltarraygt using namespace std template ltsize_t N class Tgt arrayltT Ngt make_array(const T amp v) arrayltT Ngt ret retfill(v) return ret int main() The char here can be inferred and so is optional auto a = make_arraylt10 chargt(1) for (const auto amp s a) stdcout ltlt s ltlt system(pause) return 0

1 1 1 1 1 1 1 1 1 1 Press any key to continue

Declaring and using lists

Lists are a kind of sequence container similar to vectors The elements of a list are ordered following a linear sequence with storage handled automatically by the class

List containers are implemented as doubly-linked lists and it is worth noting that elements may be in different and unrelated storage locations

Ordering of a list is kept by a relationship to each element of a link to the element preceding it and a link to the element following it

Because linking information is associated with each element (possibly to different and unrelated storage locations) extra memory may be used to keep the linking This may be important when using a large list

l is ts tend to perform better than vectors at inserting extracting and moving elements in any position within the container but lack direct access to the elements by their position and because of this have a slower access time than vectors Access to an element has to be via a known position (the beginning or the end) and there is a time cost in linking between the known position and the element to be accessed

107

lists are declared indicating the type and number of elements in the following way

listlttypegt listName

listlttypegt listName(initialSize)

listlttypegt listName(initialSize elementValues)

Examples

A list called inNumbers with no initial size to hold doubles

listltdoublegt inNumbers

A list called Name with an initial size 20 to hold characters

listltchargt Name(20)

A list called ExamMarks holding integers with initial size of 4 elements each with the value 6

listltintgt ExamMarks(46)

72 Hash Tables and Cached Calculations

This section has ultimately really been about introducing you to templates and algorithms and well mix both now in a final example

From the binary chop exercise earlier we have seen that sorted arrays provide a very efficient means of storing data for later look-up However we have to bear in mind the algorithmic cost of sorting the array in the first place ie if we have a million unsorted items in our list and we want to find a single item (only) is it better to sort the entire list first and then find the item or is it better to simply walk through the array from the beginning ndash after all we could safely assume that weve a 5050 chance of finding it in the first half of the array Of course as were sorting we could keep an eye open for our item ie we could combine a (partial) sort with look-up operation ndash over time if we repeat this procedure looking for other items we will ultimately sort our array as a side -effect of the look-up operations

But lets move on a little and just consider the fastest look-up method we know so far that carried out on a sorted array using binary chop and think about our programs overall performance when we need to insert additional items into the array When considering problems like this we always think of the worst case hellip despite their often being fans of

108

Monty Python Computer Scientists rarely look on the bright side of life The worst case here is that we need to insert an item into array position zero

Eg say we have this sorted array (look-up operations average O log2 N = fast)

15 24 25 31 78 250 255 262 277

We now have to insert the value 5 into this array Using normal array indexing methods how many operations will this take

5 15 24 25 31 78 250 255 262 277

Each item needs to be shuffled up one position to the right and if weve millions of items that is rather costly especially if the next thing were likely to do is to insert another item

So weve seen that accessing sorted data is very useful and weve also seen that sorting and especially inserting items can be costly The big question is then is there a way we can make both just as efficient - finding andor inserting an item in Olog2N or O(1) (constant time)

Hash Tables

A hash-table is a data structure designed to allow for both rapid insertion and look-up

Although any specific hash-table is implementation specific (there are very many different types of hash-table) well quickly go through the basics

The storage medium well use for our hash-table is an array of strings and we will say that this array has just 10 elements It looks like this

string myhash[10]

Well use this hash-table to store words and well determine the array index for any specific word using a hash- funct ion ndash something that will take a word as its input and return an array index as its output

109

unsigned hashfunc(string s)

unsigned result = 0

for(unsigned i = 0 i lt slength() ++i)

result = result + s[i]

return result 10

hashfunc() iterates through s keeping a running total of the sum of the ASCII codes for each of the characters eg hashfunc(hash-table) computes

h + a + s + h + - + t + a + b + l + e

where the characters ASCII values are

104 + 97 + 115 + 104 + 45 + 116 + 97 + 98 + 108 + 101

The total = 985 and 985 modulus 10 = 5

The final computed value will be used as an index into the array The modulus value used is the size of the hash-table and we use it so as to ensure that resultant computed index value cannot be greater than 9 (remember our arrays indexes are 0 ndash 9)

We can now store words in the myhash array like this

string myhash[10]

string s = hash-table

index = hashfunc(s)

if(myhash[index] = )

myhash[index] = s

else

The complex part is what to do if we have what is called a collision ndash when we find that myhash[index] is already occupied Youll probably have already thought of what value hashfunc(elbat-hsah) will have

One way to help avoid collisions to use a better hash-function and a larger array However in real life collisions are practically impossible to avoid and the only other option to deal with them is to allow more than one string to inhabit an array slot in some way ndash perhaps by having each of the original array slots contain an array ndash rather than an individual string Of course in this case we would also need some way to determine which of the n colliding entries is the one were interested in ndash is it elbat-hsah or hash-table

110

Well briefly leave our examination of hash-tables at this point and instead look at Fibonacci numbers Do not worry we will return to hash-tables very soon

Fibonacci numbers are the numbers in the following integer sequence

0 1 1 2 3 5 8 13 21 34 55 89

By definition the first two numbers in the Fibonacci sequence are 0 and 1 and each subsequent number is the sum of the previous two More formally that is

119865119899 ∶= 119865(119899) ∶=

0 119894119891 119899 = 0 1 119894119891 119899 = 1

119865(119899 minus 1) + 119865 (119899 minus 2) 119894119891 119899 gt 1

Computing Fibonacci Numbers

Task 1

Open Cached_fibonacci

Compile and run the program as is

Examine main() and the calcfib() functions

bigint calcfib(bigint n)

if(n == 1 || n == 0)

return n

else

return calcfib(n - 1) + calcfib(n - 2)

bigint is defined as a unsigned long long int and we have used typedef to save some typing

NOTE The method used to calculate Fibonacci numbers here has been selected because it is perhaps the most obvious way to turn the formal definition into code If you are interested please see the separate Fibonacci project for two other examples of how to calculate Fibonacci numbers

111

Modify the beginning of the calcfib() code

bigint calcfib(bigint n) cout ltlt calcfib was passed ltlt n ltlt endl

Modify main() to set max = 5 and re-run the program

calcfib was passed 0 Fibonacci number 0 is 0 calcfib was passed 1 Fibonacci number 1 is 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 2 is 1 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 Fibonacci number 3 is 2 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 4 is 3 calcfib was passed 5 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1

Fibonacci number 5 is 5

112

Note that to calculate Fibonacci number 5 we calculate Fibonacci number 4 and Fibonacci number 3 - even though weve previously calculated Fibonacci number 3 in order to calculate Fibonacci number 4

To fully appreciate the growth of this process re-run the program adding 10 to max for each subsequent run You maymay not like to comment out the line you inserted in Step 2

Task 2

Getting back to Hash Tables Using a hash-table to store previously computed Fibonacci numbers

As it stands the incomplete solution declares a template hash-table called fibs of the type unordered_map

Read the comments in the function fibCache() and modify the code to as to use the fibs hash-table to store previously computed Fibonacci numbers

fibs[n] = f stores f the n-th Fibonacci number in the n-th slot of fibs (which as you can see you may treat as an array for indexing into)

8 Pointers In C++ programming data (variables) can be referenced via the memory address of the variable This is done using a pointer var iable

A pointer var iable contains the address (location in memory) of a data variable

There are also functional pointers ie those that point to code rather than data and these are briefly explored later

Pointers can be particularly useful when interacting with the operating system andor when working with arrays - as the elements in an array will always occupy consecutive memory places Incrementing the pointer variable by one addresses the next array element

Lastly pointers are also used to fake pass by reference

Declarat ions

int n This is a standard variable declaration n that contains a value as yet unknown of type int

int p This is a pointer p that can hold (point to) an address that contains a variable of type int The type of p is int

Each variable declared as a pointer must be preceded by an asterisk () This modifies the type of the object being declared from thing of type to pointer to thing of type Eg int n means n is an int whereas int n says that n is a pointer to an int

113

int age height age is a pointer to an int height is an int value

double far cent are both pointers to doubles

Pointers can be initialised when they are declared or set using an assignment It is common to initialise pointers to a memory address but they can also be initialised to the predefined constant NULL ndash meaning that they do not (as yet) hold (point to) a valid memory location NULL is defined in the standard library such a pointer is called a nul l pointer

When is used in a variable declaration it indicates the variable being declared is a pointer and not a value

But do beware as is used elsewhere with pointers when the appears before a previously declared pointer variable elsewhere in the program it is said to dereference the pointer and so is used to access data stored at the address which is stored in the pointer A dereferenced pointer is essentially the variable to which the pointer was originally set to point

To complicate matters further using the pointer name without the dereference operator references whatever is stored in the pointer variable itself ndash this is the address of the object it references in memory (which maybe NULL of course)

As we have seen using can mean two things that something is being declared as a pointer or that a previously declared pointer is being dereferenced Experienced programmers sometimes enter the two usages differently ndash a notation we would highly recommend ie

int n n is an object that can hold the address of an int

int k = 0 k is an int holding the value zero

n = ampk n is set to hold ks address amp is explained below

n = 1 k (yes k) is set to hold the value 1

Note the space used in the different usages - int n vs no space in n

Initialising pointers

Pointers can be initialised in two ways

int x = 16 y = 69 variable declaration and initialisation int x_ptr = ampx pointer declaration and initialisation x_ptr holds the address of x int y_ptr pointer declaration yptr is a pointer

y_ptr = ampy pointer assignment yptr holds the address of y

Once declared a pointer variable can be assigned the address of another variable using the amp the addressof operator

114

Note the variable name should not be prefixed by the in the assignment statement unless the pointer is initialised immediately in the variable declaration

We also use pointers when creating objects on the Heap for example we can create and initialise a string object like this string pstring = new string(Hi there) Such objects are not normally tidied away as are the objects created on the stack - objects simply declared in a functionmethod and so they should explicitly be tidied away using delete eg delete pstring For more on this subject see section 9

Using pointers

Task 1

Open the project Pointers

Compile and run the program The output should be as shown in Figure 28

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int x_ptr = ampx This is x_ptr pointer declaration and initialisation

int y_ptr Declaring another pointer y_ptr

y_ptr = ampy Initialising y_ptr

y_ptr = x_ptr Assigning x_ptr contents to y_ptr Both pointers are pointing to variable x (16)

y_ptr = ampy Assigning the address of y back to pointer y_ptr

y_ptr = 170 Assign 170 to the variable at memory location of y_ptr y_ptr points to variable y so 170 has been assigned to y

115

Figure 28

Pointer Arithmetic and Arrays

We have seen that once a pointer is initialised it has a memory address and this address can be reassigned another address It is also possible to change an address using standard arithmetic

The ++ and -- increment and decrement operators can be used to move the pointer along to the next or back to the previous memory address To jump more than one memory address you would have to use the assignment operators += and -=

When using arrays and pointers the array name is the address of the first element in the array

int intArray[] = 1 2 3 4 5

int int_ptr = intArray Same as int int_ptr = ampintArray[0]

The pointer has been declared and initialised with the statement int int_ptr =

intArray Note there is no need to use the address of operator amp when initialising arrays as the array name is the address of the beginning of the array

When working with arrays each element of the array will be the type and size at declaration When an array is declared to hold integers each element will usually be 4 bytes in size An array of doubles will have element sizes of 8 bytes Note ndash these sizes are actually down to the compiler being used and are usually in turn dependent upon the operating system being used

It is not important to know how many bytes make up each element Moving the pointer through the array with the assignment operator x_ptr += 2 will move two elements further through the memory allocated for the array or 16 bytes for an array of doubles

116

Pointers and Arrays

Task 1

Open the project PointerAr i thmetic

Compile and run the program The output should be the same as Figure 29

Examine the program carefully

You may not fully follow the program at first glance as it employees a few potentially new constructs (it depends how far weve got through the lectures)

One slightly truncated new construct is

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

A struct in C++ is just like a class except that the default public and private sections are reversed By default everything in a struct is public

typedef in C++ allows the definition of our own types based on other existing data types

typedef exist ing_type new_type_name

where exist ing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining For example

117

typedef unsigned int WORD

typedef char pChar

You may also remember initialiser lists from earlier eg

s_thing(int a) a(a) b(sqrt((double)a))

If we re-write this

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

We quickly see that a(a) and b() are initialising the a and b struct members const int a and const double b

118

Remember that as these are const we cannot use assignment

typedef struct s_thing

const int a

const double b

s_thing(int a)

Error ndash a and b are const

this -gt a = a

this -gt b = sqrt(a)

thing

Lastly when dealing with pointers to compound types one may access the members of the type via dereferencing or via the so called crows foot operator

(t) dereferences t giving us a thing which was pointed to by t Then we use the dot operator to access the member (t)a

We have to parenthesiset otherwise the would bind to t first ie it would be as though we had done this (ta) which would be an error

The crows foot saves us the dereference t-gta is just like (t)a

119

Figure 29

PLUSPLUS Pointers and Arrays

Task 1

Open and modify the skeleton project called ReverseArray

In main() create an array of 10 integers Fill the array with random numbers between 0 ndash 100

Write a helper function called to output the contents of the array to the console A suitable prototype for this would be void dumpArray(int array[] int size)

Write a helper function to reverse the contents of the array Use a temporary variable as an aid A suitable prototype for this function would be void reverseArray(int array[] int size)

Reverse the values in the array using only pointers

120

Reverse the array without using a temporary variable You should use the XOR operator ^ to achieve this

Pseudo code for an XOR swap is

X = X XOR Y

Y = X XOR Y

X = X XOR Y

The completed program should look like Figure 30

Figure 30

Task 2

Reverse the array using a vector and the standard function template stdreverse()

We can also have pointers to functions in C++ (and C)

The name of a function resolves to be its address in memory (somewhat similar to the case where we use the name of an array) When we call a function we use this name to retrieve the functions address and then use the function invocation operator to execute it The function invocation operator is the set of brackets you use eg

Lets take an example

121

include ltiostreamgt

using namespace std

int lue() life the universe and everything

return 42

int main()

cout ltlt The address of the function lue is

ltlt lue

ltlt invoking it yields

ltlt lue()

ltlt endl

system(pause)

return 0

Typical output is shown in Figure 31

Figure 31

122

We can also store addresses of functions in variables (theyre just numbers) and the type system allows for us to describe and declare scalar variable types for function pointers eg this modified code fragment would produce the same output as that show above

fp is a pointer to a function taking

no arguments and returning an int

int (fp)()

fp = lue

cout ltlt The address of the function lue is

ltlt fp

ltlt invoking it yields

ltlt fp()

ltlt endl

fp is a funct ion pointer var iable so it may be used to point to any other function having the correct signature at runtime

PLUSPLUS Function pointers

Task 1

Open the project Calculator

Compile and run the program The output should be as shown in Figure 32

123

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int (fp)(int int) This is the function pointer declaration It may point to functions that take two integers and return an integer

Like all automatic storage class variables fp will currently be pointing at a random location What happens if you run the program without setting fp to point to an actual function Comment out the switch to find out

switch (Operator)

case 0 fp = Add break

case 1 fp = Subtract break

case 2 fp = Multiply break

The code could do with improving

Modify it to allow for multiple trials eg add the necessary logic to loop and perform multiple calculations ndash youll need to add some way to end the program too therefore

Modify it so that the operator may be inputted as an operator character eg + - etc Allow X x and for multiplication and add for division

All three pieces of information could be entered on a single line eg 6 x 7ltentergt Using cin to read that data just requires you to use three cin statements

cin gtgt X

cin gtgt Operator

cin gtgt Y

Lastly modify the program to that it uses floating point arithmetic

124

Figure 32

9 APIs New Delete and Dynamic Memory As has been stated earlier pointers are useful in a variety of situations However because they are easy to get wrong ndash and when they go wrong everything goes very wrong indeed ndash languages like C++ have tried to make their use the exception rather than the norm For example without reference arguments (eg void someFunc(int amp)) we would have to use pointers to achieve the same functionality and performance

On the whole the underlying philosophy when it comes to pointers is to try to avoid using them whenever possible You can get a real feel for this subject by Googling for smart pointers c++ and from Wikipedia httpenwikipediaorgwikiSmart_pointer

Two areas where we absolutely need pointers are when calling into an external API (Appl icat ion Programming Interface ) and when allocating memory for our own purposes ndash the latter case is also eased by advances in the library support in C++

Using an API

An Appl icat ion Programming Inter face is functionality provided by some third party The most obvious API whether it is Windows Linux or OSX is that exposed by an operating system

If your application needs to interact with the user in any non-portable way you will need to call into your OSs API For example if you want to display a dialog box you will need to access the OSs functionality to do so (perhaps indirectly through a framework like Nokias Qt - httpsenwikipediaorgwikiQt_(framework)) In summary if you ever want to go outside of the standard libraries andor writing consoleterminal applications you will need to call into your operating systems API

When it comes to calling into operating systems pointers are used extensively As an example 1 Google for Linux API 2 Find any website that lists the API functions and then 3 click-through to any function The odds are that the function prototype you see will contain asterisks (pointers)

125

Dynamic Memory Management

The second area where you simply must know something about pointers is when it comes to using the heap

The heap is an area of memory available to your programs You may allocate and use the heap as you wish

Why would you want to do this Normally its to create variable length arrays or to model and use an advanced data structure of some sort a self-balancing red black tree perhaps (httpenwikipediaorgwikiRedAndblack_tree) Of course the more esoteric the data structure and less likely it is that it will be incorporated into the C++ standard library (although the library does contain most of the generally useful and popular ones like doubly l inked l is ts )

To allocate memory from the heap in C++ you use the new keyword and to return it you use the delete eg

int nSize = 12

note nSize does not need to be constant

int pArray = new int[nSize]

pArray[4] = 7

delete [] pArray

10 More on Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine Encapsulation is data information or detail hiding

Once a function is written the detail of how it works is not important to the end user The user needs to understand what data to input and what output will be produced

One of the most important aspects of writing programs using functions is that the functions can be reused from one project to the next Think about the standard functions youve seen already eg the square root function sqrt() Libraries contain atomic generally useful functionality that is likely to be of use at some future time It is useful to bear this thought in mind whenever we build new programs ie we should be on the lookout for generally useful functionality (given our domain) that we should consider coding as functions for later reuse The same goes for classes of course

Probably the most important function in your program in main() ndash without it you do not have a program at all

main() is your programs entry point and as such it may be used in such a way as to inform the rest of your program as to the actions required

126

main() and command-line arguments

Task 1

Open a Command Prompt or PowerShell Prompt and enter the following

dirltreturngt

di r Odltreturngt

t ree ltreturngt

t ree altreturngt

dir and t ree etc are like mini-programs They have default functionality which may be altered by providing additional command-line arguments eg for the dir command dir L N 4 TC

Command-line arguments are passed to your programs by optional parameters eg

int main(int argc char argv[])

Where argc is a count of the number of arguments and argv is an array of pointers to arrays of character (C strings) for each argument being passed Note that argc is always at least 1 and so argv always contains at least one entry ndash this is the name of the program being run

Task 2

Open (demonstrat ion)

CommandLineArgs and Build and run the program

Examine the code

The programs configuration is Debug

In the projects Project | Debugging | Command

Arguments you will see where the programs default command-line arguments are set for debugging purposes

Using the command prompt you opened earlier navigate to your where CommandLineArgsexe is located

CommandLineArgs debug

Run the program by entering its name followed by a variety of arguments eg

gtCommandLineAgs one two threelte ntergt

127

Task 3

Open the project UserPrompter project

Run the program and then examine its code

We will modify this program to use a command-line argument However before doing that its worth pointing out that the primary purpose of this program is to demonstrate the separation of a class declarat ion with its implementat ion (the mechanismfunctionality of class prompter is defined in promptercpp but its capabilities are declared in prompter h )

Its also interesting to note that the optimal strategy is to use an algorithm called binary search or binary chop (we saw this earlier in the course) with each guess you reduce the number of possible solutions by a half This sort of algorithms Big Oh is Log n (where log is base-two logs)

httpenwikipediaorgwikiBig_O_notation

Task 4

Modify the program so that the upper range for the max value is given as a command-line argument

The UserPrompter cpp is the file youll need to modify

Test your program via the setting the projects Command Arguments as detailed above -or- by running the application standalone in a command prompt after building (also as detailed above)

See Figure 33

To convert a string into a number (weve seen one other way of doing this earlier) we can use

include ltcstdlibgt

and the function atoi() eg

atoi(argv[1])

128

Figure 33

EncryptDecrypt a file

Task 1

Open compile and run the EncodeDecode project

Complete the program so that it may be run outside of the IDE and process a file for encryptiondecryption

This is actually quite a simple task as youll only need to add a couple of lines of code However the project also demonstrates how to use the Debug and Release modes to influence the way a program runs ie that in its Debug configuration the program automatically runs through a test

Other things to note include using bitwise XOr to perform the encoding and the use of the C standard library functions putchar() and printf() to perform some of the output eg putchar() is used to output a CR to the console window (CR = char 13)

129

Figure 34

Multiple arguments overloading and default values

In C++ we can over load functions ndash meaning that we can provide different versions of the same function (the different versions must differ by the number andor type of the parameters they take) For example

130

void foo(double d) 1

cout ltlt In void foo(double d)nn

void foo(long int n) 2

cout ltlt In void foo(long int n)nn

void foo(int n) 3

cout ltlt In void foo(int n)nn

double dtest = 0

long int ltest = 0

int ntest = 0

foo(dtest) Calls 1

foo(ltest) Calls 2

foo(ntest) Calls 3

In the above the compiler works out which version of the foo() to call based upon the argument type it is given

We can also overload functions if the number of arguments differ eg

131

void bar(double d)

void bar(double d double t)

We would use a feature like this if sometimes we needed to use extra information ndash in the shape of passing in t in the above eg we would most likely implement void bar(double d) as

void bar(double d)

bar(d 25) Call bar(double d double t)

What were really saying above is that in most cases the implicit double second parameters value is normally 25 ndash perhaps its a standard discount percentage ndash and only occasionally we will need to change that value in which case wed call bar(double d double t) directly and not by going through bar(double d)

Lastly C++ has one extra feature that can make this simpler ndash defaul t arguments

Rewriting bar using this feature we get

void bar(double d double t = 25)

Note that we now only have one bar function now and that we may call it like this

bar(x)

Or like this

132

bar(x y)

In the case of bar(x) the second parameter is omitted and so will receive the default value of 25 in the second example t will receive ys value

Although outside the scope of this class for more on overloading see the (demonstrat ion) Operator Over loading project This shows how to overload the ++ pre and post increment operators overload and provide your own ltlt stream insertion operator (and one use of a friend function) and using an enum with a typedef

Passing Arrays to Functions

To pass an array to a function it is only necessary to pass the array name and the number of elements in the array

The array name is the position (address) in memory of the first element The number of elements is passed to enable the function to establish the array size

An array declared as double somearray[10] would require a function call somefunction(somearray 10)

Passing Arrays to functions

Task 1

Open and modify the skeleton project called the project called ArrayReturnValue

Pass an array to a function to read in five numbers

Pass the array to another function to calculate the average value in the array return this to main() and output to screen

Lastly at the end of the program output the values in the array from within main() The finished program should look something that that in Figure 35

Create two function prototypes

void enterMarks(double ExamMarks[] int num)

double calcAverage(double ExamMarks[] int num)

ExamMarks[] is the array to be passed As with passing variables it is not strictly necessary to give the argument a name in the prototype just its type This could have been written as calcAverage(double [] int) However it is sometimes useful to include this information as it might help explain the functions operation

It is also necessary to pass the size of the array num is the number of elements in the array its size

Within main() declare the array and initialise the elements to zero with the following statement double ExamMarks[5] = 0

This declaration explicitly initialises the first element to zero and implicitly initialises the remaining four to zero

133

Create both functions

enterMarks to read in the values and calcAverage to calculate the average (you will need a for loop in each function)

Return the average value from calcAverage to main() and output the value using cout

Call the functions from within main() with the following statements

enterMarks(ExamMarks 5)

average = calcAverage(ExamMarks 5)

You may output the average directly of course ie without first storing the value in average

At the end of main() add the statements

for(int i = 0 i lt 5 ++i)

cout ltlt Exam Mark Number

ltlt i + 1

ltlt is

ltlt ExamMarks[i]

ltlt endl

ltlt endl

134

Explain how it is possible at the end of the program to output from within main() all the values in the array entered within the function

Modify the program so that the number of exam marks (5) appears only once

In previous exercises when parameters (variables) were passed to functions the function received a value When a value is used in a function a copy is stored in a part of memory that only exists from the time the function is called to when it ends After this the memory and any value in it are lost

However the array in this exercise was initialised in main() with zeros and then passed to the function Data was then added to the array and calculations done At the end of main() the values in the array elements are output The array contains values input from within the function

The name of the array is the address of the first element of the array in the machines memory As the starting address is passed (the name of the array) the called function knows where the array is stored in memory

Because we are working with memory addresses (references ) any changes made to array elements in the function affect the memory location set up in main() for the array

C++ passes arrays to functions by reference (to the memory location of the first element) In previous exercises functions were passed values copies of the variables in main()

135

Figure 35

Passing Two-dimensional Arrays to Functions

It is common to want to store numbers in a two dimensional layout of rows and columns as shown in Table 7

187645 783473 298372

871223 629399 561201

Table 7

This arrangement is known as a two-dimensional array or matrix

C++ uses an array with two subscripts to store a two dimensional array

double Balance[2][3]

When we specify a one-dimensional array the number of elements must be given

When a two-dimensional array is specified it is necessary to specify the array elements in both dimensions We therefore specify the number of rows and columns

The Balance array in the statement above has two rows and three columns

11 Inheritance and (not presented) Polymorphism

111 Inheritance

In Object Oriented languages like C++ inheritance describes a relationship between classes of objects and which usually implies some sort of a sub-division of labour

For example lets say that we want to build an IT system that has something to do with the members of the university

136

In an OO world the first question usually is how would we categorise our significant entities and that always means naming things what names would we use to categorise university members When modelling (for that is what were going to be doing) real-world objects its sensible to use proper names So heres an attempt ndash to broadly categorise university membership

Members are members of the sets

Students

Staff

Other

What is other though

The Bodleian and the card-office issue Readers cards ndash so is a Reader a university members or are they something else And if they are something else does our system really want to concern itself them Or more broadly does our system really want to concern itself with holders of cards issued by the card-office

Are all students really the same

What sort of students do we have at Oxford (and do we want a system ndash either now or in the future ndash that might be interested in recording the differences) Lets see we have undergraduates and graduates We also have Rhodes scholars ndash but are these sorts of student that are distinct (or should be in our system) from our underpost-graduates categories And how about graduates would we want to have some sort of sub-groups Masters students MScMBAMPhil or Doctoral students DPhilDScDLitt etc Perhaps wed like to know something about how theyre being funded ndash and we might want that piece of functionality shared by our undergraduates

We can of course go through the same process when thinking about members of staff (university staff departmental staff members of congregation academic staff fulltimepart-time staff casual staff ndash and how about staff that are sometimes (or also) students) We can go on thinking about this sort of thing for a very long time and we should as its important and when its important it has a name ndash Object Oriented Design or OOD

One of the things wed hope to see appear as part of the OOD phase is the relationship between entities For example if we were to say that a common property of all university members is that they have a date-of-birth we wouldnt want to have our Student and Staff C++ objects contain this information directly by way of some datastate class member (which might seem a little odd at first) But think about it If we performed some validation on the members DoB (perhaps when its being set) we would need to include this in both Student and Staff classes Or as an alternative we would capture the validation in some external function ndash which we would call from the separate classes (if we remember) No its messy and it would be much better if we thought of things this way that all university members are people and that people all have dates of birth

To put it another way we would say that studentsstaffother are just specialisations of people ndash they are people but with a bit of extra something tagged on to them ndash like a bod card number

Now if we also had some way of capturing people stuff in say a basic Person class and could somehow use that automatically ndash perhaps by deriving a Member class from it and then doing the same from Member to both Staff and Student classes from Member One thing though ndash we wouldnt want someone to be able to instantiate a Member object

137

perhaps ie in our system Member is an abstract class Imagine a generic Car vs a Renault Clio ndash it makes no sense to create a Car object ndash there are no generic cars on the road they are all specific cars Similarly we wouldnt want a generic Member wandering around our system (if you remain unconvinced well see why later)

Modelling a student - a first attempt

Please note that in this Introduction to C++ we do not expect you to complete an exercise that requires coding from now on Please just look through the code and follow along with the discussion

Base classes

Task 1

Open the project UnivMember1

Examine the program carefully

The project contains three classes Person Member Student In main() we create a Student and then attempt to output the students name ndash which fails

name is in the protected section of Person ndash which means only Person methods or methods in derived-from-Person classes can access it

Add a public section to the Person class and relocate the name there

Eg

public

string name

Any better now

The problem now is that Student only by default inherits the private side of Person

Change class Student so that we also inherit the public members of Person hellip

class Student public Person

138

Before we tackle further problems with name lets bring in the Member class (left doing nothing until now)

We really want Student to inherit from Member and not Person Change the code to reflect this

People have dates-of-birth and Members have bod cards Add a string member dateOfBirth to Person and move the bodCardNumber member out of Student and into Member ndash make them both strings

Change the code in main() to set these extra pieces of data

If you havent done it already Persons dateOfBirth and Members bodCardNumber should be set via constructors

139

Task 2

Open and examine the project called UnivMember2

UnivMember2 is a copy of the (exercise solut ion)

UnivMember1 solution

One of the problems we have in UnivMember1 is that too much of it is public eg given Student object s we can change name to simply by using assignment eg sname =

We should protect data members at each level using the maximum level of protection we can ie private

However if we do that then cout ltlt sname will no longer work and so well need to provide access methods to the data members Eg heres a modified Member class showing the basic scheme

class Member public Person

public

Member(string bodCardNumber)

this-gtbodCardNumber = bodCardNumber

string getBodCardNumber() For access

return bodCardNumber

private

string bodCardNumber

140

Another problem is that wed really like to not use assignment at all Eg in the above ctor snippet

this -gt bodCardNumber = bodCardNumber

is using assignment

Change string bodCardNumber to const string bodCardNumber Youll see now that assignment wont now work (you have to initialise constants)

What wed really like (most likely) is to use in i t ial isat ion

We can do this via initialiser lists Ie we could change the above to the following

class Member public Person

public

Member(string bodCardNumber)

bodCardNumber(bodCardNumber)

const string getBodCardNumber()

return bodCardNumber

private

const string bodCardNumber

The initialiser list is read thus

bodCardNumber(bodCardNumber)

^^member^^ ^^parameter^^

Note that weve also modified getBodCardNumber() to show that it returns a const string

141

Modify all three classes to use initialiser lists private const data members and use access functions (getBlah() etc)

Task 3

Open and examine the project called UnivMember3

UnivMember3 is a copy of the (exercise solut ion)

UnivMember2 solution

We will now finish this project to the level of an introductory course

Things to note

The main problem with the solution as it stands is that one may create a Member object

Remember that this is analogous to being able to create a generic Car object ndash we should not be allowed to create one

Going right back to UnivMember1 you may remember a comment in there about a protected constructor

protected Protected ctor Person()

At that point in your project we were thinking two things 1) we wont want to create a generic person and 2) a protected constructor will facilitate this

And we were wrong to think both thoughts

1) A properly thought through Person class would be perfectly good to model generic people But although this is true one question here ndash would we ever want just a generic person

2) A protected constructor in a (more) base class doesnt prevent a derived class from creating a base object So what about the Member class ndash would it be ok to instantiate that

The proper means to prevent a Member being created would be to use what is called a pure v i r tual funct ion as part of its definition (such a function is one that must be overridden in a derived class) But what function

142

If you look at the classes derived from Member ndash you can take it from us that one might want to interrogate at runtime ndash to ask them what they are

So a suitable member function to declare in Member would be something like string getRole() A function that does return Student for a student and return Staff for a Staff object

If its pure virtual in in Member wed best define it in our derived classes

class Member public Person

public

virtual const string getRole() = 0

class Student public Member

public

const string getRole() return Student

143

1 Why did we want duplicate (named) functions in Member Student and Staff 2 And what does virtual really mean

We require both 1 and 2 so that we can provide specific responses when being asked the same question and all when being treated in a rather basic way

Being asked the same question means having a method invoked eg getRole() and in a rather basic way means treating us all Students and Staff (etc) as Persons and Members

112 Polymorphism

Polymorphism comes in a few forms

Ad-hoc Polymorphism via function overloading

Parametric Polymorphism or Compile-Time Polymorphism via templates

Subtype Polymorphism or Runtime Polymorphism via virtual functions and

Coercion Polymorphism via casting

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class (after all a derived from base must have or contain all that a base has) Polymorphism is the art of taking advantage of this simple but powerful and versatile feature

One way Subtype Polymorphism is applied is to use a base reference to access a collection of instances of different types that are derived from a common base ndash one way to paraphrase that is to say that related (derived from a common class) objects respond according to their type rather than according to the type of the reference one uses to access them (a base class pointer type) That is the dynamic type of the object is used instead of its static type

All of this is best demonstrated via an example of course

144

PLUSPLUS Polymorphism

Task 1

Open and examine the project called (exercise

solut ion) UnivMember3

Run the program the output should be the same as shown in Figure 36

The crucial code here is as follows

Member arr[6]

Student studs1()

Student studs2()

Staff staff1()

Student studs3()

Staff staff2()

Student studs4()

arr[0] = ampstuds1

arr[1] = ampstaff1

arr[2] = ampstuds2

arr[3] = ampstaff2

arr[4] = ampstuds3

arr[5] = ampstuds4

for(int i = 0 i lt ++i)

cout ltlt arr[i]

ltlt i ltlt s name is

ltlt arr[i]-gtgetName()

ltlt t Their role is

ltlt arr[i]-gtgetRole()

ltlt endl

Weve created an array of Members (it isnt important that weve used pointers) and note that we have set some of the members of this to be pointers to Student and Staff objects We are allowed to do this as both Student and Staff are derived from Member

However when and if we invoke member functions on these objects wed really like it if they responded as what they really are ndash Student and Staff objects

145

From the output below you can see that they indeed do respond accordingly

Figure 36

The mechanism behind allowing this is the virtualisation of the getRole() member function Remember that this was declared and made virtual in the Member class

Play about with the code eg change

Member arr[6] to Person arr[6] Everything still ok How about not using pointers here ndash easy to do

146

Lastly weve implemented (for no good reason but to show you how its done) some instance counting in all three classes Have a look for the static members and the inserted lines immediately below the class definitions that look like this int PersonCount = 0

The End Thank you for coming and we hope that you enjoyed the class

Oh and please Please PLEASE fill out the feedback form email when it arrives

147

12 Appendices

Arithmetical Operators

Operator Operation

+ Addition

- Subtraction

Multiplication

Division

Modulus

++ Increment

-- Decrement

Table 8 ndash Arithmetical Operators

Assignment Operators

Operator Example Equivalent

= a = b a = b

+= a += b a = a + b

-= a -= b a = a - b

= a = b a = a b

= a = b a = a b

= a = b a = a b

Table 9 ndash Assignment Operators

148

Assignment and Arithmetic examples

The assignment operator in C++ is =

The format is var iable = expression this can be read as assign to the var iable the value of the expression

An example to calculate the number of pence in a value in pounds would be

pence = pounds 100

Note it is easy to confuse the assignment operator = with the equals notation used in mathematics The equals notation in C++ is ==

Incrementing a var iable

month = month + 1 adds the value one to the variable month This can be written as

month++

Decrementing a var iable

month = month - 1 deducts the value one from the variable month This can be written as month--

Note that ++ and ndash can be used before or after the thing being modified eg ++x x++ --y y-- However there are some subtle differences which will be explained in the lectures

In C++ it is also possible to combine arithmetic and assignment operations

To add 2 to a variable total

total = total + 2 or total +=2

To subtract 2 from to tal

total = total - 2 or total -=2

To multiply total by 2

total = total 2 or total =2

Relational and Equality Operators

The equality operator is used to compare two operands (a == b) and returns 1 (t rue) if both are equal otherwise 0 (false ) is returned

The inequality operator (=) returns 1 (t rue) if both are NOT equal otherwise 0 (false) is returned

Both the above operators are commonly used to test the state of two variables to perform conditional branching

The relational operators also return either true or false (a gt= b) returns 1 (t rue ) if a is greater than or equal to b otherwise 0 (false ) is returned

149

Standard algebraic equality or relational

operator

C++ equality or relational operator

Sample C++ condition

Meaning of C++ condition

Relational operators

gt gt a gt b a is greater than b

lt lt a lt b a is less than b

gt= a gt= b a is greater than or equal to b

lt= a lt= b a is less than or equal to b

Equality operators

= == a == b a is equal to b

= a = b a is not equal to b

Table 10 ndash Relational Operators

Logical Operators

When using i f selection statements it is common to use the relational operators as part of the test if(num gt 5) if(size lt= 14) if(Char == A) These are fine for testing one condition

To test multiple conditions it is possible to nest i f statements but this can be a bit cumbersome

Logical Operators can be used to form more complex conditions by combining simple conditions

Logical AND (ampamp) Operator allows a test to see if two conditions are true

if(leaveBooked gt LeaveLeft ampamp staffCover == false)

cout ltlt Take your holidays sometime else

Logical OR (||) Operator allows a test to see if either or both of the conditions are true

if(Temperature lt 16 || windspeed gt 15)

cout ltlt Too cold or windy to sunbath today then

Logical Negation ( ) Operator reverses the meaning of a condition

if((windspeed == 20))

150

cout ltlt The wind speed is not 20 its ltlt windspeed

This could be written equally as well with the equality operator

if(windspeed = 20)

cout ltlt The wind speed is not 20 its ltlt windspeed

Precedence and Associativity Table

Precedence Operator Description Associativity

1 Scope resolution Left-to-right

2

++ -- Suffixpostfix increment and decrement

() Function call

[] Array subscripting

Element selection by reference

-gt Element selection through pointer

typeid() Run-time type information (see typeid)

const_cast Type cast (see const_cast)

dynamic_cast Type cast (see dynamic_cast)

reinterpret_cast Type cast (see reinterpret_cast)

static_cast Type cast (see static_cast)

3

++ -- Prefix increment and decrement Right-to-left

+ - Unary plus and minus

~ Logical NOT and bitwise NOT

(type) Type cast

Indirection (dereference)

amp Address-of

sizeof Size-of

new new[] Dynamic memory allocation

delete delete[] Dynamic memory deallocation

151

4 -gt Pointer to member Left-to-right

5 Multiplication division and remainder

6 + - Addition and subtraction

7 ltlt gtgt Bitwise left shift and right shift

8 lt lt= For relational operators lt and le respectively

gt gt= For relational operators gt and ge respectively

9 == = For relational = and ne respectively

10 amp Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 ampamp Logical AND

14 || Logical OR

15 Ternary conditional Right-to-Left

16

= Direct assignment (provided by default for C++ classes)

+= -= Assignment by sum and difference

= = = Assignment by product quotient and remainder

ltlt= gtgt= Assignment by bitwise left shift and right shift

amp= ^= |= Assignment by bitwise AND XOR and OR

17 throw Throw operator (exceptions throwing)

18 Comma Left-to-right

Table 11 ndash Precedence and Associativity Table

Escape Sequences

Escape Sequence

Description

n Newline Position the screen cursor at the beginning of the next line

152

t Horizontal tab Move the cursor to the next tab stop

r Carriage return Position the cursor at the beginning of the current line

a Alert Sound the system bell

Backslash used to print a backslash

Single quote Use to print a single quote character

Double quote Used to print a double quote character

Table 12 ndash Escape Sequences

Cast Operator

Is where the programmer explicitly asks for a change in data type It may be that the result of a calculation is a double and the user wants it to be of type integer

A double can be cast to an integer in the following way

double aNum = 237

int anInt = 0

anInt = static_castltintgt(aNum)

A C style cast may also be used eg

anInt = (int)aNum OR anInt = int(aNum)

Formatted Output

When several numbers are displayed each is printed with the minimum number of digits needed to show the value This can yield some unexpected output

The width of an output field can be set using a stream manipulator To set the next number to be printed to a width of 5 digits use cout ltlt setw(5) This command does not produce any output it manipulates the stream to change the output format of the next value Note setw() must be specified for every item output

To use any stream manipulators you must include the header include ltiomanipgt

setprecision is another manipulator and is used to set the precision of the next floating point number Note setprecis ion only has to be set once as the stream remembers the formatting directive and does not affect integer fields The format is cout ltlt

setprecision(3)

To set precision for trailing zeros (0100 will appear as 01) it is necessary to use the fixed format The notation is cout ltlt fixed Note f ixed only has to be set once

The three manipulators can be combined to achieve the required precision and field width when used in this way

153

cout ltlt fixed ltlt setprecision(3) ltlt setw(5) ltlt myDouble

Alternatively as fixed and setprecision only have to be set once this statement could be written as

cout ltlt fixed ltlt setprecision(3)

cout ltlt setw(5) ltlt myDouble

Header Files

Every program that you create will have at least one header file If you use input or output you will have to include the iostream header

If you use mathematical functions you will need cmath It can be difficult to know which header files to use for each function Some of the common header files used together with some of the older ones you may find with inherited code are shown below It is a good idea to use the help if you are unsure which header files are associated with particular functions

Standard C++ header Old header

iostream iostreamh

iomanip iomaniph

fstream fstreamh

cmath mathh

cstdlib stdlibh

string No equivalent

vector vectorh

Table 13 ndash Header Files Old and New

Matrix Libraries

The STL does not contain a Matrix type and so we must look elsewhere for a suitable implementation that suits the individuals needs

The table below lists the third party libraries that we are aware of

Some Linear AlgebraMatrix Libraries

Armadillo Blitz++ Boost

CPPLapack CPPScaLapack CVM Class Library

Eigen Elemental FLENS

Gmm++ GNU Scientific Library (GSL) HSL

154

IML++ IT++ LA library

Lapack++ LinBox Matrix Template Library (MTL)

MV++ Newmat PETSc

RNM Seldon SimuNova

SL++ (Scientific Library)

SparseLib++ SuiteSparse

TCBI (Temporary Base Class Idiom)

Template Numerical Toolkit (TNT)

Trilinos

uBlas ViennaCL

Table 14 ndash Matrix Libraries

Scope

The portion of a program where an identifier can be used is known as its scope

An identifier declared outside any function or class has f i le scope This type of identifier is known by all functions Global variables and function prototypes all have file scope

Identifiers declared inside a block of code have block scope This type of scope begins at the identifiers declaration and ends at the termination right brace ( ) of the block in which the identifier is declared

Any block can contain local variable declarations If blocks are nested it is possible to declare variables with the same name in each nested block The variable in the outer block is hidden while the inner block is being executed

Enumerating constants

The enum keyword provides a handy way to create a sequence of integer constants An example of enumeration is shown below

enum Months JAN = 1 FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC

Each of the constants will have a default value 1 greater than the constants that it follows in the list The first value in the enumeration above is explicitly set to 1 and the remaining values increment by 1 The values assigned from JAN to DEC will be 1 to 12

The statement cout ltlt DECEMBER is month number ltlt DEC ltlt endl would be output as DECEMBER is month number 12

Constants

Data that will not change during the execution of a program should be stored in a constant container rather than a variable If the program attempts to change the value stored in a constant the compiler will report an error and compilation will fail

Constant can be created for any data type by prefixing the declaration with const keyword followed by a space Note Constants must always be initialised at declaration

The following declaration declares a constant for the speed of sound at sea level ms

155

const double SpeedOfSound = 34029

Vector member functions

Some commonly used member functions of the vector class are

Vector member Functions Effect

at(element number) Gets the value contained in the specified element

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

push_back(value) Adds an element to the end of the vector containing the specified value

size() Gets the number of elements

Table 15 ndash Vector Member Functions

Global functions

Global functions are not member functions They take more than one argument and operate on a range of elements rather than on the vector container ie they can be used on other types of containers

Vector global Functions Effect

find()

ptr = find(vbegin() vend() 67)

Finds the element in the vector containing number 67 Needs iterator (ptr) to store location of element

reverse()

reverse(vbegin() vend()) Reverses the values in a vector (v)

sort()

sort(vbegin() vend()) Sorts the vector (v)

Table 16 ndash Vector Global Functions

156

list member functions

Some commonly used member functions of the list class are

List member Functions Effect

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

pop_front Removes the first element

push_back(value) Adds an element to the end of the vector containing the specified value

sort() Sorts the elements in the container from lower to higher

size() Gets the number of elements

swap() Exchanges the content of the list

Table 17 ndash List class Member Functions

cmath functions

Function Argument Result Returned Value Example Result

ceil(x) double double Smallest integer ge x

ceil(21) 30

cos(x) double double Cosine of x radians cos(10) 054

fabs(x) double double Absolute value of x

fabs(-15) 15

floor(x) double double Largest integer le 29

floor(29) 20

157

pow(x y) double double x to the yth power pow(24) 160

sin(x) double double Sine of x radians sin(10) 084

sqrt(x) double double Square root of x sqrt(4) 20

tan(x) double double Tangent of x radians

tan(10) 156

Table 18 ndash cmath Functions

158

String class

The string class defines many member funct ions A few of the basic ones are described below

Initialisation - constructors form

A string expression string str2 = str1

A character string literal string Intro = Programming with C++

A substring of another string object

string Intro = Capetown

string Mytown = Boars

string MyTown(Intro 4 5)

starts at character 4 (t)

with a length of 5 (or the rest of the string if shorter)

cout ltlt myTown ltlt endl

will produce an output town

Member Functions

length()

string myName = Sebastion

myNamelength()

will produce an output of 9

insert ()

Inserts a string into the current string starting at the specified position

string myName = Sebastion

string nameAdd = rjio

myNameinsert (2nameAdd)

cout ltlt myName ltlt endl

will produce an output Serjiobastion

erase()

Delete a substring from the current string

string myName = Sebastion

myNameerase (02)

cout ltlt myName ltlt endl

will produce an output bastion

replace()

Delete a substring from the current string and replace it with another string

string myName = Sebastion

string aName = renna

159

Member Functions

myNamereplace(3 6 aName)

cout ltlt myName ltlt endl

will produce an output Sebrenna

find()

Search for the first occurrence of the substring in the current string If the word is found return the position of the first character If not return -1

string sName

string findWord

position = sNamefind(findWord)

substr()

Returns a substring of the current string

string myName = Sebastion

string aName = myNamesubstr(0 3)

cout ltlt aName ltlt endl

will produce an output Seb

Non-member functions

getline()

string name

getline(cin name)

Table 19 ndash String Class Member Functions

160

A number of C++ operators also work with str ing objects

Operator

=

string fString = Hello

string lString

lString = fString

Assign a character (char ) to a str ing object

string aStringC

aStringC = Z

+

Concatenate two str ing objects

string str1 = C++

string str2 = Programming

string str3 = str1 + str2

+

Concatenate a string object and a character string literal

string str = Hello

string str1 = str + there

The same concatenation can be done in this way

str += there

+

Concatenate a string object and a single character

string str = Bye Bye

string strBye = str +

161

ASCII Character set

Decimal Octal Hexadecimal Binary Value Meaning

0 0 0 0 NUL (Null char)

1 1 1 1 SOH (Start of Header)

2 2 2 10 STX (Start of Text)

3 3 3 11 ETX (End of Text)

4 4 4 100 EOT (End of Transmission)

5 5 5 101 ENQ (Enquiry)

6 6 6 110 ACK (Acknowledgment)

7 7 7 111 BEL (Bell)

8 10 8 1000 BS (Backspace)

9 11 9 1001 HT (Horizontal Tab)

10 12 00A 1010 LF (Line Feed)

11 13 00B 1011 VT (Vertical Tab)

12 14 00C 1100 FF (Form Feed)

13 15 00D 1101 CR (Carriage Return)

14 16 00E 1110 SO (Shift Out)

15 17 00F 1111 SI (Shift In)

16 20 10 10000 DLE (Data Link Escape)

162

Decimal Octal Hexadecimal Binary Value Meaning

17 21 11 10001 DC1 (X ON) (Device Control 1)

18 22 12 10010 DC2 (Device Control 2)

19 23 13 10011 DC3 (X OFF)(Device Control 3)

20 24 14 10100 DC4 (Device Control 4)

21 25 15 10101 NAK (Negative Acknowledgement)

22 26 16 10110 SYN (Synchronous Idle)

23 27 17 10111 ETB (End of Trans Block)

24 30 18 11000 CAN (Cancel)

25 31 19 11001 EM (End of Medium)

26 32 01A 11010 SUB (Substitute)

27 33 01B 11011 ESC (Escape)

28 34 01C 11100 FS (File Separator)

29 35 01D 11101 GS (Group Separator)

30 36 01E 11110 RS (Request to Send)(Record Separator)

31 37 01F 11111 US (Unit Separator)

32 40 20 100000 SP (Space)

33 41 21 100001 (exclamation mark)

34 42 22 100010 (double quote)

163

Decimal Octal Hexadecimal Binary Value Meaning

35 43 23 100011 (number sign)

36 44 24 100100 $ (dollar sign)

37 45 25 100101 (percent)

38 46 26 100110 amp (ampersand)

39 47 27 100111 (single quote)

40 50 28 101000 ( (leftopening parenthesis)

41 51 29 101001 ) (rightclosing parenthesis)

42 52 02A 101010 (asterisk)

43 53 02B 101011 + (plus)

44 54 02C 101100 (comma)

45 55 02D 101101 - (minus or dash)

46 56 02E 101110 (dot)

47 57 02F 101111 (forward slash)

48 60 30 110000 0

49 61 31 110001 1

50 62 32 110010 2

51 63 33 110011 3

52 64 34 110100 4

164

Decimal Octal Hexadecimal Binary Value Meaning

53 65 35 110101 5

54 66 36 110110 6

55 67 37 110111 7

56 70 38 111000 8

57 71 39 111001 9

58 72 03A 111010 (colon)

59 73 03B 111011 (semi-colon)

60 74 03C 111100 lt (less than)

61 75 03D 111101 = (equal sign)

62 76 03E 111110 gt (greater than)

63 77 03F 111111 (question mark)

64 100 40 1000000 (AT symbol)

65 101 41 1000001 A

66 102 42 1000010 B

67 103 43 1000011 C

68 104 44 1000100 D

69 105 45 1000101 E

70 106 46 1000110 F

165

Decimal Octal Hexadecimal Binary Value Meaning

71 107 47 1000111 G

72 110 48 1001000 H

73 111 49 1001001 I

74 112 04A 1001010 J

75 113 04B 1001011 K

76 114 04C 1001100 L

77 115 04D 1001101 M

78 116 04E 1001110 N

79 117 04F 1001111 O

80 120 50 1010000 P

81 121 51 1010001 Q

82 122 52 1010010 R

83 123 53 1010011 S

84 124 54 1010100 T

85 125 55 1010101 U

86 126 56 1010110 V

87 127 57 1010111 W

88 130 58 1011000 X

166

Decimal Octal Hexadecimal Binary Value Meaning

89 131 59 1011001 Y

90 132 05A 1011010 Z

91 133 05B 1011011 [ (leftopening bracket)

92 134 05C 1011100 (back slash)

93 135 05D 1011101 ] (rightclosing bracket)

94 136 05E 1011110 ^ (caretcirumflex)

95 137 05F 1011111 _ (underscore)

96 140 60 1100000 `

97 141 61 1100001 a

98 142 62 1100010 b

99 143 63 1100011 c

100 144 64 1100100 d

101 145 65 1100101 e

102 146 66 1100110 f

103 147 67 1100111 g

104 150 68 1101000 h

105 151 69 1101001 i

106 152 06A 1101010 j

167

Decimal Octal Hexadecimal Binary Value Meaning

107 153 06B 1101011 k

108 154 06C 1101100 l

109 155 06D 1101101 m

110 156 06E 1101110 n

111 157 06F 1101111 o

112 160 70 1110000 p

113 161 71 1110001 q

114 162 72 1110010 r

115 163 73 1110011 s

116 164 74 1110100 t

117 165 75 1110101 u

118 166 76 1110110 v

119 167 77 1110111 w

120 170 78 1111000 x

121 171 79 1111001 y

122 172 07A 1111010 z

123 173 07B 1111011 (leftopening brace)

124 174 07C 1111100 | (vertical bar)

168

Decimal Octal Hexadecimal Binary Value Meaning

125 175 07D 1111101 (rightclosing brace)

126 176 07E 1111110 ~ (tilde)

127 177 07F 1111111 DEL (delete)

Table 20 ndash Full ASCII Table

169

Handy IDE Settings

Line Numbers onoff Tools | Options | Text Editor | CC++ | Line Numbers

Auto closing the console Tools | Options | Debugging | Automatically close the console window when debugging stops

Saves having to use system(pause)

170

REMAINING PAGES LEFT BLANK FOR NOTE TAKING

171

172

173

Peet Morris

peetmorrisgmailcom

C++ A Comprehensive Introduction

Arrangements

bull We Startfinish at 915am 500pm

bull Format two lectures per day (ask questions) hands-on at all other times

bull You should have Course book (copy of the slides at the back)

bull The course software is pre-installed on the machines

And also separately available from

The compilerIDE wwwvisualstudiocom

Notesslidesexercise files wwwpeetmcomC++introcoursezip

Your safety is important

Where is the fire exit

Beware of hazards

Tripping over bags and coats

Please tell us if anything does not work

Let us know if you have any other concerns

Your comfort is important

The toilets are along the corridor just outside the teaching rooms

The rest area is where you registered it has vending machines and

a water cooler

The seats are adjustable

You can adjust the monitors for brightness

What we assumehellip

What we assume

Experience of using another programming

language

Comprehensive Lots to get through

C++ and OOP

bull Created in 1985 by Bjarne Stroustrup C++ is a highly efficient

multiplatform low level Object Oriented Programming language

bull Latest version is C++17

stroustrupcom

Standard C++ Library

bull Written in the core language it is a collection of classes

(object definitions) functions and algorithms

See wwwcpluspluscomreference

IDEs amp Compilers

Visual Studio 2017

First Program

First application

include ltiostreamgt

using namespace std

int main()

int aNum = 0 aNum(0) or aNum0

cout ltlt Enter a number-

cin gtgt aNum

cout ltlt You entered ltlt aNum

return 0

hellip hellip

First Program

bull include ltiostreamgt

Adds the contents of the iostream header file into the program (for cout and cin)

bull using namespace std

So we donrsquot have to write stdcout ltlt and stdcin gtgt all of the time

bull cin is the standard input stream object that allows input from the keyboard

bull cout is the standard output stream object that allows output to the screen

bull int main() The programs entry point

Mandatory main function in every C++ program ndash always returns an integer value

First Program

bull int aNum = 0

Variable to hold a value of type integer (piece of machine memory referred to via the name aNum)

bull ltlt stream insertion operator ndash outputs to console

cout ltlt Enter a number-

bull gtgt stream extraction operator ndash waits for keyboard input

cin gtgt aNum

Other Types

Microsoft data types summary httpsdocsmicrosoftcomen-gbcppcppfundamental-types-cpp

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststack

Lots

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

x 1

y 2

x 3

y 4

p1

p2

x

y

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 copies the bit pattern from p1 to p2

x 1

y 2

x 1

y 2

p1

p2

Compound Types

Cannot define operators other than assignment

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 p2 compilation error

x 1

y 2

x 3

y 4

p1

p2

Compound Types

We can arbitrarily further compound things

struct point

int xint y

struct rectangle

point tlpoint br

struct line

point startpoint end

startxy

endxy tlxy

brxy

Compound Types

We can also group things using struct to create compound

types

struct point

int xint y

struct rectangle

point tlpoint br

int main()

rectangle r

rtlx = 1rtly = 2

rbrx = 3rbry = 4

int diff_x = abs(rtopLeftx - rbottomRightx)int diff_y = abs(rtopLefty - rbottomRighty)

cout ltlt area ltlt diff_x diff_y ltlt endl

r

tl

br

x 1

y 2

x 3

y 4

Using a Library Type

include ltstringgt

string s

cout ltlt What is your name

getline(cin s)

cout ltlt s ltlt

ltlt is

ltlt slength() ltlt

ltlt characters long ltlt endl

s

Other Types

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststackcomplex

Lots

8 bit Binary signed unsigned

00000001 1 1

00000010 2 2

00000011 3 3

01111111 127 127

10000000 -128 128

10000001 -127 129

10000010 -126 130

11111101 -3 253

11111110 -2 254

11111111 -1 255

00000000 0 0

00000001 1 1

00000010 2 2

signed vs unsigned ndash its all just 1s and 0s and adding

Adding rules

0 + 0 = 0

1 + 0 = 1

0 + 1 = 1

1 + 1 = 0 (carry 1)

1 + 1 + 1 = 1 (carry 1)

-126 + +3 =

10000010

00000011 +

10000101 = -123

-126 + -3

10000010

11111101 +

01111111 = 127 (why not -129)

Arithmetic Operators

+ Addition

- Subtraction and unary minus

Multiplication

Division

Remainder after division (moduloclock arithmetic)

int j k l = 10

j = l 3 js value will be three

k = l 3 ks value will be 1

Relational Operators

Evaluate to either true or false represented by integer values 1 and 0

== Equal to

= Not equal to

gt Greater than

lt Less than

gt= Greater than or equal to

lt= Less than or equal to

Increment and Decrement Operators

++ Increment

-- Decrement

Can be prefix or postfix

b = 3

a = b++ + 6 Add 6 to b then increment b a is 9 b is 4

b = 3

a = ++b + 6 Increment b then add 6 to b a is 10 b is 4

Assignment Operators

Symbol Operation Long Short

= Assign a = 2 a = 2

+= Assign with add a = a + 2 a += 2

-= Assign with subtract a = a ndash 2 a -= 2

= Assign with multiply a = a 2 a = 2

= Assign with divide a = a 2 a = 2

= Assign with remainder a = a 2 a = 2

Basic Control Flow - if

Sequence

What we have been doing already

Selection

if statement if this then that

if (boolean expression) if (score gt= 50)

statement cout ltlt Passed

Logical Operators

Boolean expressions may be combined using

ampamp And

|| Or

Not

Operands and result resolves being either true or false

if (x ampamp (y || z))

else

Precedence and Associativity table in course book

Logical Operators

a b =

true true true

true false false

false true false

false false false

a b =

true true true

true false true

false true true

false false false

a =

true false

false true

a ampamp b a || b a

Logical Operators

if (x ampamp (y || z))

else

The value 0 (zero) is evaluated to mean false any other value is true

x ampamp (y || z) result

false ampamp (false || false) falsefalse ampamp (false || true ) falsefalse ampamp (true || false) falsefalse ampamp (true || true ) falsetrue ampamp (false || true ) falsetrue ampamp (false || false) truetrue ampamp (true || false) truetrue ampamp (true || true ) true

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp (y | ~z))

else

Bitwise Operators

unsigned int x = 11

unsigned int y = 7

unsigned int z = 25

if (x amp (y | ~z))

else

11 (x) = 000010117 (y) = 0000011125 (z) = 00011001

~z = 11100110 (230 or -26)

y | ~z = 11100111 (231 or -25)

x amp (y | ~z) = 00000011 = 3

Operands and the result resolve to a values

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp 1) x is odd

if (x gt y)

x = x ^ y

y = y ^ x XOr swap

x = x ^ y

Control Flow - if else

Selection

ifelse statements

if (boolean exp) if (score gt= 50)

statement cout ltlt Passed

else else

statement cout ltlt Failed

Control Flow -

Selection

Conditional (or Ternary) Operator

boolean exp true result false result

cout ltlt score gt= 50 Passed Failed

Control Flow

if (x gt= y)

if (y 2)

else

if (x gt= y)

if (y 2)

else

Control Flow ndash else if

if (exp)

else if (exp)

else if (exp)

else catch all remaining

if (aNum == 0)

else if (aNum == 1 || aNum == 2)

else if (aNum == 3)

else catch all remaining

aNum not 0123

Control Flow - switch

Selection

switch multiple selection statements

bull test must be an integral value 1 10 A x eg not 1056

bull case values must be constants

switch (aNum)

case 0

break

case 1 Fall through

case 2

break

default catch all

break

Repetition - while

while (exp)

statements

while (n lt k)

cout ltlt Enter mark

cin gtgt mark

t += mark

n++

Repetition - for

for (init exp inc)

statements

for (t = 0 n lt k n++)

cout ltlt Enter mark

cin gtgt mark

t += mark

Preferable to while if the range is known

Repetition - for

for (init exp inc)

statements

for () infinite loop

break causes loop to exit

Preferable to while if the range is known

Repetition - do

do

statements

while (exp)

do

cout ltlt Continue yn

cin gtgt yn

yn = tolower(yn)

while (yn = y ampamp yn = n)

There are a huge number of exercises and we donrsquot expect you to attempt

them all during this course

bull If yoursquore completely new to programming itrsquos probably best to tackle

them in sequence

bull If yoursquove some programming experience you should read through the

exercise summaries and then start wherever you feel comfortable

Exercises

Exercises

Topics covered in ex1 ndash ex6

Functions = mini programs

bull Used to combine data with operations and through functional

decomposition to promote code re-use

bull Simplifies coding

bull Functions for discrete tasks

bull Not hundreds of lines of code

bull Consumer only needs to know

bull What goes in and what comes out

Functions

Like everything else the compiler needs to have seen a prototype or a

definition of a function before we can use it

Prototypes lets the compiler generate the correct code

int min(int int)

int min(int int int)

void drawLine(point to point from = 00)

int square(int)

int main()

void beep()

string getNextPacket(void)

Return type Function name (Parameter list)

min

int min(int int) min prototypes (forward declarations)int min(int int int)

int main()

Having seen the prototypes the compilerc = min(x y) can generate the required code

int min (int a int b) min function definition 1

return a lt b a b

int min (int a int b int c) min function definition 2

return min(min(a b) c)

inline min

int main()

c = min(x y)

inline int min (int a int b)

return a lt b a b

int main()

c = x lt y x y

inline int min (int a int b)

return a lt b a b

Function Parameters

bull Pass by Value

bull A Copy of the parameter is passed to the called function

bull Pass by Reference

bull The actual parameter is passed to the called function

bull Pass by Memory Address (pointer)

bull Same effect as Pass by Reference (tomorrow)

Pass by value

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

return n_copy n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 10

n_copy 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp x)

x just another name for real_n

return x x

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

x 10

Pass by value (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

n_copy = n_copy n_copy

return n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 100

n_copy 100

Pass by reference (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

real_n = real_n real_n

return real_n

100

100

Mem Addr Contents

0x2786 100

real_n 100

Mem Addr Contents

0x2786 100

real_n 100

const Parameters

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Recursion

unsigned long long int fibonacci(int n)

switch(n)

case 0 Fall through - [[fallthrough]]

case 1

return n

break

default

return fibonacci(n - 1) + fibonacci(n - 2) Very inefficient

Arrays (Part 1)

Data structure containing same type of data (int double string char object)

bull Built in to C++

bull Series of elements each containing one item of data (contiguous memory locations)

Size (number of elements) set at compile time

Arrays (1)

int numbers[10] an array of 10 integers Each box sizeof(int) bytes wide

numbers

index values - 0 to 9

0 1 2 3 4 5 6 7 8 9

Arrays (1)

int numbers[10] an array of 10 integers

int n = 0

cout ltlt numbers ltlt endl address of the first element

cout ltlt numbers[n] ltlt endl contents of the nth element

cout ltlt ampnumbers[n] ltlt endl address of the nth element

cout ltlt numbers + n ltlt endl address of the nth element

0 1 2 3 4 5 6 7 8 9

42 hellip hellip hellip hellip hellip hellip hellip hellip hellip

0x1526

Arrays

char name[5] name - an array of five characters

thing t[5] t - an array of five things

examMarks ndash an array of three doubles initialised to 12 39 95double examMarks[] = 12 39 95 C++11 - double examMarks[] 12 39 95

header ndash an array of fifty unsigned chars (bytes) first three elements set to 0 1 255 and the rest to zerotypedef unsigned char bytebyte header[50] = 0 1 -1

Arrays

Accessing array data

define MARKS 5 or const int MARKS = 5

double examMarks[MARKS]

for(int i = 0 i lt MARKS i++)

cout ltlt Enter Exam Mark

ltlt i + 1 ltlt

cin gtgt examMarks[i]

for(i = 0 i lt MARKS i++)

cout ltlt examMarks[i]

Multidimensional Arrays

Two dimensional array Two subscripts First identifies row second identifies column

const int students = 6 const int marks = 3

double examMarks[students][marks] = 0 set to zero

for (int s = 0 s lt students ++s)

for (int m = 0 m lt marks ++m)

cout ltlt Enter mark ltlt m + 1 ltlt for student ltlt s + 1 ltlt endl

cin gtgt examMarks[s][m]

00 01 02

10 11 12

20 21 22

30 31 32

40 41 42

50 51 52

Memory laid out in row column order (more later)

00 01 02 10 11 12 20 21 22 30 31 32 40 41 42 50 51 52

Matrices

Provider Link

Armadillo armasourceforgenet

Blitz blitzsourceforgenet

Boost boostorg

Eigen eigentuxfamilyorg

Elemental libelementalorg

FLENS apfelmathematikuni-ulmde

HSL hslrlacuk

LEDA algorithmic-solutionscom

PETSc mcsanlgov

SimuNova simunovacom

SuiteSparse facultycsetamuedu

TNT mathnistgov

Trilinos trilinosorg

ViennaCL viennaclsourceforgenet

Exercises

Topics covered in ex7 ndash ex16

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people and dice

Recap Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

1 61 61 61 61 6

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

3 11 24 56 12 3

C++ and OOP

Encapsulation Keeping related stuff together

Member functionsmethods

an objectrsquos capabilities functionality and performable actions

int Throw()

Member variablesproperties

an objectrsquos current state values its dumb data

int sides

Dice throwing 3

struct dice

int sides State

dice(int n) Constructor

sides = n

int Throw() Member function (method)

return (rand() sides) + 1

int main()

Could also use dice d1 = 6 or d16 syntaxdice d1(6) d2(6)

d1sides = 6 d2sides = 10 Allow this

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

struct diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

class diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing ndash professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

diceh my-appcpp

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

dicecpp

Compiler

diceobj my-appobj

Linker

my-appexe

other librarycode objectfiles

Dice throwing - professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Compiler

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

diceobj my-appobj

diceh dicecpp my-appcpp

Linker

my-appexe

other librarycode objectfiles

Only items provided to the end-usercustomer

Classes and Objects

the includeltstringgt header file from the standard library

class string

your cpp source code files

include ltstringgt include information about class string

string Name a class string instance

string Address a class string instance

Classes and Objects

the include carh header file

class car

your cpp source code files

include carh include information about class car

car c a class car instance

Classes and Objects

the include househpp header file

class house

your cpp source code files

include househpp include information about class house

house no1 a class house instance

house no2 a class house instance

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do with it

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

cstart()

cenginestart() Or should cstart() internally use enginestart()

OOD

Time for a break

class student

What properties and methods do we need

class student

public

string name

string DoB

string college

string bodCardNumber

float age()

int main()

student s

sname =

sDoB =

How to guarantee an objectrsquos integrity

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s

sname = Compilation errors

sDoB =

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s( )

cout ltlt sage()

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB Error ndash cant assign to a constant

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_name(name) m_DoB(DoB)

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_namename m_DoBDoB

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Exceptions

class student

int main()

try

student s( )

catch(const char msg)

cout ltlt msg ltlt endl

student initialisation failed

Exceptions

try

catch(const char msg)

cout ltlt msg ltlt endl

catch (const invalid_argument amp e)

cout ltlt ewhat() ltlt endl

catch (exception amp e)

cout ltlt ewhat() ltlt endl

catch ()

cout ltlt Something went wrong ltlt endl

student invalid arg 2

if using C++11 see stdcurrent_exception

Reuse and inheritance

Say we now want to add a new type to our system ndash class academic With what we have seen so far we would proceed something like this

class academic

private

string m_name string m_DoB

Duplicating everything we had in class student

class person (generalisation)

OOP is sometimes called Programming by Describing the differences

student and academic are all specialisations of a more generalised and abstract class ndash person

class student public personpublic

student(string name) person(name)

class academic public personpublic

academic(string name) person(name)

class personprotected

person(string name) m_name(name)

private

string m_name

public

base class derived class

derived class

Specialised State

class student public person

private

const string m_bodCard

public

student(string name string DoB string bc ) person(name DoB) m_bodCard(bc)

Multiple inheritance

class student public person public oxMember

public

student(string name int age string bc) person(name age) oxMember(bc)

class academic public person public oxMember

public

academic(string name int age string bc) person(name age) oxMember(bc)

Destructors

class foo

private

int m_x int m_y

public

foo() foo(0 0)

foo(int x) foo(x 0)

foo(int x int y) m_x(x) m_y(y) only ctor that accesses private state

~foo() any necessary tidy up code

Dice throwing 5

class diceprivate

int sides

public

dice(int n) sides(n)

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

srand((unsigned)time(0)) Happy with this

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 6

class diceprivate

int sides

public

dice(int n) sides(n)

classshared state static bool seeded = false

if (seeded)srand((unsigned)time(0))seeded = true

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

3 65 21 44 22 6

Dice throwing 7

class dice private

int sides

public

dice(int n) sides(n)

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

Dice throwing 7

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyesDouble 14 33 5

Dice throwing 8

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6) int t

for(int n = 0 n lt 5 ++n)

cout ltlt (t = d1Throw()) ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp t = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Dice throwing 9

class dice private

int sidesint _lastThrow

public

const int amp lastThrow read-only stateproperty

dice(int n) _lastThrow(-1) lastThrow(_lastThrow) sides(n)

int Throw()

return _lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp d1lastThrow = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Exercises

Topics covered in ex17 ndash ex22

Vectors

Like an array a data structure containing same type of data (int double object)

bull A container class part of the standard library a wrapper similar to arrays

Need to includeltvectorgt

bull Can resize grow shrink as elements are added or removed from the end

bull Algorithms to manipulate data

bull Iterators to cycle through all the elements

Vectors

vectorltchargt name(5) vector of five characters

vectorltthinggt t(5) vector of five things

vectorltdoublegt examMarks 12 39 95 initialised vector of three doubles

typedef unsigned char byte

a vector of fifty bytes first three elements set to 0 1 255 and the rest to zerobyte char b[50] = 0 1 255 fully populate array

calc itemCountint itemCount = sizeof(b) sizeof(b[0])

vectorltbytegt bytes (b ampb[0] + itemCount) then init with vector 50 items

Vectors (iteration 1)

include ltvectorgt

vectorltintgt vec(20) 20 ints

for(int i = 0 i lt vecsize() i++) input values into vec

cin gtgt vec[i]

for(i = 0 i lt vecsize() i++) output vec

cout ltlt vec[i] ltlt

Vectors (iteration 2) (C++11 and later)

for(type identifier container)

statements

vectorltintgt vec(20)

for (int amp i vec)

Vectors

Adding an extra element

cout ltlt Enter an Extra Value

cin gtgt aNum

vecpush_back(aNum)

for (int i = 0 i lt vecsize() i++)

cout ltlt vec[i] ltlt endl

cout ltlt vecat(i) ltlt endl same as above but range checked (ie slowsafe)

Vectors (most of the methods)

docsmicrosoftcomen-uscppstandard-libraryvector-classFull list

Method Purpose

assign Erases a vector and copies the specified elements to the empty vector

at Returns a reference to the element at a specified location in the vector

back Returns a reference to the last element of the vector

begin Returns a random-access iterator to the first element in the vector

capacity Returns the number of elements that the vector could contain without allocating more storage

clear Erases the elements of the vector

C++11 data Returns a pointer to the first element in the vector

C++11 emplace Inserts an element constructed in place into the vector at a specified position

C++11 emplace_back Adds an element constructed in place to the end of the vector

empty Tests if the vector container is empty

end Returns a random-access iterator that points to the end of the vector

erase Removes an element or a range of elements in a vector from specified positions

front Returns a reference to the first element in a vector

insert Inserts an element or a number of elements into the vector at a specified position

max_size Returns the maximum length of the vector

pop_back Deletes the element at the end of the vector

push_back Add an element to the end of the vector

rbegin Returns an iterator to the first element in a reversed vector

rend Returns an iterator to the end of a reversed vector

reserve Reserves a minimum length of storage for a vector object

resize Specifies a new size for a vector

C++11 shrink_to_fit Discards excess capacity

size Returns the number of elements in the vector

swap Exchanges the elements of two vectors

Vectors (iteration 3)

include ltalgorithmgt

vectorltintgt vec

for(int i = 1 i lt= 5 ++i)vecpush_back(i)

1 2 3 4 5

5 4 3 2 1

vectorltintgtiterator it

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Reverse the vectorreverse(vecbegin() vecend())

cout ltlt endl

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Arrays (2) (C++11 and later)

arrayltint 5gt arr Thin veneer over an array ndash so requires fixed size

arrfill(0) int j = 0

for (int amp i arr)

supports latest iteration style

reverse(arrbegin() arrend()) and iterators for use with algorithms

C++11 - Uniform initialisers

C++98

complexltdoublegt c( 271828 314159 )

int a[] = 1 2 3 4

vectorltintgt v

for( int i = 1 i lt= 4 ++i )

vpush_back(i)

C++11

complexltdoublegt c 271828 314159

int a[] 1 2 3 4

vectorltintgt v 1 2 3 4

Pointers ndash What

A pointer is a scalar variable that is used to hold the memory-address of

another variable or function the stored address is said to point to the thing

it holds ndash thus the name

Pointers have a type ndash the type of the thing they point to

int n = 10I (p) am a pointer to an integer and I point to n over thereint p = ampn

Pointers ndash Why

In no particular order

bull Because external libraries and APIs (like the operating system (all of them)) are written using them

bull Create custom data structures like linked-lists trees graphs etc

bull Create tables of functions or single functions for handling events callback or signals

bull Access data on to the heap (allocate memory dynamically)

bull Writecall functions that change their input parameters

1 2

3

4 5 6 nilhead

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

Recap - Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference using Pointers

int main()

int real_n = 10

cout ltlt square(ampreal_n)

cout ltlt real_n

return 0

int square(const int real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x5110 0x2786

real_n 0x2786

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt pcout ltlt pcout ltlt ampxcout ltlt xcout ltlt ampp

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

15438

11

15438

11

17216

Pointers

int main(int argc char argv)

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )(argv + n) ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv + 0 C

argv + 1

argv + 2

argv + 3

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

int main(int argc char argv[])

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )argv[n] ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv[0] C

argv[1]

argv[2]

argv[3]

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

Memory Stack vs Heap

Stack (last in first out - LIFO)

Space automatically allocated

The place where arguments of a function call are stored

The place where local function data is allocated (eg variables)

The place where a function leaves its result (if any)

Heap

Space must be explicitly allocated

A place for allocating memory that is not part of last-in first-out approach

ie dynamically allocated data structures that survive function calls

Stack vs Heap

int stackArray[100] Allocate 100 ints on the stack

stackArray[n] = 0 Do something with it

int heapArray = new int[100] 100 ints on the heap C++

int heapArray = malloc(100 sizeof(int)) 100 ints on the heap C

heapArray[n] = 0 Or (heapArray + n) = 0 Do something with it C++ and C

delete [] heapArray When youre done C++

free(heapArray) When youre done C

Exercises

Topics covered in ex22 onwards

If time allows look through the remaining

exercises and attempt those that fit best

with your requirements

  • C++ Notes TPLO 12-11-2019 Blackbox
  • C++ Slides TPLO 12-11-2019 - Copy

Creating a multidimensional array 95

Creating a vector to hold exam results 100

Using insert() and iterators 103

Computing Fibonacci Numbers 110

Using pointers 114

Pointers and Arrays 116

PLUSPLUS Pointers and Arrays 119

PLUSPLUS Function pointers 122

main() and command-line arguments 126

EncryptDecrypt a file 128

Passing Arrays to functions 132

Base classes 137

PLUSPLUS Polymorphism 144

The PowerPoint slides entitled Exercises show the inclusive fromto exercise numbers which cover the topics discussed in the previous section It is not at all necessary to attempt to work through the entire quoted range variety is the spice of life ndash just choose those that appeal

1

1 Introduction Welcome to C++ A Comprehensive Introduction

These notes accompany the course delivered by Oxfords IT Services IT Learning Programme

If at any time you are not clear about any aspect of the course please make sure you ask your lecturer or demonstrator for some help If you are away from the class you can get help by email from your lecturer or from helpitoxacuk

Please also note that the university subscribes to Lyndacom ndash please check there for other C++ resources

11 What you should already know

The prerequisite for this course says that Either experience in another programming language or attendance on one of the PHP JavaScript or Python Kick-Start courses Is required

The more programming knowledge you have the better That said the documentation and lectures are structured such that those with very little knowledge should still be able to work through the course at their own pace

12 What you will learn

We will cover the following topics

Working with Microsofts Visual Studio Fundamental data types

Control Flow amp Iteration Header Files

Strings Functions

Arrays and Vectors Classes and Objects

Constructors and Destructors Member functions

Pointers And much more

13 Where can I get a copy of the softwaretools used

wwwvisualstudiocom (Microsofts C++ Compiler IDE and tools)

wwwpeetmcomC++introcoursezip (latest course code notes slides etc)

2 Things to understand

21 Compilers new and old

Students on this course often have to work with enhance or bug-fix existing code This sub-section is primarily for their consideration (it assumes some prior C++ knowledge)

2

Not all C++ compilers comply with the latest official ISO C++ standard (C++17) which was finally approved in December 20171

What does this mean It means that the code you write compile and run on one machine may not compile on the next machine if you are using a different compiler (even if it is using the same operating system) In this course you will be using Microsofts C++ Compiler (part of Visual Studio 2019)

Some older header files you may see with inherited C++ code are

include ltiostreamhgt have a h extension The C++ standard for this header file is include ltiostreamgt Your program may run correctly by adding a h but simply adding a h suffix will not work for all included files

include ltstringhgt has been replaced with include ltstringgt The stringh header file does not include C++ strings it includes C strings

include ltmathhgt has been replaced with include ltmathgt

The lesson to be learnt here is that a lot of C++ code you come across will have been created using older compilers Some of the header file and other code will not be recognised and may cause compilation errors when compiled on a machine which is more compliant with the C++ standard

If you are using the Gnu Compiler Collection (gcc g++ etc) you can specify standards compliancy via the ndashstd option eg -std=c++17 (other options are C++98

C++11 C++14)

Visual Studio can also be configured to use LLVM and clang Please see the relevant online documentation of how to install and use these if you wish to use them httpsllvmorgdocsGettingStartedVShtml

22 The C++ Standard Template Library (STL)

enwikipediaorgwikiStandard_Template_Library

The C++ programs you write will consist of the classes and functions that you write or modify (we provide partial solutions to every exercise)

However we will also look at what is still commonly referred to as the STL (now just part of the C++ Standard Library ) which holds a collection of existing classes functions and algorithms that you can use in the programs you will be creating

Some of the classes and template classes we will be looking at are

The string class The vector container template

The sort algorithm The list container template

The find algorithm

In addition you should also look at and be aware of another powerful library called Boost (parts of the STL come directly from the Boost library) wwwboostorg

The Boost library is easy to install (on any platform) as most Boost libraries are what is called header-only ie they consist entirely of header files containing templates and inline

1 A draft of this is included with your course files (n4660pdf) Its worth mentioning that this draft is in effect the published C++17 standard

3

functions and require no separately-compiled library binaries or special treatment when linking

23 Visual Studio 2019

What is Visual Studio (VS) VS is Microsofts freely available integrated development environment (IDE) and comes complete with optional compilerstools for a variety of languages We have only installed the IDE and the C++ compi ler (clexe etc) for this course

So what is a compiler

A compiler is a computer program that allows us to write programs in some specially defined language (unfortunately not English yet) in our case C++ (a so called high- level

language ) As you heard earlier the tex t we write in C++ is called source-code it is just simple text that one could write in Notepadexe for example

Sadly source-code is not directly understood by operat ing systems such as Windows Linux and macOS etc and it is the compilers job to convert our source-code into the terse concise and highly optimised machine-code that computers understand directly

Machine-code is often called executable or object-code and the compiled version of the source code is really just a file that contains numbers ndash a series of 8-bit bytes each holding a value between 0 and 255 The numbers either encode l ow-level instruct ions (code) or data that working together define the program Because these numbers may not encode displayable characters (see the ASCII table in the appendices to see a mapping between the numbers and the displayable characters) opening such a file an exe file in something like Windows notepad application would result in something like this being displayed (just the beginning shown)

However if we open this same executable file in a program that simply displays the files content as numbers and not what characters if any are represented by those numbers as Notepad is doing) we see this (the numbers are shown in base-16 or hexadecimal format)

4

The first two numbers 4D and 5A can be displayed as the text M and Z2 (see the first two characters at the top left in the previous notepad view of this file) 4D in base 10 is 77 and 5A is 90 ie the ASCII values for M amp Z (you can look these up in the ASCII table in the back of your course book)

Also take note of the line sequence starting 55 8B EC Then read on

2 MZ (0x4D5A) at the beginning of a file is an example of whats known as a magic number these are often used to identify a file type ndash in this case an MS-DOS executable file Trivia MZ are the initials of Mark Zbikowski the designer of the MS-DOS executable file format

5

If we have Visual Studio we can open the same file to see how such numbers translate into instructions and data

55 8B EC is the real beginning of our program In the above we see the numbers on the left and on the right what they actually mean Eg the first number 55 means push ebp which is an Intel CPU instruction Likewise 8B and EC together mean mov ebp esp The next line 81 EC C0 00 00 00 combines instructions and data and translate into sub esp 0C0h (subtract from esp the value C0 or 192 in base-10)

This is the entire program really the extra data shown in the previous views are for housekeeping

What does this program actually do then

Well youre about to find out ndash youre optionally now going to recreate it in Exercise 1

6

Creating your first program in Visual Studio 2019

Exercise 1 (Optional) Creating a first and default program

IMPORTANT

This exercise starts with a walk-through of using Visual Studio to create a new solution which you then go on to modify You should have already seen the steps needed to create a new solution in class so if youd rather just get on with the modification part simply open the (exercise solut ion)

f i rs t folder (in the Course folder) and double click the f i rs t s ln file If you choose to do this you can skip over the next few pages to the Explanation section (232) or even jump further on to Task 1 on page 14

Note You will not need to create any completely new programs during the course so even if you didnt fully follow the steps you can still safely move on to the modification part However if you really want to walk it through for yourself

Start the Visual Studio 2019 Integrated Development Environment (IDE) and create a new C++ Console application project You should have a shortcut to Visual Studio on your desktop failing that look for it on the Start menu

If they appear follow the prompts as shown below (if youre asked about keyboard mappings or Develop options select the C++ option)

7

Click Create a new project

Select Console App and click Next

8

Well locate the first project in a folder called first in your C drives Temp folder If the folder doesnt exist it will be created for you Click Create

Something like the above should appear (if you dont see the Solution Explorer panel open it via the View menu)

9

Alter the code adding the lines in bold as show here

include ltiostreamgt using namespace std int main() stdcout ltlt Hello Worldn system(pause)

Build and run the project by pressing the green arrow or by pressing F5

10

Explanation

Disclaimer at this stage you do not need to fully follow all of this just now

include ltiostreamgt

iostream is a standard C++ library file Files of this type are called header files They are text files usually containing C++ declarations definitions and code

Including iostream allows us to use some pre-defined objects to output messages to a console window This file must be included for any program that outputs data to the screen - or inputs data from the keyboard for that matter

The C++ compiler operates in passes through our code In the first pass ndash called the pre-processing pass ndash include directives are processed which are really text-substitution directives To be precise what include ltiostreamgt says is ldquoGo and find the text file called iostream and replace the directive with the contents of that filerdquo

The file name following a include directive can be enclosed in double quotes or chevrons ie include iostream or include ltiostreamgt The meaning of each is defined by the implementation (Microsofts C++ compiler in our case)

However it is common practice that if file name is in quotes it will be looked for locally first - in the same folder as the cpp file containing it and before being sought elsewhere Conversely if it is in chevrons the compiler will usually look for the file in a central include folder that was installed with the compiler ndash this folder is usually reserved for include files that come with the compiler as opposed to those that you might write yourself eg standard includes (like iostream) We therefore usually use quotes when we want to include our own custom project specific include files and chevrons when wanting to use include files that come with the compiler

You may also see that the filename sometimes has a h file extension This typically means that the header file being used is a C language header file and not a C++ one There are other variations (you are welcome to use your own) for example you might also see the occasional hxx file extension or something else entirely

using namespace std

The using namespace std code above doesnt actually appear in the automatically generated code In our project and solution files we will add it just after any include directives

namespaces in summary are very simple Everything within a namespace has a unique name and so theyre often used to help divide larger projects into more manageable chunks and to avoid name clashes

Standard C++ places a lot of its routines and functionality within a namespace call std Wed like to use this functionality and so we say we want to use all of the std namespace In the real world this isnt terribly good practice

11

However by declaring that were using namespace std throughout we can access members of this namespace without having to say exactly where they are (in which namespace) or worry about name clashes - where two objects in different files have been given the same name

The members of std that we will be using throughout are

cin (Console In) and cout (Console Out) and we must use include ltiostreamgt in order to use them

endl - is a stream manipulator that writes a new line to output endl stands for end

of l ine and is pronounced end all

If we dont declare that we were using the std namespace (which is the case in the automatically generated code) we have to prefix any use of cin cout and endl with std eg stdcin stdcout stdendl If youve added the using namespace std directive you may now remove the std in front of the stdcout ltlt Hello Worldn line

int main()

This is the entry point to our program ndash every C++ program must have this same entry point defined main() is a function the body of a function is defined within the opening and closing braces that come after its name The int to the left of main() says that this function returns (or resolves to beevaluates to) an integer value Returning a value requires you to use a return statement However as it is normal practice to simply return the value zero if you omit the return statement a value of zero is returned for you (only where main is concerned) If you want to explicitly return the value yourself you could modify the code to read

int main() stdcout ltlt Hello Worldn system(pause) return 0

So why return a value anyway Our added line return 0 means in this case that our main doing whatever it does as part of its function eventually resolves to the value 0 The value is returned to whatever called our programs entry point in this case and as usually that is the operating system ndash which has been waiting for us to return a value at this point However the operating system will simply ignore whatever value we ultimately return Why do it then

12

Consider the case when one of your programs needs to run another program to perform a part of its entire function Your main program needs to start this other program and wait until it completes successfully before continuing See the description of the system(pause) code line below

stdcout ltlt Hello Worldn

cout is an object declared in iostream ndash think of its name meaning console out Anything sent to cout using the double chevron operator ltlt appears on the console the

The n in the text means that cout should also output a carriage-return linefeed sequence (terms taken from the days of typewriters and telex machines) basically it means start any new output on a newline underneath the current line An alternative to using n is to use endl eg stdcout ltlt Hello World ltlt endl endl does more or less the same thing as n

system(pause)

system() is a standard function that is used to run an external program (here thats a standard Windows program called pauseexe) The system() function waits for the pause program to complete before continuing Going back to the discussion on return 0 earlier this is an example of one program starting another ndash here thats our program starting the pause program The pause program returns a value as part of its completion and we can examine that if we want Programs usually return 0 for success or some other integer value that means something went wrong ndash the value returned indicates what went wrong Ie a returned value of say 42 might mean that we cant answer the ultimate question with this computer3

So what is pause pauseexe is a standard Windows program that simply outputs the message Press any key to continue and then waits for a key to be pressed before exiting We use that facility here so that our program doesnt simply shutdown and disappear as it falls off the end of main()s closing or encounters a return statement If we did allow it to exit we would hardly have time to examine our programs output before it disappeared off the screen Try that and see (comment out the line using a double-slash like this system(pause))

If you run any of the course code on Linux or a Mac youll need to change this line to something like cinget()

3 An unashamed reference to the Hitch Hikers Guide to the Galaxy and the Deep Thought computer

13

Your projects default code template

In the course exercises when it comes to you writing code we will always ask you to open and then modify a partially complete projectsolution so you wont have to fiddle with projects and boilerplate code like this again

Nevertheless should you wish to start from scratch or simply experiment with Visual Studio we recommend using the code below as a starting point

include ltiostreamgt using namespace std int main() Start coding after here system(pause) return 0

14

Task 1

Immediately above system(pause) Replace the stdcout ltlt Hello Worldn line with the code shown here

int anum = 0

cout ltlt Enter a number

cin gtgt anum

cout ltlt The number you entered is

ltlt anum

ltlt endl

Test your modified program Tip remember you may hit the F5 key to build and then run your program

Try entering some text instead of a number Did it work

Alter the spacing (use of spaces and tab characters) in your code ndash does the C++ compiler care about this so called whi tespace

The statement int anum = 0 defines a variable (a memory location) which we will refer to in our code as anum to store a number of type int to hold an in teger (ie 1 -4 27) The memory location is being initialised with a value of 0 here It is good practice to initialise variables when you define them In C++11 a new type of uniform initialisation syntax was introduced and also encouraged eg int anum 0

cout ltlt Enter a number cout is a name that belongs to the namespace std The ltlt is called the stream insert ion operator When the program executes the value to the right of the operator (Enter a number) is inserted in the output stream and ultimately output to console window

cin gtgt anum cin is the input stream object of the namespace std gtgt is called the stream extract ion operator and is used here to read a number from the keyboard

cout ltlt The number you entered is ltlt anum ltlt endl This statement concatenates the output by using multiple stream insertion operators ltlt endl is the stream manipulator that adds a new line

The next Exercise starts on page 26 The pages between here and page 26 contain

code that you may like to try out by further modifying this project if not just read through the textcode until you get to page 26

15

Arithmetic Operators

Most computer programs perform arithmetic calculations Table 1 summarises the standard C++ arithmetic operators When working with integer division where both the numerator and denominator are integer the expression 15 6 evaluates to 2 To get the remainder after integer division you would use the modulus operator Note the modulus operator can only be used with integer operands

To establish the complete result of the following integer division 156 requires two operations

15 6 = 2

15 6 = 3

The result being 2 remainder 3

C++ Operation C++

arithmetic operator

Algebraic expression C++ expression

Addition + y + 6 y + 6

Subtraction - a - b a - b

Multiplication c times d or cd c d

Division xy or y

x or yx x y

Modulus p mod q p q

Table 1 - C++ arithmetic operators

Other fundamental data types Table 2 shows how you would declare and initialise four other data types for use in programs (there are more data types available)

16

Data type Example

Float float aFloat = 1234

Double (the precision of a Float) double aDouble = 123456

Char char aChar = A

Bool bool aBoolean = true

Table 2 - C++ numerical types4

Characters

Characters are normally stored in variables of type char but can also be stored as in t(eger) data types Characters are represented as single byte integers in the computer so it is possible to output a character as an integer or as a character

All characters have a numerical representation in the computer and the ASCII (American Standard Code for Information Interchange) character set shows each character and its decimal equivalent (also note that a combination of characters may be used to form more complex Unicode characters) See appendix 111

Characters can be read in with the following statements

char aChar declares a variable (aChar) of type char

cin gtgt aChar this statement is used to read a character into the variable aChar

Note After entering a character the ltENTERgtkey must be pressed before the character is read by the program

The following four statements correctly declare a variable of type char output a user prompt then read a character and store it in the variable aChar

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar

4 See httpencppreferencecomwcpplanguagetypes for a complete list (or the official ISO standard of course)

17

Header (include) Files

So far weve seen that to use certain functionality we had to include ltiostreamgt We have to do similar to use other functionality which is not part of the code C++ language ie we will need to include anything that comes as part of the standard library

In its current form Visual Studio comes with the following include files (most of which are standard files)

h files (95 C language files)

agentsh agileh ammintrinh amph amprth amprt_exceptionsh amp_graphicsh amp_mathh amp_short_vectorsh armintrh arm_neonh cfguardh collectionh comdefh comdefsph comiph comutilh concrth concrtrmh ConcurrencySalh concurrent_priority_queueh concurrent_queueh concurrent_unordered_maph concurrent_unordered_seth concurrent_vectorh crtdefsh crtversionh delayimph dloadsuph dvech ehh emmintrinh excpth fvech gcrooth immintrinh internal_concurrent_hashh internal_split_ordered_listh intrinh intrin0h invkprxyh iso646h ivech limitsh mm3dnowh mmintrinh nmmintrinh omph pgobootrunh pmmintrinh pplh pplawaith pplcancellation_tokenh pplinterfaceh ppltasksh ppltaskschedulerh pplwinh rtcapih salh setjmph setjmpexh smmintrinh srvh stdargh stdboolh stdexcpth stdinth tmmintrinh typeinfoh use_ansih vadefsh varargsh vcclrh vccorlibh vcruntimeh vcruntime_exceptionh vcruntime_newh vcruntime_new_debugh vcruntime_startuph vcruntime_stringh vcruntime_typeinfoh wmmintrinh xatomich xatomic0h xkeycheckh xlocinfoh xmmintrinh xsmf_controlh xstring_inserth xtgmathh xxamph xxamp_inlh ymathh yvalsh zmmintrinh

115 C++ files

algorithm allocators any array atomic bitset cassert ccomplex cctype cerrno cfenv cfloat chrono cinttypes ciso646 cliext climits clocale cmath CodeAnalysis codecvt complex condition_variable csetjmp csignal cstdalign cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cuchar cvt cwchar cwctype deque exception experimental filesystem forward_list fstream functional future hash_map hash_set initializer_list iomanip ios iosfwd iostream istream iterator limits list locale Manifest

18

map memory msclr mutex new numeric optional ostream queue random ratio regex scoped_allocator set shared_mutex sstream stack stdexcept streambuf string string_view strstream system_error thr thread tuple typeindex typeinfo type_traits unordered_map unordered_set utility valarray variant vector xcomplex xfacet xfunctional xhash xiosbase xlocale xlocbuf xlocinfo xlocmes xlocmon xlocnum xloctime xmemory xmemory0 xstddef xstring xtr1common xtree xutility xxatomic

Strings

Next to numbers strings are the most commonly used data type in programming

A string is both a datatype (string) and also literal character data ie a sequence of characters such as Oxford or StAndrews In C++ string literals are enclosed in quotes The quotes are not part of the string they identify the data type as a string

Actually this isnt quite true the double quoted strings are a sequence of characters and are taken from the C programming language The things declared of the string type are C++ string objects ndash which may be initialised using the C language literal

C++ strings can be declared and initialised in this way

string institution = Oxford

string name = Peet

To use the string type in your programs add the header file include ltstringgt at the top of your program This allows the use of part of the C++ library of classes called the string class (and its member functionsmethods explanations will follow soon)

Of course strings are normally used when requesting an input Consider this code

string aName aDept Two string objects

cout ltlt Enter your full name

cin gtgt aName

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

19

If in answer to the first prompt we were to enter say Fred Brooks 5 the interaction and output of our program would immediately result in this

Enter your full name Fred Brooks

Enter your department Fred is associated with Brooks

Why When reading in a string with a space such as FredltspgtBrooks only the first part Fred is read into aName ndash and the input is said to be space delimited by cin ndash and consists of two separate inputs (so the Brooks parts is read into the aDept string variable)

We could use multiple prompts to read in a name of course but this is inconvenient

To handle this situation we can use the standard getline(cin aName) function to read in a name instead of using cin gtgt aName This reads all key-strokes into aName until the ltENTERgt key is pressed at which point it returns a string containing all of the characters from the input

cout ltlt Enter your full name

getline(cin aName)

cout ltlt Enter your department

cin gtgt aDept

cout ltlt aName ltlt is associated with ltlt aDept

The string class has many useful functions you can use to manipulate strings An example is the length() member functionmethod

string aName = Fred Brooks

cout ltlt The length of the string aName is ltlt aNamelength() ltlt endl

This statement will output - The length of the str ing aName is 11

See section 12119 for more information on the string class and its member functions

5 Fred Brooks is a real person and a legendary computer scientist httpenwikipediaorgwikiFred_Brooks

20

The LF (Line Feed) Problem and Reading Keys

Continuing on consider the following code

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

string aName

cout ltlt Enter your full name

getline(cin aName)

cout ltlt You entered ltlt aName ltlt endl

system(pause)

The intent here is to first ask for a character and then to use getline() to ask for a name

If only things were that simple

If we were to enter say a Z to satisfy the first prompt the program would immediately output

Enter a character Z

You entered Z

Enter your full name You entered

Press any key to continue

The problem here is that being a keyboard key theltENTERgt key is itself being seen as a valid input so when we enter Z followed by the ltENTERgt key were actually entering two keys ndash Z and the ltENTERgt key The first keys placed into aChar whilst the enter key is left in the keyboards buffer This is quite reasonable if you think about it you entered two keys (Z and ltENTERgt) but provided a home for just one of them in aChar

Ok so whats the problem Well the problem is that we really need to use something like getline() to read text that contains spaces and it just so happens that getline() given this scenario will see the residual ltENTERgt key left in the buffer and it will assume that you didnt enter anything you just hit the enter key

This problem - that of having a mischievous ltENTERgt key waiting to surprise us ndash will occur whenever you read a key from the keyboard using cin Luckily theres an easy fix as we can use another input function to read and then discard the waiting ltENTERgt key Its called cinget() Here is a modified version of the code above that fixes the problem

21

char aChar

cout ltlt Enter a character

cin gtgt aChar

cout ltlt You entered ltlt aChar ltlt endl

cinget() REMOVE THE ENTER KEY discarding the got character

string aName

cout ltlt Enter your full name

getline(cin aName)

Used like this cinget() reads and discards a character from the input stream You can do the same using cinignore() cinget extracts a single character from the stream and returns it cinignore() extracts any number of characters and discards them (the details are specified via passed parameters to the function) or a single character if no arguments to the function are provided

You can easily use cinignore() to ignore a number of characters or until a certain token (character) is met eg the following code reads in a users first and last names and then outputs their initials

22

char first last Two 8-bit characters

cout ltlt Please enter your first name followed by your surname

first = cinget() Get one character

The first parameter is the maximum number of characters to

extract (and ignore) The second parameter is a

delimiting character The function stops extracting characters

as soon as an extracted character matches this one

cinignore(2566 ) Ignore until a space is seen

last = cinget() Get one character

cout ltlt Your initials are ltlt first ltlt last ltlt endl

Casts

On occasions in your programs you may want to store a value in a variable of a different type (when there is a danger of a loss of information the compiler will issue a warning for example when storing a double in an int) If you store a double as an integer you lose information in two ways

any mantissa (fractional part) will be lost

the magnitude of the double being stored may be too large to fit into the integer

Eg it is not possible7 to store 6678 x 10000 as a 16-bit unsigned integer because 667800 is 10000010011011100 in binary (17-bits) and is therefore larger than the maximum storable value of 65535 (1111111111111111) However you can store 1230 as an integer8

When you need to represent a value as a different type you can use the static_cast notation as shown here to change a double to an integer

6 If this is exactly numeric_limitsltstreamsizegtmax() there is no limit As many characters are extracted as needed until delim (or the end-of-file) is found

7 Actually the result of attempting to store 66780 in a 16-bit unsigned integer will be 10011011100 or 1244 Do you see how this value comes about

8 Also see the (demonst rat ion) L imi ts project

23

int anInt

anInt = static_castltintgt(doResult) where dResult is a double

You may also use the following historic classic C-style9 notation to cast to different data types

anInt = (int)dResult

Eg to change an integer to a character

char aChar

aChar = static_castltchargt(bInt) where bInt is an integer

You may also combine this using the

object-constructionfunction-call syntax of C++ eg

double d = 314157

int n = (int)d Convert ds value to an integer

int j = int(d) Ditto

9 C-style casts are usually considered to be too powerful ndash in that they indiscriminately allow unsafe and downright dangerous conversions C++ casts were introduced to solve this problem

24

Other Cast Types

Although outside the scope of this introductory course for reference here is a summary of the cast types in C++ (feel free to skip this for now and come back to it at a later time)

static_castlttypegt(object)

The type parameter must be a data type for which there is a known method for converting object to whether this be a built-in or through a casting function (constructor) All types of conversions that are well-defined and allowed by the compiler are done using static_cast

The static_cast operator may be used for operations such as converting a pointer of a base class to a pointer of a derived class converting numeric data types such as enums to ints or ints to floats However static_cast conversions are not necessarily safe as no run-time type check is done which can cause casting between incompatible data types for example initialised pointers However this is checked at compile time to prevent casting obvious incompatibles Also be aware that a static_cast between pointer of base to pointer of derived may produce an erroneous result (where the actual object pointed to is of type base not derived)

dynamic_castlttypegt(object)

In the C++ programming language the dynamic_cast operator is a part of the run-time type information (RTTI) system that performs a typecast Unlike the static_cast the target of the dynamic_cast must be pointer or reference to class Unlike static_cast and C-style typecast (where a type check is made during compilation) a type safety check is performed at runtime If the types are not compatible an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers)

reinterpret_castlttypegt(object)

Allows any pointer to be converted into any other pointer type Also allows any integral type to be converted into any pointer type and vice versa

The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument (unlike static_cast but like const_cast the reinterpret_cast expression does not compile to any CPU instructions It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type)

You cannot cast away a const or volatile qualification You can explicitly perform the following conversions

const_castlttypegt(object) A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is

25

identical except for the const and volatile qualifiers For pointers and references the result will refer to the original object For pointers to data members the result will refer to the same member as the original (uncast) pointer to data member Depending on the type of the referenced object a write operation through the resulting pointer reference or pointer to data member may produce undefined behaviour

26

Exercise 2 CreatingModifying additional projects

Examine how comments look in a program

Examine the use of some fundamental data types

Using different data types

Using the cast operator

Using the string class

Task 1

Open the skeleton project called EvenI

The project folder is

EvenIEvenI s ln

Modify the projects code in to prompt for two numbers of type double and two numbers of type integer

The program should output the sum the product and the difference of the double numbers Also output the quotient and the fractional part of the two integers10

Youll need something along the lines of hellip

double aDouble double bDouble

etc

To read a number into aDouble you could use

cin gtgt aDouble

Task 2

Modify your EvenI program to read in two characters Enter the characters a and Z

Output the two characters with the character case changed ie a becomes A and Z becomes z

You will need to look online or at in 12120 to establish the ASCII integer values of each character hellip you can alter a characters case by treating it as an integer and

To convert integers (or the results of evaluating integer expressions) to say characters we need to use a cast Eg

int i = 65

cout ltlt static_castltchargt(i + 32)

10 Trivia quotient comes from the Latin quotiens for how many times For example when dividing twenty by three the quotient is six and two thirds You can use a modulus b to get the fractional part

27

then by addingsubtracting tofrom it

Task 3

Open the skeleton project called Address and modify it so that it can be used to collect some user data

Output this collected data to screen as shown in Figure 1

Note that youll have to have include ltstringgt in order to use getline()

Figure 1

Visual Studio builds projects in one of two different modes ndash Debug or Release we will always use the Debug mode (a Release build is normally only used when a product is being beta tested ie late in the cycle)

When using Visual Studio (or most other IDEs for that matter) we normally do not have to concern ourselves with the location of the executable that is built by the program ndash because we normally run it from within Visual Studio itself However and just for your information really the exe for a debug build will always be located in the Debug folder immediately below the projects root folder ie for this project Addressexe is located in the (exercise solut ion) Address Debug folder whilst a version built in Release mode would be in the (exercise solut ion) Address Release folder

Debug builds contain extra diagnostic code that is automatically inserted by the compiler

28

3 Basic Control Flow The programs you have created so far are limited in that they run through a sequence of instructions once and then stop Most computer programs will make decisions and carry out different actions determined by the user input

C++ has three kinds of control structures

Sequence statement - the computer executes the statements one after another All the programs you have written so far use sequence statements

Select ion statements - if ifelse switch

The if selection statement selects an action if a condition is true or skips the action if the condition is false

The ifelse selection statement selects an action if a condition is true or performs a different action if the condition is false

The switch multiple selection statement can be used to perform many different actions based on a character or integer value

Repeti t ion statements - while for do while

The while and for statements perform actions within their bodies zero or more times If the loop condition test is initially false no actions will occur

The dowhile statement will perform the actions in the body at least once (the test ndash as to whether to continue - is at the end)

Selection - ifhellipelse statement

The if selection structure is used to choose among alternative courses of action The structure of the statement is

if(mark gt= 50)

cout ltlt Passed

else

cout ltlt Failed

If the condition (mark gt= 50) is t rue the statement following it is executed cout ltlt Passed

If the condition is false the statement is ignored and control is passed to the else part of the selection and statement following else is then executed cout ltlt Failed

ifelse selection statements can also be nested within other ifelse selection statements

29

Exercise 3 SearchString

Task 4

Open the skeleton project called SearchStr ing

You will need to include ltstringgt at the top of the code to complete this exercise See page 158 for more on the string class functionality

Modify the program to display a string of text to the user

The user should then be prompted to select a word from the sentence and input a replacement word Your program should replace one with the other You will want to See section 12119 on string functionality

The prompting string should be shown both before and after the update

Tips

Given a string s initialised to

string s = C++ at the University of Oxford

string t

int i = sfind(U)

cout ltlt i ltlt endl 11

t = ssubstr(0 i) bit before U in t

t = t + ancient + + ssubstr(i) +

Outputs C++ at the ancient University of Oxford

cout ltlt t ltlt endl

Puzzled Programmers

Using if if else nested ifs switch and the conditional operator -

Task 1

Solving puzzles

Open the I fp project and WITHOUT compilingrunning it determine its output

You will need to consult the operator precedence table in section 1216

You shouldnt compile or run the program to start with ndash the idea here is for you to determine its output on paper11

Tip you might want to consider tidying up the codes layout before attempting to solve it

void out(int n) is a function We havent covered functions yet but it makes sense to use one here and so we have Suffice to say for now that using out(some value) will output the value to the console window

11 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

30

Functions will be explained fully soon

Compile and run the program ndash if your workings from Step 1 differ from the output you should determine where you went wrong

Selection - switch multiple selection statement

The switch multiple selection statement can be used to perform many different actions based only on a single integer value Note however the switch statement can only be applied in narrow circumstances The tests must be constants and be integers Lets compare the two statements

int num switch(num) case 1 cout ltlt num = one

double num switch(num) case 11 cout ltlt num = 11

OK ndash Test is 1 a constant and an integer NOT OK ndash Test is not constant integer

Repetition ndash while dohellipwhile and for loops

The while statement is commonly used to carry out repeated steps perhaps reading in values before doing a calculation on values read in The format of the code is

while(condition)

statement

This can be read as whi le the condition is t rue continue to do the statements until the condition is false

31

The Collatz Conjecture

Win a million dollars

Task 1

Open and complete the project called Col latz (use a while() loop)

Given any positive integer if the number is even divide it by two else treble it and then add one If the result is one stop else repeat the process

The Collatz conjecture says that given any starting value the process above will eventually hal t (goes to one and stops)

Eg setting n to 9 as a starting point successive values would be

28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is not known whether the Collatz conjecture is true Fame and fortune await anyone who can prove it httpenwikipediaorgwikiCollatz_conjecture

A Collatz tree as visualised by Edmund Harriss

32

This image is a sample from the colouring book Visions of the Universe by Alex Bellos and Edmund Harriss

Get your own hi-res version for colouring-in here and see here for an explanation

33

Task 2

Re-implement your code so as to use a for() loop (this will be a lot easier than you might first think)

Not essential for this task but as we mention for loops you might like to look at the for project to see how a for loop can be animated to show how the three sections of it work in order

Mixing loops

Task 1

Open and modify the skeleton project called Factor ial

Modify it to use different repetition statements to calculate and display the factorial of a value entered by the user (they should enter a value between 1 and 10 inclusive)

Example use a while loop to prompt for an input value (between 1 and 10) and a for loop to calculate the factorial result

The output should be like that shown in Figure 2 below

Factorials12

The factorial of 5 (usually written as 5) is

1 x 2 x 3 x 4 x 5 = 120

If factorials are new to you think of them as defining the number of ways to arrange n items

To avoid displaying results in scient i f ic notat ion use

cout ltlt setprecision(0) ltlt fixed

setprecision() requires include ltiomanipgt

12 0 Is defined to be 1

34

Figure 2

PLUSPLUS Recursion

Come back to this after weve covered functions

Note that our solution optionally also uses a function and recursion to find the same factorial If you open it you will see that just after where we perform the output above we have commented out an extra line of code (uncomment and rebuild to see it in action)

We havent covered recursion in this C++ course yet but its basically the process of solving a problem in terms of smaller versions of the same problem Since the problem gets smaller each time the process eventually terminates in a problem (the base case) that can be solved directly When defining a recursive function be sure of three things 1 The problem gets smaller each time 2 Include a solution for the base case And 3 Each case is handled correctly

The recursive function looks like this ndash add then test it in your own solution

Factorial function using recursion

long long int recur_factorial(long long int n)

return n lt 1 1 n recur_factorial(n - 1)

The question mark is the conditional operator and is used with the colon to form the functional equivalent of an if then else

35

If the expression before the is true then the expressionstatement to the left of the is evaluated otherwise the one after the is evaluated Eg these are equivalent

x boo() hoo()

if(x)

boo()

else

hoo()

4 Logical and Bitwise Operators

41 Logical

Quite often we will want to perform some action if two things are true and we can achieve this using nested if statements eg

if(onething == true)

if(secondthing == true)

do something

In C++ we can achieve the same result through the use of the l ogical And operator - ampamp

if(onething == true ampamp secondthing == true)

do something

ampamp is a binary operator ndash meaning that it takes two arguments (nothing to do with base 2) eg Op1 ampamp Op2 The expressions Op1 and Op2 must be capable of evaluating to t rue or false (false in C++ has the value 0 whilst any other value is considered true) and both Op1 and Op2 have to be true in order to have the conditional part execute eg if(x ampamp y) Z = 10 Here both x and y must have non-zero values in order for z to be assigned the value 10 Note again that this is equivalent to

36

if(x)

if(y)

z = 10

The truth table for logical And is as follows ndash note that both Op1 AND Op2 have to be true for the result to be true

Logical And

Op1 Op2 Result

True True True

True False False

False True False

False False False

We also have a Logical Or operator (||) in C++ and its truth table looks like this ndash note that its one OR the other that has to be true in order for the result to be true here

Logical Or

Op1 Op2 Result

True True True

True False True

False True True

False False False

The remaining logical operator we have is the unary Logical Not (the exclamation mark is used for this)

Logical Not

Op1 Result

True False

False True

Logical ampamp and Logical || short-circuit ie for ampamp if the expression on the left-hand side is found to be false then the expression on the right is never evaluated as the whole will evaluate to false (because to be true both sides have to be true and we know that the first one is false at this point)

37

The same is true for logical || in that the right-hand expression is not evaluated if the left is found to be true (the whole will evaluate to true because the left is true so there is no need to evaluate the right-hand expression)

42 Bitwise

PLUSPLUS Base Two and Bits

We also have bitwise versions of the logical operators ndash plus some extra ones Bitwise operators work on a variables individual binary bits ndash rather than the value of all the bits taken as a whole For bitwise And we do not use ampamp but use just a single amp The same is true for bitwise Or we just use a single | and not || Bitwise Not is a little different we use ~ (the tilde) for bitwise Not

The additional bitwise operators we have are for bitwise XOr ndash for which we use the ^ symbol and lastly for left and right bit shifting we use ltlt and gtgt

Bitwise operators work on binary bits (1s and 0s) whereas the logical operators work on values equating to either true or false

For example consider the following code

int w = 10 int x = 42

int y = w amp x

int z = w ampamp x

cout ltlt y ltlt endl

cout ltlt z ltlt endl

The base-2 binary representation of 10 is 001010 and for 42 it is 101010 So w amp x means

001010 101010 amp ------ 001010 ------

Remember And is one and the other

Now let us consider w ampamp x Here were not interested in ws or xs bits just whether when taken together they are zero or something else Here both are non-zero so both are considered to be t rue and if we refer to our truth table from earlier on we will see that the result will be t rue When we assign that to an integer like were doing here the value assigned will be 1

38

Shifts

The shift operators shift the binary bits left or right Bits that do not fit fall off the ends and bits are replaced with zeros when shifting left ie bits do not rotate and come back on the other end again When shifting right the sign-bit may be preserved depending upon whether youre using a signed or unsigned integer

Shifts are useful for all sorts of things but one of the obvious uses is to multiply and divide eg x = 2 x = x ltlt 1 shifts the bits in x one place to the left so given that xs value is 00000010 in binary x = x ltlt 1 turns x into 00000100 which is 4 So x = x ltlt 1 is like saying x = x 2 You can of course divide by right shifting

XOr

The rule for XOr is one or the other but not both ie 1 ^ 0 = 1 (just like 1 | 0) but whereas 1 | 1 = 1 with 1 ^ 1 the answer is 0

Note that we do not have a logical XOr operator in C++ as we can just use = (not equal to) ndash see the (demonstrat ion) Logical XOr project

Practising with Logical and Bitwise operators

You will need to use the Precedence and Associativity table in 1216 to complete these tasks

Task 1

Open the Logical project As earlier DO NOT compilerun this yet

You will need to consult the operator precedence table in section 1216

On paper determine the programs output13

Run the program ndash output as expected

Task 2

Open the Bitwise ndash

unsigned project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Unsigned The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

13 This puzzle is taken from The C Puzzle Book by Alan R Feuer ISBN-10 0201604612

39

PLUSPLUS Signs and bits

Task 1

This one is tough as you should really know something about Twos Complement arithmetic to complete this

Open the Bitwise ndash s igned

project Again DO NOT compilerun this yet

(exercise solut ion)

Bi twise-Signed The solution has a running commentary

On paper determine the programs output

Run the program ndash output as expected

5 Introduction to Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine (which will also be a function) Encapsulat ion is data information or detail hiding If youre mathematically minded you may think of a C++ function as being very similar to one in mathematics ie a mechanism for mapping one thing to another

Once a function is written the detail of how it works is not important It is only necessary to understand what if any inputs the function needs (its parameters) and what output is produced (the functions return value)

The use of functions provides several benefits but the main one is that it makes programs significantly easier to understand and maintain The main program function can consist of a series of function calls rather than hundreds of lines of code A second benefit is that well written functions can be reused across multiple programs

You have to tell the compiler about a function before you use it and this is normally done using a prototype early in the program A function prototype consists of the return type a funct ion name and a parameter l is t - indicating the data the function will receive ndash and is terminated using a semicolon Eg

int someFunc(int int)

This tells the compiler that there is a function (somewhere) called someFunc that takes two integers as its input and returns an integer value for its output

40

Using a prototype is a way of telling the compiler the data types of any return value and of any parameters being passed and enables error checking to be done

The function defini t ion consists of the modified prototype and a function body which is a block of code enclosed in parenthesis which does the work Eg

int someFunc(int a int b)

return a + b

Here we have named the two inputs a and b and we can see that the functions job is to add these two value and to return them As this function returns a value (the sum of a and b) it may be used to expressions like this

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

Arguments can be passed to functions in two ways pass-by-value the default is where a copy of the argument value in the main program is made and then passed to the function The copy in the function only exists in memory as long as the function is active When the code within function has been run to completion the memory is released and the value held there is lost Any changes made to the copy passed to the function do not affect the original variable in any way For example if we altered and used someFunc like this

int someFunc(int a int b)

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 20

41

Note that because we passed a copy of b to the function that the line b = b 2 alters the copy (which then isnt used) and not the original

Arguments can also be passed-by-reference When arguments are passed in this way any changes made to the arguments in the function are reflected by corresponding changes to that data variable in the calling part of the program Pass-by-reference is good for performance reasons because it can eliminate the pass-by-value overhead of copying large amounts of data (In later sections we will examine how pointers can be used to fake pass-by-reference) Eg this will alter b now

int someFunc(int a int amp b) Note the amp

int res = a + b

b = b 2

return res

int a = 10 b = 20 c = 30

cout ltlt c + someFunc(a b) outputs 60

cout ltlt b outputs 40

See section 521 for more on this subject

Creating a function

The format of a function prototype is

return_data_type FunctionName ( argument_l ist )

The function CtoF - void CtoF(int temp) - has no return data type (void) its name is CtoF and it accepts a single input argument called temp of type int (integer)

It is not strictly necessary to give the argument a name (temp) in a function prototype you saw this above in int someFunc(int int) However the argument type must be specified The statement void CtoF(int) is therefore an alternative prototype

The following exercise is an introduction to functions You will learn a lot more about functions in later exercises

42

Writing functions

Task 1

Open the project EvenI you created earlier and change the structure of the program to make use of functions

Solution in (exercise solut ion)

EvenI I

Read two integers in to main() and pass them to a function The prototype is void intCalcs(int int)

intCalcs() function should calculate and display the result of the division and modulus of the two variables passed see Figure 3

Read in two doubles to variables in main() Pass the two doubles and the value of one integer to the second function the prototype is int Calcs(double double int)

Within function Calcs() write statements to produce the output as shown in Figure 3 Most of the code already exists within main()

Return the result of the multiplication of one double and an integer cast this value as an integer

Display the returned value within main() as shown in Figure 3

Figure 3

43

Using a struct

Task 1

Open the project Person

Solution in (exercise solut ion)

Person

As you saw during the presentation we can keep related data together using the struct keyword For example say we define a thing as follows

struct thing

int x

string y

double z

Having done this we can now create as many thing objects as we wish ndash simply by declaring them as we would say an integer

thing a

thing b

Each thing object a and b contains its own x y and z member variables eg

ax = 10 thing as x member set to 10

bx = 20 thing bs x member set to 20

cout ltlt ax ltlt endl outputs 10

cout ltlt bx ltlt endl outputs 20

Complete the exercise by creating and populating a struct Person object Once populated amend the printPerson() function so as to output the persons details

44

PLUSPLUS When Things Go Wrong

Going back to Exercise 8 if you havent tried it already enter zero as your second number What happens

C++ contains mechanisms for catching errors in the form of a trycatch mechanism

cin gtgt y Enter zero

try

intResult = x y

catch(myException amp e)

cout ltlt ewhat() ltlt endl

catch()

cout ltlt Generic oops ltlt endl

Modify your code so as to catch the divide by zero

Hopefully try and catch are fairly self-evident try something and catch any error if something goes wrong

There are two catch blocks here One tries to catch a myException object (we cannot see the definition of this classstruct here) and the other tries to catch anything else that is missed by catch(myException amp e) The amp says that the myException object e is being passed to the catch handler by reference Well learn what this means a little later in section 521

So did you see the Generic oops message appear

Your C++ compiler doesnt have to catch the divide by zero error ndash doing such a thing results in undefined behaviour This is because an arithmetic exception is an OS or processor exception - which is not the same as a C++ exception - hence it cannot be caught by a in a try catch block

To catch errors like this we either need extra support from the compiler14 andor operating system or to write some extra code For example we could do this

14 See also C signal handling httpenwikipediaorgwikiC_signal_handling

45

cin gtgt y Enter zero

if(y gt 0)

intResult = x y

However first we have to realise that this is a possible source of a runtime error and secondly we have to write (correctly) the code to handle the condition

Windows has built-in exception handling ndash called Structured Exception Handl ing (SEH) and we can generate code that uses this in support of the try catch structure used earlier

To enable this we need to tell the compiler to generate code that links into the SEH mechanism

To do this open the Project | ltproject namegt Properties hellip dialog box and in the Code Generation section select Yes wi th SEH Exceptions ( EHa) in the Enable C++

Exceptions line See Figure 4

46

Figure 4

The Monty Hall problem

The Monty Hall problem is a probability puzzle loosely based on the American television game show Lets Make a Deal and named after the shows original host Monty Hall

It goes like this

You are on a game show where you are shown three closed doors You are told that behind one of them is a new car and that behind the other two are goats

Two pieces of essential information at this stage 1 your goal is to win the car 2 the game show host knows what is behind each door

Lets walk through a trial game

The game show hosts asks you to choose a door ndash lets say you choose door number 1 (your door remains closed) The host now opens one of the remaining doors to reveal a goat (as there are two goats they can of course always do this) lets say they open door number 3

47

The situation is now as follows you have chosen door number 1 Only door number 3 is open and it reveals a goat The host now asks you if you would like to switch your door to the only other closed door - door number 2 At this stage you must either stick with door number 1 or switch to door number 2 and at that point the host will open the door youve chosen to reveal your prize

The question is when youre offered the chance should you stick or should you swap - will swapping increase your chance of winning the car or is it just 5050 The claim made here is that by swapping doors you will double your chance of winning the car What does your completed project claim

Task 1

Open and complete the incomplete project MontyHal l

The goal of this project to provide a simulation of problem outlined above

The function

int getRandomDoor(int n = 3)

return rand() n + 1

is used to choose a door number between 1 and 3 (inclusive)

Note that it has a default argument ie if it is called without an argument like this int val = getRandomDoor() the argument n is set to 3 by default and val will be set to a value between 1 and 3 However if it is called like this int val = getRandomDoor(10) then n is set to 10 and val will receive a value in the range of 1 to 10

48

More Functions

Task 1

Open the incomplete project IsLeap

The program asks for a year and determines whether the year is or will be a leap year

You need to complete the function IsLeap(int y) to implement the necessary code

Although the program is incomplete the program contains pseudo code for the algorithm required to compute the answer The pseudo is also show opposite

if year modulo 4 is 0

then

if year modulo 100 is 0

then

if year modulo 400 is 0

then

is_leap_year

else

not_leap_year

else

is_leap_year

else

not_leap_year

Figure 5

49

PLUSPLUS IsLeap in a line

Task 1

Extra points for implementing the IsLeap() function in just a single line of code This could be done using ampamp and || or by using the operator (a short form of if then else)

If you completed this step how readable is your code when compared to the if else version on the right

52 Algorithms

Algorithms

An Aside Big-O notation and Algorithm Complexity feel free to jump over this to Task 1

As programmers we usually implement the various parts of any new program in the simplest and most straight-forward way possible Then later if we find parts of our program are slow (causing what are called hot-spots) we will look again at the code to see if there is a better way to do whatever it is that is taking up the time

As a general rule the most optimal algorithms run in the shortest possible constant t ime ndash such algorithms are often symbolised using O(1) whereas the worst run in quadratic cubic exponential or factorial time (you can think of the O [called Big-Oh] as meaning in the Order of for some input n)

Usually were often happy with those running in O(n) (in the order of n) time ie their running time scales linearly with the number of steps or operations they involve Loops invariably signal O(n) parts of any algorithm

This is best explained using an example

50

Task 1 Understanding Gauss algorithm

Q How would you sum the integers from 1 to n where n is say 100

The obvious way is to use a loop

int tot = 0

for(int i = 1 n = 100 i lt= n ++i)

tot += i

This is fine for small values of n but not so good for very large ones

Interestingly it is said that this self-same problem was once given to a class of children which included one Carl Friedrich Gauss (presumably the teacher wanted to keep his charges occupied for a time) While most of the children started working at the problem (using the loop approach above) Gauss thought about it for a moment and then wrote down the solution 5050

The algorithm Gauss used may be easily demonstrated using the values 1 ndash 10

Gauss realised that if he wrote out the values twice (whether on paper or just in his head) once forward and once in reverse that he could sum each column formed to 11

1 2 3 4 5 6 7 8 9 10

10 9 8 7 6 5 4 3 2 1

1+10 2+9 3+8 4+7 5+6 6+5 7+4 8+3 9+2 10+1

=11 =11 =11 =11 =11 =11 =11 =11 =11 =11

Then sum of 1 ndash 10 is then 11 10 (columns) = 110 2 = 55 (we divided by two because we used each value twice)

Coming back to algorithm runtimes you can see that when using a loop summing 1 ndash 1000 will take ten times longer than summing 1 ndash 100 which will take ten times longer than summing 1 - 10 However by using Gauss approach we can arrive at the answer for any range of values in the same time this is what we mean by a constant time algorithm

51

Task 2

Open the incomplete project SumIntSeries

Complete the project so as to implement Gauss algorithm for any continuous range of integers

The solution project is (exercise solut ion)

SumIntSer ies

The general formula required is

((119948 minus 119947) + 120783)(119947 + 119948)

120784

Or in a more code form

Sum = ((k - j) + 1) (j + k) 2

Where j and k are the starting and ending values in the range respectively (both inclusive)

Functions and Pass by Reference

In the previous section when working with functions all arguments passed to the functions were copies of variable values from main() The arguments were passed by their value

Pass by Value is the default argument passing mechanism for C++ (and the C language)

In pass by value when a function is passed an argument it receives a copy of the value from the calling function (main() in previous examples) This copy remains in scope until the called function has completed and returned at which time the copy is destroyed

Therefore a function that takes value-arguments cannot change a passed variables value because any changes only apply to copies and not to the actual callers variables

An alternate passing scheme is called Pass by Reference

Passing variables to functions by reference is very useful when we need to change or update variable(s) via a function (it is also a faster mechanism than pass by value as no copies have to be made)

Under the covers pass by reference involves passing a memory address and not a copy of the data to the function This is usually more efficient than passing by value because there is no requirement to copy memory However this argument passing mechanism enables a function to modify any argument even if its not supposed to To avoid this we usually declare all read-only parameters as const and pass them by reference

The format of a function prototype when using call by reference is

return-data-type funct ion-name (reference parameter) To indicate a reference parameter an ampersand (amp) is written in the function prototype and header after the parameter type name

The statement void squared(int amp) has no return data type (void) its name is squared and it accepts a reference parameter (amp) of type int (integer)

52

The function definition would be something like this

void squared(int amp inVal)

inVal = inVal inVal inVal

The function call to it would look like this

squared(aValue)

As mentioned above pass by reference is normally used for one of two reasons 1 Because we want to be able to change a passed variable inside a called function 2 Because we want the speed associated with a pass by reference

In 2 we will normally protect our argument by using const in the called function Eg say we want to pass the double argument x to a function f() and take the least possible time about doing it (and given that function f() shouldnt alter x) we would use the following code

void f(const double x)

Use x in some calculation Note that if

x appears on the left hand side of an assignment operator

that it will result in a compilation error

Pass arguments by reference

Task 1

Open the project (demonstrat ion) FunctionRef

Compile and run the program The output should be the same as shown in Figure 6

53

Figure 6

Examine the function prototype

void squared(int amp)

This shows the function squared accepts a reference

parameter of type int The reference parameter is ndash under the covers - the memory address of the argument passed to the function

The function uses this address to both get and set the value stored in variable a (value 21) in main() A reference to this address is passed to the function with the function call squared(a)

Examine the function void squared(int amp x)

Under the covers references to x refer to the address of the variable a in main (that holds the value 21) Ie x and a reference the same piece of memory (the word object was deliberately not used there) So we can think of x and a as two names for the same item

Returning values from functions

In previous programs we have most often produced output (using cout) from within the functions However to be of most use and general utility functions should return resultsinformation rather than output it

Functions may return results in one of two ways 1 via a return value or 2 via arguments ndash either passed as references or via pointer (address)

Non void Functions return a single value ndash if you will they evaluate to this value As such non-void functions may be used in expressions Eg

54

w = x sqrt(y) z

The function sqrt() is replaced with the value of whatever the square root of y happens to be For example if y has the value 4 then to evaluate x sqrt(y) z fully the sqrt() function has to be called ndash where it returns 2 This value is then substituted into the expression for further evaluation ie it becomes w = x 2 z

The second way for functions to return results is via its parameters ndash if they are references or passed via memory addresses Eg

void doubleIt(int amp n)

return n 2 Error The void means doesnt return a value

doubleIt() is a void function ndash so it cannot contain a return statement ndash so it cannot evaluate to anything ndash so it cannot be used in an expression

x = doubleIt(y) error

However the function is still able to return a result (modify something outside of itself is perhaps a better way of putting it)

void doubleIt(int amp n) using amp - a reference

n = n 2

55

doubleIt() cannot (still) be used in an expression but it can change things

int x = 10

doubleIt(x)

cout ltlt x Outputs 20

Why would you use references like this Well references are mainly used for speed (by passing an actual external entity a copy does not have to be made) but they are also useful when multiple values (entities) might best be updated via a single operation (function call)

int x y z

x = y = z = 10

doubleAll(x y z)

void doubleAll(int amp a int amp b int amp c)

a = a 2 b = b 2 c = c 2

Side effects

Going back to w = x sqrt(y) z

Lets replace sqrt() with our own function and cause some havoc

double havoc(double amp d)

++x

d = sqrt(d)

return d

x = 3

w = x havoc(y) z

56

Here the value of y has been changed (yet it is not clear that could happen from the functions call site ndash where it was called from) and so has x Also what value for x will be used in x havoc(y) z Will it be 3 or 4 These sorts of issues are called side-effects

This is one problem (or advantage) with reference arguments ndash and that is that they can cause a change in a variable outside of the function being called

One way to protect against this is to use const references eg

double havoc(const double amp d)

++x

d = sqrt(d) Compilation error here

return d

57

Returning a value from a function

Task 1

Open the TempConver t

project

Run the program The output should be the same as shown in Figure 7

Examine the function prototype

double convert(double temp int mode)

This function prototype has a return type of double When the function is called and calculations are completed a double value is returned to the caller

Examine the function definition The function definition matches the prototype indicating a double and an integer are being passed to the function and a double is being returned

Examine the function body The two statements below convert the temperature input The conversion type required is identified using the user input mode and a switch selection

The statement (temp - 32) 5 9 is used to calculate the temp in Centigrade

The statement 18 temp + 32 is used to calculate the temp in Fahrenheit

Figure 7

58

PLUSPLUS Arithmetic Bases

Task 2

Open compile and run the partially complete Bases project

Note that the project isnt complete

The program uses intrinsic functionality to output values in hexadecimal and octal ndash base 16 and base 8 Both these bases are useful in programming its all to do with binary and the size of a byte

Note that there isnt a bin equivalent to hex and oct and that we have instead written a function called bin1() to convert a value into its binary (base 2) representation

Understanding how bin1() works

bin1 uses the modulus operator () and the right shift operator (gtgt) to work eg 42 in binary is 101010

25 24 23 22 21 20

32 16 8 4 2 1

----------------------

1 0 1 0 1 0

----------------------

1 32 + 0 16 + 1 8 + 0 4 + 1 2 + 0 1 = 42

The function progresses like this

42 2 has remainder zero (false as evaluated in the if) If the if test is true we store a 1 else we store a 0 We then divide 42 by 2 by right shifting it one place ndash but just replace that with n = 42 2 if you prefer We then loop while we have a non-zero value in n to operate on hellip

42 2 = 210 42 2 = 0 if(42 2) = false string value = 0

21 2 = 105 21 2 = 1 if(21 2) = true string value = 1

10 2 = 50 10 2 = 0 if(10 2) = false string value = 0

5 2 = 25 5 2 = 1 if(5 2) = true string value = 1

2 2 = 10 2 2 = 0 if(2 2) = false string value = 0

1 2 = 05 1 2 = 1 if(1 2) = true string value = 1

59

Task 3

The project needs completing specifically it needs the function bin2() writing

We could write such a function as bin1 in a variety of ways and wed like you to write a new function called bin2() that produces the same output as bin1() here

Heres a step by step algorithm for implementing bin2()

Youll use either gtgt or and the bitwise And (amp) operator

Take the functions input (the number to convert) in as a parameter called n To keep it as simple as possible for now you could use plain int types rather than the unsigned long long type we used so the functions signature would look like string bin2(int n)

1 In the function create an integer called i and initialise it to 1

2 Realise that if you left shift the single bit in i (use ltlt or multiply it by 2) it will take on the values 2 4 8 16 32 hellip until it eventually goes to 0 ndash as you shift the bit off of the end

3 Recognise that you could compare your shifting bit with one in the same position in n using bitwise And Ie if((n amp i) == 1) then you know youll need a 1 in your output string for the bit position in n (2 4 8 ) given by is value at this point

4 Build up your result string as you proceed

Change your int n and int i to unsigned long long int and re-run

Try using other integer types ndash signed and unsigned

Lastly examine the solution project in (exercise

solut ion) Bases

60

Figure 8

61

Searching for Sequences

Task 1

Open and modify the incomplete project called called HeadsOrTai ls

When all completed the output should be similar to that shown in

Figure 9

This is the (exercise

solut ion) HeadsOrTai ls project

The programs purpose is to look for a sequence of simulated coin tosses ndash a series consisting of Hs and Ts

The program is complete (as in it runs) but it has some issues At first test it using quite short sequences

The timing information displayed by the application is included simply to demonstrate a timing mechanism that can be used to test the efficiency of the code

The first problem is that the user can currently enter characters other than H or T (h and t are ok as the input is converted to uppercase ndash note the string is passed by reference to toupper() which uses a pointer (which well cover later) to process the string

The second problem is that as it stands the algorithm isnt very optimal if we do not find our pattern we add the result of another coin toss to the current sequence and then re-check the sequence in its entirety

For example if were looking for HHTHH and the generated sequence is currently HTTHHHTTHTHHTTH we will fail to find HHTHH and then proceed to add another coin-toss result at the end ndash HTTHHHTTHTHHTTHH We will then scan this for HHTHH However as we know that we failed to find HHTHH before we added the extra coin-toss re-checking the previously checked sequence is pointless and very time consuming (think how this would (or wouldnt) scale) Your task here is to think of and implement another more optimal approach

62

Figure 9

Task 2

Open the HTTvsHTH project you will find that the project will compile correctly but displays an incorrect result

When completed the program can be used to check how many coin-tosses are required on average to see a particular sequence

Why should that be of interest Because sometimes its rather surprising For example test how many tosses are needed to see say HTH and then HTT

When the program is corrected the output should be as shown in Figure 10

63

Figure 10

PLUSPLUS Optimising Searching for Sequences

Task 1

As it stands the program (yours and ours) encodes a coin toss as a character ndasheither an H or a T Each character is encoded using at least 8-bits and so checking whether a generated sequence is the sequence were looking for means performing a string comparison which is costly in terms of clock-cycles Of course generating and storing the new coin toss also requires the use of these costly string operations

As we have just two tokens as an alternative to generating and storing characters and performing string operations we could encode a sequence as a series of bits For example the sequence HTH could be encoded as 101 in binary (5 in decimal) You can set the corresponding individual bits in an int using the bitwise Or operator | (a vertical bar) eg int n = 0 n = n | i which youd most likely do as a result of scanning the users entered search-sequence string a character at a time In this way you could encode the sequence HTHHTHHTHHTHHTHH in a single sixteen bit unsigned int

Additional operators needed to implement sequence checking and H or T bit manipulation are bitwise And (amp) and the left shift operator (ltlt)

You will find more information on some of these operators just a little below

64

Evolving Searching for Sequences

Task 1

Looking for sequences in stringssequences is an interesting and complex problem in computing and also in genetics where the string being searched could be a DNA sequence and pattern could represent a gene perhaps with a snip (a modificationmutation)

Modify your HeadsOrTai ls program (or our solution) so that instead of Hs and Ts it generates and searches for Gs As Ts and Cs instead

Randomly generate a GCTA sequence and a similar pattern to find within the sequence

How much more time and variation is required in this slightly more complex situation

Conduct a few experiments and using Excel graph your results (copy and paste some data highlight it and then select Excels line graph ndash Excel should then automatically plot your data)

Extrapolate The human genome is how long A gene might contain how many bases How difficult is the task of finding interesting sequences in the human genome How about checking for the odd mutation (insertion transposition deletion) ndash fuzzy matching

A solution for this problem can be found in the (demonstrat ion) GATTACA project

6 Classes and Objects In the previous section we have been working with simple programs that display messages to the user store data input as different data types manipulate the data in some way and output the results to screen

We will now start to look at C++ objects and classes

In the real world there are objects everywhere students staff cars birds houses and many more All objects have at tr ibutes these are similar to the variables created in previous tasks Some attributes of a student may be height weight race course of study etc All objects exhibit behaviours or operations cars accelerate and decelerate students matriculate enrol on courses and leave university

65

Now what is the relationship between a class and an object A good analogy would be from an architects blueprint for a house it would be possible to build many houses Similarly from a class in C++ it would be possible to build many objects

If we had a student class we could create many objects from the student class to represent the many students enrolling Each of these objects would be uniquely identified They would share common attributes and exhibit common behaviours If we wanted an object to perform some task we would call the appropriate member function allowing an operationaction to take place changing the behaviour of that object

Member functions are different from the functions you have created so far Member functions are always associated with objects and are usually called or invoked using a dot notation object member funct ionname() An example is student1getName() The object instance is student1 and the member function is getName()

Member functions contain the detail of how the technical aspects of some operation will be processed When member functions are invoked these technical issues are hidden from the end user When the member function is asked to do some operation a message is sent (a member-function call) telling the member function of that object to perform the operation detailed in the function

Functions are not completely new we have had a brief introduction and you have already created some of your own Note also that main() is a function that is called automatically when you run your program However it is not a member function as there is no object associated with it

Creating your first class

Creating a class

Task 1

Open the project called StudentUG

Compile and run the program It should look like Figure 11

66

Figure 11

Before you can create the object myName it is necessary to define the class from which the object will be created The class definition is shown below

class StudentUG Start of class definition

public

void displayName() Start of member function

cout ltlt My name is Michael Cain ltlt endl

Note a semicolon is required at the end of the class definition

Within main() the statement StudentUG myName creates the object myName of class StudentUG In effect StudentUG is a new type

The statement myNamedisplayName() is used to call the member function displayName() of object myName

As we have seen previously the function main() is called automatically when our programs are executed However member functions (displayname() is one we could have many) must be called in this way objectInstanceNamefunctionName() when dealing with an

67

object directly and like this objectInstanceName-gtfunctionName() if working through a pointer to an object (more on pointers later)

The member function displayName() is preceded by the word void All functions can return values this one does not The word void preceding the function name indicates nothing is being returned If this function returned an integer the definition would be int displayName()

When you use functions it is common to pass data (called parameters) to the function The function then manipulates the data before displaying an output andor returning a value

To pass a parameter to the function in the studentUG class the calling statement in main() would be

myNamedisplayName(name) where name is a string (a series of characters) that contains a value read in from the keyboard

In order for the function displayName() to recognise the parameter being passed the function declaration is changed to include the parameter (name) and type (string) as shown in below

void displayName(string name)

cout ltlt My name is ltlt name ltlt endl

Figure 12

Member functions and Passing parameters

Passing parameters

Task 1

Modify StudentUG to read in a student name The name should be passed to a member function The parameter should be output from within the function to welcome the user to C++ programming

68

Task 2

Modify the program in the above task to read in two more names Each name will be for a different student and you will need to create additional objects (instances) of the class

Data Members

In most of the programs written so far the variables have been declared inside the main() function Variables declared inside a function are local to that function and cannot be accessed from outside that function

You have created a student class and it would be reasonable to assume that a student would be following a particular course So courseName might be one of several attributes of a StudentUG object Attributes are represented as variables in a class defini t ion These variables are called data members and must be declared inside a class definition When you create an object of a StudentUG class each object has a unique memory location for its data members

Figure 13 shows data member name declared in the class definition The access specifier private means that only member functions of the class in which the attribute was declared can use this data member

private string name

Figure 13

When data members are declared as private the data is hidden This is called encapsulat ion and means the attributes of the object are hidden and can only be accessed via member functions

As there is no direct way to change a data member you will also need to create a member

funct ion to set the data member to a value and create a second member funct ion to output the value held there

Data members can also be declared public A data member that is declared public can be accessed from any (non-member) function

A protected data member can only be accessed by member functions of its own class and by member functions of classes derived from this class We will learn more about derived classes and inheritance later

69

Using data members

Task 1

Open the project called StudentCoursesln

Compile and run the program it should look like Figure 14

Figure 14

Task 2

Examine the member function getCourse() shown in Figure 15

string getCourse()

return course

Figure 15

Task 3

Modify the StudentCourse source file to enable the user to add a student name enrolment date and number of years of course Once entered this data should be output to screen You will need to create additional data members and member funct ions to achieve this

70

More Objects

Task 1

So far you have created one StudentCourse object It is about time we had a second student on the course Create a second object of the class StudentCourse You will need to add the second statement shown in Figure 16 to add the new object student2 Call the member functions passing parameters as necessary

Figure 16

Constructors

When you create objects from the StudentCourse class it is necessary to give initial values to all the data members If we were entering data for five people and they were all following the same course of study it would make sense to initialise the course data member (it is possible to initialise some or all of the data members) when each object is created

A constructor is a special kind of function that must have the same name as the class Constructors are normally defined to be publ ic and never have a return type They can be used to automatically initialise data members

In previous programs you have written a defaul t constructor has been provided by the compiler However it is not possible to pass parameters to a default constructor function so the data members in the programs created so far have not been automatically

71

initialised To initialise these data members you created member functions that assigned values to data members

Although a default constructor is provided at compilation time it is a good idea to create your own so that the data members can be initialised

It is worth noting here that functions (constructors are functions) can be over loaded This means it is possible to have more than one function with the same name Note that overloaded functions (functions with the same name) must have different types of or number of arguments

Constructors (functions) can also be overloaded with more than one function with the same name but different types or number of parameters Fortunately for us the compiler automatically calls the correct function whose parameters match the arguments used in the function call

Using constructors

Task 1

Open the project called Constructorss ln

Compile and run the program it should look like Figure 17

Figure 17

72

Task 2

In the constructor shown in Figure 18 what is the purpose behind course = Note that as the string parameter name has the same name as the class variable that we use the hidden this pointer to access the class variable in the assignment If we didnt do this and simply used name = name instead then all we would be doing is assigning the value in the parameter back to the parameter

StudentCourse(string name)

this -gt name = name

course =

Figure 18

Task 3

Create a third constructor that will take an argument enrolment_date

Add a third object call it student3

Write code that will test this additional constructor

Solution in (exercise

solut ion) Constructors

If time allows add other useful properties (data members) access methods (functions) and constructors

Separating use from declaration and definition

C++ is all about objects and any decent project will usually make use of a number of application or domain specific classes

To keeps things maintainable and to promote code reuse C++ projects usually contain a number of cpp and h files where each h files will usually contain a declaration of a class (sometimes called an interface) Note though that the definition of the class (sometimes called the implementation) ndash the code that implements it ndash will be absent from the h file and will instead reside in an accompanying cpp file

Aside from allowing different teams to more easily work on separate parts of the program one of the main reasons for separating definition from declaration is to enforce abstraction which is a programming (and design) technique that relies on the separation of declaration and implementation For example lets say that your team needs a class that acts a bit like a stack (a last-in first-out or LIFO structure) and as this is required

73

urgently you decide to implement it using a simple array You would then only want to give your team what is absolutely necessary to use this class a single h file for your team members to include in their cpp files If they look in the h file they will only see information on how to use the class but how it does what it does is kept elsewhere in the cpp and that youve withheld Consumers shouldnt need to know how a thing works in order to use it

An obvious advantage to this is that there is no danger in you changing how it works Perhaps you later decide to use a vector instead of the array You go ahead and alter the implementation and your team members are none the wiser ndash after all the interface hasnt altered just the implementation

So how does the project get built Of course the implementation of this class will be required at compile time and you can either do that by including the cpp file directly (which will give away the implementation details of course) or by including it as object code ie compiled C++ code (binary machine code) This is how valuable commercial source code is kept in-house while the binary implementation complete with a h file is provided to customers (you will see an example of this just below in Using external

l ibrar ies and thi rd par ty header f i les )

Any discussion on separating use from declaration and definition should include something on namespaces You introduce a namespace by simply using the keyword and braces Anything entered inside these braces is inside the namespace eg

namespace securityModule class Encryptor using namespace std using namespace securityModule int main() Encryptor e Without the using we would have had to use securityModuleEncryptor e securityModuleEncryptor e2

See the (demonstrat ion) Namespaces project for more on this

74

Separating declaration and definition

Using a header and source file to separate class declaration from definition

Task 1

Open and modify the partially complete skeleton project called Precis ionTimers

Like HeadsOrTai ls this project makes use of the Windows operating system to very precisely measure elapsed time However unlike HeadsOrTai ls we have separated the stopWatch class interface from its implementation

As weve previously mentioned Gauss and algorithm efficiency we could test our theory that summing in a loop is O(n) ie that the time taken scales with n

Examine the project files hrTimercpp and hrTimerh noting that the h file contains just enough information for someone to use the declared class stopWatch whilst htTimercpp contains the implementation of the class

Now look in PrecisionTimerscpp You will see that an instance of the stopWatch class is declared Also note that we include hrTimerh but make no reference to hrTimercpp

As it stands the code calls two functions to calculate the sum of a range of integers sumGauss() and sumLoop() The program outputs the clock-ticks used and time taken in seconds

Note that sumLoop() is incomplete

Complete the sumLoop() function and then choosing suitable values for the ranges upper-bound carry out a few experiments to test if the loop is really O(n)

What is this used to do in hrTimerh15

ifndef HRTIMER

define HRTIMER

endif

15 You should also see pragma once as this is rapidly becoming the alternate way to do this ndash whatever this is of course

75

PLUSPLUS Providing object code only

Task 2

We have provided a separate demonstration project that takes the discussion on this one step further (demonstrat ion)

Separat ingThings

In its current form the project wont compile To compile the project in the Solution Explorer add the existing carcpp file to the source files list that just contains SeparatingThingscpp and recompile carcpp is in the same folder as SeparatingThingscpp

Once youve done that right-click on carcpp in the Solution Explorer and select Remove Very importantly when youre prompted for confirmation choose Remove do not choose Delete Now recompile once more youll see that the project fails to compile as the definition of car has been removed

76

But hold on we created carobj - the compiled object-code version of carcpp during our previous compilation so we could tell the linker about that and all should be well (this more or less duplicates the scene whereby you do not provide source code but provide only object code)

The carobj file will be located somewhere like

CUsersDesktopCourse(demonstration) Separating Things(demonstration) Separating Thingsbincarobj

To add this to your project go to Project | Properties | Configuration Properties | Linker | Input

77

In the right-hand window select Additional Dependencies drop down the list and select ltEdit gt

In the dialog that appears add the full path to carobj (see earlier in Step 2) and press Ok

Lastly recompile the code once more It should compile and run At this point you could if you wanted to delete carcpp altogether

One last thing

If you look in the comments in SeparatingThingscpp you will find a discussion that goes into the advanced topic of hiding things even further This includes a brief discussion of the the so called pimpl pattern (pronounced Pimple this stands for Pointer to Implementation16)

16 httpenwikipediaorgwikiOpaque_pointer

78

PLUSPLUS Using external libraries and third party

header files

Task 3

Open and modify the project called Lot to

Examine the projects comments to understand the programs function Run the program ndash does it work

It is supposed to compute the odds of winning the UKs lottery httpwwwnational-lotterycouk (try as we might we couldnt find the odds on their own website)

The program uses the recursive factorial function used earlier in the course (with bigint being typedef ed as unsigned long long int)

Factorial function using recursion

bigint recur_factorial(bigint n)

return n lt 1 1 n recur_factorial(n - 1)

There is a problem here however in that to compute the odds we must compute some significant factorials ie

49 = 608281864034267560872252163321295376887552831379210240000000000

and

6 (49 - 6) = 43498989405629161658895695089330078205230448640000000000

Sadly our bigint (unsigned long long) can hold a maximum value of 2^64 ndash 1 = 18446744073709551615 ie not hardly big enough

Fortunately in C++ we can define new types like an arbitrarily sized integer (outside of the scope of this course but see the (demonstrat ion) newINT project for a small taste) However this is object orientation ndash surely we can just use an existing already defined arbitrarily sized integer class

79

Task 4

The good news is that in this class you can You can use LEDA (The L ibrary of

Eff ic ient Data types and Algor i thms ) a professional class library of advanced numerical functionality

You will need to download the program called

LEDA-63 i386 msc 10 ( NET 2010) 32 bi t

or

LEDA-63 i386 msc 10 ( NET 2010) 64 bi t

Go to wwwalgorithmic-solutionsinfofreeindexphp Accept the licence terms and download the appropriate version (usually the 64 bit version)

The LEDA installation program will install additional numerical libraries and header files from the Algorithmic Solutions company

Once the setup is complete modify the Lotto program

In the Solut ion Explorer right-click on your project (Lot to ) and left-click on Proper t ies A dialog-box appears

Under the CC++ section

1 Click on General Choose Addi t ional include di rec tor ies and enter the directory CAlgor i thmic Solut ions LEDA-63- free-win-msc10-

s td incl

2 Click on Preprocessor and add LEDA_DLL to the end of Preprocessor

Defini t ions Note the semicolon is required

3 Click on Code Generat ion and check that Runtime Library is set to Mult i - threaded Debug DLL ( MDd)

Under the Linker section

4 Click on General

5 Choose Addi t ional l ibrary di rector ies and enter the directory CAlgor i thmic Solut ionsLEDA-63- free-win-msc10-s td

6 Click on Input and add l ibGeoW_mdd_dl l l ib leda_mddl ib to the end of Addi t ional Dependencies Again the semicolon is significant

You may now close Properties dialog-box

7 Modify your code Add the following under include ltiostreamgt

include ltLEDAnumbersintegerhgt using ledainteger using namespace std

80

Then modify the recur_factorial() function so that it accepts and returns a type called simply integer rather than bigint

Save the project and exit Visual Studio

In order to build and execute Lottoexe Windows needs to have l eda_mdddl l in its search path for DLLs Therefore we need to add the path to the folder containing leda_mdddll to the PATH environment variable

8 In Windows Explorer navigate to My Computer then right-click on it and select Propert ies

9 Click on the Advanced tab and then on the Environment Var iables button

10 In the bottom section (System var iables ) of the dialog box highlight Path and then click the Edi t button

At the end of the existing path add -

11 CAlgor i thmic Solut ions LEDA-63- free-win-msc10-s td

Once more note the leading semicolon is significant

81

12 Restart Visual Studio and re-open Lot to Build and run the application as normal

It might seem that this was a lot of work for such an apparently trivial result but the fact is that you now have access to (and have seen how to use) an advanced numerical library of functionality And anyway when all is said and done you must admit that at least you got a return here ndash which is more than you should reasonably expect from the lottery

Figure 19

Task 5

Explore the LEDA samples and documentation ndash if you installed it there should be a shortcut in your start menu to LEDA-63-free-win-msc10-s td

Task 6

Modify the Lotto program to see how the odds change when there are more balls andor when more balls need to be matched (you might also display more of the intermediate results of calculations ndash like 49)

Destructors

Both constructors and destructors are special class methods We have seen how a constructor is called whenever an object is defined

A destructor has the class name prefixed by a tilde ~ Like constructors destructors cannot return values and therefore they have no return type specified but unlike constructors destructors have no arguments and thus cannot be overloaded

An objects destructor is called whenever an object goes out of scope The purpose of the destructor is to clean up eg to free any dynamically allocated memory that the object was using and release other system resources such as files and database connections etc

In the examples used so far no destructor has been provided for any class created In these programs it has been unnecessary If the programmer does not explicitly provide a

82

destructor the compiler will create an empty destructor in the same way that an empty constructor is created if one is not explicitly created

When classes are created any objects instantiated from them that contain dynamically allocated memory will need destructor methods added to implicitly free any dynamically allocated memory when the object goes out of scope

In the class example shown below the destructor function is ~StudentCourse()

~StudentCourse()

cout ltlt Im being destroyed

7 Arrays vectors lists and hash-tables Arrays vectors and lists are all types of data structures Data structures are areas of memory where collections of the same data type are held The main difference between arrays vectors and lists is that arrays stay the same size throughout the program execution whereas vectors and lists can grow automatically

Arrays consist of a series of elements (variables) all of the same type placed consecutively in memory Each of the elements can be individually referenced by adding an index to the arrays name We saw this type of notation earlier when using arrays

Eg

int examMarks[10]

This declares an array of ten scores score 1 is accessed via an index of zero ndash examMarks[0] and score 10 is access through an index of nine ndash examMarks[9] Very important note that indexes start at zero

The advantage of using arrays compared to using discrete variables (the way we have stored values so far) is it is possible to store any number of values of the same type in an array using the same identifier

With arrays it is possible to store 100 student exam marks or 100 student names with using one unique identifier

Vectors and lists are container classes which were originally part of the Standard

Template Library (STL) The STL evolved into C++ Standard Library ndash which includes iostream etc This is the general-purpose C++ library of functions algorithms and data structures that we can use in our programs While some aspects of the library are very complex it can often be applied in a very straightforward way that allows reuse of sophisticated data structures and algorithms

There are many container classes in the library ndash note that C++ now also provides such a class for the more primitive array

ltarraygt

New in C++11 and TR1 (Technical Report One)

83

A container for a fixed sized array

ltbitsetgt

A bit array

ltdequegt

A double-ended queue

ltforward_listgt

New in C++11 and TR1 A singly linked list

ltlistgt

A doubly linked list

ltmapgt

Sorted associative array and multi-map

ltqueuegt

A single-ended queue

ltsetgt

Sorted associative containers or sets

ltstackgt

A stack

ltunordered_mapgt

New in C++11 and TR1 Hash tables

ltunordered_setgt

An unordered_set unordered_multiset

ltvectorgt

A dynamic array

As with an array vector and l is t can hold objects of various types However unlike arrays vectors and lists can resize shrink and grow as elements are added or removed

The standard library provides access via iterators or subscripting Iterators are classes that are abstractions of pointers (more on pointers later) They provide access to container classes using pointer-like syntax and have other useful methods as well

The use of vectors lists and iterators is preferred to arrays and pointers By using containers common problems involving accessing past the bounds of an array are avoided Additionally the C++ standard library includes generic algorithms (an algorithm is a set of instructions on how to perform a task) that can be applied to vectors lists and other container classes

Declaring and using arrays

Arrays are declared indicating the type and number of elements in the following way

type ar rayName[arraySize]

84

Examples are

int inNumbers[20] an array called i nNumbers of 20 in tegers

char inName [20] an array called i nName of 20 characters

float ExamMarks[5] = 0 an array called ExamMarks of 5 floats with all elements explicitly initialised to zero

const int size = 5 declaring a constant variable size

float ExamMarks[size] When the constant variable size is applied to the array declaration the number of elements is set to 5 This cannot be changed during runtime of the program However it is handy when the number of array elements needs to be changed Changing the constant value size changes the number of elements wherever the ExamMarks array is used in the program

int numArray [2][3] is a multidimensional array with 2 rows and 3 columns

Note Arrays have been used in C++ for many years and there will be code you work with that was written before vectors became available Vectors are are usually preferred to using arrays and pointers Common problems involving accessing past the bounds of an array are avoided when using vectors

Creating an array to hold exam results

Task 1

Open the project Array s ln

Compile and run the program

Run the program adding five exam results The output should be similar to Figure 20

Figure 20

85

Examine the following statements

double ExamMarks[5] = 0 This statement declares the array setting its size to 5 elements and explicitly initialising all elements to zero

cout ltlt Enter Exam Mark ltlt i + 1 ltlt This statement prompts the user to enter an Exam mark into the array at element i + 1

Using the notation i + 1 indicates to the user to enter Exam Mark 1 not exam mark 0 which would be less intuitive

Array elements are numbered from 0 to n - 1 So an array that holds 20 integers will be addressed from element 0 to 19

ExamMarks[0] -ExamMarks[19]

The first number will be entered into element [0 ] The last into element [19]

cin gtgt ExamMarks[i]

This statement reads in the user input and stores the values in the array elements of ExamMarks[i] i is incremented within the for loop and starts at 0

Task 2

As it stands the program could be generally improved ndash see the notes in the code and consider how you might make such improvements

Next modify the program to output the highest and lowest marks entered

Task 3

Modify the program so that the number of marks may be easily changed (at compile time)

86

Task 4

Modify the program so as to break out the part that calculates the average and put it into a separate function

Write another function that given an array of this sort returns the mode mean and median values ndash you will need to pass in references as the function will need to return three values

Lastly put your two new functions into a separate cpp (you will also have to create a h file for Arraycpp to use ndash this will contain the new functions prototypes)

87

Searching Arrays with Linear Search

Linear search allows the user to search the array and establish whether the array contains a value that matches a search criteria defined by the user

The search compares each element of the array with the user input The array is not sorted and this method of searching works well for small arrays For large arrays linear searching is inefficient and it is necessary to use other forms of array searching after the array has been sorted

Linear Search

Task 1

Open the project LinearSearch

Compile and run the program - choose a number between 1 and 100 The output should be similar to Figure 21

Figure 21

88

Examine the following statements

myArray[i] = (1 + rand() 100) This statement uses the rand function part of the ltstdlibhgt header file (included via iostream being included) 1 + rand() 100 produces integers in the range 0 to 99

The function l inearSearch takes three arguments The array name the size of the array the third argument is the search value

if(theArray[j] == value)

return j

This selection statement compares each element to the search value If the search value is in the array the element number is returned to main() otherwise -1 is returned

The if selection statement if(containingElement = -1) in main() is used select the output indicating a successful or unsuccessful search

Task 2

Currently the program searches for the first occurrence the search value only

Modify the program so that it outputs al l matching element locations

This function can be used for turning an int value into a string See also the comment below about C++11s to_string() functions

string convertInt(int number)

stringstream ss

ss ltlt number

return ssstr()

Youll need to include ltsstreamgt to use the stringstream class

89

Task 3

Modify the program so that repeated searches may be carried out

See Figure 22

If using C++11 or later you can also use the to_string() helper functions of the string class eg to_string(10) yields 10

Figure 22

PLUSPLUS Debugging Linear Search

Task 1

For debugging purposes modify the program so as to output the contents of the array

Open and run (exercise solution) LinearSearch to see what this might look like You might want to use the modulus operator () to work out when to neatly break a line

You may or may not like to have the program generate varying sets of random numbers To facilitate this youll need to seed the random number generator by inserting a line of code like this

srand((unsigned)time(NULL))

Note the use of the cast

To use srand() include timeh at the top of your program

90

Sorting Arrays with Insertion Sort

When working with large quantities of data in an array you will need to sort the data at some point This makes searching for information quicker and there are many algorithms available that can be used In the following exercise you will learn how to sort numbers stored in an array in ascending order

SortingSearching an array

Task 1

Open the project Sorts

Run the program and examine the code

The program currently uses a class (sorts) which is defined in sortsh to implement one popular sorting algorithm called Inser t ion Sor t

For details on this algorithm see

httpenwikipediaorgwikiInsertion_sort

91

Task 2

Add a new sort to the sorts class

The text file quicksor t txt (in the Sorts folder) contains the C++ code required to implement another popular sorting algorithm called Quicksor t17

For details on this algorithm see

httpenwikipediaorgwikiQuicksort

Add the quicksort code found in quicksor t tx t to the sorts class - considering what parts of it need to be publicprivate

quicksort tx t is in the same folder as the Sortss ln project file

Step 2

Test the quicksort implementation on a range of values

Alter the quicksort implementation so as to have it sort in descending order

Following on from Step 3 parameterise the quickSort() function so as to add an option to have the array sorted in either ascending or descending order

17 Invented by C A R Hoare ndash Sir Tony Hoare with Christopher Strachey the most distinguished computer scientists Oxfords ever produced

92

Figure 23

93

PLUSPLUS Binary Search (Binary Chop)

Task 1

Now that the array is sorted we can implement a very efficient searching algorithm usually called either binary search or binary chop search

See Figure 24

Modify your project to allow the sorted array to be searched for a value using the binary chop algorithm See opposite

The algorithm for binary chop is quite straight forward

1 Look at the value of the middle element of the array If the value = target then youre done

2 If the value is lt than target discard the lower half of the array treating the upper half as though it were the complete array

If the value found is gt than target you obviously want to look in the lower half

3 Repeat step 1 until the item is found or else the index value becomes invalid

Pseudo code for this algorithm is here

first integer = 0

mid integer = 0

last integer = NumberOfItems

while first ltgt last

begin

mid = first + last 2

if List[mid] = target

exit while Found item

If List[mid]gt target

last = mid In the first half

else

first = mid + 1 In the last half

end

found boolean = List[mid] = target

94

Figure 24

Multidimensional Arrays

Multidimensional arrays with two dimensions (arrays can have more than two dimensions) may be thought of as consisting of data arranged in rows and columns see Table 3

Each element in the array is identified by using two subscripts as shown in Table 3 The first subscript identifies the element row and the second identifies the element column a[0] [1] identifies a value in Row 0 Column 1

The array in Table 3 contains two rows and three columns and can be called a 2 by 3 array

Column 0 Column 1 Column 2

Row 0 a[0] [0] a[0] [1] a[0] [2]

Row 1 a[1] [0] a[1] [1] a[1] [2]

Table 3 ndash Array Layout

A multidimensional (2 by 3) array of doubles is shown in Table 4

Column 0 Column 1 Column 2

Row 0 2367 6792 8557

Row 1 1276 9132 2789

Table 4 ndash Array Values

95

Creating a multidimensional array

Task 1

Open the Mult iDimArray

project

Compile and run the program adding 2 exam results for each of the two students The output should be similar to Figure 25

Figure 25

96

Task 2

Examine the code used to write values to and read from a multidimensional array

Examine the following code segments

double ExamMarks[2][2] = 0 This statement creates a two-dimensional array having two rows and two columns and initialises the elements to 0

Every element in the array is identified by an element name in the form a[x] [y] where a is the name of the array and x and y are the subscripts that uniquely identify each element in a Notice that the names of the elements in row 0 all have a first subscript of 0 see Table 5 The names of the elements in column 1 all have a second subscript of 1

Note multidimensional arrays can have two or more dimensions (subscripts) Three-dimensional arrays are uncommon

Column 0 Column 1

Row 0

a[0] [0] a[0] [1]

Row 1

a[1] [0] a[1] [1]

Table 5 ndash Array Indexing

97

Examine the following code segment used to read values in to the array

for(int row = 0 row lt 2 ++row)

for(int col = 0 col lt 2 ++col)

cout ltlt Enter Exam Mark No

ltlt col + 1

ltlt for student No

ltlt row + 1 ltlt

cin gtgt ExamMarks[row][col]

cout ltlt endl

The two for loops work taking one row at a time (the outer for loop) and looping through the columns in that row (the inner for loop) When the marks have been entered for all the columns in row 0 row 1 is selected and values entered for each column cell in row 1

Table 6 shows how four results would be allocated in a 2 x 2 multidimensional array

Exam mark 1 Exam mark 2

Student 1 67 71

Student 2 61 58

Table 6 ndash Populated Array

98

Examine the following code segment used to calculate the total of each students marks

if(row == 0)

r1total += ExamMarks[row][col]

else

r2total += ExamMarks[row][col]

r1total is a variable to hold the sum of values in column 0 and 1 for row 0 (Stud1) r2total sums the values in the columns for row 1 (Stud 2)

Selection for each row is made with if(row == 0) this is Stud1 If row is not 0 then row must be 1 and the mark can be added to r2total If three exam marks were input per student the code for selecting the marks would need to change

Task 3

Modify the program to read in four exam marks for f ive students

Establish the highest and average mark for each student Output the results

One way to do this is to keep a separate array to record the students statistics An alternative would be to extend the existing arrays row so that it may hold the necessary student data

99

Declaring and using vectors

Vectors are declared indicating the type and number of elements in the following way

vectorlttypegtvectorName

vectorlttypegtvectorName(initialSize)

vectorlttypegtvectorName(initialSize elementValues)

Examples

A vector called i nNumbers with no initial size to hold doubles

vectorltdoublegt inNumbers

A vector called Name with an initial size 20 to hold characters

vectorltchargt Name(20)

A vector called ExamMarks holding integers with initial size of 4 elements each with the value 6

vectorltintgt ExamMarks(46)

Note In previous exercises you have created your own member functions In the following exercises you will use some of the vector class member functions Some of these are begin() end() erase() and size() See section 12115 for more detail

The standard library also includes a large collection of algor i thms that manipulate the data stored in containers (vectors are one of several types of container)

You can sort the order of elements in a vector (vec) for example by using the sort algorithm

sort(vecbegin() vecend()) C++11 sort(begin(vec) end(vec))

You can find a value (69) in a vector by using the find algorithm

ptr = find(vecbegin() vecend() 69) See C++ note above

100

ptr is an iterator to store the memory location of the element found

You can reverse the order of elements in a vector for example by using the reverse algorithm

reverse(vecbegin() vecend()) See C++ note above

There are two important points to notice about the call to reverse First it is a global

function (as are find and sort) not a member function Second it takes two arguments rather than one and operates on a range of elements rather than on the container (vector container in this case)

With the above examples the range is the entire container from begin() to end() (vecbegin() to vecend()) reverse like the other standard algorithms is decoupled from the libraries container classes The reverse algorithm can be used to reverse elements in vectors in lists (another container) and even elements in C arrays

int myArray[] = 1 6 20 4

reverse(myArray myArray + 4)

for(int i = 0 i lt 4 ++i) Lets see the reversed array

cout ltlt Array[ ltlt i ltlt ] = ltlt myArray[i]

In the above example the first argument to reverse is a pointer (pointers are covered in Section 8 but for now we can say the first argument points to the address in memory that is the start of the vector ) to the beginning of the range and the second argument points one element past the end of the range This range is denoted (myArray myArray + 4)

Arguments to reverse are i terators which are a generalization of pointers which is why it is possible to reverse the elements of a C array using the array address and pointer notation

Creating a vector to hold exam results

Task 1

Open the Vector project

Compile and run the program adding five exam results The output should be similar to Figure 26

101

Figure 26

Examine the following statements

include ltvectorgt This statement includes the header file vector enabling the program to use the class template vector (templates allow the use of generic functions that admit any data type as parameters and return a value more on this later)

vectorltdoublegt ExamMarks(5) This statement declares the vector to hold doubles and sets the initial size to 5 elements

Note Although vectors can grow to any size it is good practice and more efficient to specify the size when this is known When no size is given and the contiguous memory spaces have been exhausted the elements must be copied to a larger memory space to increase the size of the vector

cin gtgt ExamMarks[i] This statement reads in the user input and stores the values in the vector slot i of ExamMarks[i] i is incremented within the for loop Note that we the same indexingsubscripting syntax as we used previously with arrays ie[ ]

102

Task 2

Modify the code so as to accommodate the adding of an extra exam mark

Note this should not be done (simply) as part of the loop but as a separate action later and you should use the vectors push_back() method to facilitate this

push_back() is a member function of the vector class that adds an additional vector element at the end

After adding the extra mark you will need to generate a new set of statistics ie the average will have changed now To do this separate out the statistical code and place it in a separate function so that you may re-use later (after the new data has been entered)

size() is a member function (method) of the vector class It can be used to establish the size of a vector

The statement for(int i = 0 i lt ExamMarkssize() i++) uses the vector member function size() available to the vector ExamMarks to obtain the size (number of elements) in the vector The size of the vector is used to identify a terminating value that ends iteration of the for loop

Task 3

Open VectorSor t

You will see three TODO sections in the code which need completing

1 Populate a vector with 100 randomly generated numbers

2 Sort the vector

3 Reverse the vector

For sortingreversing you will can use the algorithms sort() and reverse()

Heres a useful link hellip

httpwwwcpluspluscomreferencealgorithm

103

Using insert() and iterators

Task 1

Open and modify the skeleton project called Inser t

Important areas of the program are explained in the steps opposite

Examine the code

vectorltintgtiterator it

This statement creates an iterator that is used to access members of the vector

Iterators are used to access members of the container classes (the container type vector in this case) and can be used in a similar manner to pointers

In the example iterator it is used with the insert() function to place the value (200) at the beginning of the vector nums

it = numsbegin()

This statement uses the vector member function begin() to initialise the iterator it with the address of the start of the vector

it = numsinsert(it 200)

This statement uses the member function insert() and iterator it to insert 200 at the beginning of the vector (it)

Note that an iterator is returned by the function insert() that points to the newly inserted element

104

numsinsert(it + 1 numsTwobegin()

numsTwoend())

This version of the insert() function takes 3 arguments and is used for copying in part or full another collection This may be a vector a plain C++ array or some other collection that is accessed using pointersiterators

This statement inserts a second vector (numsTwo) into nums The three parameters are (copy to nums+1 from star t of numsTwo to end of numsTwo)

it = numsinsert(it + 2 696 )

This version of the insert() function takes 2 arguments The iterator it + 2 points to element number three it points to the beginning of the vector and the 2 moves two elements in The value 696 is inserted at that element

void display(vectorltintgt amp vec)

cout ltlt Vector contains

for(

unsigned int i = 0

i lt vecsize()

++i

)

cout ltlt vecat(i) ltlt

Function display() is passed a reference to a vector and outputs the vector contents used throughout program

105

Task 2

Add the code shown in Figure 27 to the program and using the insert() member function add the array to the nums vector at position two (in the vector) Output the contents of the nums vector to screen

int myArray[] = 5 6 3 4

Figure 27

stdarray

C++11 Introduced a new template array type called stdarray

stdvector is a template class that encapsulates a dynamic array that is stored on the heap and that grows and shrinks automatically if elements are added or removed It provides all the hooks (begin() end() i terators etc) that make it work fine with the rest of the STL It also has several useful methods that let you perform operations that on a normal array would be cumbersome like inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes) Since it stores the elements in memory allocated on the heap it has some overhead in respect to static arrays

stdarray is a template class that encapsulates a static array that is stored inside the object itself which means that if you instantiate the class on the stack the static array will be on the stack Its size has to be known at compile time (it is passed as a template parameter) and it cannot grow or shrink

It is more limited than stdvector but it is often more efficient especially for small sizes because in practice it is mostly a lightweight wrapper around a C-style array However it is more secure since the implicit conversion to a pointer is disabled and it provides much of the STL-related functionality of stdvector and of the other containers so you can use it easily with STL algor i thms

Here is a small example demonstrating the template and some other C++11 extras such as auto and a ranged-based for loop

106

include ltstringgt include ltiteratorgt include ltiostreamgt include ltarraygt using namespace std template ltsize_t N class Tgt arrayltT Ngt make_array(const T amp v) arrayltT Ngt ret retfill(v) return ret int main() The char here can be inferred and so is optional auto a = make_arraylt10 chargt(1) for (const auto amp s a) stdcout ltlt s ltlt system(pause) return 0

1 1 1 1 1 1 1 1 1 1 Press any key to continue

Declaring and using lists

Lists are a kind of sequence container similar to vectors The elements of a list are ordered following a linear sequence with storage handled automatically by the class

List containers are implemented as doubly-linked lists and it is worth noting that elements may be in different and unrelated storage locations

Ordering of a list is kept by a relationship to each element of a link to the element preceding it and a link to the element following it

Because linking information is associated with each element (possibly to different and unrelated storage locations) extra memory may be used to keep the linking This may be important when using a large list

l is ts tend to perform better than vectors at inserting extracting and moving elements in any position within the container but lack direct access to the elements by their position and because of this have a slower access time than vectors Access to an element has to be via a known position (the beginning or the end) and there is a time cost in linking between the known position and the element to be accessed

107

lists are declared indicating the type and number of elements in the following way

listlttypegt listName

listlttypegt listName(initialSize)

listlttypegt listName(initialSize elementValues)

Examples

A list called inNumbers with no initial size to hold doubles

listltdoublegt inNumbers

A list called Name with an initial size 20 to hold characters

listltchargt Name(20)

A list called ExamMarks holding integers with initial size of 4 elements each with the value 6

listltintgt ExamMarks(46)

72 Hash Tables and Cached Calculations

This section has ultimately really been about introducing you to templates and algorithms and well mix both now in a final example

From the binary chop exercise earlier we have seen that sorted arrays provide a very efficient means of storing data for later look-up However we have to bear in mind the algorithmic cost of sorting the array in the first place ie if we have a million unsorted items in our list and we want to find a single item (only) is it better to sort the entire list first and then find the item or is it better to simply walk through the array from the beginning ndash after all we could safely assume that weve a 5050 chance of finding it in the first half of the array Of course as were sorting we could keep an eye open for our item ie we could combine a (partial) sort with look-up operation ndash over time if we repeat this procedure looking for other items we will ultimately sort our array as a side -effect of the look-up operations

But lets move on a little and just consider the fastest look-up method we know so far that carried out on a sorted array using binary chop and think about our programs overall performance when we need to insert additional items into the array When considering problems like this we always think of the worst case hellip despite their often being fans of

108

Monty Python Computer Scientists rarely look on the bright side of life The worst case here is that we need to insert an item into array position zero

Eg say we have this sorted array (look-up operations average O log2 N = fast)

15 24 25 31 78 250 255 262 277

We now have to insert the value 5 into this array Using normal array indexing methods how many operations will this take

5 15 24 25 31 78 250 255 262 277

Each item needs to be shuffled up one position to the right and if weve millions of items that is rather costly especially if the next thing were likely to do is to insert another item

So weve seen that accessing sorted data is very useful and weve also seen that sorting and especially inserting items can be costly The big question is then is there a way we can make both just as efficient - finding andor inserting an item in Olog2N or O(1) (constant time)

Hash Tables

A hash-table is a data structure designed to allow for both rapid insertion and look-up

Although any specific hash-table is implementation specific (there are very many different types of hash-table) well quickly go through the basics

The storage medium well use for our hash-table is an array of strings and we will say that this array has just 10 elements It looks like this

string myhash[10]

Well use this hash-table to store words and well determine the array index for any specific word using a hash- funct ion ndash something that will take a word as its input and return an array index as its output

109

unsigned hashfunc(string s)

unsigned result = 0

for(unsigned i = 0 i lt slength() ++i)

result = result + s[i]

return result 10

hashfunc() iterates through s keeping a running total of the sum of the ASCII codes for each of the characters eg hashfunc(hash-table) computes

h + a + s + h + - + t + a + b + l + e

where the characters ASCII values are

104 + 97 + 115 + 104 + 45 + 116 + 97 + 98 + 108 + 101

The total = 985 and 985 modulus 10 = 5

The final computed value will be used as an index into the array The modulus value used is the size of the hash-table and we use it so as to ensure that resultant computed index value cannot be greater than 9 (remember our arrays indexes are 0 ndash 9)

We can now store words in the myhash array like this

string myhash[10]

string s = hash-table

index = hashfunc(s)

if(myhash[index] = )

myhash[index] = s

else

The complex part is what to do if we have what is called a collision ndash when we find that myhash[index] is already occupied Youll probably have already thought of what value hashfunc(elbat-hsah) will have

One way to help avoid collisions to use a better hash-function and a larger array However in real life collisions are practically impossible to avoid and the only other option to deal with them is to allow more than one string to inhabit an array slot in some way ndash perhaps by having each of the original array slots contain an array ndash rather than an individual string Of course in this case we would also need some way to determine which of the n colliding entries is the one were interested in ndash is it elbat-hsah or hash-table

110

Well briefly leave our examination of hash-tables at this point and instead look at Fibonacci numbers Do not worry we will return to hash-tables very soon

Fibonacci numbers are the numbers in the following integer sequence

0 1 1 2 3 5 8 13 21 34 55 89

By definition the first two numbers in the Fibonacci sequence are 0 and 1 and each subsequent number is the sum of the previous two More formally that is

119865119899 ∶= 119865(119899) ∶=

0 119894119891 119899 = 0 1 119894119891 119899 = 1

119865(119899 minus 1) + 119865 (119899 minus 2) 119894119891 119899 gt 1

Computing Fibonacci Numbers

Task 1

Open Cached_fibonacci

Compile and run the program as is

Examine main() and the calcfib() functions

bigint calcfib(bigint n)

if(n == 1 || n == 0)

return n

else

return calcfib(n - 1) + calcfib(n - 2)

bigint is defined as a unsigned long long int and we have used typedef to save some typing

NOTE The method used to calculate Fibonacci numbers here has been selected because it is perhaps the most obvious way to turn the formal definition into code If you are interested please see the separate Fibonacci project for two other examples of how to calculate Fibonacci numbers

111

Modify the beginning of the calcfib() code

bigint calcfib(bigint n) cout ltlt calcfib was passed ltlt n ltlt endl

Modify main() to set max = 5 and re-run the program

calcfib was passed 0 Fibonacci number 0 is 0 calcfib was passed 1 Fibonacci number 1 is 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 2 is 1 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 Fibonacci number 3 is 2 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 Fibonacci number 4 is 3 calcfib was passed 5 calcfib was passed 4 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 3 calcfib was passed 2 calcfib was passed 1 calcfib was passed 0 calcfib was passed 1

Fibonacci number 5 is 5

112

Note that to calculate Fibonacci number 5 we calculate Fibonacci number 4 and Fibonacci number 3 - even though weve previously calculated Fibonacci number 3 in order to calculate Fibonacci number 4

To fully appreciate the growth of this process re-run the program adding 10 to max for each subsequent run You maymay not like to comment out the line you inserted in Step 2

Task 2

Getting back to Hash Tables Using a hash-table to store previously computed Fibonacci numbers

As it stands the incomplete solution declares a template hash-table called fibs of the type unordered_map

Read the comments in the function fibCache() and modify the code to as to use the fibs hash-table to store previously computed Fibonacci numbers

fibs[n] = f stores f the n-th Fibonacci number in the n-th slot of fibs (which as you can see you may treat as an array for indexing into)

8 Pointers In C++ programming data (variables) can be referenced via the memory address of the variable This is done using a pointer var iable

A pointer var iable contains the address (location in memory) of a data variable

There are also functional pointers ie those that point to code rather than data and these are briefly explored later

Pointers can be particularly useful when interacting with the operating system andor when working with arrays - as the elements in an array will always occupy consecutive memory places Incrementing the pointer variable by one addresses the next array element

Lastly pointers are also used to fake pass by reference

Declarat ions

int n This is a standard variable declaration n that contains a value as yet unknown of type int

int p This is a pointer p that can hold (point to) an address that contains a variable of type int The type of p is int

Each variable declared as a pointer must be preceded by an asterisk () This modifies the type of the object being declared from thing of type to pointer to thing of type Eg int n means n is an int whereas int n says that n is a pointer to an int

113

int age height age is a pointer to an int height is an int value

double far cent are both pointers to doubles

Pointers can be initialised when they are declared or set using an assignment It is common to initialise pointers to a memory address but they can also be initialised to the predefined constant NULL ndash meaning that they do not (as yet) hold (point to) a valid memory location NULL is defined in the standard library such a pointer is called a nul l pointer

When is used in a variable declaration it indicates the variable being declared is a pointer and not a value

But do beware as is used elsewhere with pointers when the appears before a previously declared pointer variable elsewhere in the program it is said to dereference the pointer and so is used to access data stored at the address which is stored in the pointer A dereferenced pointer is essentially the variable to which the pointer was originally set to point

To complicate matters further using the pointer name without the dereference operator references whatever is stored in the pointer variable itself ndash this is the address of the object it references in memory (which maybe NULL of course)

As we have seen using can mean two things that something is being declared as a pointer or that a previously declared pointer is being dereferenced Experienced programmers sometimes enter the two usages differently ndash a notation we would highly recommend ie

int n n is an object that can hold the address of an int

int k = 0 k is an int holding the value zero

n = ampk n is set to hold ks address amp is explained below

n = 1 k (yes k) is set to hold the value 1

Note the space used in the different usages - int n vs no space in n

Initialising pointers

Pointers can be initialised in two ways

int x = 16 y = 69 variable declaration and initialisation int x_ptr = ampx pointer declaration and initialisation x_ptr holds the address of x int y_ptr pointer declaration yptr is a pointer

y_ptr = ampy pointer assignment yptr holds the address of y

Once declared a pointer variable can be assigned the address of another variable using the amp the addressof operator

114

Note the variable name should not be prefixed by the in the assignment statement unless the pointer is initialised immediately in the variable declaration

We also use pointers when creating objects on the Heap for example we can create and initialise a string object like this string pstring = new string(Hi there) Such objects are not normally tidied away as are the objects created on the stack - objects simply declared in a functionmethod and so they should explicitly be tidied away using delete eg delete pstring For more on this subject see section 9

Using pointers

Task 1

Open the project Pointers

Compile and run the program The output should be as shown in Figure 28

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int x_ptr = ampx This is x_ptr pointer declaration and initialisation

int y_ptr Declaring another pointer y_ptr

y_ptr = ampy Initialising y_ptr

y_ptr = x_ptr Assigning x_ptr contents to y_ptr Both pointers are pointing to variable x (16)

y_ptr = ampy Assigning the address of y back to pointer y_ptr

y_ptr = 170 Assign 170 to the variable at memory location of y_ptr y_ptr points to variable y so 170 has been assigned to y

115

Figure 28

Pointer Arithmetic and Arrays

We have seen that once a pointer is initialised it has a memory address and this address can be reassigned another address It is also possible to change an address using standard arithmetic

The ++ and -- increment and decrement operators can be used to move the pointer along to the next or back to the previous memory address To jump more than one memory address you would have to use the assignment operators += and -=

When using arrays and pointers the array name is the address of the first element in the array

int intArray[] = 1 2 3 4 5

int int_ptr = intArray Same as int int_ptr = ampintArray[0]

The pointer has been declared and initialised with the statement int int_ptr =

intArray Note there is no need to use the address of operator amp when initialising arrays as the array name is the address of the beginning of the array

When working with arrays each element of the array will be the type and size at declaration When an array is declared to hold integers each element will usually be 4 bytes in size An array of doubles will have element sizes of 8 bytes Note ndash these sizes are actually down to the compiler being used and are usually in turn dependent upon the operating system being used

It is not important to know how many bytes make up each element Moving the pointer through the array with the assignment operator x_ptr += 2 will move two elements further through the memory allocated for the array or 16 bytes for an array of doubles

116

Pointers and Arrays

Task 1

Open the project PointerAr i thmetic

Compile and run the program The output should be the same as Figure 29

Examine the program carefully

You may not fully follow the program at first glance as it employees a few potentially new constructs (it depends how far weve got through the lectures)

One slightly truncated new construct is

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

A struct in C++ is just like a class except that the default public and private sections are reversed By default everything in a struct is public

typedef in C++ allows the definition of our own types based on other existing data types

typedef exist ing_type new_type_name

where exist ing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining For example

117

typedef unsigned int WORD

typedef char pChar

You may also remember initialiser lists from earlier eg

s_thing(int a) a(a) b(sqrt((double)a))

If we re-write this

typedef struct s_thing

const int a

const double b

s_thing(int a) a(a) b(sqrt((double)a))

thing

We quickly see that a(a) and b() are initialising the a and b struct members const int a and const double b

118

Remember that as these are const we cannot use assignment

typedef struct s_thing

const int a

const double b

s_thing(int a)

Error ndash a and b are const

this -gt a = a

this -gt b = sqrt(a)

thing

Lastly when dealing with pointers to compound types one may access the members of the type via dereferencing or via the so called crows foot operator

(t) dereferences t giving us a thing which was pointed to by t Then we use the dot operator to access the member (t)a

We have to parenthesiset otherwise the would bind to t first ie it would be as though we had done this (ta) which would be an error

The crows foot saves us the dereference t-gta is just like (t)a

119

Figure 29

PLUSPLUS Pointers and Arrays

Task 1

Open and modify the skeleton project called ReverseArray

In main() create an array of 10 integers Fill the array with random numbers between 0 ndash 100

Write a helper function called to output the contents of the array to the console A suitable prototype for this would be void dumpArray(int array[] int size)

Write a helper function to reverse the contents of the array Use a temporary variable as an aid A suitable prototype for this function would be void reverseArray(int array[] int size)

Reverse the values in the array using only pointers

120

Reverse the array without using a temporary variable You should use the XOR operator ^ to achieve this

Pseudo code for an XOR swap is

X = X XOR Y

Y = X XOR Y

X = X XOR Y

The completed program should look like Figure 30

Figure 30

Task 2

Reverse the array using a vector and the standard function template stdreverse()

We can also have pointers to functions in C++ (and C)

The name of a function resolves to be its address in memory (somewhat similar to the case where we use the name of an array) When we call a function we use this name to retrieve the functions address and then use the function invocation operator to execute it The function invocation operator is the set of brackets you use eg

Lets take an example

121

include ltiostreamgt

using namespace std

int lue() life the universe and everything

return 42

int main()

cout ltlt The address of the function lue is

ltlt lue

ltlt invoking it yields

ltlt lue()

ltlt endl

system(pause)

return 0

Typical output is shown in Figure 31

Figure 31

122

We can also store addresses of functions in variables (theyre just numbers) and the type system allows for us to describe and declare scalar variable types for function pointers eg this modified code fragment would produce the same output as that show above

fp is a pointer to a function taking

no arguments and returning an int

int (fp)()

fp = lue

cout ltlt The address of the function lue is

ltlt fp

ltlt invoking it yields

ltlt fp()

ltlt endl

fp is a funct ion pointer var iable so it may be used to point to any other function having the correct signature at runtime

PLUSPLUS Function pointers

Task 1

Open the project Calculator

Compile and run the program The output should be as shown in Figure 32

123

Examine the following statements Only the important parts of the program are explained the rest has been covered in previous exercises

int (fp)(int int) This is the function pointer declaration It may point to functions that take two integers and return an integer

Like all automatic storage class variables fp will currently be pointing at a random location What happens if you run the program without setting fp to point to an actual function Comment out the switch to find out

switch (Operator)

case 0 fp = Add break

case 1 fp = Subtract break

case 2 fp = Multiply break

The code could do with improving

Modify it to allow for multiple trials eg add the necessary logic to loop and perform multiple calculations ndash youll need to add some way to end the program too therefore

Modify it so that the operator may be inputted as an operator character eg + - etc Allow X x and for multiplication and add for division

All three pieces of information could be entered on a single line eg 6 x 7ltentergt Using cin to read that data just requires you to use three cin statements

cin gtgt X

cin gtgt Operator

cin gtgt Y

Lastly modify the program to that it uses floating point arithmetic

124

Figure 32

9 APIs New Delete and Dynamic Memory As has been stated earlier pointers are useful in a variety of situations However because they are easy to get wrong ndash and when they go wrong everything goes very wrong indeed ndash languages like C++ have tried to make their use the exception rather than the norm For example without reference arguments (eg void someFunc(int amp)) we would have to use pointers to achieve the same functionality and performance

On the whole the underlying philosophy when it comes to pointers is to try to avoid using them whenever possible You can get a real feel for this subject by Googling for smart pointers c++ and from Wikipedia httpenwikipediaorgwikiSmart_pointer

Two areas where we absolutely need pointers are when calling into an external API (Appl icat ion Programming Interface ) and when allocating memory for our own purposes ndash the latter case is also eased by advances in the library support in C++

Using an API

An Appl icat ion Programming Inter face is functionality provided by some third party The most obvious API whether it is Windows Linux or OSX is that exposed by an operating system

If your application needs to interact with the user in any non-portable way you will need to call into your OSs API For example if you want to display a dialog box you will need to access the OSs functionality to do so (perhaps indirectly through a framework like Nokias Qt - httpsenwikipediaorgwikiQt_(framework)) In summary if you ever want to go outside of the standard libraries andor writing consoleterminal applications you will need to call into your operating systems API

When it comes to calling into operating systems pointers are used extensively As an example 1 Google for Linux API 2 Find any website that lists the API functions and then 3 click-through to any function The odds are that the function prototype you see will contain asterisks (pointers)

125

Dynamic Memory Management

The second area where you simply must know something about pointers is when it comes to using the heap

The heap is an area of memory available to your programs You may allocate and use the heap as you wish

Why would you want to do this Normally its to create variable length arrays or to model and use an advanced data structure of some sort a self-balancing red black tree perhaps (httpenwikipediaorgwikiRedAndblack_tree) Of course the more esoteric the data structure and less likely it is that it will be incorporated into the C++ standard library (although the library does contain most of the generally useful and popular ones like doubly l inked l is ts )

To allocate memory from the heap in C++ you use the new keyword and to return it you use the delete eg

int nSize = 12

note nSize does not need to be constant

int pArray = new int[nSize]

pArray[4] = 7

delete [] pArray

10 More on Functions Functions are used to encapsulate a set of operations and return information to the main program or calling routine Encapsulation is data information or detail hiding

Once a function is written the detail of how it works is not important to the end user The user needs to understand what data to input and what output will be produced

One of the most important aspects of writing programs using functions is that the functions can be reused from one project to the next Think about the standard functions youve seen already eg the square root function sqrt() Libraries contain atomic generally useful functionality that is likely to be of use at some future time It is useful to bear this thought in mind whenever we build new programs ie we should be on the lookout for generally useful functionality (given our domain) that we should consider coding as functions for later reuse The same goes for classes of course

Probably the most important function in your program in main() ndash without it you do not have a program at all

main() is your programs entry point and as such it may be used in such a way as to inform the rest of your program as to the actions required

126

main() and command-line arguments

Task 1

Open a Command Prompt or PowerShell Prompt and enter the following

dirltreturngt

di r Odltreturngt

t ree ltreturngt

t ree altreturngt

dir and t ree etc are like mini-programs They have default functionality which may be altered by providing additional command-line arguments eg for the dir command dir L N 4 TC

Command-line arguments are passed to your programs by optional parameters eg

int main(int argc char argv[])

Where argc is a count of the number of arguments and argv is an array of pointers to arrays of character (C strings) for each argument being passed Note that argc is always at least 1 and so argv always contains at least one entry ndash this is the name of the program being run

Task 2

Open (demonstrat ion)

CommandLineArgs and Build and run the program

Examine the code

The programs configuration is Debug

In the projects Project | Debugging | Command

Arguments you will see where the programs default command-line arguments are set for debugging purposes

Using the command prompt you opened earlier navigate to your where CommandLineArgsexe is located

CommandLineArgs debug

Run the program by entering its name followed by a variety of arguments eg

gtCommandLineAgs one two threelte ntergt

127

Task 3

Open the project UserPrompter project

Run the program and then examine its code

We will modify this program to use a command-line argument However before doing that its worth pointing out that the primary purpose of this program is to demonstrate the separation of a class declarat ion with its implementat ion (the mechanismfunctionality of class prompter is defined in promptercpp but its capabilities are declared in prompter h )

Its also interesting to note that the optimal strategy is to use an algorithm called binary search or binary chop (we saw this earlier in the course) with each guess you reduce the number of possible solutions by a half This sort of algorithms Big Oh is Log n (where log is base-two logs)

httpenwikipediaorgwikiBig_O_notation

Task 4

Modify the program so that the upper range for the max value is given as a command-line argument

The UserPrompter cpp is the file youll need to modify

Test your program via the setting the projects Command Arguments as detailed above -or- by running the application standalone in a command prompt after building (also as detailed above)

See Figure 33

To convert a string into a number (weve seen one other way of doing this earlier) we can use

include ltcstdlibgt

and the function atoi() eg

atoi(argv[1])

128

Figure 33

EncryptDecrypt a file

Task 1

Open compile and run the EncodeDecode project

Complete the program so that it may be run outside of the IDE and process a file for encryptiondecryption

This is actually quite a simple task as youll only need to add a couple of lines of code However the project also demonstrates how to use the Debug and Release modes to influence the way a program runs ie that in its Debug configuration the program automatically runs through a test

Other things to note include using bitwise XOr to perform the encoding and the use of the C standard library functions putchar() and printf() to perform some of the output eg putchar() is used to output a CR to the console window (CR = char 13)

129

Figure 34

Multiple arguments overloading and default values

In C++ we can over load functions ndash meaning that we can provide different versions of the same function (the different versions must differ by the number andor type of the parameters they take) For example

130

void foo(double d) 1

cout ltlt In void foo(double d)nn

void foo(long int n) 2

cout ltlt In void foo(long int n)nn

void foo(int n) 3

cout ltlt In void foo(int n)nn

double dtest = 0

long int ltest = 0

int ntest = 0

foo(dtest) Calls 1

foo(ltest) Calls 2

foo(ntest) Calls 3

In the above the compiler works out which version of the foo() to call based upon the argument type it is given

We can also overload functions if the number of arguments differ eg

131

void bar(double d)

void bar(double d double t)

We would use a feature like this if sometimes we needed to use extra information ndash in the shape of passing in t in the above eg we would most likely implement void bar(double d) as

void bar(double d)

bar(d 25) Call bar(double d double t)

What were really saying above is that in most cases the implicit double second parameters value is normally 25 ndash perhaps its a standard discount percentage ndash and only occasionally we will need to change that value in which case wed call bar(double d double t) directly and not by going through bar(double d)

Lastly C++ has one extra feature that can make this simpler ndash defaul t arguments

Rewriting bar using this feature we get

void bar(double d double t = 25)

Note that we now only have one bar function now and that we may call it like this

bar(x)

Or like this

132

bar(x y)

In the case of bar(x) the second parameter is omitted and so will receive the default value of 25 in the second example t will receive ys value

Although outside the scope of this class for more on overloading see the (demonstrat ion) Operator Over loading project This shows how to overload the ++ pre and post increment operators overload and provide your own ltlt stream insertion operator (and one use of a friend function) and using an enum with a typedef

Passing Arrays to Functions

To pass an array to a function it is only necessary to pass the array name and the number of elements in the array

The array name is the position (address) in memory of the first element The number of elements is passed to enable the function to establish the array size

An array declared as double somearray[10] would require a function call somefunction(somearray 10)

Passing Arrays to functions

Task 1

Open and modify the skeleton project called the project called ArrayReturnValue

Pass an array to a function to read in five numbers

Pass the array to another function to calculate the average value in the array return this to main() and output to screen

Lastly at the end of the program output the values in the array from within main() The finished program should look something that that in Figure 35

Create two function prototypes

void enterMarks(double ExamMarks[] int num)

double calcAverage(double ExamMarks[] int num)

ExamMarks[] is the array to be passed As with passing variables it is not strictly necessary to give the argument a name in the prototype just its type This could have been written as calcAverage(double [] int) However it is sometimes useful to include this information as it might help explain the functions operation

It is also necessary to pass the size of the array num is the number of elements in the array its size

Within main() declare the array and initialise the elements to zero with the following statement double ExamMarks[5] = 0

This declaration explicitly initialises the first element to zero and implicitly initialises the remaining four to zero

133

Create both functions

enterMarks to read in the values and calcAverage to calculate the average (you will need a for loop in each function)

Return the average value from calcAverage to main() and output the value using cout

Call the functions from within main() with the following statements

enterMarks(ExamMarks 5)

average = calcAverage(ExamMarks 5)

You may output the average directly of course ie without first storing the value in average

At the end of main() add the statements

for(int i = 0 i lt 5 ++i)

cout ltlt Exam Mark Number

ltlt i + 1

ltlt is

ltlt ExamMarks[i]

ltlt endl

ltlt endl

134

Explain how it is possible at the end of the program to output from within main() all the values in the array entered within the function

Modify the program so that the number of exam marks (5) appears only once

In previous exercises when parameters (variables) were passed to functions the function received a value When a value is used in a function a copy is stored in a part of memory that only exists from the time the function is called to when it ends After this the memory and any value in it are lost

However the array in this exercise was initialised in main() with zeros and then passed to the function Data was then added to the array and calculations done At the end of main() the values in the array elements are output The array contains values input from within the function

The name of the array is the address of the first element of the array in the machines memory As the starting address is passed (the name of the array) the called function knows where the array is stored in memory

Because we are working with memory addresses (references ) any changes made to array elements in the function affect the memory location set up in main() for the array

C++ passes arrays to functions by reference (to the memory location of the first element) In previous exercises functions were passed values copies of the variables in main()

135

Figure 35

Passing Two-dimensional Arrays to Functions

It is common to want to store numbers in a two dimensional layout of rows and columns as shown in Table 7

187645 783473 298372

871223 629399 561201

Table 7

This arrangement is known as a two-dimensional array or matrix

C++ uses an array with two subscripts to store a two dimensional array

double Balance[2][3]

When we specify a one-dimensional array the number of elements must be given

When a two-dimensional array is specified it is necessary to specify the array elements in both dimensions We therefore specify the number of rows and columns

The Balance array in the statement above has two rows and three columns

11 Inheritance and (not presented) Polymorphism

111 Inheritance

In Object Oriented languages like C++ inheritance describes a relationship between classes of objects and which usually implies some sort of a sub-division of labour

For example lets say that we want to build an IT system that has something to do with the members of the university

136

In an OO world the first question usually is how would we categorise our significant entities and that always means naming things what names would we use to categorise university members When modelling (for that is what were going to be doing) real-world objects its sensible to use proper names So heres an attempt ndash to broadly categorise university membership

Members are members of the sets

Students

Staff

Other

What is other though

The Bodleian and the card-office issue Readers cards ndash so is a Reader a university members or are they something else And if they are something else does our system really want to concern itself them Or more broadly does our system really want to concern itself with holders of cards issued by the card-office

Are all students really the same

What sort of students do we have at Oxford (and do we want a system ndash either now or in the future ndash that might be interested in recording the differences) Lets see we have undergraduates and graduates We also have Rhodes scholars ndash but are these sorts of student that are distinct (or should be in our system) from our underpost-graduates categories And how about graduates would we want to have some sort of sub-groups Masters students MScMBAMPhil or Doctoral students DPhilDScDLitt etc Perhaps wed like to know something about how theyre being funded ndash and we might want that piece of functionality shared by our undergraduates

We can of course go through the same process when thinking about members of staff (university staff departmental staff members of congregation academic staff fulltimepart-time staff casual staff ndash and how about staff that are sometimes (or also) students) We can go on thinking about this sort of thing for a very long time and we should as its important and when its important it has a name ndash Object Oriented Design or OOD

One of the things wed hope to see appear as part of the OOD phase is the relationship between entities For example if we were to say that a common property of all university members is that they have a date-of-birth we wouldnt want to have our Student and Staff C++ objects contain this information directly by way of some datastate class member (which might seem a little odd at first) But think about it If we performed some validation on the members DoB (perhaps when its being set) we would need to include this in both Student and Staff classes Or as an alternative we would capture the validation in some external function ndash which we would call from the separate classes (if we remember) No its messy and it would be much better if we thought of things this way that all university members are people and that people all have dates of birth

To put it another way we would say that studentsstaffother are just specialisations of people ndash they are people but with a bit of extra something tagged on to them ndash like a bod card number

Now if we also had some way of capturing people stuff in say a basic Person class and could somehow use that automatically ndash perhaps by deriving a Member class from it and then doing the same from Member to both Staff and Student classes from Member One thing though ndash we wouldnt want someone to be able to instantiate a Member object

137

perhaps ie in our system Member is an abstract class Imagine a generic Car vs a Renault Clio ndash it makes no sense to create a Car object ndash there are no generic cars on the road they are all specific cars Similarly we wouldnt want a generic Member wandering around our system (if you remain unconvinced well see why later)

Modelling a student - a first attempt

Please note that in this Introduction to C++ we do not expect you to complete an exercise that requires coding from now on Please just look through the code and follow along with the discussion

Base classes

Task 1

Open the project UnivMember1

Examine the program carefully

The project contains three classes Person Member Student In main() we create a Student and then attempt to output the students name ndash which fails

name is in the protected section of Person ndash which means only Person methods or methods in derived-from-Person classes can access it

Add a public section to the Person class and relocate the name there

Eg

public

string name

Any better now

The problem now is that Student only by default inherits the private side of Person

Change class Student so that we also inherit the public members of Person hellip

class Student public Person

138

Before we tackle further problems with name lets bring in the Member class (left doing nothing until now)

We really want Student to inherit from Member and not Person Change the code to reflect this

People have dates-of-birth and Members have bod cards Add a string member dateOfBirth to Person and move the bodCardNumber member out of Student and into Member ndash make them both strings

Change the code in main() to set these extra pieces of data

If you havent done it already Persons dateOfBirth and Members bodCardNumber should be set via constructors

139

Task 2

Open and examine the project called UnivMember2

UnivMember2 is a copy of the (exercise solut ion)

UnivMember1 solution

One of the problems we have in UnivMember1 is that too much of it is public eg given Student object s we can change name to simply by using assignment eg sname =

We should protect data members at each level using the maximum level of protection we can ie private

However if we do that then cout ltlt sname will no longer work and so well need to provide access methods to the data members Eg heres a modified Member class showing the basic scheme

class Member public Person

public

Member(string bodCardNumber)

this-gtbodCardNumber = bodCardNumber

string getBodCardNumber() For access

return bodCardNumber

private

string bodCardNumber

140

Another problem is that wed really like to not use assignment at all Eg in the above ctor snippet

this -gt bodCardNumber = bodCardNumber

is using assignment

Change string bodCardNumber to const string bodCardNumber Youll see now that assignment wont now work (you have to initialise constants)

What wed really like (most likely) is to use in i t ial isat ion

We can do this via initialiser lists Ie we could change the above to the following

class Member public Person

public

Member(string bodCardNumber)

bodCardNumber(bodCardNumber)

const string getBodCardNumber()

return bodCardNumber

private

const string bodCardNumber

The initialiser list is read thus

bodCardNumber(bodCardNumber)

^^member^^ ^^parameter^^

Note that weve also modified getBodCardNumber() to show that it returns a const string

141

Modify all three classes to use initialiser lists private const data members and use access functions (getBlah() etc)

Task 3

Open and examine the project called UnivMember3

UnivMember3 is a copy of the (exercise solut ion)

UnivMember2 solution

We will now finish this project to the level of an introductory course

Things to note

The main problem with the solution as it stands is that one may create a Member object

Remember that this is analogous to being able to create a generic Car object ndash we should not be allowed to create one

Going right back to UnivMember1 you may remember a comment in there about a protected constructor

protected Protected ctor Person()

At that point in your project we were thinking two things 1) we wont want to create a generic person and 2) a protected constructor will facilitate this

And we were wrong to think both thoughts

1) A properly thought through Person class would be perfectly good to model generic people But although this is true one question here ndash would we ever want just a generic person

2) A protected constructor in a (more) base class doesnt prevent a derived class from creating a base object So what about the Member class ndash would it be ok to instantiate that

The proper means to prevent a Member being created would be to use what is called a pure v i r tual funct ion as part of its definition (such a function is one that must be overridden in a derived class) But what function

142

If you look at the classes derived from Member ndash you can take it from us that one might want to interrogate at runtime ndash to ask them what they are

So a suitable member function to declare in Member would be something like string getRole() A function that does return Student for a student and return Staff for a Staff object

If its pure virtual in in Member wed best define it in our derived classes

class Member public Person

public

virtual const string getRole() = 0

class Student public Member

public

const string getRole() return Student

143

1 Why did we want duplicate (named) functions in Member Student and Staff 2 And what does virtual really mean

We require both 1 and 2 so that we can provide specific responses when being asked the same question and all when being treated in a rather basic way

Being asked the same question means having a method invoked eg getRole() and in a rather basic way means treating us all Students and Staff (etc) as Persons and Members

112 Polymorphism

Polymorphism comes in a few forms

Ad-hoc Polymorphism via function overloading

Parametric Polymorphism or Compile-Time Polymorphism via templates

Subtype Polymorphism or Runtime Polymorphism via virtual functions and

Coercion Polymorphism via casting

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class (after all a derived from base must have or contain all that a base has) Polymorphism is the art of taking advantage of this simple but powerful and versatile feature

One way Subtype Polymorphism is applied is to use a base reference to access a collection of instances of different types that are derived from a common base ndash one way to paraphrase that is to say that related (derived from a common class) objects respond according to their type rather than according to the type of the reference one uses to access them (a base class pointer type) That is the dynamic type of the object is used instead of its static type

All of this is best demonstrated via an example of course

144

PLUSPLUS Polymorphism

Task 1

Open and examine the project called (exercise

solut ion) UnivMember3

Run the program the output should be the same as shown in Figure 36

The crucial code here is as follows

Member arr[6]

Student studs1()

Student studs2()

Staff staff1()

Student studs3()

Staff staff2()

Student studs4()

arr[0] = ampstuds1

arr[1] = ampstaff1

arr[2] = ampstuds2

arr[3] = ampstaff2

arr[4] = ampstuds3

arr[5] = ampstuds4

for(int i = 0 i lt ++i)

cout ltlt arr[i]

ltlt i ltlt s name is

ltlt arr[i]-gtgetName()

ltlt t Their role is

ltlt arr[i]-gtgetRole()

ltlt endl

Weve created an array of Members (it isnt important that weve used pointers) and note that we have set some of the members of this to be pointers to Student and Staff objects We are allowed to do this as both Student and Staff are derived from Member

However when and if we invoke member functions on these objects wed really like it if they responded as what they really are ndash Student and Staff objects

145

From the output below you can see that they indeed do respond accordingly

Figure 36

The mechanism behind allowing this is the virtualisation of the getRole() member function Remember that this was declared and made virtual in the Member class

Play about with the code eg change

Member arr[6] to Person arr[6] Everything still ok How about not using pointers here ndash easy to do

146

Lastly weve implemented (for no good reason but to show you how its done) some instance counting in all three classes Have a look for the static members and the inserted lines immediately below the class definitions that look like this int PersonCount = 0

The End Thank you for coming and we hope that you enjoyed the class

Oh and please Please PLEASE fill out the feedback form email when it arrives

147

12 Appendices

Arithmetical Operators

Operator Operation

+ Addition

- Subtraction

Multiplication

Division

Modulus

++ Increment

-- Decrement

Table 8 ndash Arithmetical Operators

Assignment Operators

Operator Example Equivalent

= a = b a = b

+= a += b a = a + b

-= a -= b a = a - b

= a = b a = a b

= a = b a = a b

= a = b a = a b

Table 9 ndash Assignment Operators

148

Assignment and Arithmetic examples

The assignment operator in C++ is =

The format is var iable = expression this can be read as assign to the var iable the value of the expression

An example to calculate the number of pence in a value in pounds would be

pence = pounds 100

Note it is easy to confuse the assignment operator = with the equals notation used in mathematics The equals notation in C++ is ==

Incrementing a var iable

month = month + 1 adds the value one to the variable month This can be written as

month++

Decrementing a var iable

month = month - 1 deducts the value one from the variable month This can be written as month--

Note that ++ and ndash can be used before or after the thing being modified eg ++x x++ --y y-- However there are some subtle differences which will be explained in the lectures

In C++ it is also possible to combine arithmetic and assignment operations

To add 2 to a variable total

total = total + 2 or total +=2

To subtract 2 from to tal

total = total - 2 or total -=2

To multiply total by 2

total = total 2 or total =2

Relational and Equality Operators

The equality operator is used to compare two operands (a == b) and returns 1 (t rue) if both are equal otherwise 0 (false ) is returned

The inequality operator (=) returns 1 (t rue) if both are NOT equal otherwise 0 (false) is returned

Both the above operators are commonly used to test the state of two variables to perform conditional branching

The relational operators also return either true or false (a gt= b) returns 1 (t rue ) if a is greater than or equal to b otherwise 0 (false ) is returned

149

Standard algebraic equality or relational

operator

C++ equality or relational operator

Sample C++ condition

Meaning of C++ condition

Relational operators

gt gt a gt b a is greater than b

lt lt a lt b a is less than b

gt= a gt= b a is greater than or equal to b

lt= a lt= b a is less than or equal to b

Equality operators

= == a == b a is equal to b

= a = b a is not equal to b

Table 10 ndash Relational Operators

Logical Operators

When using i f selection statements it is common to use the relational operators as part of the test if(num gt 5) if(size lt= 14) if(Char == A) These are fine for testing one condition

To test multiple conditions it is possible to nest i f statements but this can be a bit cumbersome

Logical Operators can be used to form more complex conditions by combining simple conditions

Logical AND (ampamp) Operator allows a test to see if two conditions are true

if(leaveBooked gt LeaveLeft ampamp staffCover == false)

cout ltlt Take your holidays sometime else

Logical OR (||) Operator allows a test to see if either or both of the conditions are true

if(Temperature lt 16 || windspeed gt 15)

cout ltlt Too cold or windy to sunbath today then

Logical Negation ( ) Operator reverses the meaning of a condition

if((windspeed == 20))

150

cout ltlt The wind speed is not 20 its ltlt windspeed

This could be written equally as well with the equality operator

if(windspeed = 20)

cout ltlt The wind speed is not 20 its ltlt windspeed

Precedence and Associativity Table

Precedence Operator Description Associativity

1 Scope resolution Left-to-right

2

++ -- Suffixpostfix increment and decrement

() Function call

[] Array subscripting

Element selection by reference

-gt Element selection through pointer

typeid() Run-time type information (see typeid)

const_cast Type cast (see const_cast)

dynamic_cast Type cast (see dynamic_cast)

reinterpret_cast Type cast (see reinterpret_cast)

static_cast Type cast (see static_cast)

3

++ -- Prefix increment and decrement Right-to-left

+ - Unary plus and minus

~ Logical NOT and bitwise NOT

(type) Type cast

Indirection (dereference)

amp Address-of

sizeof Size-of

new new[] Dynamic memory allocation

delete delete[] Dynamic memory deallocation

151

4 -gt Pointer to member Left-to-right

5 Multiplication division and remainder

6 + - Addition and subtraction

7 ltlt gtgt Bitwise left shift and right shift

8 lt lt= For relational operators lt and le respectively

gt gt= For relational operators gt and ge respectively

9 == = For relational = and ne respectively

10 amp Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 ampamp Logical AND

14 || Logical OR

15 Ternary conditional Right-to-Left

16

= Direct assignment (provided by default for C++ classes)

+= -= Assignment by sum and difference

= = = Assignment by product quotient and remainder

ltlt= gtgt= Assignment by bitwise left shift and right shift

amp= ^= |= Assignment by bitwise AND XOR and OR

17 throw Throw operator (exceptions throwing)

18 Comma Left-to-right

Table 11 ndash Precedence and Associativity Table

Escape Sequences

Escape Sequence

Description

n Newline Position the screen cursor at the beginning of the next line

152

t Horizontal tab Move the cursor to the next tab stop

r Carriage return Position the cursor at the beginning of the current line

a Alert Sound the system bell

Backslash used to print a backslash

Single quote Use to print a single quote character

Double quote Used to print a double quote character

Table 12 ndash Escape Sequences

Cast Operator

Is where the programmer explicitly asks for a change in data type It may be that the result of a calculation is a double and the user wants it to be of type integer

A double can be cast to an integer in the following way

double aNum = 237

int anInt = 0

anInt = static_castltintgt(aNum)

A C style cast may also be used eg

anInt = (int)aNum OR anInt = int(aNum)

Formatted Output

When several numbers are displayed each is printed with the minimum number of digits needed to show the value This can yield some unexpected output

The width of an output field can be set using a stream manipulator To set the next number to be printed to a width of 5 digits use cout ltlt setw(5) This command does not produce any output it manipulates the stream to change the output format of the next value Note setw() must be specified for every item output

To use any stream manipulators you must include the header include ltiomanipgt

setprecision is another manipulator and is used to set the precision of the next floating point number Note setprecis ion only has to be set once as the stream remembers the formatting directive and does not affect integer fields The format is cout ltlt

setprecision(3)

To set precision for trailing zeros (0100 will appear as 01) it is necessary to use the fixed format The notation is cout ltlt fixed Note f ixed only has to be set once

The three manipulators can be combined to achieve the required precision and field width when used in this way

153

cout ltlt fixed ltlt setprecision(3) ltlt setw(5) ltlt myDouble

Alternatively as fixed and setprecision only have to be set once this statement could be written as

cout ltlt fixed ltlt setprecision(3)

cout ltlt setw(5) ltlt myDouble

Header Files

Every program that you create will have at least one header file If you use input or output you will have to include the iostream header

If you use mathematical functions you will need cmath It can be difficult to know which header files to use for each function Some of the common header files used together with some of the older ones you may find with inherited code are shown below It is a good idea to use the help if you are unsure which header files are associated with particular functions

Standard C++ header Old header

iostream iostreamh

iomanip iomaniph

fstream fstreamh

cmath mathh

cstdlib stdlibh

string No equivalent

vector vectorh

Table 13 ndash Header Files Old and New

Matrix Libraries

The STL does not contain a Matrix type and so we must look elsewhere for a suitable implementation that suits the individuals needs

The table below lists the third party libraries that we are aware of

Some Linear AlgebraMatrix Libraries

Armadillo Blitz++ Boost

CPPLapack CPPScaLapack CVM Class Library

Eigen Elemental FLENS

Gmm++ GNU Scientific Library (GSL) HSL

154

IML++ IT++ LA library

Lapack++ LinBox Matrix Template Library (MTL)

MV++ Newmat PETSc

RNM Seldon SimuNova

SL++ (Scientific Library)

SparseLib++ SuiteSparse

TCBI (Temporary Base Class Idiom)

Template Numerical Toolkit (TNT)

Trilinos

uBlas ViennaCL

Table 14 ndash Matrix Libraries

Scope

The portion of a program where an identifier can be used is known as its scope

An identifier declared outside any function or class has f i le scope This type of identifier is known by all functions Global variables and function prototypes all have file scope

Identifiers declared inside a block of code have block scope This type of scope begins at the identifiers declaration and ends at the termination right brace ( ) of the block in which the identifier is declared

Any block can contain local variable declarations If blocks are nested it is possible to declare variables with the same name in each nested block The variable in the outer block is hidden while the inner block is being executed

Enumerating constants

The enum keyword provides a handy way to create a sequence of integer constants An example of enumeration is shown below

enum Months JAN = 1 FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC

Each of the constants will have a default value 1 greater than the constants that it follows in the list The first value in the enumeration above is explicitly set to 1 and the remaining values increment by 1 The values assigned from JAN to DEC will be 1 to 12

The statement cout ltlt DECEMBER is month number ltlt DEC ltlt endl would be output as DECEMBER is month number 12

Constants

Data that will not change during the execution of a program should be stored in a constant container rather than a variable If the program attempts to change the value stored in a constant the compiler will report an error and compilation will fail

Constant can be created for any data type by prefixing the declaration with const keyword followed by a space Note Constants must always be initialised at declaration

The following declaration declares a constant for the speed of sound at sea level ms

155

const double SpeedOfSound = 34029

Vector member functions

Some commonly used member functions of the vector class are

Vector member Functions Effect

at(element number) Gets the value contained in the specified element

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

push_back(value) Adds an element to the end of the vector containing the specified value

size() Gets the number of elements

Table 15 ndash Vector Member Functions

Global functions

Global functions are not member functions They take more than one argument and operate on a range of elements rather than on the vector container ie they can be used on other types of containers

Vector global Functions Effect

find()

ptr = find(vbegin() vend() 67)

Finds the element in the vector containing number 67 Needs iterator (ptr) to store location of element

reverse()

reverse(vbegin() vend()) Reverses the values in a vector (v)

sort()

sort(vbegin() vend()) Sorts the vector (v)

Table 16 ndash Vector Global Functions

156

list member functions

Some commonly used member functions of the list class are

List member Functions Effect

back() Gets the value in the final element

begin() Points to the first element in vector

clear() Erases the vector

empty() Returns true (1) if the vector is empty or false (0) otherwise

end() Points to the last element in vector

front() Gets the value in the first element

insert() Insert new elements before position

pop_back Removes the final element

pop_front Removes the first element

push_back(value) Adds an element to the end of the vector containing the specified value

sort() Sorts the elements in the container from lower to higher

size() Gets the number of elements

swap() Exchanges the content of the list

Table 17 ndash List class Member Functions

cmath functions

Function Argument Result Returned Value Example Result

ceil(x) double double Smallest integer ge x

ceil(21) 30

cos(x) double double Cosine of x radians cos(10) 054

fabs(x) double double Absolute value of x

fabs(-15) 15

floor(x) double double Largest integer le 29

floor(29) 20

157

pow(x y) double double x to the yth power pow(24) 160

sin(x) double double Sine of x radians sin(10) 084

sqrt(x) double double Square root of x sqrt(4) 20

tan(x) double double Tangent of x radians

tan(10) 156

Table 18 ndash cmath Functions

158

String class

The string class defines many member funct ions A few of the basic ones are described below

Initialisation - constructors form

A string expression string str2 = str1

A character string literal string Intro = Programming with C++

A substring of another string object

string Intro = Capetown

string Mytown = Boars

string MyTown(Intro 4 5)

starts at character 4 (t)

with a length of 5 (or the rest of the string if shorter)

cout ltlt myTown ltlt endl

will produce an output town

Member Functions

length()

string myName = Sebastion

myNamelength()

will produce an output of 9

insert ()

Inserts a string into the current string starting at the specified position

string myName = Sebastion

string nameAdd = rjio

myNameinsert (2nameAdd)

cout ltlt myName ltlt endl

will produce an output Serjiobastion

erase()

Delete a substring from the current string

string myName = Sebastion

myNameerase (02)

cout ltlt myName ltlt endl

will produce an output bastion

replace()

Delete a substring from the current string and replace it with another string

string myName = Sebastion

string aName = renna

159

Member Functions

myNamereplace(3 6 aName)

cout ltlt myName ltlt endl

will produce an output Sebrenna

find()

Search for the first occurrence of the substring in the current string If the word is found return the position of the first character If not return -1

string sName

string findWord

position = sNamefind(findWord)

substr()

Returns a substring of the current string

string myName = Sebastion

string aName = myNamesubstr(0 3)

cout ltlt aName ltlt endl

will produce an output Seb

Non-member functions

getline()

string name

getline(cin name)

Table 19 ndash String Class Member Functions

160

A number of C++ operators also work with str ing objects

Operator

=

string fString = Hello

string lString

lString = fString

Assign a character (char ) to a str ing object

string aStringC

aStringC = Z

+

Concatenate two str ing objects

string str1 = C++

string str2 = Programming

string str3 = str1 + str2

+

Concatenate a string object and a character string literal

string str = Hello

string str1 = str + there

The same concatenation can be done in this way

str += there

+

Concatenate a string object and a single character

string str = Bye Bye

string strBye = str +

161

ASCII Character set

Decimal Octal Hexadecimal Binary Value Meaning

0 0 0 0 NUL (Null char)

1 1 1 1 SOH (Start of Header)

2 2 2 10 STX (Start of Text)

3 3 3 11 ETX (End of Text)

4 4 4 100 EOT (End of Transmission)

5 5 5 101 ENQ (Enquiry)

6 6 6 110 ACK (Acknowledgment)

7 7 7 111 BEL (Bell)

8 10 8 1000 BS (Backspace)

9 11 9 1001 HT (Horizontal Tab)

10 12 00A 1010 LF (Line Feed)

11 13 00B 1011 VT (Vertical Tab)

12 14 00C 1100 FF (Form Feed)

13 15 00D 1101 CR (Carriage Return)

14 16 00E 1110 SO (Shift Out)

15 17 00F 1111 SI (Shift In)

16 20 10 10000 DLE (Data Link Escape)

162

Decimal Octal Hexadecimal Binary Value Meaning

17 21 11 10001 DC1 (X ON) (Device Control 1)

18 22 12 10010 DC2 (Device Control 2)

19 23 13 10011 DC3 (X OFF)(Device Control 3)

20 24 14 10100 DC4 (Device Control 4)

21 25 15 10101 NAK (Negative Acknowledgement)

22 26 16 10110 SYN (Synchronous Idle)

23 27 17 10111 ETB (End of Trans Block)

24 30 18 11000 CAN (Cancel)

25 31 19 11001 EM (End of Medium)

26 32 01A 11010 SUB (Substitute)

27 33 01B 11011 ESC (Escape)

28 34 01C 11100 FS (File Separator)

29 35 01D 11101 GS (Group Separator)

30 36 01E 11110 RS (Request to Send)(Record Separator)

31 37 01F 11111 US (Unit Separator)

32 40 20 100000 SP (Space)

33 41 21 100001 (exclamation mark)

34 42 22 100010 (double quote)

163

Decimal Octal Hexadecimal Binary Value Meaning

35 43 23 100011 (number sign)

36 44 24 100100 $ (dollar sign)

37 45 25 100101 (percent)

38 46 26 100110 amp (ampersand)

39 47 27 100111 (single quote)

40 50 28 101000 ( (leftopening parenthesis)

41 51 29 101001 ) (rightclosing parenthesis)

42 52 02A 101010 (asterisk)

43 53 02B 101011 + (plus)

44 54 02C 101100 (comma)

45 55 02D 101101 - (minus or dash)

46 56 02E 101110 (dot)

47 57 02F 101111 (forward slash)

48 60 30 110000 0

49 61 31 110001 1

50 62 32 110010 2

51 63 33 110011 3

52 64 34 110100 4

164

Decimal Octal Hexadecimal Binary Value Meaning

53 65 35 110101 5

54 66 36 110110 6

55 67 37 110111 7

56 70 38 111000 8

57 71 39 111001 9

58 72 03A 111010 (colon)

59 73 03B 111011 (semi-colon)

60 74 03C 111100 lt (less than)

61 75 03D 111101 = (equal sign)

62 76 03E 111110 gt (greater than)

63 77 03F 111111 (question mark)

64 100 40 1000000 (AT symbol)

65 101 41 1000001 A

66 102 42 1000010 B

67 103 43 1000011 C

68 104 44 1000100 D

69 105 45 1000101 E

70 106 46 1000110 F

165

Decimal Octal Hexadecimal Binary Value Meaning

71 107 47 1000111 G

72 110 48 1001000 H

73 111 49 1001001 I

74 112 04A 1001010 J

75 113 04B 1001011 K

76 114 04C 1001100 L

77 115 04D 1001101 M

78 116 04E 1001110 N

79 117 04F 1001111 O

80 120 50 1010000 P

81 121 51 1010001 Q

82 122 52 1010010 R

83 123 53 1010011 S

84 124 54 1010100 T

85 125 55 1010101 U

86 126 56 1010110 V

87 127 57 1010111 W

88 130 58 1011000 X

166

Decimal Octal Hexadecimal Binary Value Meaning

89 131 59 1011001 Y

90 132 05A 1011010 Z

91 133 05B 1011011 [ (leftopening bracket)

92 134 05C 1011100 (back slash)

93 135 05D 1011101 ] (rightclosing bracket)

94 136 05E 1011110 ^ (caretcirumflex)

95 137 05F 1011111 _ (underscore)

96 140 60 1100000 `

97 141 61 1100001 a

98 142 62 1100010 b

99 143 63 1100011 c

100 144 64 1100100 d

101 145 65 1100101 e

102 146 66 1100110 f

103 147 67 1100111 g

104 150 68 1101000 h

105 151 69 1101001 i

106 152 06A 1101010 j

167

Decimal Octal Hexadecimal Binary Value Meaning

107 153 06B 1101011 k

108 154 06C 1101100 l

109 155 06D 1101101 m

110 156 06E 1101110 n

111 157 06F 1101111 o

112 160 70 1110000 p

113 161 71 1110001 q

114 162 72 1110010 r

115 163 73 1110011 s

116 164 74 1110100 t

117 165 75 1110101 u

118 166 76 1110110 v

119 167 77 1110111 w

120 170 78 1111000 x

121 171 79 1111001 y

122 172 07A 1111010 z

123 173 07B 1111011 (leftopening brace)

124 174 07C 1111100 | (vertical bar)

168

Decimal Octal Hexadecimal Binary Value Meaning

125 175 07D 1111101 (rightclosing brace)

126 176 07E 1111110 ~ (tilde)

127 177 07F 1111111 DEL (delete)

Table 20 ndash Full ASCII Table

169

Handy IDE Settings

Line Numbers onoff Tools | Options | Text Editor | CC++ | Line Numbers

Auto closing the console Tools | Options | Debugging | Automatically close the console window when debugging stops

Saves having to use system(pause)

170

REMAINING PAGES LEFT BLANK FOR NOTE TAKING

171

172

173

Peet Morris

peetmorrisgmailcom

C++ A Comprehensive Introduction

Arrangements

bull We Startfinish at 915am 500pm

bull Format two lectures per day (ask questions) hands-on at all other times

bull You should have Course book (copy of the slides at the back)

bull The course software is pre-installed on the machines

And also separately available from

The compilerIDE wwwvisualstudiocom

Notesslidesexercise files wwwpeetmcomC++introcoursezip

Your safety is important

Where is the fire exit

Beware of hazards

Tripping over bags and coats

Please tell us if anything does not work

Let us know if you have any other concerns

Your comfort is important

The toilets are along the corridor just outside the teaching rooms

The rest area is where you registered it has vending machines and

a water cooler

The seats are adjustable

You can adjust the monitors for brightness

What we assumehellip

What we assume

Experience of using another programming

language

Comprehensive Lots to get through

C++ and OOP

bull Created in 1985 by Bjarne Stroustrup C++ is a highly efficient

multiplatform low level Object Oriented Programming language

bull Latest version is C++17

stroustrupcom

Standard C++ Library

bull Written in the core language it is a collection of classes

(object definitions) functions and algorithms

See wwwcpluspluscomreference

IDEs amp Compilers

Visual Studio 2017

First Program

First application

include ltiostreamgt

using namespace std

int main()

int aNum = 0 aNum(0) or aNum0

cout ltlt Enter a number-

cin gtgt aNum

cout ltlt You entered ltlt aNum

return 0

hellip hellip

First Program

bull include ltiostreamgt

Adds the contents of the iostream header file into the program (for cout and cin)

bull using namespace std

So we donrsquot have to write stdcout ltlt and stdcin gtgt all of the time

bull cin is the standard input stream object that allows input from the keyboard

bull cout is the standard output stream object that allows output to the screen

bull int main() The programs entry point

Mandatory main function in every C++ program ndash always returns an integer value

First Program

bull int aNum = 0

Variable to hold a value of type integer (piece of machine memory referred to via the name aNum)

bull ltlt stream insertion operator ndash outputs to console

cout ltlt Enter a number-

bull gtgt stream extraction operator ndash waits for keyboard input

cin gtgt aNum

Other Types

Microsoft data types summary httpsdocsmicrosoftcomen-gbcppcppfundamental-types-cpp

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststack

Lots

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

x 1

y 2

x 3

y 4

p1

p2

x

y

Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 copies the bit pattern from p1 to p2

x 1

y 2

x 1

y 2

p1

p2

Compound Types

Cannot define operators other than assignment

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

p2 = p1 p2 compilation error

x 1

y 2

x 3

y 4

p1

p2

Compound Types

We can arbitrarily further compound things

struct point

int xint y

struct rectangle

point tlpoint br

struct line

point startpoint end

startxy

endxy tlxy

brxy

Compound Types

We can also group things using struct to create compound

types

struct point

int xint y

struct rectangle

point tlpoint br

int main()

rectangle r

rtlx = 1rtly = 2

rbrx = 3rbry = 4

int diff_x = abs(rtopLeftx - rbottomRightx)int diff_y = abs(rtopLefty - rbottomRighty)

cout ltlt area ltlt diff_x diff_y ltlt endl

r

tl

br

x 1

y 2

x 3

y 4

Using a Library Type

include ltstringgt

string s

cout ltlt What is your name

getline(cin s)

cout ltlt s ltlt

ltlt is

ltlt slength() ltlt

ltlt characters long ltlt endl

s

Other Types

C++ types (native to the compiler)bool[signedunsigned] char[signedunsigned] int[signedunsigned] short int[signedunsigned] long int[signedunsigned] long long int

floatdoublelong doublepointers

include-ed types (defined in the library)

stringvectorarrayliststackcomplex

Lots

8 bit Binary signed unsigned

00000001 1 1

00000010 2 2

00000011 3 3

01111111 127 127

10000000 -128 128

10000001 -127 129

10000010 -126 130

11111101 -3 253

11111110 -2 254

11111111 -1 255

00000000 0 0

00000001 1 1

00000010 2 2

signed vs unsigned ndash its all just 1s and 0s and adding

Adding rules

0 + 0 = 0

1 + 0 = 1

0 + 1 = 1

1 + 1 = 0 (carry 1)

1 + 1 + 1 = 1 (carry 1)

-126 + +3 =

10000010

00000011 +

10000101 = -123

-126 + -3

10000010

11111101 +

01111111 = 127 (why not -129)

Arithmetic Operators

+ Addition

- Subtraction and unary minus

Multiplication

Division

Remainder after division (moduloclock arithmetic)

int j k l = 10

j = l 3 js value will be three

k = l 3 ks value will be 1

Relational Operators

Evaluate to either true or false represented by integer values 1 and 0

== Equal to

= Not equal to

gt Greater than

lt Less than

gt= Greater than or equal to

lt= Less than or equal to

Increment and Decrement Operators

++ Increment

-- Decrement

Can be prefix or postfix

b = 3

a = b++ + 6 Add 6 to b then increment b a is 9 b is 4

b = 3

a = ++b + 6 Increment b then add 6 to b a is 10 b is 4

Assignment Operators

Symbol Operation Long Short

= Assign a = 2 a = 2

+= Assign with add a = a + 2 a += 2

-= Assign with subtract a = a ndash 2 a -= 2

= Assign with multiply a = a 2 a = 2

= Assign with divide a = a 2 a = 2

= Assign with remainder a = a 2 a = 2

Basic Control Flow - if

Sequence

What we have been doing already

Selection

if statement if this then that

if (boolean expression) if (score gt= 50)

statement cout ltlt Passed

Logical Operators

Boolean expressions may be combined using

ampamp And

|| Or

Not

Operands and result resolves being either true or false

if (x ampamp (y || z))

else

Precedence and Associativity table in course book

Logical Operators

a b =

true true true

true false false

false true false

false false false

a b =

true true true

true false true

false true true

false false false

a =

true false

false true

a ampamp b a || b a

Logical Operators

if (x ampamp (y || z))

else

The value 0 (zero) is evaluated to mean false any other value is true

x ampamp (y || z) result

false ampamp (false || false) falsefalse ampamp (false || true ) falsefalse ampamp (true || false) falsefalse ampamp (true || true ) falsetrue ampamp (false || true ) falsetrue ampamp (false || false) truetrue ampamp (true || false) truetrue ampamp (true || true ) true

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp (y | ~z))

else

Bitwise Operators

unsigned int x = 11

unsigned int y = 7

unsigned int z = 25

if (x amp (y | ~z))

else

11 (x) = 000010117 (y) = 0000011125 (z) = 00011001

~z = 11100110 (230 or -26)

y | ~z = 11100111 (231 or -25)

x amp (y | ~z) = 00000011 = 3

Operands and the result resolve to a values

Bitwise Operators

Bitwise expressions may be combined using

amp And

| Or

~ Not

^ XOr

gtgt Right shift

ltlt Left shift

if (x amp 1) x is odd

if (x gt y)

x = x ^ y

y = y ^ x XOr swap

x = x ^ y

Control Flow - if else

Selection

ifelse statements

if (boolean exp) if (score gt= 50)

statement cout ltlt Passed

else else

statement cout ltlt Failed

Control Flow -

Selection

Conditional (or Ternary) Operator

boolean exp true result false result

cout ltlt score gt= 50 Passed Failed

Control Flow

if (x gt= y)

if (y 2)

else

if (x gt= y)

if (y 2)

else

Control Flow ndash else if

if (exp)

else if (exp)

else if (exp)

else catch all remaining

if (aNum == 0)

else if (aNum == 1 || aNum == 2)

else if (aNum == 3)

else catch all remaining

aNum not 0123

Control Flow - switch

Selection

switch multiple selection statements

bull test must be an integral value 1 10 A x eg not 1056

bull case values must be constants

switch (aNum)

case 0

break

case 1 Fall through

case 2

break

default catch all

break

Repetition - while

while (exp)

statements

while (n lt k)

cout ltlt Enter mark

cin gtgt mark

t += mark

n++

Repetition - for

for (init exp inc)

statements

for (t = 0 n lt k n++)

cout ltlt Enter mark

cin gtgt mark

t += mark

Preferable to while if the range is known

Repetition - for

for (init exp inc)

statements

for () infinite loop

break causes loop to exit

Preferable to while if the range is known

Repetition - do

do

statements

while (exp)

do

cout ltlt Continue yn

cin gtgt yn

yn = tolower(yn)

while (yn = y ampamp yn = n)

There are a huge number of exercises and we donrsquot expect you to attempt

them all during this course

bull If yoursquore completely new to programming itrsquos probably best to tackle

them in sequence

bull If yoursquove some programming experience you should read through the

exercise summaries and then start wherever you feel comfortable

Exercises

Exercises

Topics covered in ex1 ndash ex6

Functions = mini programs

bull Used to combine data with operations and through functional

decomposition to promote code re-use

bull Simplifies coding

bull Functions for discrete tasks

bull Not hundreds of lines of code

bull Consumer only needs to know

bull What goes in and what comes out

Functions

Like everything else the compiler needs to have seen a prototype or a

definition of a function before we can use it

Prototypes lets the compiler generate the correct code

int min(int int)

int min(int int int)

void drawLine(point to point from = 00)

int square(int)

int main()

void beep()

string getNextPacket(void)

Return type Function name (Parameter list)

min

int min(int int) min prototypes (forward declarations)int min(int int int)

int main()

Having seen the prototypes the compilerc = min(x y) can generate the required code

int min (int a int b) min function definition 1

return a lt b a b

int min (int a int b int c) min function definition 2

return min(min(a b) c)

inline min

int main()

c = min(x y)

inline int min (int a int b)

return a lt b a b

int main()

c = x lt y x y

inline int min (int a int b)

return a lt b a b

Function Parameters

bull Pass by Value

bull A Copy of the parameter is passed to the called function

bull Pass by Reference

bull The actual parameter is passed to the called function

bull Pass by Memory Address (pointer)

bull Same effect as Pass by Reference (tomorrow)

Pass by value

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

return n_copy n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 10

n_copy 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp x)

x just another name for real_n

return x x

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

x 10

Pass by value (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int n_copy)

n_copy = n_copy n_copy

return n_copy

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x7121 100

n_copy 100

Pass by reference (parameter treated as variable)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(int amp real_n)

real_n = real_n real_n

return real_n

100

100

Mem Addr Contents

0x2786 100

real_n 100

Mem Addr Contents

0x2786 100

real_n 100

const Parameters

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Recursion

unsigned long long int fibonacci(int n)

switch(n)

case 0 Fall through - [[fallthrough]]

case 1

return n

break

default

return fibonacci(n - 1) + fibonacci(n - 2) Very inefficient

Arrays (Part 1)

Data structure containing same type of data (int double string char object)

bull Built in to C++

bull Series of elements each containing one item of data (contiguous memory locations)

Size (number of elements) set at compile time

Arrays (1)

int numbers[10] an array of 10 integers Each box sizeof(int) bytes wide

numbers

index values - 0 to 9

0 1 2 3 4 5 6 7 8 9

Arrays (1)

int numbers[10] an array of 10 integers

int n = 0

cout ltlt numbers ltlt endl address of the first element

cout ltlt numbers[n] ltlt endl contents of the nth element

cout ltlt ampnumbers[n] ltlt endl address of the nth element

cout ltlt numbers + n ltlt endl address of the nth element

0 1 2 3 4 5 6 7 8 9

42 hellip hellip hellip hellip hellip hellip hellip hellip hellip

0x1526

Arrays

char name[5] name - an array of five characters

thing t[5] t - an array of five things

examMarks ndash an array of three doubles initialised to 12 39 95double examMarks[] = 12 39 95 C++11 - double examMarks[] 12 39 95

header ndash an array of fifty unsigned chars (bytes) first three elements set to 0 1 255 and the rest to zerotypedef unsigned char bytebyte header[50] = 0 1 -1

Arrays

Accessing array data

define MARKS 5 or const int MARKS = 5

double examMarks[MARKS]

for(int i = 0 i lt MARKS i++)

cout ltlt Enter Exam Mark

ltlt i + 1 ltlt

cin gtgt examMarks[i]

for(i = 0 i lt MARKS i++)

cout ltlt examMarks[i]

Multidimensional Arrays

Two dimensional array Two subscripts First identifies row second identifies column

const int students = 6 const int marks = 3

double examMarks[students][marks] = 0 set to zero

for (int s = 0 s lt students ++s)

for (int m = 0 m lt marks ++m)

cout ltlt Enter mark ltlt m + 1 ltlt for student ltlt s + 1 ltlt endl

cin gtgt examMarks[s][m]

00 01 02

10 11 12

20 21 22

30 31 32

40 41 42

50 51 52

Memory laid out in row column order (more later)

00 01 02 10 11 12 20 21 22 30 31 32 40 41 42 50 51 52

Matrices

Provider Link

Armadillo armasourceforgenet

Blitz blitzsourceforgenet

Boost boostorg

Eigen eigentuxfamilyorg

Elemental libelementalorg

FLENS apfelmathematikuni-ulmde

HSL hslrlacuk

LEDA algorithmic-solutionscom

PETSc mcsanlgov

SimuNova simunovacom

SuiteSparse facultycsetamuedu

TNT mathnistgov

Trilinos trilinosorg

ViennaCL viennaclsourceforgenet

Exercises

Topics covered in ex7 ndash ex16

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people

C++ and OOP

Object Oriented Programming

A mechanism allowing us to model both real world and abstract entities by

extending the type system

strings lists cars houses people and dice

Recap Compound Types

We can also group things using struct to create compound types

struct point

int xint y

int main()

point p1point p2

p1x = 1p1y = 2

p2x = 3p2y = 4

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 1

struct dice

int sides

int diceThrow(dice d)

srand((unsigned)time(0))

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

1 61 61 61 61 6

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

Dice throwing 2

struct dice

int sides

int diceThrow(dice d)

return (rand() dsides) + 1

int main()

dice d1 d2

d1sides = 6 d2sides = 6

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt diceThrow(d1) ltlt ltlt diceThrow(d2) ltlt endl

return 0

3 11 24 56 12 3

C++ and OOP

Encapsulation Keeping related stuff together

Member functionsmethods

an objectrsquos capabilities functionality and performable actions

int Throw()

Member variablesproperties

an objectrsquos current state values its dumb data

int sides

Dice throwing 3

struct dice

int sides State

dice(int n) Constructor

sides = n

int Throw() Member function (method)

return (rand() sides) + 1

int main()

Could also use dice d1 = 6 or d16 syntaxdice d1(6) d2(6)

d1sides = 6 d2sides = 10 Allow this

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

struct diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 4

class diceprivate Access modifier

int sides

public Access modifier

dice(int n)

sides = n

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

d1sides = 6 d2sides = 6 illegal now

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing ndash professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

diceh my-appcpp

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

dicecpp

Compiler

diceobj my-appobj

Linker

my-appexe

other librarycode objectfiles

Dice throwing - professional layout amp IPR

class diceprivate

int sides

public

dice(int n)

int Throw()

include ltiostreamgtinclude ltctimegtinclude diceh

using namespace std

int main()

dice d1(6) d2(6)

srand((unsigned)time(0))

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Compiler

include ltrandomgtinclude diceh

dicedice(int n)

sides = n

int diceThrow()

return (rand() sides) + 1

diceobj my-appobj

diceh dicecpp my-appcpp

Linker

my-appexe

other librarycode objectfiles

Only items provided to the end-usercustomer

Classes and Objects

the includeltstringgt header file from the standard library

class string

your cpp source code files

include ltstringgt include information about class string

string Name a class string instance

string Address a class string instance

Classes and Objects

the include carh header file

class car

your cpp source code files

include carh include information about class car

car c a class car instance

Classes and Objects

the include househpp header file

class house

your cpp source code files

include househpp include information about class house

house no1 a class house instance

house no2 a class house instance

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do with it

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

class car

What properties and methods do we need Think how wed use a ltcargt and what wed want it to be able to do

include carh

int main()

car c

cwheels = 4

cengine = V8

cstart()

caccelerate()

cstart()

cenginestart() Or should cstart() internally use enginestart()

OOD

Time for a break

class student

What properties and methods do we need

class student

public

string name

string DoB

string college

string bodCardNumber

float age()

int main()

student s

sname =

sDoB =

How to guarantee an objectrsquos integrity

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s

sname = Compilation errors

sDoB =

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

m_name = name m_DoB = DoB

float age()

return calcAge(m_DoB)

int main()

student s( )

cout ltlt sage()

Class Constructor

class student

private

string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB )

if(namelength() || DoBlength())

throw(student initialisation failed)

else

m_name = name m_DoB = DoB Error ndash cant assign to a constant

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_name(name) m_DoB(DoB)

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Class Constructor

class student

private

const string m_name string m_DoB

public

student(string name string DoB ) m_namename m_DoBDoB

if(checkName(m_name) || checkDoB(m_DoB)) Check - post initialisation

throw(student initialisation failed)

initialisation

Exceptions

class student

int main()

try

student s( )

catch(const char msg)

cout ltlt msg ltlt endl

student initialisation failed

Exceptions

try

catch(const char msg)

cout ltlt msg ltlt endl

catch (const invalid_argument amp e)

cout ltlt ewhat() ltlt endl

catch (exception amp e)

cout ltlt ewhat() ltlt endl

catch ()

cout ltlt Something went wrong ltlt endl

student invalid arg 2

if using C++11 see stdcurrent_exception

Reuse and inheritance

Say we now want to add a new type to our system ndash class academic With what we have seen so far we would proceed something like this

class academic

private

string m_name string m_DoB

Duplicating everything we had in class student

class person (generalisation)

OOP is sometimes called Programming by Describing the differences

student and academic are all specialisations of a more generalised and abstract class ndash person

class student public personpublic

student(string name) person(name)

class academic public personpublic

academic(string name) person(name)

class personprotected

person(string name) m_name(name)

private

string m_name

public

base class derived class

derived class

Specialised State

class student public person

private

const string m_bodCard

public

student(string name string DoB string bc ) person(name DoB) m_bodCard(bc)

Multiple inheritance

class student public person public oxMember

public

student(string name int age string bc) person(name age) oxMember(bc)

class academic public person public oxMember

public

academic(string name int age string bc) person(name age) oxMember(bc)

Destructors

class foo

private

int m_x int m_y

public

foo() foo(0 0)

foo(int x) foo(x 0)

foo(int x int y) m_x(x) m_y(y) only ctor that accesses private state

~foo() any necessary tidy up code

Dice throwing 5

class diceprivate

int sides

public

dice(int n) sides(n)

int Throw()

return (rand() sides) + 1

int main()

dice d1(6) d2(6)

srand((unsigned)time(0)) Happy with this

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

Dice throwing 6

class diceprivate

int sides

public

dice(int n) sides(n)

classshared state static bool seeded = false

if (seeded)srand((unsigned)time(0))seeded = true

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

3 65 21 44 22 6

Dice throwing 7

class dice private

int sides

public

dice(int n) sides(n)

int Throw()

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

Dice throwing 7

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyesDouble 14 33 5

Dice throwing 8

class dice private

int sidesint lastThrow

public

dice(int n) sides(n)

int Throw()

return lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

friend ostream amp operator ltlt (ostream amp os dice const amp d)

return os ltlt dlastThrow

int main()

dice d1(6) d2(6) int t

for(int n = 0 n lt 5 ++n)

cout ltlt (t = d1Throw()) ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp t = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Dice throwing 9

class dice private

int sidesint _lastThrow

public

const int amp lastThrow read-only stateproperty

dice(int n) _lastThrow(-1) lastThrow(_lastThrow) sides(n)

int Throw()

return _lastThrow = (rand() sides) + 1

int operator + (dice d)

return lastThrow + dlastThrow

bool operator == (dice d)

return lastThrow == dlastThrow

int main()

dice d1(6) d2(6)

for(int n = 0 n lt 5 ++n)

cout ltlt d1Throw() ltlt ltlt d2Throw() ltlt endl

if (d1 + d2 == 2)

cout ltlt Snake eyes ltlt endl

if(d1 == d2 ampamp d1lastThrow = 1)

cout ltlt Double ltlt ltlt d1 ltlt endl

1 55 5Double 51 1Snake eyes4 33 5

Exercises

Topics covered in ex17 ndash ex22

Vectors

Like an array a data structure containing same type of data (int double object)

bull A container class part of the standard library a wrapper similar to arrays

Need to includeltvectorgt

bull Can resize grow shrink as elements are added or removed from the end

bull Algorithms to manipulate data

bull Iterators to cycle through all the elements

Vectors

vectorltchargt name(5) vector of five characters

vectorltthinggt t(5) vector of five things

vectorltdoublegt examMarks 12 39 95 initialised vector of three doubles

typedef unsigned char byte

a vector of fifty bytes first three elements set to 0 1 255 and the rest to zerobyte char b[50] = 0 1 255 fully populate array

calc itemCountint itemCount = sizeof(b) sizeof(b[0])

vectorltbytegt bytes (b ampb[0] + itemCount) then init with vector 50 items

Vectors (iteration 1)

include ltvectorgt

vectorltintgt vec(20) 20 ints

for(int i = 0 i lt vecsize() i++) input values into vec

cin gtgt vec[i]

for(i = 0 i lt vecsize() i++) output vec

cout ltlt vec[i] ltlt

Vectors (iteration 2) (C++11 and later)

for(type identifier container)

statements

vectorltintgt vec(20)

for (int amp i vec)

Vectors

Adding an extra element

cout ltlt Enter an Extra Value

cin gtgt aNum

vecpush_back(aNum)

for (int i = 0 i lt vecsize() i++)

cout ltlt vec[i] ltlt endl

cout ltlt vecat(i) ltlt endl same as above but range checked (ie slowsafe)

Vectors (most of the methods)

docsmicrosoftcomen-uscppstandard-libraryvector-classFull list

Method Purpose

assign Erases a vector and copies the specified elements to the empty vector

at Returns a reference to the element at a specified location in the vector

back Returns a reference to the last element of the vector

begin Returns a random-access iterator to the first element in the vector

capacity Returns the number of elements that the vector could contain without allocating more storage

clear Erases the elements of the vector

C++11 data Returns a pointer to the first element in the vector

C++11 emplace Inserts an element constructed in place into the vector at a specified position

C++11 emplace_back Adds an element constructed in place to the end of the vector

empty Tests if the vector container is empty

end Returns a random-access iterator that points to the end of the vector

erase Removes an element or a range of elements in a vector from specified positions

front Returns a reference to the first element in a vector

insert Inserts an element or a number of elements into the vector at a specified position

max_size Returns the maximum length of the vector

pop_back Deletes the element at the end of the vector

push_back Add an element to the end of the vector

rbegin Returns an iterator to the first element in a reversed vector

rend Returns an iterator to the end of a reversed vector

reserve Reserves a minimum length of storage for a vector object

resize Specifies a new size for a vector

C++11 shrink_to_fit Discards excess capacity

size Returns the number of elements in the vector

swap Exchanges the elements of two vectors

Vectors (iteration 3)

include ltalgorithmgt

vectorltintgt vec

for(int i = 1 i lt= 5 ++i)vecpush_back(i)

1 2 3 4 5

5 4 3 2 1

vectorltintgtiterator it

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Reverse the vectorreverse(vecbegin() vecend())

cout ltlt endl

for(it = vecbegin() it = vecend() ++it)cout ltlt ltlt it

Arrays (2) (C++11 and later)

arrayltint 5gt arr Thin veneer over an array ndash so requires fixed size

arrfill(0) int j = 0

for (int amp i arr)

supports latest iteration style

reverse(arrbegin() arrend()) and iterators for use with algorithms

C++11 - Uniform initialisers

C++98

complexltdoublegt c( 271828 314159 )

int a[] = 1 2 3 4

vectorltintgt v

for( int i = 1 i lt= 4 ++i )

vpush_back(i)

C++11

complexltdoublegt c 271828 314159

int a[] 1 2 3 4

vectorltintgt v 1 2 3 4

Pointers ndash What

A pointer is a scalar variable that is used to hold the memory-address of

another variable or function the stored address is said to point to the thing

it holds ndash thus the name

Pointers have a type ndash the type of the thing they point to

int n = 10I (p) am a pointer to an integer and I point to n over thereint p = ampn

Pointers ndash Why

In no particular order

bull Because external libraries and APIs (like the operating system (all of them)) are written using them

bull Create custom data structures like linked-lists trees graphs etc

bull Create tables of functions or single functions for handling events callback or signals

bull Access data on to the heap (allocate memory dynamically)

bull Writecall functions that change their input parameters

1 2

3

4 5 6 nilhead

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

amp and

Overloaded

amp

address of ampnumbers[n]

reference int amp square(int amp x)

bitwise AND if(n amp 1)

logical AND if(fu() ampamp bar())

rvalue reference obj ampamp process()

pointer declaration int p = nullptr

multiplication int k = n y

pointer dereference int j = p

Recap - Pass by reference (amp)

int main()

int real_n = 10

cout ltlt square(real_n)

cout ltlt real_n

return 0

int square(const int amp real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x2786 10

real_n 10

Pass by reference using Pointers

int main()

int real_n = 10

cout ltlt square(ampreal_n)

cout ltlt real_n

return 0

int square(const int real_n)

return real_n real_n

100

10

Mem Addr Contents

0x2786 10

real_n 10

Mem Addr Contents

0x5110 0x2786

real_n 0x2786

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

-8763948576

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p -532765818

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

10

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt p

cout ltlt pcout ltlt ampx

cout ltlt x

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

Pointers

int p

x = 10

p = ampx

p = 11

cout ltlt pcout ltlt pcout ltlt ampxcout ltlt xcout ltlt ampp

15438 x

Address

0

1

2

Machine Memory

11

int x

17216 p 15438

15438

11

15438

11

17216

Pointers

int main(int argc char argv)

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )(argv + n) ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv + 0 C

argv + 1

argv + 2

argv + 3

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

int main(int argc char argv[])

for(int n = 0 n lt argc ++n)

cout ltlt n ltlt

ltlt (char )argv[n] ltlt endl

Pointers to Pointers

Cfooexe one two three

argc = 4

argv = 0xhellip argv[0] C

argv[1]

argv[2]

argv[3]

f o o e x e

o n e

t w o

t h r e e

0

0

0

0

0 Cfooexe

1 one

2 two

3 three

Memory Stack vs Heap

Stack (last in first out - LIFO)

Space automatically allocated

The place where arguments of a function call are stored

The place where local function data is allocated (eg variables)

The place where a function leaves its result (if any)

Heap

Space must be explicitly allocated

A place for allocating memory that is not part of last-in first-out approach

ie dynamically allocated data structures that survive function calls

Stack vs Heap

int stackArray[100] Allocate 100 ints on the stack

stackArray[n] = 0 Do something with it

int heapArray = new int[100] 100 ints on the heap C++

int heapArray = malloc(100 sizeof(int)) 100 ints on the heap C

heapArray[n] = 0 Or (heapArray + n) = 0 Do something with it C++ and C

delete [] heapArray When youre done C++

free(heapArray) When youre done C

Exercises

Topics covered in ex22 onwards

If time allows look through the remaining

exercises and attempt those that fit best

with your requirements

  • C++ Notes TPLO 12-11-2019 Blackbox
  • C++ Slides TPLO 12-11-2019 - Copy

Recommended