Sie sind auf Seite 1von 560

Basics

Machine, software, and


program design

JPC and JWD © 2002 McGraw-Hill, Inc.


Computer Organization
CPU - central processing unit
 Where decisions are made, computations are

performed, and input/output requests are delegated


Memory
 Stores information being processed by the CPU

Input devices
 Allows people to supply information to computers

Output devices
 Allows people to receive information from computers
Computer Organization

Memory

Input Output
Devices Devices

CPU
CPU
Brains of the computer
 Arithmetic calculations are performed using the

Arithmetic/Logical Unit or ALU


 Control unit decodes and executes instructions

Arithmetic operations are performed using binary


number system
Control Unit
The fetch/execute cycle Fetch the instruction to
is the steps the CPU which the PC points
takes to execute an
instruction
Performing the action
specified by an Increment the PC
instruction is known as
executing the instruction
The program counter
Execute the fetched
(PC) holds the memory
instruction
address of the next
instruction
Input and Output Devices
Accessories that allow computer to perform specific
tasks
 Receive information for processing

 Return the results of processing

 Store information

Common input and output devices


 Speakers Mouse Scanner
 Printer Joystick CD-ROM
 Keyboard Microphone DVD

Some devices are capable of both input and output


 Floppy drive Hard drive Magnetic tape
units
Monitor
Display device that operates like a television
 Also known as CRT (cathode ray tube)

Controlled by an output device called a graphics card


Displayable area
 Measured in dots per inch, dots

are often referred to as


pixels (short for picture
element) 1280 1024
 Standard resolution pixels pixels
across
is 640 by 480 down
screen screen
 Many cards support

resolution of 1280 by
1024 or better
 Number of colors supported varies from 16 to billions
Software
Application software
 Programs designed to perform specific tasks that are

transparent to the user

System software
 Programs that support the execution and

development of other programs


 Two major types

 Operating systems
 Translation systems
Application Software
Application software is the software that has made
using computers indispensable and popular

Common application software


 Word processors

 Desktop publishing programs

 Spreadsheets

 Presentation managers

 Drawing programs

Learning how to develop application software is our


focus
Operating System
Examples
 Windows®, UNIX®, Mac OS X®

Controls and manages the computing resources

Important services that an operating system provides


 File system

 Directories, folders, files


 Commands that allow for manipulation of the file

system
 Sort, delete, copy
 Ability to perform input and output on a variety of

devices
Translation System
Set of programs used to develop software

A key component of a translation system is a translator

Some types of translators


 Compiler

 Converts from one language to another


 Linker

 Combines resources

Examples
 Microsoft Visual C++®, CBuilder®, g++, Code
Warrior®
 Performs compilation, linking, and other activities.
Software Development
Activities
Editing

Compiling

Linking with precompiled files


 Object files

 Library modules

Loading and executing

Viewing the behavior of the program


Software Development Cycle

Source Program

Compile
Library routines
Edit Link
Other object files
Think Load

Execute
IDEs
Integrated Development Environments or IDEs
 Supports the entire software development cycle

 E.g., MS Visual C++, Borland, Code Warrior

Provides all the capabilities for developing software


 Editor

 Compiler

 Linker

 Loader

 Debugger

 Viewer
Engineering Software
Software engineering
 Area of computer science concerned with building

large software systems

Challenge
 Tremendous advances in hardware have not been

accompanied by comparable advances in software


Complexity Trade-off
System complexity tends to grow as the system
becomes more user friendly

High

Total Software
Complexity
Complexity

User Simplicity

Low
Software Engineering Goals
Reliability
 An unreliable life-critical system can be fatal

Understandability
 Future development is difficult if software is hard to

understand
Cost Effectiveness
Cost Effectiveness
 Cost to develop and maintain should not exceed profit
Adaptability
Adaptability
 System that is adaptive is easier to alter and expand
Reusability
Reusability
 Improves reliability, maintainability, and profitability
Software Engineering
Principles
Abstraction
 Extract the relevant properties while ignoring

inessentials
Encapsulation
Encapsulation
 Hide and protect essential information through a

controlled interface
Modularity
Modularity
 Dividing an object into smaller modules so that it is

easier to understand and manipulate


Hierarchy
Hierarchy
 Ranking or ordering of objects based on some

relationship between them


Abstraction
Extract the relevant object properties while ignoring
inessentials
 Defines a view of the object

Example - car
 Car dealer views a car from selling features

standpoint
 Price, length of warranty, color, …

 Mechanic views a car from systems maintenance


Price? standpoint Oil change?
 Size of the oil filter, type of spark plugs, …
Encapsulation
Steps
 Decompose an object into parts

 Hide and protect essential information

 Supply interface that allows information to be modified in

a controlled and useful manner

Internal representation can be changed without affecting


other system parts

Example - car radio


 Interface consists of controls

and power and antenna connectors


 The details of how it works is hidden
 To install and use a radio

 Do not need to know anything about the radio’s


electronics
Modularity
Dividing an object into smaller pieces or modules so
that the object is easier to understand and manipulate

Most complex systems are modular

Example - Automobile can be decomposed into


subsystems
 Cooling system
 Radiator Thermostat Water pump

 Ignition system
 Battery Starter Spark plugs
Hierarchy
Hierarchy
 Ranking or ordering of objects based on some

relationship between them


Help us understand complex systems
 Example - a company hierarchy helps employees

understand the company and their positions within it


For complex systems, a useful way of ordering similar
abstractions is a taxonomy from least general to most
general
Northern Timber Wolf
Taxonomy
Kingdom Animalia
Phylum Chordata
Class Mammalia
Order Carnivora
Family Caninae
Genus Canis
Species Canis lupus
Subspecies Canis lupus occidentalis
Northern Timber Wolf
OO Design and Programming
Object-oriented design and programming methodology
supports good software engineering
 Promotes thinking in a way that models the way we
think and interact with the real world
H554SL9000S-RMT

Example - watching television


 The remote is a physical object with

properties
 Weight, size, can send message
to the television
 The television is also a physical object

with various properties


Objects
An object is almost anything with the following
characteristics
 Name
 Properties
 The ability to act upon receiving a message
 Basic message types
 Directive to perform an action

 Request to change one of its properties


Binary Arithmetic

The individual digits of a binary number are referred to as


bits
 Each bit represents a power of two

01011 = 0 • 24 + 1 • 23 + 0 • 22 + 1 • 21 + 1 • 20
= 11

00010 = 0 • 24 + 0 • 23 + 0 • 22 + 1 • 21 + 0 • 20
= 2
00010 2 Equivalent
Binary
+ 01011 + 11 decimal
addition
01101 13 addition
Binary Arithmetic
Binary Equivalent decimal
multiplication multiplication

0101 5
× 0011 × 3
0101 15
0101
0000
0000
0001111
Two’s Complement
Representation for signed binary numbers

Leading bit is a sign bit


 Binary number with leading 0 is positive

 Binary number with leading 1 is negative

Magnitude of positive numbers is just the binary


representation

Magnitude of negative numbers is found by


 Complement the bits

 Replace all the 1's with 0's, and all the 0's with 1's

 Add one to the complemented number

The carry in the most significant bit position is thrown


away when performing arithmetic
Two’s Complement
Performing two's complement on the decimal 7 to get -7
 Using a five-bit representation

7 = 00111 Convert to binary

11000 Complement the bits

11000 Add 1 to the complement


+ 00001
11001 Result is -7 in two's complement
Two's Complement
Arithmetic
Computing 8 - 7 using a two's complement
representation with five-bit numbers

8 - 7 = 8 + (-7) = 1

01000 Two's complement of 8

11001 Two's complement of -7


Throw away the
high-order 01000 Add 8 and -7
carry as we are + 11001
using a five bit 100001
representation
00001 Is the five-bit result
Fundamentals of C++
Basic programming elements
and concepts

JPC and JWD © 2002 McGraw-Hill, Inc.


Program Organization
Program statement
 Definition

 Declaration

 Action

Executable unit
 Named set of program statements

 Different languages refer to executable units by

different names
 Subroutine: Fortran and Basic
 Procedure: Pascal
 Function : C++
Program Organization
C++ program
 Collection of definitions, declarations and functions

 Collection can span multiple files

Advantages
 Structured into small understandable units

 Complexity is reduced

 Overall program size decreases


Object
Object is a representation of some information
 Name

 Values or properties

 Data members
 Ability to react to requests (messages)!!

 Member functions
When an object receives a message, one of two actions
are performed
 Object is directed to perform an action

 Object changes one of its properties


A First Program -
Greeting.cpp
Preprocessor // Program: Display greetings
directives // Author(s): Ima Programmer
// Date: 1/24/2001 Comments
#include <iostream>
#include <string>
Provides simple access
using namespace std;
Function int main() {
named cout << "Hello world!" << endl;
main() return 0;
indicates }
start of
program
Ends executions Insertion
Function
of main() which ends statement
program
Greeting Output
#include <iostream>
using namespace std;
int main() {
Area.cpp
// Extract length and width
cout << "Rectangle dimensions: ";
float Length; Definitions
float Width;
cin >> Length >> Width; Extraction

// Compute and insert the area


Definition with
float Area = Length * Width; initialization

cout << "Area = " << Area << " = Length "
<< Length << " * Width " << Width << endl;
return 0;
}
Visual C++ IDE with
Area.cpp
Area.cpp Output
Comments
Allow prose or commentary to be included in program
Importance
 Programs are read far more often than they are

written
 Programs need to be understood so that they can be

maintained
C++ has two conventions for comments
 // single line comment (preferred)

 /* long comment */ (save for debugging)

Typical uses
 Identify program and who wrote it

 Record when program was written

 Add descriptions of modifications


Fundamental C++ Objects
C++ has a large number of fundamental or built-in
object types
The fundamental object types fall into one of three
categories
 Integer objects

 Floating-point objects Z
5 1.28345
 Character objects

1 3.14
P
Integer Object Types
The basic integer object type is int
 The size of an int depends on the machine and the

compiler
 On PCs it is normally 16 or 32 bits
Other integers object types
 short: typically uses less bits

 long: typically uses more bits

Different types allow programmers to use resources


more efficiently
Standard arithmetic and relational operations are
available for these types
Integer Constants
Integer constants are positive or negative whole
numbers
Integer constant forms
 Decimal

 Octal (base 8)

 Digits 0, 1, 2, 3, 4, 5, 6, 7
 Hexadecimal (base 16)

 Digits 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a , b, c, d, e, f, A,
B, C, D, E, F
Consider
 31 oct and 25 dec
Decimal Constants
Examples
 97
L or l indicates long
 40000L
integer
 50000

 23a (illegal)

The type of the constant depends on its size, unless


the type specifier is used
Character Object Types
Character type char is related to the integer types
Characters are encoded using a scheme where an
integer represents a particular character
ASCII is the dominant encoding scheme
 Examples

 ' ' encoded as 32 '+' encoded as 43


 'A' encoded as 65 'Z' encoded as 90
 'a' encoded as 97 'z' encoded as
122

 Appendix A gives the complete ASCII character set


Character Operations
Arithmetic and relational operations are defined for
characters types
 'a' < 'b' is true

 '4' > '3' is true

 '6' <= '2' is false


Character Constants
Explicit (literal) characters within single quotes
 'a','D','*'

Special characters - delineated by a backslash \


 Two character sequences (escape codes)
 Some important special escape codes
 \t denotes a tab \n denotes a new line
 \\ denotes a backslash \' denotes a single
quote
 \" denotes a double quote

 '\t' is the explicit tab character, '\n' is the explicit


new line character, and so on
Literal String Constants
A literal string constant is a sequence of zero or more
characters enclosed in double quotes
 "We are even loonier than you think"
 "Rust never sleeps\n"
 "Nilla is a Labrador Retriever"

Not a fundamental type


Floating-Point Object Types
Floating-point object types represent real numbers
 Integer part

 Fractional part

The number 108.1517 breaks down into the following


parts
 108 - integer part

 1517 - fractional part

C++ provides three floating-point object types


 float

 double

 long double
Floating-Point Constants
Standard decimal notation
134.123 F or f indicates single
0.15F precision floating point
value
Standard scientific notation
1.45E6 L or l indicates long double
0.979e-3L floating point value

When not specified, floating-point constants are of type


double
Names
Used to denote program values or components
A valid name is a sequence of
 Letters (upper and lowercase)

 Digits

 A name cannot start with a digit


 Underscores

 A name should not normally start with an


underscore
Names are case sensitive
 MyObject is a different name than MYOBJECT

There are two kinds of names


 Keywords

 Identifiers
Keywords
Keywords are words reserved as part of the language
 int, return, float, double

They cannot be used by the programmer to name


things

They consist of lowercase letters only

They have special meaning to the compiler


Identifiers
Identifiers should be
 Short enough to be reasonable to type (single word
is norm)
 Standard abbreviations are fine (but only
standard abbreviations)
 Long enough to be understandable
 When using multiple word identifiers capitalize
the first letter of each word
Examples
 Min

 Temperature

 CameraAngle

 CurrentNbrPoints
Definitions
All objects that are used in a program must be defined

An object definition specifies


 Type

 Name

General definition form


Known List of one or
type more identifiers

Type Id, Id, ..., Id;

 Our convention is one definition per statement!


Examples
char Response;
int MinElement; Objects are uninitialized with
float Score; this definition form
float Temperature; (Value of a object is
int i; whatever is in its
int n; assigned memory location)
char c;
float x;
Arithmetic Operators
Common
 Addition +
 Subtraction -
 Multiplication * Write m*x + b
 Division
not mx + b
/
 Mod %
Note
 No exponentiation operator

 Single division operator

 Operators are overloaded to work with more than

one type of object


Integer Division
Integer division produces an integer result
 Truncates the result

Examples
 3 / 2 evaluates to 1

 4 / 6 evaluates to 0

 10 / 3 evaluates to 3
Mod
Produces the remainder of the division

Examples
 5 % 2 evaluates to 1

 12 % 4 evaluates to 0

 4 % 5 evaluates to 4
Operators and Precedence
Consider mx + b
 Consider m*x + b which of the following is it equivalent
to
 (m * x) + b
 m * (x + b)
 Operator precedence tells how to evaluate expressions
 Standard precedence order
 () Evaluate first, if nested innermost
done first
 */% Evaluate second. If there are
several,
then evaluate from left-to-right
 +- Evaluate third. If there are several,
then evaluate from left-to-right
Operator Precedence
Examples
20 - 4 / 5 * 2 + 3 * 5 % 4

(4 / 5)
((4 / 5) * 2)
((4 / 5) * 2) (3 * 5)
((4 / 5) * 2) ((3 * 5) % 4)
(20 -((4 / 5) * 2)) ((3 * 5) % 4)
(20 -((4 / 5) * 2)) + ((3 * 5) % 4)
Defining and Initializing
When an object is defined using the basic form, the
memory allotted to it contains random information

Better idea to specify its desired value at the same time


 Exception is when the next statement is an

extraction for the object

Remember our convention of one definition per


statement!
Examples
int FahrenheitFreezing = 32;
char FinalGrade = 'A';
cout << "Slope of line: ";
float m;
cin >> m;
cout << "Intercept: ";
float b;
cin >> b;
cout << "X value of interest: ";
float x;
cin >> x;
float y = (m * x) + b;
Modifying Objects
Operators and Expressions

JPC and JWD © 2002 McGraw-Hill, Inc.


Memory Depiction
1001
float y = 12.5; 1002
y 12.5 1003
1004
Memory Depiction
1001
float y = 12.5; 1002
y 12.5 1003
int Temperature = 32;
1004
Temperature 32 1005
1006
Memory Depiction
1001
float y = 12.5; 1002
y 12.5 1003
int Temperature = 32;
1004
char Letter = 'c'; Temperature 32 1005
1006
Letter 'c' 1007
Memory Depiction
1001
float y = 12.5; 1002
y 12.5 1003
int Temperature = 32;
1004
char Letter = 'c'; 1005
Temperature 32 1006
int Number; Letter 'c' 1007
1008
Number - 1009
Assignment Statement
Target becomes source
Basic form
 object = expression ;

Celsius = (Fahrenheit - 32) * 5 / 9;


y = m * x + b;

Action
 Expression is evaluated

 Expression value stored in object


Definition
int NewStudents = 6; NewStudents 6
Definition
int NewStudents = 6; NewStudents 6
int OldStudents = 21; OldStudents 21
Definition
int NewStudents = 6; NewStudents 6
int OldStudents = 21; OldStudents 21
int TotalStudents; TotalStudents -
Assignment Statement
int NewStudents = 6; NewStudents 6
int OldStudents = 21; OldStudents 21
int TotalStudents; TotalStudents ?

TotalStudents = NewStudents + OldStudents;


Assignment Statement
int NewStudents = 6; NewStudents 6
int OldStudents = 21; OldStudents 21
int TotalStudents; TotalStudents 27

TotalStudents = NewStudents + OldStudents;


Assignment Statement
int NewStudents = 6; NewStudents 6
int OldStudents = 21; OldStudents ?
int TotalStudents; TotalStudents 27

TotalStudents = NewStudents + OldStudents;

OldStudents = TotalStudents;
Assignment Statement
int NewStudents = 6; NewStudents 6
int OldStudents = 21; OldStudents 27
int TotalStudents; TotalStudents 27

TotalStudents = NewStudents + OldStudents;

OldStudents = TotalStudents;
Consider
int Value1 = 10; Value1 10
Consider
int Value1 = 10; Value1 10
int Value2 = 20; Value2 20
Consider
int Value1 = 10; Value1 10
int Value2 = 20; Value2 20
int Hold = Value1; Hold 10
Consider
int Value1 = 10; Value1 ?
int Value2 = 20; Value2 20
int Hold = Value1; Hold 10

Value1 = Value2;
Consider
int Value1 = 10; Value1 20
int Value2 = 20; Value2 20
int Hold = Value1; Hold 10

Value1 = Value2;
Consider
int Value1 = 10; Value1 20
int Value2 = 20; Value2 ?
int Hold = Value1; Hold 10

Value1 = Value2;

Value2 = Hold;
Consider
int Value1 = 10; Value1 20
int Value2 = 20; Value2 10
int Hold = Value1; Hold 10

Value1 = Value2;

Value2 = Hold;

We swapped the values of objects Value1 and Value2


using Hold as temporary holder for Value1’s starting
value!
Incrementing
int i = 1;
i 1
Incrementing
int i = 1;
i 1

i = i + 1; i 2

Assign the value of expression i + 1 to i

Evaluates to 2
Const Definitions
Modifier const indicates that an object cannot be
changed
 Object is read-only

Useful when defining objects representing physical and


mathematical constants
const float Pi = 3.1415;

Value has a name that can be used throughout the


program
const int SampleSize = 100;

Makes changing the constant easy


 Only need to change the definition and recompile
Assignment Conversions
Floating-point expression assigned to an integer object
is truncated

Integer expression assigned to a floating-point object is


converted to a floating-point value

Consider
float y = 2.7;
int i = 15;
int j = 10;
i = y; // i is now 2
cout << i << endl;
y = j; // y is now 10.0
cout << y << endl;
Nonfundamental Types
Nonfundamental as they are additions to the language
 C++ permits definition of new types and classes
 A class is a special kind of type
 Class objects typically have
 Data members that represent attributes and values
 Member functions for object inspection and
manipulation
 Members are accessed using the selection operator
(.)
j = s.size();
 Auxiliary functions for other behaviors
 Libraries often provide special-purpose types and
classes
Examples
Standard Template Library (STL) provides class string

EzWindows library provides several graphical types and


classes
 SimpleWindow is a class for creating and
manipulating window objects
 RectangleShape is a class for creating and
manipulating rectangle objects
Class string
Class string
 Used to represent a sequence of characters as a

single object
Some definitions
string Name = "Joanne";
string DecimalPoint = ".";
string empty = "";
string copy = name;
string Question = '?'; // illegal
Nonfundamental Types
To access a library use a preprocessor directive to add
its definitions to your program file
#include <string>
The using statement makes syntax less clumsy
 Without it

std::string s = "Sharp";
std::string t = "Spiffy";
 With it

using namespace std; // std contains string


string s = "Sharp";
string t = "Spiffy";
EzWindows Library Objects
Definitions are the same form as other objects
Example
SimpleWindow W;
 Most non-fundamental classes have been created so
that an object is automatically initialized to a
sensible value

SimpleWindow objects have member functions to


process messages to manipulate the objects
 Most important member function is Open() which

causes the object to be displayed on the screen


 Example
W.Open();
Initialization
Class objects may have several attributes to initialize

Syntax for initializing an object with multiple attributes


Type Identifier(Exp1, Exp2, ..., Expn);

SimpleWindow object has several optional attributes


SimpleWindow W("Window Fun", 8, 4);
 First attribute
 Window banner
 Second attribute
 Width of window in centimeters
 Third attribute
 Height of window in centimeters
An EzWindows Program
#include <iostream>
using namespace std;
#include "ezwin.h"
int ApiMain() {
SimpleWindow W("A Window", 12, 12);
W.Open();

cout << "Enter a character to exit" << endl;


char a;
cin >> a;

return 0;
}
An EzWindows Project File
An EzWindows Project File
Sample Display Behavior
RectangleShape Objects
EzWindows also provides RectangleShape for manipulating
rectangles
RectangleShape objects can specify the following attributes
 SimpleWindow object that contains the rectangle
(mandatory)
 Offset from left edge of the SimpleWindow
 Offset from top edge of the SimpleWindow
 Offsets are measured in centimeters from rectangle
center
 Width in centimeters
 Height in centimeters
 Color
RectangleShape Objects
Examples
SimpleWindow W1("My Window", 20, 20);
SimpleWindow W2("My Other Window", 15, 10);

RectangleShape R(W1, 4, 2, Blue, 3, 2);


RectangleShape S(W2, 5, 2, Red, 1, 1);
RectangleShape T(W1, 3, 1, Black, 4, 5);
RectangleShape U(W1, 4, 9);
RectangleShape Objects
Some RectangleShape member functions for processing
messages
 Draw()
 Causes rectangle to be displayed in its associated
window
 GetWidth()
 Returns width of object in centimeters
 GetHeight()
 Returns height of object in centimeters
 SetSize()
 Takes two attributes -- a width and height -- that
are used to reset dimensions of the rectangle
Another EzWindows Program
#include <iostream>
using namespace std;
#include "rect.h"
int ApiMain() {
SimpleWindow W("Rectangular Fun", 12, 12);
W.Open();
RectangleShape R(W, 5.0, 2.5, Blue, 1, 2);
R.Draw();
cout << "Enter a character to exit" << endl;
char Response;
cin >> Response;
return 0;
}
Sample Display Behavior
Compound Assignment
C++ has a large set of operators for applying an
operation to an object and then storing the result back
into the object

Examples
int i = 3;
i += 4; // i is now 7
cout << i << endl;

float a = 3.2;
a *= 2.0; // a is now 6.4
cout << a << endl;
Increment and Decrement
C++ has special operators for incrementing or
decrementing an object by one
Examples
int k = 4;
++k; // k is 5
k++; // k is 6
cout << k << endl;
int i = k++; // i is 6, k is 7
cout << i << " " << k << endl;
int j = ++k; // j is 8, k is 8
cout << j << " " << k << endl;
Class string
Some string member functions
 size() determines number of characters in the string
string Saying = "Rambling with Gambling";
cout << Saying.size() << endl; // 22
 substr() determines a substring (Note first position has
index 0)
string Word = Saying.substr(9, 4); // with
 find() computes the position of a subsequence
int j = Saying.find("it"); // 10
int k = Saying.find("its"); // ?
Class string
Auxiliary functions and operators
 getline() extracts the next input line
string Response;
cout << "Enter text: ";
getline(cin, Response, '\n');
cout << "Response is \"" << Response
<< "\"” << endl;
 Example run
Enter text: Want what you do
Response is "Want what you do"
Class string
Auxiliary operators
 + string concatenation
string Part1 = "Me";
string Part2 = " and ";
string Part3 = "You";
string All = Part1 + Part2 + Part3;
 += compound concatenation assignment
string ThePlace = "Brooklyn";
ThePlace += ", NY";
#include <iostream>
using namespace std;
int main() {
cout << "Enter the date in American format: "
<< "(e.g., January 1, 2001) : ";
string Date;
getline(cin, Date, '\n');
int i = Date.find(" ");
string Month = Date.substr(0, i);
int k = Date.find(",");
string Day = Date.substr(i + 1, k - i - 1);
string Year = Date.substr(k + 2, Date.size() - 1);
string NewDate = Day + " " + Month + " " + Year;
cout << "Original date: " << Date << endl;
cout << "Converted date: " << NewDate << endl;
return 0;
}
If Control Construct
A mechanism for deciding
whether an action should be
taken

JPC and JWD © 2002 McGraw-Hill, Inc.


Boolean Algebra
Logical expressions have the one of two values - true or
false
 A rectangle has three sides

 The instructor has a pleasant smile

The branch of mathematics is called Boolean algebra


 Developed by the British mathematician George

Boole in the 19th century

Three key logical operators


 And

 Or

 Not
Boolean Algebra
Truth tables
 Lists all combinations of operand values and the

result of the operation for each combination

Example

P Q P and Q

False False False


False True False
True False False
True True True
Boolean Algebra
Or truth table

P Q P or Q

False False False


False True True
True False True
True True True
Boolean Algebra
Not truth table

P not P

False True
True False
Boolean Algebra
Can create complex logical expressions by combining
simple logical expressions

Example
 not (P and Q)

A truth table can be used to determine when a logical


expression is true
P Q P and Q not (P and Q)

False False False True


False True False True
True False False True
True True True False
A Boolean Type
C++ contains a type named bool
Type bool has two symbolic constants
 true

 false

Boolean operators
 The and operator is &&

 The or operator is ||

 The not operator is !

Warning
 & and | are also operators so be careful what you

type
A Boolean Type
Example logical expressions

bool P = true;
bool Q = false;
bool R = true;
bool S = (P && Q);
bool T = ((!Q) || R);
bool U = !(R && (!Q));
Relational Operators
Equality operators
 ==

 !=

Examples
 int i = 32;

 int k = 45;

 bool q = (i == k);

 bool r = (i != k);
Relational Operators
Ordering operators
 <

 >

 >=

 <=

Examples
 int i = 5;

 int k = 12;

 bool p = (i < 10);


 bool q = (k > i);
 bool r = (i >= k);
 bool s = (k <= 12);
Operator Precedence
Revisited
Precedence of operators (from highest to lowest)
 Parentheses
 Unary operators
 Multiplicative operators
 Additive operators
 Relational ordering
 Relational equality
 Logical and
 Logical or
 Assignment
Operator Precedence
Revisited
Consider
5 * 15 + 4 == 13 && 12 < 19 || !false == 5 < 24
Operator Precedence
Revisited
Consider
5 * 15 + 4 == 13 && 12 < 19 || !false == 5 < 24

Yuck! Do not write expressions like this!


Operator Precedence
Revisited
 Consider
5 * 15 + 4 == 13 && 12 < 19 || !false == 5 < 24

 However, for your information it is equivalent to


((((5 *15) + 4) == 13) && (12 < 19))
||
((!false) == (5 < 24))
Conditional Constructs
Provide
 Ability to control whether a statement list is

executed

Two constructs
 If statement
 if
 if-else
 if-else-ef

 Switch statement
 Left for reading
The Basic If Statement
Syntax
if (Expression)
Action
Expression
If the Expression is true then
execute Action
true false

Action is either a single


statement or a group of Action
statements within braces
Example
if (Value < 0) {
Is our number negative?
Value = -Value;
}
If Value is less than Value < 0
zero then we need to
update its value to
true false
that of its additive
inverse If Value is not less
than zero then our
Value = -Value number is fine as is

Our number is
now definitely
nonnegative
Sorting Two Numbers
cout << "Enter two integers: ";
int Value1;
int Value2;
cin >> Value1 >> Value2;
if (Value1 > Value2) {
int RememberValue1 = Value1;
Value1 = Value2;
Value2 = RememberValue1;
}
cout << "The input in sorted order: "
<< Value1 << " " << Value2 << endl;
Semantics Are the numbers
out of order
Rearrange value1
and value2 to value2 < value1
put their values
in the proper
order true false

int rememberValue1 = value1


value1 = value2
value2 = rememberValue1

The numbers were


rearranged into the
proper order
The numbers were
initially in order
The numbers are in
order
What is the Output?
int m = 5;
int n = 10;

if (m < n)
++m;
++n;

cout << " m = " << m << " n = " n << endl;
The If-Else Statement
Syntax

if (Expression)
Action1
else
Action2 Expression
If Expression is true then execute
Action1 otherwise execute Action2 true false

if (v == 0) {
cout << "v is 0"; Action1 Action2
}
else {
cout << "v is not 0";
}
Finding the Max
cout << "Enter two integers: ";
int Value1;
int Value2;
cin >> Value1 >> Value2;
int Max;
if (Value1 < Value2) {
Max = Value2;
}
else {
Max = Value1;
}
cout << "Maximum of inputs is: " << Max << endl;
Finding the Max Is Value2 larger than Value1

Yes, it is . So Value2 is
larger than Value1. In
this case, Max is set No, its not. So Valu
to Value2 is at least as large a
Value2. In this case
Value1 < Value2 Max is set to Value
true false

Max = Value2 Max = Value1

Either case, Max is set


correctly
Selection
It is often the case that depending upon the value of an
expression we want to perform a particular action

Two major ways of accomplishing this choice


 if-else-if statement
 if-else statements “glued” together

 Switch statement
 An advanced construct
An If-Else-If Statement
if ( nbr < 0 ){
cout << nbr << " is negative" << endl;
}
else if ( nbr > 0 ) {
cout << nbr << " is positive" << endl;
}
else {
cout << nbr << " is zero" << endl;
}
A Switch Statement
switch (ch) {
case 'a': case 'A':
case 'e': case 'E':
case 'i': case 'I':
case 'o': case 'O':
case 'u': case 'U':
cout << ch << " is a vowel" << endl;
break;
default:
cout << ch << " is not a vowel" << endl;
}
cout << "Enter simple expression: ";
int Left;
int Right;
char Operator;
cin >> Left >> Operator >> Right;
cout << Left << " " << Operator << " " << Right
<< " = ";
switch (Operator) {
case '+' : cout << Left + Right << endl; break;
case '-' : cout << Left - Right << endl; break;
case '*' : cout << Left * Right << endl; break;
case '/' : cout << Left / Right << endl; break;
default: cout << "Illegal operation" << endl;
}
Iterative Constructs
Mechanisms for deciding under
what conditions an action should
be repeated

JPC and JWD © 2002 McGraw-Hill, Inc.


Averaging
Determining Average
Magnitude
Suppose we want to calculate the average apparent
brightness of a list of five star magnitude values
 Can we do itit?
 Yes, it would be easy

Suppose we want to calculate the average apparent


brightness of a list of 8,479 stars visible from earth
 Can we do it

 Yes, but it would be gruesome without the use of


iteration
C++ Iterative Constructs
Three constructs
 while statement

 for statement

 do-while statement
While Syntax

Logical expression that determines Action to be iteratively


whether the action is to be executed performed until logical
expression is false

while ( Expression ) Action


While Semantics Expression is
evaluated at the
start of each
iteration of the
loop

Expression
If Expression is
true, Action is true false
executed If Expression is
false, program
Action execution
continues with
next statement
Computing an Average
int listSize = 4;
int numberProcessed = 0;
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4

int listSize = 4;
int numberProcessed = 0;
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 0
int listSize = 4;
int numberProcessed = 0;
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 0
int listSize = 4; sum 0
int numberProcessed = 0;
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 0
int listSize = 4; sum 0
int numberProcessed = 0;
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 0
int listSize = 4; sum 0
int numberProcessed = 0; value --
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 0
int listSize = 4; sum 0
int numberProcessed = 0; value 1
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 0
int listSize = 4; sum 0
1
int numberProcessed = 0; value 1
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 0
1
int listSize = 4; sum 1
int numberProcessed = 0; value 1
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 1
int listSize = 4; sum 1
int numberProcessed = 0; value 1
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 1
int listSize = 4; sum 1
int numberProcessed = 0; value --
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 1
int listSize = 4; sum 1
int numberProcessed = 0; value 5
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 1
int listSize = 4; sum 1
6
int numberProcessed = 0; value 5
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 1
2
int listSize = 4; sum 6
int numberProcessed = 0; value 5
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 2
int listSize = 4; sum 6
int numberProcessed = 0; value 5
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 2
int listSize = 4; sum 6
int numberProcessed = 0; value --
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 2
int listSize = 4; sum 6
int numberProcessed = 0; value 3
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 2
int listSize = 4; sum 6
9
int numberProcessed = 0; value 3
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 2
3
int listSize = 4; sum 9
int numberProcessed = 0; value 3
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 3
int listSize = 4; sum 9
int numberProcessed = 0; value 3
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 3
int listSize = 4; sum 9
int numberProcessed = 0; value --
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 3
int listSize = 4; sum 9
int numberProcessed = 0; value 1
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 3
int listSize = 4; sum 10
9
int numberProcessed = 0; value 1
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 3
4
int listSize = 4; sum 10
int numberProcessed = 0; value 1
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 3
4
int listSize = 4; sum 10
int numberProcessed = 0; value 1
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 3
4
int listSize = 4; sum 10
int numberProcessed = 0; average 2.5
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace listSize 4
numberProcessed 3
4
int listSize = 4; sum 10
int numberProcessed = 0; average 2.5
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Suppose input contains: 1 5 3 1
6
Execution Trace
Stays in stream until
int listSize = 4; extracted
int numberProcessed = 0;
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Power of Two Table
const int TableSize = 20;

int i = 0;
long Entry = 1;

cout << "i" << "\t\t" << "2 ** i" << endl;

while (i < TableSize) {


cout << i << "\t\t" << Entry << endl;
Entry = 2 * Entry;
++i;
}
Better Way of Averaging
int numberProcessed = 0; The value of the input
operation corresponds to
double sum = 0;
true only if a successful
double value; extraction was made
while ( cin >> value ) {
sum += value; What if list is
++numberProcessed; empty?
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
Even Better Way of
Averaging
int numberProcessed = 0;
double sum = 0;
double value;
while ( cin >> value ) {
sum += value;
++numberProcessed;
}
if ( numberProcessed > 0 ) {
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
}
else {
cout << "No list to average" << endl;
}
The For Statement
Syntax
for (ForInit ; ForExpression; PostExpression)
Action

Example
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
Evaluated once
at the beginning
of the for
statements's ForInit
The ForExpr is
execution evaluated at the
start of each
iteration of the
loop
If ForExpr is ForExpr
true, Action is
executed true false

After the Action If ForExpr is


has completed, Action
false, program
the execution
PostExpression continues with
is evaluated next statement

PostExpr

After evaluating the


PostExpression, the next
iteration of the loop starts
Execution Trace
i 0
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
Execution Trace
i 0
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
Execution Trace
i 0
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
Execution Trace
i 0
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
Execution Trace
i 1
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
Execution Trace
i 1
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
Execution Trace
i 1
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
Execution Trace
i 1
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
Execution Trace
i 2
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
Execution Trace
i 2
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
Execution Trace
i 2
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
i is 2
Execution Trace
i 2
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
i is 2
Execution Trace
i 3
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
i is 2
Execution Trace
i 3
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
i is 2
Execution Trace
i 3
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;

i is 0
i is 1
i is 2
all done
Table Revisiting
const int TableSize = 20;

long Entry = 1;

cout << "i" << "\t\t" << "2**i" << endl;

for (int i = 0; i <= TableSize; ++i) {


cout << i << "\t\t" << Entry << endl;
Entry *= 2;
}
Table Revisiting
const int TableSize = 20;

long Entry = 1;

cout << "i" << "\t\t" << "2**i" << endl;

for (int i = 0; i < TableSize; ++i) {


cout << i << "\t\t" << Entry << endl;
Entry = 2 * Entry;
}

cout << "i is" << i << endl; // illegal

The scope of i is limited


to the loop!
Displaying a Diagonal
SimpleWindow W("One diagonal", 5.5, 2.25);
W.Open();
for (int j = 1; j <= 3; ++j) {
float x = j * 0.75 + 0.25;
float y = j * 0.75 - 0.25;
float Side = 0.4;
RectangleShape S(W, x, y, Blue, Side, Side);
S.Draw();
}
Sample Display
Displaying Three Diagonals
SimpleWindow W("Three diagonals", 6.5, 2.25);
W.Open();
for (int i = 1; i <= 3; ++i) {
for (int j = 1; j <= 3; ++j) {
float x = i - 1 + j * 0.75 + 0.25;
float y = j * 0.75 - 0.25;
float Side = 0.4;
RectangleShape S(W, x, y, Blue, Side, Side);
S.Draw();
}
} The scope of i includes the inner loop.
The scope of j is just the inner loop.
Sample Display
int Counter1 = 0;
int Counter2 = 0;
int Counter3 = 0;
int Counter4 = 0;
int Counter5 = 0;

++Counter1;
for (int i = 1; i <= 10; ++i) {

++Counter2;

for (int j = 1; j <= 20; ++j) {


++Counter3;
}
++Counter4;
}
++Counter5;
cout << Counter1 << " " << Counter2 << " "
<< Counter3 << " " << Counter4 << " "
<< Counter5 << endl;
For Into While
Observation
 The for statement is equivalent to

{
ForInit;
while (ForExpression) {
Action;
PostExpression;
}
}
Counting Characters
int NumberOfNonBlanks = 0;
int NumberOfUpperCase = 0;
char c; Only extracts
while (cin >> c) { nonblank characters
++NumberOfNonBlanks;
if ((c >= 'A') && (c <= 'Z')) {
++NumberOfUpperCase;
}
}
cout << "Nonblank characters: " << NumberOfNonBlanks
<< endl << "Uppercase characters: "
<< NumberOfUpperCase << endl;
Counting All Characters
char c;
int NumberOfCharacters = 0;
int NumberOfLines = 0;
Extracts all
while ( cin.get(c) ) { characters
++NumberOfCharacters;
if (c == '\n') {
++NumberOfLines
}
}
cout << "Characters: " << NumberOfCharacters
<< endl << "Lines: " << NumberOfLines
<< endl;
#include <iostream>
#include <fstream>
using namespace std;
File Processing
int main() {
ifstream fin("mydata.txt");
int ValuesProcessed = 0;
float ValueSum = 0;
float Value;
while ( fin >> Value ) {
ValueSum += Value;
++ValuesProcessed;
}
if (ValuesProcessed > 0) {
ofstream fout("average.txt");
float Average = ValueSum / ValuesProcessed;
fout << "Average: " << Average << endl;
return 0;
}
else {
cerr << "No list to average" << endl;
return 1;
}
}
Iteration Do’s
Key Points
 Make sure there is a statement that will eventually

terminate the iteration criterion


 The loop must stop!
 Make sure that initialization of loop counters or

iterators is properly performed


 Have a clear purpose for the loop

 Document the purpose of the loop


 Document how the body of the loop advances the
purpose of the loop
The Do-While Statement
Syntax
do Action
while (Expression)
Semantics Action
 Execute Action

 If Expression is true

then execute Action true


again
 Repeat this process

until Expression Expression


evaluates to false
Action is either a single
statement or a group of false
statements within braces
Waiting for a Proper Reply
char Reply;
do {
cout << "Decision (y, n): ";
if (cin >> Reply)
Reply = tolower(Reply);
else
Reply = 'n';
} while ((Reply != 'y') && (Reply != 'n'));
Libraries
Computational assistants

JPC and JWD © 2002 McGraw-Hill, Inc.


Functions
 Previous examples
 Programmer-defined functions
 main()
 ApiMain()
 Library-defined functions
 cin.get()
 string member functions size()
 RectangleShape member function Draw()
 SimpleWindow member function Open()
Advice
 Don’t reinvent the wheel! There are lots of libraries out

there
Terminology
A function is invoked by a function call / function
invocation

y = f(a);
Terminology
A function call specifies
 The function name

 The name indicates what function is to be called

y = f(a);

 The actual parameters to be used in the invocation


 The values are the information that the called
function requires from the invoking function to do
its task

y = f(a);
Terminology
A function call produces a return value
 The return value is the value of the function call

y = f(a);
Invocation Process
Flow of control is temporarily transferred to the invoked
function
 Correspondence established between actual

parameters of the invocation with the formal


parameters of the definition

cout << "Enter number: ";


double f(double x) {
double a;
double result =
cin >> a;
y = f(a); x*x + 2*x + 5;
cout << y; return result;
 Value of a is given to x }
Invocation Process
Flow of control is temporarily transferred to the invoked
function
 Local objects are also maintained in the invocation’s

activation record. Even main() has a record

cout << "Enter number: ";


double a;
cin >> a; double f(double x) {
y = f(a); double result =
cout << y;
x*x + 2*x + 5;
 Activation record is large
enough to store values return result;
associated with each object
that is defined by the function}
Invocation Process
Flow of control is temporarily transferred to the invoked
function
 Other information may also be maintained in the

invocation’s activation record

cout << "Enter number: ";


double a;
cin >> a; double f(double x) {
y = f(a); double result =
cout << y;
x*x + 2*x + 5;
 Possibly a pointer to the
current statement being return result;
executed and a pointer to
the invoking statement }
Invocation Process
Flow of control is temporarily transferred to the invoked
function
 Next statement executed is the first one in the

invoked function

cout << "Enter number: ";


double a; double f(double x) {
cin >> a;
double result =
y = f(a);
x*x + 2*x + 5;
cout << y;
return result;
}
Invocation Process
Flow of control is temporarily transferred to the invoked
function
 After function completes its action, flow of control is

returned to the invoking function and the return


value is used as value of invocation
cout << "Enter number: ";
double a; double f(double x) {
cin >> a;
double result =
y = f(a);
x*x + 2*x + 5;
cout << y;
return result;
}
Execution Process
Function body of invoked function is executed

Flow of control then returns to the invocation statement

The return value of the invoked function is used as the


value of the invocation expression
Function Prototypes
Before a function can appear in an invocation its
interface must be specified
 Prototype or complete definition

Type of value that A description of the form the


the function returns parameters (if any) are to take
Identifier name of
function

FunctionType FunctionName ( ParameterList )

int Max(int a, int b)


Function Prototypes
Before a function can appear in an invocation its
interface must be specified
 Prototypes are normally kept in library header files

Type of value that A description of the form the


the function returns parameters (if any) are to take
Identifier name of
function

FunctionType FunctionName ( ParameterList )

int Max(int a, int b)


Libraries
Library
 Collection of functions, classes, and objects grouped

by commonality of purpose
 Include statement provides access to the names and

descriptions of the library components


 Linker connects program to actual library definitions

Previous examples
 String: STL’s string class

 Graphics: EzWindows
Basic Translation Process
Source program

Link object file


Process Check with standard
preprocessor translation object files
directives to unit for legal and other
produce a syntax and object files to
translation compile it into produce an
unit an object file executable
unit

Executable Unit
Some Standard Libraries
fstream
 File stream processing

assert
 C-based library for assertion processing

iomanip
 Formatted input/output (I/O) requests

ctype
 C-based library for character manipulations

math
 C-based library for trigonometric and logarithmic

functions

Note

Library Header Files
Describes library components

Typically contains
 Function prototypes

 Interface description
 Class definitions

Sometimes contains
 Object definitions

 Example: cout and cin in iostream


Library Header Files
Typically do not contain function definitions
 Definitions are in source files

 Access to compiled versions of source files provided

by a linker
#include <iostream>
#include <cmath> Library header files
using namespace std;
int main() {
cout << "Enter Quadratic coefficients: ";
double a, b, c;
cin >> a >> b >> c; Invocation
if ( (a != 0) && (b*b - 4*a*c > 0) ) {
double radical = sqrt(b*b - 4*a*c);
double root1 = (-b + radical) / (2*a);
double root2 = (-b - radical) / (2*a);
cout << "Roots: " << root1 << " " << root2;
}
else {
cout << "Does not have two real roots";
}
return 0;
}
#include <iostream>
#include <fstream> // file stream library
using namespace std;
int main() {
ifstream fin("mydata.txt");
int ValuesProcessed = 0;
float ValueSum = 0;
float Value;
while (fin >> Value) {
ValueSum += Value;
++ValuesProcessed;
}
if (ValuesProcessed > 0) {
ofstream fout("average.txt");
float Average = ValueSum / ValuesProcessed;
fout << "Average: " << Average << endl;
return 0;
}
else {
cerr << "No list to average" << endl;
return 1;
}
}
ifstream sin("in1.txt"); // extract from in1.txt
ofstream sout("out1.txt"); // insert to out1.txt
string s;
while (sin >> s) {
sout << s << endl;
}
sin.close(); // done with in1.txt
sout.close(); // done with out1.txt
sin.open("in2.txt"); // now extract from in2.txt
sout.open("out.txt", // now append to out2.txt
(ios_base::out | ios_base::app));
while (sin >> s) {
sout << s << endl;
}
sin.close(); // done with in2.txt
sout.close(); // done with out2.txt
Programmer-defined
Functions
Development of simple
functions using value and
reference parameters

JPC and JWD © 2002 McGraw-Hill, Inc.


Function Definition
Includes description of the interface and the function
body
 Interface

 Similar to a function prototype, but parameters’


names are required
 Body

 Statement list with curly braces that comprises its


actions
 Return statement to indicate value of invocation
Function Definition
Return type Function name Formal parameter

float CircleArea (float r) {


Local const float Pi = 3.1415;
object return Pi * r * r;
definition }

Return statement Function body


Function Invocation

Actual parameter

cout << CircleArea(MyRadius) << endl;

To process the invocation, the function that contains the


insertion statement is suspended and CircleArea() does its
job. The insertion statement is then completed using the value
supplied by CircleArea().
Simple Programs
Single file
 Include statements

 Using statements

 Function prototypes

 Function definitions

 Functions use value parameter passing


 Also known as pass by value or call by value
 The actual parameter is evaluated and a copy is
given to the invoked function
#include <iostream>
using namespace std;
float CircleArea(float r);
// main(): manage circle computation
int main() {
cout << "Enter radius: ";
float MyRadius;
cin >> MyRadius;
float Area = CircleArea(MyRadius);
cout << "Circle has area " << Area;
return 0;
}
// CircleArea(): compute area of radius r circle
float CircleArea(float r) {
const float Pi = 3.1415;
return Pi * r * r;
}
Value Parameter Rules
Formal parameter is created on function invocation and
it is initialized with the value of the actual parameter

 Changes to formal parameter do not affect actual


parameter

 Reference to a formal parameter produces the value for


it in the current activation record

 New activation record for every function invocation


 Formal parameter name is only known within its
function

 Formal parameter ceases to exist when the function


completes
Information to function
can come from
parameters or an input
stream

Parameters

Input stream Output stream


Function data
data

Return
value
Information from
function can come
through a return
value or an output
stream
PromptAndRead()
// PromptAndRead(): prompt and extract next
// integer

int PromptAndRead() {
cout << "Enter number (integer): ";
int Response;
cin >> Response;

return Response;
}
Sum()
// Sum(): compute sum of integers in a ... b
int Sum(int a, int b) {
int Total = 0;
for (int i = a; i <= b; ++i) {
Total += i;
}
return Total;
}
Problem
Definition
 Input two numbers that represent a range of integers

and display the sum of the integers that lie in that


range

Design
 Prompt user and read the first number

 Prompt user and read the second number

 Calculate the sum of integers in the range

smaller...larger by adding in turn each integer in that


range
 Display the sum
Range.cpp
#include <iostream>
using namespace std;
int PromptAndRead();
int Sum(int a, int b);
int main() {
int FirstNumber = PromptAndRead();
int SecondNumber = PromptAndRead();
int RangeSum = Sum(FirstNumber , SecondNumber);
cout << "The sum from " << FirstNumber
<< " to " << SecondNumber
<< " is " << RangeSum << endl;
return 0;
}
Range.cpp
// PromptAndRead(): prompt & extract next integer
int PromptAndRead() {
cout << "Enter number (integer): ";
int Response;
cin >> Response;
return Response;
}
// Sum(): compute sum of integers in a ... b
int Sum(int a, int b) {
int Total = 0;
for (int i = a; i <= b; ++i) {
Total += i;
}
return Total;
}
Blocks and Local Scope
 A block is a list of statements within curly braces
 Blocks can be put anywhere a statement can be put
 Blocks within blocks are nested blocks
 An object name is known only within the block in which
it is defined and in nested blocks of that block
 A parameter can be considered to be defined at the
beginning of the block corresponding to the function
body
Local Object Manipulation
void f() {
int i = 1;
cout << i << endl; // insert 1
{
int j = 10;
cout << i << j << endl; // insert 1 10
i = 2;
cout << i << j << endl // insert 2 10
}
cout << i << endl; // insert 2
cout << j << endl; // illegal
}
Name Reuse
If a nested block defines an object with the same name
as enclosing block, the new definition is in effect in the
nested block
However, Don’t Do This At
Home
void f() {
{
int i = 1;
cout << i << endl; // insert 1
{
cout << i << endl; // insert 1
char i = 'a';
cout << i << endl; // insert a
}
cout << i << endl; // insert 1
}
cout << i << endl; // illegal insert
}
Global Scope
Objects not defined within a block are global objects

 A global object can be used by any function in the file


that is defined after the global object
 It is best to avoid programmer-defined global objects

 Exceptions tend to be important constants

Global objects with appropriate declarations can even


be used in other program files
 cout, cin, and cerr are global objects that are

defined in by the iostream library

 Local objects can reuse a global object's name


 Unary scope operator :: can provide access to global
object even if name reuse has occurred
Don’t Do This At Home Either
int i = 1;
int main() {
cout << i << endl; // insert 1
{
char i = 'a';
cout << i << endl; // insert a
::i = 2;
cout << i << endl; // insert a
cout << ::i << endl; // insert 2
}
cout << i << endl;
return 0;
}
Consider
int main() {
int Number1 = PromptAndRead();
int Number2 = PromptAndRead();
if (Number1 > Number2) {
Swap(Number1, Number2);
}
cout << "The numbers in sorted order:"
<< Number1 << ", " << Number2 << endl;
return 0;
}
Using
void Swap(int a, int b) {
int Temp = a;
a = b;
b = Temp;
return;
}
Doesn’t do what we want!
Consider
A parameter passing style where
 Changes to the formal parameter change the actual

parameter
That would work!
Reference Parameters
If the formal argument declaration is a reference
parameter then
 Formal parameter becomes an alias for the actual

parameter
 Changes to the formal parameter change the
actual parameter
 Function definition determines whether a parameter’s
passing style is by value or by reference
 Reference parameter form
ptypei &pnamei

void Swap(int &a, int &b)


Reconsider
int main() {
int Number1 = PromptAndRead();
int Number2 = PromptAndRead();
if (Number1 > Number2) {
Swap(Number1, Number2);
}
cout << "The numbers in sorted order: "
<< Number1 << ", " << Number2 << endl;
return 0;
}
Using
void Swap(int &a, int &b) {
int Temp = a;
a = b;
b = Temp;
return; Passed by reference -- in an
} invocation the actual
parameter is given rather
than a copy

Return statement not


necessary for void functions
Consider
int i = 5; void Swap(int &a, int &b) {
int j = 6; int Temp = a;
Swap(i, j); a = b;
int a = 7; b = Temp;
int b = 8; return;
Swap(b, a); }
Extraction
Function to extract a value from a given stream

void GetNumber(int &MyNumber, istream &sin) {


sin >> MyNumber;
return;
}

Why is MyNumber a
reference parameter? Why is the stream a
reference parameter?
Getnum.cpp
int main() {
ifstream fin("mydata.txt");
int Number1;
int Number2;
cout << "Enter number: ";
GetNumber(Number1, cin);
// not needed: cout << "Enter number: ";
GetNumber(Number2, fin);
if (Number1 > Number2) {
Swap(Number1, Number2);
}
cout << "The numbers in sorted order: "
<< Number1 << ", " << Number2 << endl;
return 0;
}
Constant Parameters
The const modifier can be applied to formal parameter
declarations
 const indicates that the function may not modify the

parameter
void PromptAndGet(int &n, const string &s) {
cout << s ;
cin >> n ;
// s = "Got it"; // illegal assignment
} // caught by compiler

 Sample invocation
int x;
PromptAndGet(x, "Enter number (n): ");
Constant Parameters
Usefulness
 When we want to pass an object by reference, but

we do not want to let the called function modify the


object

Question
 Why not just pass the object by value?

Answer
 For
? large objects, making a copy of the object can be
very inefficient
Passing Constant Rectangles
void DrawBoxes(const RectangleShape &R1,
const RectangleShape &R2) {
R1.Draw();
R2.Draw();
}

int ApiMain() {
SimpleWindow Demo("Demo Program");
Demo.Open();
RectangleShape Rect1(Demo, 3, 2, Blue);
RectangleShape Rect2(Demo, 6, 5, Yellow);
DrawBoxes(Rect1, Rect2);
return 0;
}
Default Parameters
Observations
 Our functions up to this point required that we

explicitly pass a value for each of the function


parameters
 It would be convenient to define functions that

accept a varying number of parameters

Default parameters
 Allows programmer to define a default behavior

 A value for a parameter can be implicitly passed


 Reduces need for similar functions that differ only
in the number of parameters accepted
Default Parameters
If the formal argument declaration is of the form

ptypei pnamei = dvaluei

then

If there is no ith argument in the function invocation,
pnamei is initialized to dvaluei
 The parameter pnamei is an optional value
parameter

 Optional reference parameters are also permitted


Consider
void PrintChar(char c = '=', int n = 80) {
for (int i = 0; i < n; ++i)
cout << c;
}

What happens in the following invocations?

PrintChar('*', 20);
PrintChar('-');
PrintChar();
Default Parameters
Default parameters must appear after any mandatory
parameters

Bad example
void Trouble(int x = 5, double z, double y) {
...
}

Cannot come before


mandatory parameters
Default Parameters
Consider
bool GetNumber(int &n, istream &sin = cin) {
return sin >> n ;
}
Some possible invocations
int x, y, z;
ifstream fin("Data.txt");
GetNumber(x, cin);
GetNumber(y);
GetNumber(z, fin);

Design your functions for ease and reuse!


Function Overloading
A function name can be overloaded
 Two functions with the same name but with different

interfaces
 Typically this means different formal parameter
lists
 Difference in number of parameters

Min(a, b, c)
Min(a, b)
 Difference in types of parameters

Min(10, 20)
Min(4.4, 9.2)
Function Overloading
int Min(int a, int b) {
cout << "Using int min()" << endl;
if (a > b)
return b;
else
return a;
}
double Min(double a, double b) {
cout << "Using double min()" << endl;
if (a > b)
return b;
else
return a;
}
Function Overloading
int main() {
int a = 10;
int b = 20;
double x = 4.4;
double y = 9.2;
int c = Min(a, b);
cout << "c is " << c << endl;
int z = Min(x, y);
cout << "z is " << z << endl;
return 0;
}
Function Overloading
Compiler uses function overload resolution to call the
most appropriate function
 First looks for a function definition where the formal

and actual parameters exactly match


 If there is no exact match, the compiler will attempt

to cast the actual parameters to ones used by an


appropriate function

The rules for function definition overloading are very


complicated
 Advice

 Be very careful when using this feature


Random Numbers
Generating a sequence of random numbers is often
useful
 In a game, it ensures that a player does not see

the same behavior each time


 In a simulation of a complex system,

random numbers can be used to


help generate random events
 Car crash in a simulation
of a highway system
 Likelihood of a gene in cell mutation
 Weather simulation
Uniform Random Numbers
Uniform random number sequence
 A sequence of random numbers where

 Each value in the sequence is drawn from the


same range of numbers
 In each position of the sequence, any value in the
number range is equally likely to occur
Random Numbers
Examples
 Generate a uniform random

number sequence in the range


1 to 6
 Use a fair six-sided die
 Each roll represents a new random number

 Generate a uniform random number


sequence in the range 1 to 2
 Use a fair coin
 Heads: 1, Tails: 2
Random Numbers
We can write an algorithm
for generating what looks
like random numbers 30 21 9 28 29 ...

Because it’s an algorithm,


we know the rules for generating the next number
 The generated numbers are not really random

 They are properly called pseudorandom numbers


Stdlib Library
Provides in part functions for generating pseudorandom
numbers
 rand()

 Returns a uniform pseudorandom unsigned int


from the inclusive interval 0 to RAND_MAX
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main() {
for (int i = 1; i <= 5; ++i)
cout << rand() << endl;
return 0;
}
Different Sequences
To produce a different sequence, invoke
void srand(unsigned int);

Consider seed.cpp
int main() {
cout << "Enter a seed: ";
unsigned int Seed;
cin >> Seed;
srand(Seed);
for (int i = 1; i <= 5; ++i)
cout << rand() << endl;
return 0;
}
Different Sequences
To automatically get a different sequence each time
 Need a method of setting the seed to a random
value
 The standard method is to use the computer's
clock as the value of the seed
 The function invocation time() can be used
 Returns an integral value of type time_t
 Invocation time(0) returns a suitable value
for generating a random sequence
Randseed.cpp
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
srand((unsigned int) time(0));
for (int i = 1; i <= 5; ++i)
cout << rand() << endl;
return 0;
}
Class Construct
Defining objects with
attributes and behavior

JPC and JWD © 2002 McGraw-Hill, Inc.


Class Types
Class construct
 Allows programmers to define new data types for

representing information

 Class type objects can have both attribute


components and behavior components

 Provides the object-oriented programming in C++

Example we shall consider is


 RectangleShape
Terminology
Client
 Program using a class

Object behaviors
 Realized in C++ via member functions (methods)

 RectangleShapes can be drawn or resized

Object attributes
 Are known as data members in C++

 RectangleShapes have width, height, position,


color
Member Functions
Provide a controlled interface to data members and
object access and manipulation
 Create objects of the class

 Inspect, mutate, and manipulate object of the class

 Can be used to keep data members in a correct state

 SetSize()
 SetColor()
 Draw()
Member Functions
Constructors
 Member functions that initialize an object during its

definition
RectangleShape R(W, x, y, c, w, h);

 Factoid
 Constructors do not have a type
 Considered superfluous
Member Functions
Inspectors
 Member functions that act as a messenger that

returns the value of an attribute

 Example
 RectangleShapes have an inspector GetColor()

color CurrColor = R.GetColor();


Member Functions
Mutators
 Changes the value of an attribute

 Example
 RectangleShapes have a mutator SetColor()

R.SetColor(Black);
Member Functions
Facilitators
 Causes an object to perform some action or service

 Example
 RectangleShapes have a facilitator Draw()

R.Draw();
A Simple RectangleShape
Class
Consider a simpler version of the RectangleShape than
what is defined in rect.h

Giving the class definition not the implementation

The definition in rect.h uses inheritance and member


functions with default parameters
 If you are wondering what is missing

 Default constructor parameters


 Member function
 Erase()

 Inherited member functions


 HasBorder(), SetBorder(), and ClearBorder()
Simple RectangleShape
Header File
#ifndef RECT_SHAPE_H Preprocessor directives
#define RECT_SHAPE_H
#include "ezwin.h"
class RectangleShape { Passed by reference, do not want
public: a copy of the window
// constructor
Access RectangleShape(SimpleWindow &Window,
right float XCoord, float YCoord, const color &c,
indicates
float Width, float Height);
no
limitations // facilitator
on who void Draw(); ezwin.h get us definitions of
can use SimpleWindow and color
these
members
Simple RectangleShape
// inspectors
Indicates the member
color GetColor() const; functions won’t
float GetWidth() const; change the object
float GetHeight() const;
void GetSize(float &Width, float &Height)
const;
void GetPosition(float &XCoord, float &YCoord)
const;
SimpleWindow& GetWindow() const;
Reference return,
brings actual
window (not a
copy)
Simple RectangleShape
Lack of const indicate the member
function might change the object

// mutators
void SetColor(const color &c);
void SetPosition(float XCoord, float YCoord);
void SetSize(float Width, float Height);
Simple RectangleShape
Access right
private:
// data members A client cannot
SimpleWindow &Window; directly access either
private or protected
float thisXCenter; data members
float thisYCenter;
color thisColor;
float thisWidth;
float thisHeight;
};

#endif
Close of #ifndef directive
Access Tests
Consider
SimpleWindow W("Testing", 20, 10);
RectangleShape R(W, 2, 2, Blue, 4, 3);
const RectangleShape S(W, 15, 10, Red, 5, 6);

Can we do the following?


 color c = R.GetColor();

 color d = S.GetColor();

 color d = R.thisColor;

 R.DetColor(Yellow);

 S.SetColor(Black);
The RectangleShape Class
Public access
 All clients and class members

have access to the public


members Private data
Access
denied members and
Private access member functions
 Only class
members Public data
have access members and
Access from
to the member functions
outside of class
private
members
C: RectangleShape
DM: Window, Color,
XCenter, YCenter,
Width, Height
MF: Draw(), GetColor(), GetSize(),
GetWidth(), GetHeight(), GetPosition(),
GetWindow(), SetColor(),
SetPosition(),SetSize()

Instantiations

O: R1 O: R2
DM: Window: &W, DM: Window: &W,
Color: Cyan, Color: Red,
XCenter: 1, YCenter: 4 XCenter: 6, YCenter: 4
Width: 3, Height: 3 Width: 1, Height: 2
#include "rect.h”
SimpleWindow ColorWindow("Color Palette", 8.0, 8.0);
int ApiMain() {
const int SideSize = 1;
float XPosition = 1.5;
const float YPosition = 4;
ColorWindow.Open();
RectangleShape ColorPatch(ColorWindow,
XPosition, YPosition, White, SideSize, SideSize);
for (int c = Red; c <= Magenta; c = color(c + 1)) {
ColorPatch.SetColor(color(c));
ColorPatch.SetPosition(XPosition, YPosition);
ColorPatch.Draw();
XPosition += SideSize;
}
return 0;
}
Abstract Data Types

Development and
Implementation

JPC and JWD © 2002 McGraw-Hill, Inc.


Our Goal
Well-defined representations that allow objects to be
created and used in an intuitive manner

 User should not have to bother with unnecessary


details

Example
 programming a microwave to make popcorn should

not require a physics course


Golden Rule
Use information hiding and encapsulation to support
integrity of data

 Put implementation details in a separate module


 Implementation details complicate the class
declarations

 Data members are private so that use of the


interface is required
 Makes clients generally immune to
implementation changes
Another Golden Rule
Keep it simple – class minimality rule

 Implement a behavior as a nonmember function


when possible

 Only add a behavior if it is necessary


Abstract Data Type
Well-defined and complete data abstraction using the
information-hiding principle
Rational Number Review
Rational number
 Ratio of two integers: a/b

 Numerator over the denominator

Standard operations
 Addition Multiplication
a c ad+bc a c ac
+ = * =
b d bd b d bd

 Subtraction Division
a c ad - bc a c ad
- = / =
b d bd b d bc
Abstract Data Type
Consider
Rational a(1,2); // a = 1/2
Rational b(2,3); // b = 2/3
cout << a << " + " << b << " = " << a + b;
Rational s; // s = 0/1
Rational t; // t = 0/1
cin >> s >> t;
cout << s << " * " << t << " = " << s * t;

Observation
 Natural look that is analogous to fundamental-type

arithmetic objects
Rational Attributes
A numerator and denominator
 Implies in part a class representation with two

private int data members


 NumeratorValue and DenominatorValue
Rational Public Behaviors
Rational arithmetic
 Addition, subtraction, multiplication, and division

Rational relational
 Equality and less than comparisons

 Practice rule of class minimality


Rational Public Behaviors
Construction
 Default construction

 Design decision 0/1


 Specific construction

 Allow client to specify numerator and


denominator
 Copy construction

 Provided automatically

Assignment
 Provided automatically

Insertion and extraction


Non-Public Behaviors
Inspection and mutation of data members

 Clients deal with a Rational object!


Auxiliary Behaviors
Operations (necessarily public)
 Arithmetic, relational, insertion, and extraction

operations
 Provides the natural form we expect
 Class definition provides a functional form that

auxiliary operators use

 Provides commutativity consistency


 For C++ reasons 1 + r and r + 1 would not
be treated the same if addition was a member
operation
Class Rational
Public interface: Add(), Subtract(),
Multiply(),Divide(), Equal(),
LessThan(), Insert(),Extract()
Data members: NumeratorValue,
DenominatorValue
Other members: GetNumerator(), GetDenominator(),
SetNumerator(), SetDenominator(),

Instantiation Instantiation
Rational a(1,2); Rational b(2,3);

Object a Object b
Attributes: Attributes:
NumeratorValue(1) NumeratorValue(2)
DenominatorValue(2) DenominatorValue(3)
Library Components
Rational.h
 Class definitions and library function prototypes

Rational.cpp
 Implementation source code – member and auxiliary

function definitions
 Auxiliary functions are assisting global functions
that provide expected but non-member
capabilities

Rational.obj
 Translated version of Rational.cpp (linkable)

 Rational.lib
 Library version of Rational.obj that is more readily
linkable
MyProgram.cpp
Making use of the Rational
class. The header file provides
#include <iostream> access to the class definition
using namespace std; and to auxiliary function
#include "rational.h" prototypes. The header file
int main() { does not provide member and
auxiliary definitions
Rational r;
Rational s;
cout << "Enter two rationals(a/b): ";
cin >> r >> s;
Rational Sum = r + s;
cout << r << " + " << s << " = " << Sum;
return 0;
}
Producing MyProgram.exe
Preprocessor combines the definitions and prototypes in
iostream and rational headers along with
MyProgram.cpp to produce a compilation unit
 Compiler must be told where to look for Rational.h

 Compiler translates the unit and produces


MyProgram.obj
 Compiler recognizes that MyProgram.obj does not
contain actual definitions of Rational constructor, +, >>,
and <<
 Linker is used to combine definitions from the Rational
library file with MyProgram.obj to produce
MyProgram.exe
 Compiler must be told where to find the Rational
Producing MyProgram.exe
MyProgram.cpp

Link object file


Process Check with standard
preprocessor translation unit library files
directives to for legal syntax and rational
produce a and compile it library file to
translation into object file produce
unit MyProgram.obj executable
unit

MyProgram.exe
Rational Header File
Overview
File layout
 Class definition and library prototypes nested within

preprocessor statements
 Ensures one inclusion per translation unit
 Class definition precedes library prototypes

#ifndef RATIONAL_H
#define RATIONAL_H
class Rational {
// …
} ;
// library prototypes …
#endif
Class Rational Overview
class Rational { // from rational.h
public:
// for everybody including clients
protected:
// for Rational member functions and for
// member functions from classes derived
// from rational
private:
// for Rational member functions
} ;
Rational Public Section
public:
// default constructor
Rational();
// specific constructor
Rational(int numer, int denom = 1);
// arithmetic facilitators
Rational Add(const Rational &r) const;
Rational Multiply(const Rational &r) const;
// stream facilitators
void Insert(ostream &sout) const;
void Extract(istream &sin);
Rational Protected Section
protected:
// inspectors
int GetNumerator() const;
int GetDenominator() const;
// mutators
void SetNumerator(int numer);
void SetDenominator(int denom);
Rational Private Section
private:
// data members
int NumeratorValue;
int DenominatorValue;
Auxiliary Operator
Prototypes
// after the class definition in rational.h

Rational operator+(
const Rational &r, const Rational &s);

Rational operator*(
const Rational &r, const Rational &s);

ostream& operator<<(
ostream &sout, const Rational &s);

istream& operator>>(istream &sin, Rational &r);


Auxiliary Operator
Importance
Rational r; Rational r;
Rational s; Rational s;
r.Extract(cin); cin >> r;
s.Extract(cin); cin >> s;
Rational t = r + s;
Rational t = r.Add(s);
cout << t;
t.Insert(cout);
Natural look
Should << be a
member?
 Consider

r << cout;
Const Power
const Rational OneHalf(1,2);
cout << OneHalf; // legal
cin >> OneHalf; // illegal
Rational Implementation
#include <iostream> // Start of rational.cpp
#include <string>
using namespace std;
#include "rational.h" Is this necessary?

// default constructor
Rational::Rational() {
SetNumerator(0); Which objects are
SetDenominator(1); being referenced?
}
Example
Rational r; // r = 0/1
Remember
Every class object
 Has its own data members

 Has its own member functions


 When a member function accesses a data
member
 By default the function accesses the data

member of the object to which it belongs!

 No special notation needed


Remember
Auxiliary functions
 Are not class members

 To access a public member of an object, an auxiliary


function must use the dot operator on the desired
object

object.member
Specific Constructor
// (numer, denom) constructor
Rational::Rational(int numer, int denom) {
SetNumerator(numer);
SetDenominator(denom);
}

Example
Rational t(2,3); // t = 2/3

Rational u(2); // u = 2/1 (why?)


Inspectors
int Rational::GetNumerator() const {
Which object is
return NumeratorValue;
being referenced?
}

int Rational::GetDenominator() const {


return DenominatorValue;
} Why the const?

Where are the following legal?


int a = GetNumerator();
int b = t.GetNumerator();
Numerator Mutator
void Rational::SetNumerator(int numer) {
NumeratorValue = numer;
}
Why no const?

Where are the following legal?

SetNumerator(1);

t.SetNumerator(2);
Denominator Mutator
void Rational::SetDenominator(int denom) {
if (denom != 0) {
DenominatorValue = denom;
}
else {
cerr << "Illegal denominator: " << denom
<< "using 1" << endl;
DenominatorValue = 1;
}
}

Example
SetDenominator(5);
Addition Facilitator
Rational Rational::Add(const Rational &r) const {
int a = GetNumerator();
int b = GetDenominator();
int c = r.GetNumerator();
int d = r.GetDenominator();
return Rational(a*d + b*c, b*d);
}

Example
cout << t.Add(u);
Multiplication Facilitator
Rational Rational::Multiply(const Rational &r)
const {
int a = GetNumerator();
int b = GetDenominator();
int c = r.GetNumerator();
int d = r.GetDenominator();
return Rational(a*c, b*d);
}

Example
t.Multiply(u);
Insertion Facilitator
void Rational::Insert(ostream &sout) const {
sout << GetNumerator() << '/' << GetDenominator();
return;
}

Example
t.Insert(cout);

Why is sout a reference parameter?


Basic Extraction Facilitator
void Rational::Extract(istream &sin) {
int numer;
int denom;
char slash;
sin >> numer >> slash >> denom;
assert(slash == '/');
SetNumerator(numer);
SetDenominator(denom);
return;
}

Example
t.Extract(cin);
Auxiliary Arithmetic
Operators
Rational operator+(
const Rational &r, const Rational &s) {
return r.Add(s);
}

Rational operator*(
const Rational &r, const Rational &s) {
return r.Multiply(s);
}

Example
cout << (t + t) * t;
Auxiliary Insertion Operator
ostream& operator<<(
ostream &sout, const Rational &r) {
r.Insert(sout);
return sout;
}

Why a reference return?

Note we can do either

t.Insert(cout); cout << endl; // unnatural


cout << t << endl; // natural
Auxiliary Extraction Operator
// extracting a Rational
istream& operator>>(istream &sin, Rational &r) {
r.Extract(sin);
return sin;
}

Why a reference return?

We can do either

t.Extract(cin); // unnatural
cin >> t; // natural
What’s Happening Here?
Suppose the following definitions are in effect
Rational a(2,3);
Rational b(3,4);
Rational c(1,2);
Why do the following statements work
Rational s(a);
Rational t = b;
c = a
C++ has automatically provided us a copy constructor
and an assignment operator
Copy Construction
Default copy construction
 Copy of one object to another in a bit-wise manner

 The representation of the source is copied to the


target in a bit-by-bit manner

 This type of copy is called shallow copying

Class developers are free to implement their own copy


constructor

Rational does need a special one, but we will define one


for the experience
A Rational Copy Constructor
Rational::Rational(const Rational &r) {
int a = r.GetNumerator();
int b = r.GetDenomiator();

SetNumerator(a);
SetDenominator(b);
}

Rational s(a);
Rational t = b;
Gang Of Three
If it is appropriate to define a copy constructor then
 Consider also defining

 Assignment operator
 Copy source to target and return target

 A = B = C

 Destructor
 Clean up the object when it goes out of scope

We give the name Gang of three to the


 Copy constructor, assignment operator, and the

destructor
A Rational Assignment
Operator
Rational& Rational::operator =(const Rational &r) {
int a = r.GetNumerator();
int b = r.GetDenomiator();

SetNumerator(a);
SetDenominator(b);
*this is C++ syntax for
return *this; the object whose member
} function was invoked

a = b;
a = b = c;
Rational Destructor
Rational::~Rational() {
// nothing to do
}
Arrays
A Mechanism for representing
lists

JPC and JWD © 2002 McGraw-Hill, Inc.


Lists
Problem solving often requires information be viewed as
a list
 List may be one-dimensional or multidimensional

C++ provides two list mechanisms


 Arrays

 Traditional and important because of legacy


libraries
 Restrictions on its use
 Container classes

 First-class list representation


 Common containers provided by STL
 Vector, queue, stack, map, …

 Preferred long-term programming practice


Lists
Analogies
 Egg carton

 Apartments

 Cassette carrier
Array Terminology
 List is composed of elements
 Elements in a list have a common name
 The list as a whole is referenced through the
common name
 List elements are of the same type — the base type
 Elements of a list are referenced by subscripting or
indexing the common name
C++ Restrictions
 Subscripts are denoted as expressions within brackets: [
]
 Base type can be any fundamental, library-defined, or
programmer-defined type
 The index type is integer and the index range must be
0 ... n-1
 where n is a programmer-defined constant

expression.
Parameter passing style
 Always call by reference (no indication necessary)
Basic Array Definition
BaseType Id [ SizeExp ] ;

Type of Bracketed constant


values in expression
list Name indicating number
of list of elements in list

double X [ 100 ] ;

// Subscripts are 0 through 99


Example Definitions
 Suppose
const int N = 20;
const int M = 40;
const int MaxStringSize = 80;
const int MaxListSize = 1000;
Then the following are all correct array definitions
int A[10]; // array of 10 ints
char B[MaxStringSize]; // array of 80 chars
double C[M*N]; // array of 800 floats
int Values[MaxListSize]; // array of 1000 ints
Rational D[N-15]; // array of 5 Rationals
Subscripting
Suppose
int A[10]; // array of 10 ints A[0], … A[9]
 To access individual element must apply a subscript to list
name A
 A subscript is a bracketed expression also known as the

index
 First element of list has index 0

A[0]
 Second element of list has index 1, and so on

A[1]
 Last element has an index one less than the size of the

list
A[9]
 Incorrect indexing is a common error
Array Elements
Suppose
int A[10]; // array of 10 uninitialized ints

A -- -- -- -- -- -- -- -- -- --
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]

To access an individual element we must apply a


subscript to list name A
Array Element Manipulation
Consider
int i = 7, j = 2, k = 4;
A[0] = 1;
A[i] = 5;
A[j] = A[i] + 3;
A[j+1] = A[i] + A[0];
A[A[j]] = 12;
cin >> A[k]; // where next input value is 3

A -- -- -- -- -- -- -- -- -- --
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
Array Element Manipulation
Consider
int i = 7, j = 2, k = 4;
A[0] = 1;
A[i] = 5;
A[j] = A[i] + 3;
A[j+1] = A[i] + A[0];
A[A[j]] = 12;
cin >> A[k]; // where next input value is 3

A 1 -- -- -- -- -- -- -- -- --
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
Array Element Manipulation
Consider
int i = 7, j = 2, k = 4;
A[0] = 1;
A[i] = 5;
A[j] = A[i] + 3;
A[j+1] = A[i] + A[0];
A[A[j]] = 12;
cin >> A[k]; // where next input value is 3

A 1 -- -- -- -- -- -- 5 -- --
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
Array Element Manipulation
Consider
int i = 7, j = 2, k = 4;
A[0] = 1;
A[i] = 5;
A[j] = A[i] + 3;
A[j+1] = A[i] + A[0];
A[A[j]] = 12;
cin >> A[k]; // where next input value is 3

A 1 -- 8 -- -- -- -- 5 -- --
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
Array Element Manipulation
Consider
int i = 7, j = 2, k = 4;
A[0] = 1;
A[i] = 5;
A[j] = A[i] + 3;
A[j+1] = A[i] + A[0];
A[A[j]] = 12;
cin >> A[k]; // where next input value is 3

A 1 -- 8 6 -- -- -- 5 -- --
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
Array Element Manipulation
Consider
int i = 7, j = 2, k = 4;
A[0] = 1;
A[i] = 5;
A[j] = A[i] + 3;
A[j+1] = A[i] + A[0];
A[A[j]] = 12;
cin >> A[k]; // where next input value is 3

A 1 -- 8 6 -- -- -- 5 12 --
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
Array Element Manipulation
Consider
int i = 7, j = 2, k = 4;
A[0] = 1;
A[i] = 5;
A[j] = A[i] + 3;
A[j+1] = A[i] + A[0];
A[A[j]] = 12;
cin >> A[k]; // where next input value is 3

A 1 -- 8 6 3 -- -- 5 12 --
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
Extracting Values For A List
int A[MaxListSize];
int n = 0;
int CurrentInput;
while((n < MaxListSize) && (cin >> CurrentInput)){
A[n] = CurrentInput;
++n;
}
Displaying A List
// List A of n elements has already been set
for (int i = 0; i < n; ++i) {
cout << A[i] << " ";
}
cout << endl;
Smallest Value
Problem
 Find the smallest value in a list of integers

Input
 A list of integers and a value indicating the number

of integers
Output
 Smallest value in the list

Note
 List remains unchanged after finding the smallest

value!
Preliminary Design
Realizations
 When looking for value with distinguishing

characteristics, need a way of remembering best


candidate found so far
 Make it a function -- likely to be used often
Design
 Search array looking for smallest value

 Use a loop to consider each element in turn


 If current element is smallest so far, then update
smallest value so far candidate
 When done examining all of the elements, the

smallest value seen so far is the smallest value


Necessary Information
Information to be maintained
 Array with values to be inspected for smallest value

 Number of values in array

 Index of current element being considered

 Smallest value so far


A More Detailed Design
Solution
 Function that takes array of values and array size as

its two in parameters; returns smallest value seen as


its value
 Initialize smallest value so far to first element

 For each of the other elements in the array in turn

 If it is smaller than the smallest value so far,


update the value of the smallest value so far to
be the current element
 Return smallest value seen as value of function
Passing An Array
Notice brackets are empty

int ListMinimum(const int A[], int asize) {


assert(asize >= 1);
int SmallestValueSoFar = A[0]; Could we just
assign a 0
for (int i = 1; i < asize; ++i) { and have it
if (A[i] < SmallestValueSoFar ) { work?
SmallestValueSoFar = A[i];
}
}
return SmallestValueSoFar ;
}
Using ListMinimum()
What happens with the following?

int Number[6];
Number[0] = 3; Number[1] = 88; Number[2] = -7;
Number[3] = 9; Number[4] = 1; Number[5] = 24;

cout << ListMinimum(Number, 6) << endl;

Notice no brackets
int List[3];
List[0] = 9; List[1] = 12; List[2] = 45;

cout << ListMinimum(List, 3) << endl;


Remember
Arrays are always passed by reference
 Artifact of C

Can use const if array elements are not to be modified

Do not need to include the array size when defining an


array parameter
Some Useful Functions
void DisplayList(const int A[], int n) {
for (int i = 0; i < n; ++i) {
cout << A[i] << " ";
}
cout << endl;
}
void GetList(int A[], int &n, int MaxN = 100) {
for (n = 0; (n < MaxN) && (cin >> A[n]); ++n) {
continue;
}
}
Useful Functions Being Used
const int MaxNumberValues = 25;
int Values[MaxNumberValues];
int NumberValues;

GetList(Values, NumberValues, MaxNumberValues);


DisplayList(Values, NumberValues);
Searching
Problem
 Determine whether a value key is one of the element

values
Does it matter if
 Element values are not necessarily numbers

 Element values are not necessarily unique

 Elements may have key values and other fields


Sequential List Searching
int Search(const int List[], int m, int Key) {
for (int i = 0; i < m; ++i) {
if (List[i] == Key) {
return i;
}
}
return m;
}

Run time is proportional to number of elements


Example Invocation
cin >> val;
int spot = Search(Values, NumberValues, val);
if (spot != NumberValues) {
// its there, so display it
cout << Values[spot] << endl;
}
else { // its not there, so add it
Values[NumberValues] = val;
++NumberValues;
}
Sorting
Problem
 Arranging elements so that they are ordered

according to some desired scheme


 Standard is non-decreasing order
 Why don't we say increasing order?

Major tasks
 Comparisons of elements

 Updates or element movement


Common Sorting Techniques
Selection sort
 On ith iteration place the ith smallest element in the

ith list location

Bubble sort
 Iteratively pass through the list and examining

adjacent pairs of elements and if necessary swap


them to put them in order. Repeat the process until
no swaps are necessary
Common Sorting Techniques
Insertion sort
 On ith iteration place the ith element with respect to

the i-1 previous elements


 In text

Quick sort
 Divide the list into sublists such that every element

in the left sublist <= to every element in the right


sublist. Repeat the Quick sort process on the sublists
 In text
SelectionSort
void SelectionSort(int A[], int n) {
for (int i = 0; i < n-1; ++i) {
int k = i;
for (int j = i + 1; j < n; ++j) {
if (A[j] < A[k])
k = j;
}
if (i != k)
swap(A[k], A[i]);
}
}
Complexity
SelectionSort() Question
 How long does the function take to run

 Proportional to n*n time units, where n is the


number of elements in the list

General question
 How fast can we sort using the perfect comparison-

based method
 The best possible worst case time is proportional
to
n log n time units
Vectors
First-class mechanism for
representing lists

JPC and JWD © 2002 McGraw-Hill, Inc.


Standard Template Library
What is it?
 Collection of container types and algorithms

supporting basic data structures


What is a container?
 A generic list representation allowing programmers

to specify which types of elements their particular


lists hold
 Uses the C++ template mechanism
Have we seen this library before?
 String class is part of the STL
STL Container Classes
Sequences
 deque, list, and vector

 Vector supports efficient random-access to


elements
Associative
 map, set

Adapters
 priority_queue, queue, and stack
Vector Class Properties
Provides list representation comparable in efficiency to
arrays
First-class type
Efficient subscripting is possible
 Indices are in the range 0 … size of list - 1

List size is dynamic


 Can add items as we need them

Index checking is possible


 Through a member function

Iterators
 Efficient sequential access
Example
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> A(4, 0); // A: 0 0 0 0
A.resize(8, 2); // A: 0 0 0 0 2 2 2 2
vector<int> B(3, 1); // B: 1 1 1
for (int i = 0; i < B.size(); ++i) {
A[i] = B[i] + 2;
} // A: 3 3 3 0 2 2 2 2
A = B; // A: 1 1 1
return 0;
}
Some Vector Constructors
vector()
 The default constructor creates a vector of zero

length

vector(size_type n, const T &val = T())


 Explicit constructor creates a vector of length n with

each element initialized to val

vector(const T &V)
 The copy constructor creates a vector that is a

duplicate of vector V.
 Shallow copy!
Construction
Container name
Basic construction

vector<T> List;

Base element
type
Example
vector<int> A; // 0 ints
vector<float> B; // 0 floats
vector<Rational> C; // 0 Rationals
Construction
Container name
Basic construction

vector<T> List(SizeExpression);
Number of
elements to be
Base element
default
type
constructed
Example
vector<int> A(10); // 10 ints
vector<float> B(20); // 20 floats
vector<Rational> C(5); // 5 Rationals
int n = PromptAndRead();
vector<int> D(n); // n ints
Construction
Container name
Basic construction Initial
value
vector<T> List(SizeExpression, Value);
Number of
elements to be
Base element
default
type
constructed
Example
vector<int> A(10, 3); // 10 3s
vector<float> B(20, 0.2); // 20 0.2s
Rational r(2/3);
vector<Rational> C(5, r); // 5 2/3s
Vector Interface
size_type size() const
 Returns the number of elements in the vector

cout << A.size(); // display 3

bool empty() const


 Returns true if there are no elements in the vector;

otherwise, it returns false

if (A.empty()) {
// ...
Vector Interface
vector<T>& operator = (const vector<T> &V)
 The member assignment operator makes its vector

representation an exact duplicate of vector V.


 Shallow copy
 The modified vector is returned

vector<int> A(4, 0); // A: 0 0 0 0


vector<int> B(3, 1); // B: 1 1 1
A = B; // A: 1 1 1
Vector Interface
reference operator [](size_type i)
 Returns a reference to element i of the vector

 Lvalue

const_reference operator [](size_type i) const


 Returns a constant reference to element i of the

vector
 Rvalue
Example
vector<int> A(4, 0); // A: 0 0 0 0
const vector<int> B(4, 0); // B: 0 0 0 0

for (int i = 0; i < A.size(); ++i) {


A[i] = 3;
} // A: 3 3 3 3

for (int i = 0; i < A.size(); ++i) {


cout << A[i] << endl; // lvalue
cout << B[i] << endl; // rvalue
}
Vector Interface
reference at(size_type i)
 If i is in bounds, returns a reference to element i of

the vector; otherwise, throws an exception

const_reference at(size_type i) const


 If i is in bounds, returns a constant reference to

element i of the vector; otherwise, throws an


exception
Example
vector<int> A(4, 0); // A: 0 0 0 0

for (int i = 0; i <= A.size(); ++i) {


A[i] = 3;
} // A: 3 3 3 3 ??

for (int i = 0; i <= A.size(); ++i) {


A.at(i) = 3;
} // program terminates
// when i is 4
Vector Interface
void resize(size_type s, T val = T())
 The number of elements in the vector is now s.

 To achieve this size, elements are deleted or


added as necessary
 Deletions if any are performed at the end

 Additions if any are performed at the end

 New elements have value val

vector<int> A(4, 0); // A: 0 0 0 0


A.resize(8, 2); // A: 0 0 0 0 2 2 2 2
A.resize(3,1); // A: 0 0 0
Function Examples
void GetList(vector<int> &A) {
int n = 0;
while ((n < A.size()) && (cin >> A[n])) {
++n;
}
A.resize(n);
}

vector<int> MyList(3);
cout << "Enter numbers: ";
GetList(MyList);
Examples
void PutList(const vector<int> &A) {
for (int i = 0; i < A.size(); ++i) {
cout << A[i] << endl;
}
}

cout << "Your numbers: ";


PutList(MyList)
Vector Interface
pop_back()
 Removes the last element of the vector

push_back(const T &val)
 Inserts a copy of val after the last element of the

vector
Example
void GetValues(vector<int> &A) {
A.resize(0);
int Val;
while (cin >> Val) {
A.push_back(Val);
}
}

vector<int> List;
cout << "Enter numbers: ";
GetValues(List);
Overloading >>
istream& operator>>(istream& sin, vector<int> &A) {
A.resize(0);
int Val;
while (sin >> Val) {
A.push_back(Val);
}
return sin;
}

vector<int> B;
cout << "Enter numbers: ";
cin >> B;
Vector Interface
reference front()
 Returns a reference to the first element of the vector

const_reference front() const


 Returns a constant reference to the first element of

the vector

vector<int> B(4,1); // B: 1 1 1 1
int& val = B.front();
val = 7; // B: 7 1 1 1
Vector Interface
reference back()
 Returns a reference to the last element of the vector

const_reference back() const


 Returns a constant reference to the last element of the

vector

vector<int> C(4,1); // C: 1 1 1 1
int& val = C.back();
val = 5; // C: 1 1 1 5
Iterators
Iterator is a pointer to an element
 Really pointer abstraction

Mechanism for sequentially accessing the elements in


the list
 Alternative to subscripting

 There is an iterator type for each kind of vector list

 Notes
 Algorithm component of STL uses iterators
 Code using iterators rather than subscripting can
often be reused by other objects using different
container representations
Vector Interface
iterator begin()
 Returns an iterator that points to the first element of
the vector

iterator end()
 Returns an iterator that points to immediately beyond
the last element of the vector

vector<int> C(4); // C: 0 0 0 0
C[0] = 0; C[1] = 1; C[2] = 2; C[3] = 3;
vector<int>::iterator p = C.begin();
vector<int>::iterator q = C.end();
Iterators
To avoid unwieldy syntax programmers typically use typedef
statements to create simple iterator type names

typedef vector<int>::iterator iterator;


typedef vector<int>::reverse_iterator reverse_iterator;
typedef vector<int>::const_reference const_reference;

vector<int> C(4); // C: 0 0 0 0
iterator p = C.begin();
iterator q = C.end();
Iterator Operators
* dereferencing operator
 Produces a reference to the object to which the iterator p

points
*p

++ point to next element in list


 Iterator p now points to the element that followed the

previous element to which p points


++p

-- point to previous element in list


 Iterator p now points to the element that preceded the

previous element to which p points


--p
typedef vector<int>::iterator iterator;
typedef vector<int>::reverse_iterator reverse_iterator;
vector<int> List(3);

List[0] = 100; List[1] = 101; List[0] = 102;

iterator p = List.begin();
cout << *p; // 100
++p;
cout << *p; // 101
--p;
cout << *p; // 100
reverse_iterator q = List.rbegin();
cout << *q; // 102
++q;
cout << *q; // 101
--q;
cout << *q; // 102
Vector Interface
insert(iterator pos, const T &val = T())
 Inserts a copy of val at position pos of the vector

and returns the position of the copy into the vector

erase(iterator pos)
 Removes the element of the vector at position pos
SelectionSort Revisited
void SelectionSort(vector<int> &A) {
int n = A.size();
for (int i = 0; i < n); ++i) {
int k = i;
for (int j = i + 1; j < n; ++j) {
if (A[j] < A[k])
k = j;
}
if (i != k)
swap(A[k], A[i]);
}
}
QuickSort
QuickSort
 Divide the list into sublists such that every element in the

left sublist <= to every element in the right sublist


 Repeat the QuickSort process on the sublists

void QuickSort(vector<char> &A, int left, int right) {


if (left < right) {
Pivot(A, left, right);
int k = Partition(A, left, right);
QuickSort(A, left, k-1);
QuickSort(A, k+1, right);
}
}
Picking The Pivot Element
void Pivot(vector<char> &A, int left, int right) {
if (A[left] > A[right]) {
Swap(A[left], A[right]);
}
}
Decomposing Into Sublists
int Partition(vector<char> &A, int left, int right) {
char pivot = A[left];
int i = left;
int j = right+1;
do {
do ++i; while (A[i] < pivot);
do --j; while (A[j] > pivot);
if (i < j) {
Swap(A[i], A[j]);
}
} while (i < j);
Swap(A[j], A[left]);
return j;
}
Sorting Q W E R T Y U I O P
QWERTYUIOP 9…9

IOEPTYURWQ
8…9
EOIPTYURWQ
EOIPTYURWQ 7…9 8…7

EIOPTYURWQ
5…9 7…6
EIOPTYURWQ
EIOPTYURWQ 4…9 5…5
EIOPQYURWT
4…3
EIOPQYURWT
EIOPQRTUWY 0…9 2…2
EIOPQRTUWY
EIOPQRTUWY 1…2

EIOPQRTUWY 0…2 1…0


EIOPQRTUWY
EIOPQRTUWY 0 … -1
InsertionSort
void InsertionSort(vector<int> &A) {
for (int i = 1; i < A.size(); ++i) {
int key = A[i]
int j = i - 1;
while ((j > 0) && (A[j] > key)) {
A[j+1] = A[j]
j = j - 1
}
A[j+1] = key
}
Searching Revisited
Problem
 Determine whether a value key is one of the element

values in a sorted list

Solution
 Binary search

 Repeatedly limit the section of the list that could


contain the key value
BSearch(const vector<int> &A, int a, int b, int key){
if (a > b){
return b+1;
}
int m = (a + b)/2
if (A[m] == key) {
Run time is proportional to
return m;
}
the log of the number
else if (a == b) {
of elements
return –1;
}
else if (A[m] < key) {
return BSearch(A, m+1, b, key);
}
else // A[m] > key
return BSearch(A, a, m-1, key);
}
String Class Revisited
void GetWords(vector<string> &List) {
List.resize(0);
string s;
while (cin >> s) {
List.push_back(s);
}
}
Using GetWords()
Suppose standard input contains
A list of words to be read.
vector<string> A;
GetWords(A);
Would set A in the following manner:
A[0]: "A"
A[1]: "list"
A[2]: "of"
A[3]: "words"
A[4]: "to"
A[5]: "be"
A[6]: "read."
String Class As Container
Class
A string can be viewed as a container because it holds a
sequence of characters
 Subscript operator is overloaded for string objects

Suppose t is a string object representing "purple"


 Traditional t view
t: "purple"
 Alternative view
t[0]: 'p'
t[1]: 'u'
t[2]: 'r'
t[3]: 'p'
t[4]: 'l'
t[5]: 'e'
Example
#include <cctype>
using namespace std;
...
string t = "purple";
t[0] = 'e';
t[1] = 'o';
cout << t << endl; // t: people
for (int i = 0; i < t.size(); ++i) {
t[i] = toupper(t[i]);
}
cout << t << endl; // t: PEOPLE
Reconsider A
Where
vector<string> A;

Is set in the following manner


A[0]: "A"
A[1]: "list"
A[2]: "of"
A[3]: "words"
A[4]: "to"
A[5]: "be"
A[6]: "read."
Counting o’s
The following counts number of o’s within A
Size of A
count = 0;
for (int i = 0; i < A.size(); ++i) {
Size of A[i]
for (int j = 0; A[i].size(); ++j) {
if (A[i][j] == 'o') {
++count;
To reference jth character of
} A[i] we need double subscripts
}
}
Explicit Two-Dimensional List
Consider definition
vector< vector<int> > A;
Then
A is a vector< vector<int> >
 It is a vector of vectors

A[i] is a vector<int>
 i can vary from 0 to A.size() - 1

A[i][j] is a int
 j can vary from 0 to A[i].size() - 1
Multi-Dimensional Arrays
Syntax
btype mdarray[size_1][size_2] ... [size_k]
Where
 k - dimensional array

 mdarray: array identifier

 size_i: a positive constant expression

 btype: standard type or a previously defined user

type and is the base type of the array elements

Semantics
 mdarray is an object whose elements are indexed by

a sequence of k subscripts
 the i-th subscript is in the range 0 ... size_i - 1
Memory Layout

Multidimensional arrays are laid out in row-major order


Consider
int M[2][4];

M is two-dimensional array that consists of 2 subarrays


each with 4 elements.
 2 rows of 4 elements

The array is assigned to a contiguous section of memory


 The first row occupies the first portion

 The second row occupies the second portion

-- ... -- -- ... --
M[0][0] M[0][3] M[1][0] M[1][3]
Identity Matrix Initialization
const int MaxSize = 25;
float A[MaxSize][MaxSize];
int nr = PromptAndRead();
int nc = PromptAndRead();
assert((nr <= MaxSize) && (nc <= MaxSize));
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
A[r][c] = 0;
}
A[r][r] = 1;
}
Matrix Addition Solution
Notice only first
brackets are empty

void MatrixAdd(const float A[][MaxCols],


const float B[][MaxCols], float C[][MaxCols],
int m, int n) {
for (int r = 0; r < m; ++r {
for (int c = 0; c < n; ++c) {
C[r][c] = A[r][c] + B[r][c];
}
}
}
EzWindows API

A Graphical Application
Programmer Interface

JPC and JWD © 2002 McGraw-Hill, Inc.


Event-based Programming
Messages are sent to
your program by the
operating system
 Mouse down

 Mouse up
C : SimpleWindow User start
 Key down
Mouse click
 Key up

 Refresh Timer tick


C : User Program
 Quit User end

 Timer

Handle messages by
registering a call back
EzWindows Coordinate
System
Use centimeters X coordinate: distance Y coordinate:
from left edge of distance from top
 Metric screen (4 cm) of screen (4 cm)

 Simpler to understand

than pixels Height of window (5 cm)


 Device independent

 Helps introduce

notion
of information hiding
or encapsulation

Length of window (10 cm)


Class Position
For earlier objects, the position was specified by given
both an x-coordinate and a y-coordinate
We can now introduce a new object called Position and
use it
Position
class Position {
public:
Position(float x = 0.0, float y = 0.0);
float GetXDistance() const;
float GetYDistance() const;
Position Add(const Position &p) const;
protected:
void SetXDistance(float x);
void SetYDistance(float y);
private:
float XDistance;
float YDistance;
};

Position operator+(const Position &x, const Position &y);


EzWindows Auxiliary
Functions
long int GetMilliseconds()
 Returns the value of a timer that is ticking

continuously. The resolution of the timer is


milliseconds.
void Terminate()
 Sends a terminate message to the EzWindows

window manager.
Class SimpleWindow
Writing text in a window
void SimpleWindow::RenderText(const Position
&UpperLeft, const Position &LowerRight,
const string &Msg = "Message",
const color &TextColor = Black,
const color &BackGroundColor = White)
First coordinate of the
bounding box

Message

Second coordinate of
the bounding box
Hello EzWindows
#include <assert.h>
#include "ezwin.h"

// Create a 10 x 4 window
SimpleWindow HelloWindow("Hello EzWindows",
10.0, 4.0, Position(5.0, 6.0));

// ApiMain(): create a window and display greeting


int ApiMain() {
HelloWindow.Open();
assert(HelloWindow.GetStatus() == WindowOpen);

// Get Center of Window


Position Center = HelloWindow.GetCenter();
Hello EzWindows
// Create bounding box for text
Position UpperLeft = Center + Position(-1.0, -1.0);
Position LowerRight = Center + Position(1.0, 1.0);

// Display the text


HelloWindow.RenderText(UpperLeft, LowerRight,
"Hello EzWindows", Black, White);

return 0;
}
Hello EzWindows
// ApiEnd(): shutdown the window
int ApiEnd() {
HelloWindow.Close();

return 0;
}
Class SimpleWindow
Simple Window constructor

SimpleWindow::SimpleWindow(
const string &t =
"Untitled“
float w = 8,
float h = 8,
const Position &p = Position(0,0)
)
Bitmaps
Class BitMap
Uses BitMapStatus

enum BitMapStatus {
NoBitMap, BitMapOkay, NoWindow
};
Class BitMap
Class BitMap can display .bmp files in a SimpleWindow
window

BitMap’s constructor is
BitMap::BitMap(SimpleWindow &w)

Additional key member functions are


BitMapStatus BitMap::Load(string Filename)
BitMapStatus BitMap::GetStatus() const
void BitMap::SetPosition(const Position &p)
int BitMap::Draw()
int BitMap::Erase()
int BitMap::IsInside(const Position &p) const
Fun with Pictures
// Display a bit map image of the authors in the
// center of a window
#include <assert.h>
#include "bitmap.h"
// Open a window to display photograph
SimpleWindow PhotoWindow("The Authors", 10.0, 7.0,
Position(5.0, 3.0));
// ApiMain(): display a bitmap photo
int ApiMain() {
PhotoWindow.Open();
assert(PhotoWindow.GetStatus() == WindowOpen);
const Position WindowCenter =
PhotoWindow.GetCenter();
Fun with Pictures
// Create a bitmap
BitMap Photo(PhotoWindow);
// Load the image
Photo.Load("photo.bmp");
assert(Photo.GetStatus() == BitMapOkay);
// Compute position of logo so it is centered
Position PhotoPosition = WindowCenter +
Position(-.5 * Photo.GetWidth(), -.5 *
Photo.GetHeight());
Photo.SetPosition(PhotoPosition);
// Draw bitmap and we’re done
Photo.Draw();
return 0;
}
Fun with Pictures
Mouse Events
Before we can react to a mouse event in a
SimpleWindow
 Must tell window what function to call when an event

occurs
 Registering a callback

To register a callback use the SimpleWindow member


function SetMouseClickCallback.

W1.SetMouseClickCallback(f);

 Says if the mouse is clicked in window W1, call


function f()
 f() is passed a Position that is the coordinate of
the location of the mouse when the button was
Mouse Events
int ApiMain() {
// Open the window
W1.Open();
assert(W1.GetStatus() == WindowOpen);
// Load the image
B.Load("wizards.bmp");
assert(B.GetStatus() == BitMapOkay);
// Display the bit maps at a starting position
B.SetPosition(Position(1.0, 1.0));
B.Draw();
// Register the callbacks for each window
W1.SetMouseClickCallback(ReceiveMouseClick);
return 0;
}
Mouse Events
#include <assert.h>
#include "bitmap.h"
SimpleWindow W1("Window One", 10.0, 7.0, Position(1.0,
1.0));
BitMap B(W1); // Define a bitmap
// Mouse callback function
int ReceiveMouseClick(const Position &p) {
// Erase the bitmap
B.Erase();
// Set its new position and display it
B.SetPosition(p);
B.Draw();
return 1;
}
Timer Events
The SimpleWindow class supports a timer mechanism

 You can set a timer to go off periodically

 When the timer goes off, a call back is made to the


function specified by the user
Timer Functions
void SimpleWindow::SetTimerCallback(
TimerTickCallbackFunction f)
 Registers a callback for a timer tick

 Function f() will be called when a timer tick occurs.

 The function f() must be declared to take no

parameters, and it should return an int


 The return value of f() indicates whether the event

was handled successfully


 A value of 1 is to indicate success

 A value of 0 is to indicate an error occurred


Timer Functions
int SimpleWindow::StartTimer(int Interval)
 Starts timer running

 Parameter Interval is the number of milliseconds

between timer events


 The return value indicates whether the timer was

successfully started
 A return value of 1 indicates success

 A return value of 0 indicates the timer could not be

set up

void SimpleWindow::StopTimer()
 Turns timer off
#include <assert.h>
#include "bitmap.h“ Example
SimpleWindow W1("Fun", 15.0, 9.0, Position(1.0, 1.0));

BitMap B(W1); // Define a bitmap

// W1TimerEvent(): move bitmap to a new location


int W1TimerEvent() {
// Erase the bitmap
B.Erase();
// Compute a new position and display it
// Make sure the bitmap is completely in the window
int XCoord = Uniform(1, W1.GetWidth());
if (XCoord + B.GetWidth() > W1.GetWidth())
XCoord = XCoord - B.GetWidth();
int YCoord = Uniform(1, W1.GetHeight());
if (YCoord + B.GetHeight() > W1.GetHeight())
YCoord = YCoord - B.GetHeight();
B.SetPosition(Position(XCoord, YCoord));
B.Draw();
}
Example
int ApiMain() {
W1.Open(); // Open the window
assert(W1.GetStatus() == WindowOpen);
B.Load("davidson.bmp"); // Load the image
assert(B.GetStatus() == BitMapOkay);
// Display the bit maps at a starting position
B.SetPosition(Position(1.0, 1.0));
B.Draw();
// Register the callbacks for each window
// and start the timers to go off every 500 ms
W1.SetTimerCallback(W1TimerEvent);
W1.StartTimer(500);
return 0;
}
Example
int ApiEnd() {
// Stop the timers and close the windows
W1.StopTimer();
W1.Close();
return 0;
}
Pointers and Dynamic
Objects
Mechanisms for developing
flexible list representations

JPC and JWD © 2002 McGraw-Hill, Inc.


Usefulness
Mechanism in C++ to pass command-line parameters to
a program
 This feature is less important now with the use of

graphical interfaces

Necessary for dynamic objects


 Objects whose memory is acquired during program

execution as the result of a specific program request


 Dynamic objects can survive the execution of the
function in which they are acquired
 Dynamic objects enable variable-sized lists
Categorizing Expressions
Lvalue expressions
 Represent objects that can be evaluated and

modified
Rvalue expressions
 Represent objects that can only be evaluated

Consider
int a;
vector<int> b(3);
int c[3];
a = 1; // a: lvalue
c[0] = 2*a + b[0]; // c[0], a, b[0]: lvalues
Observation
 Not all lvalues are the names of objects
Basics
Pointer
 Object whose value represents the location of

another object
 In C++ there are pointer types for each type of
object
 Pointers to int objects

 Pointers to char objects

 Pointers to RectangleShape objects

 Even pointers to pointers


 Pointers to pointers to int objects
Syntax
Examples of uninitialized pointers
Indicates pointer object

int *iPtr; // iPtr is a pointer to an int


char *s; // s is a pointer to a char
Rational *rPtr; // rPtr is a pointer to a
// Rational
Examples of initialized pointers
int i = 1; Indicates to take the address of the object
char c = 'y';
int *ptr = &i; // ptr is a pointer to int i
char *t = &c; // t is a pointer to a char c
Memory Depiction
int i = 1;
char c = 'y';
int *ptr = &i;
char *t = &c
Indirection Operator
An asterisk has two uses with regard to pointers
 In a definition, it indicates that the object is a pointer

char *s; // s is of type pointer to char


 In expressions, when applied to a pointer it evaluates
to the object to which the pointer points

int i = 1;
int *ptr = &i; // ptr points to i
*ptr = 2;
cout << i << endl; // display a 2
* indicates indirection or dereferencing
*ptr is an lvalue
Address Operator
& use is not limited to definition initialization

int i = 1;
int j = 2;
int *ptr;
ptr = &i; // ptr points to location of i
*ptr = 3; // contents of i are updated
ptr = &j; // ptr points to location of j
*ptr = 4; // contents of j are updated
cout << i << " " << j << endl;
Null Address
0 is a pointer constant that represents the empty or null
address
 Its value indicates that pointer is not pointing to a
valid object
 Cannot dereference a pointer whose value is null

int *ptr = 0;
cout << *ptr << endl; // invalid, ptr
// does not point to
// a valid int
Member Indirection
Consider

Rational r(4,3);
Rational rPtr = &r;
 To select a member of r using rPtr and member selection,
operator precedence requires
Invokes member Insert() of
the object to which rPtr
(*rPtr).Insert(cout); points (r)
This syntax is clumsy, so C++ provides the indirect
member selector operator ->

rPtr->Insert(cout);
Invokes member Insert() of
the object to which rPtr
points (r)
Traditional Pointer Usage
void IndirectSwap(char *Ptr1, char *Ptr2) {
char c = *Ptr1;
*Ptr1 = *Ptr2;
*Ptr2 = c;
} In C, there are no reference
parameters. Pointers are
int main() {
used to simulate them.
char a = 'y';
char b = 'n';
IndirectSwap(&a, &b);
cout << a << b << endl;
return 0;
}
Constants and Pointers
A constant pointer is a pointer such that we cannot
change the location to which the pointer points
char c = 'c';
const char d = 'd';
char * const ptr1 = &c;
ptr1 = &d; // illegal
A pointer to a constant value is a pointer object such
that the value at the location to which the pointer points
is considered constant
const char *ptr2 = &d;
*ptr2 = 'e'; // illegal: cannot change d
// through indirection with ptr2
Differences
Local objects and Dynamic object
objects
parameters
 Object memory is  Object memory is
acquired acquired by program
automatically with an allocation
request
 new operation
 Object memory is  Dynamic objects can
returned exist beyond the
automatically when function in which they
object goes out of were allocated
scope  Object memory is
returned by a
deallocation request
 delete operation
General New Operation
Behavior
Memory for dynamic objects
 Requested from the free store

 Free store is memory controlled by operating


system
Operation specifies
 The type and number of objects

 If there is sufficient memory to satisfy the request


 A pointer to sufficient memory is returned by the
operation
 If there is insufficient memory to satisfy the request
 An exception is generated
 An exception is an error state/condition which if
not handled (corrected) causes the program to
terminate
The Basic New Form
Syntax
Ptr = new SomeType ;
 Where

 Ptr is a pointer of type SomeType

Beware
 The newly acquired memory is uninitialized unless

there is a default SomeType constructor


Examples
int *iptr = new int;
Rational *rptr = new Rational;

Uninitialized int object

iptr —

rptr 0/1

Rational object with default


initialization
Another Basic New Form
Syntax

SomeType *Ptr = new SomeType(ParameterList);


 Where
 Ptr is a pointer of type SomeType

Initialization
 The newly acquired memory is initialized using a
SomeType constructor
 ParameterList provides the parameters to the
constructor
Examples
int *iptr = new int(10);
Rational *rptr = new Rational(1,2);

iptr 10

rptr 1/2
The Primary New Form
Syntax

P = new SomeType [Expression] ;


 Where
 P is a pointer of type SomeType
 Expression is the number of contiguous objects of
type SomeType to be constructed -- we are
making a list
 Note
 The newly acquired list is initialized if there is a
default SomeType constructor

Because of flexible pointer syntax


 P can be considered to be an array
Examples
int *A = new int [3];
Rational *R = new Rational[2];
A[1] = 5;
Rational r(2/3);
R[0] = r;

A — 5 —

R 2/3 0/1
Right Array For The Job
cout << "Enter list size: ";
int n;
cin >> n;
int *A = new int[n];
GetList(A, n);
SelectionSort(A, n);
DisplayList(A, n);

Note
 Use of the container classes of the STL is preferred
from a software engineering viewpoint
 Example vector class
Delete Operators
Forms of request

delete P; // used if storage came from new


delete [] P; // used if storage came from new[]
 Storage pointed to by P is returned to free store
 P is now undefined
Cleaning Up
int n;
cout << "Enter list size: ";
cin >> n;
int *A = new int[n];
GetList(A, n);
SelectionSort(A, n);
DisplayList(A, n);
delete [] A;
Dangling Pointer Pitfall
int *A = new int[5];
for (int i = 0; i < 5; ++i) A[i] = i;
int *B = A;
A
0 1 2 3 4
B

delete [] A;

Locations do not belong to program

A —

?
B
Memory Leak Pitfall
int *A = new int [5];
for (int i = 0; i < 5; ++i) A[i] = i;
A 0 1 2 3 4

A = new int [5];


These locations cannot be
accessed by program

A 0 1 2 3 4

— — — — —
A Simple Dynamic List Type
What we want
 An integer list data type IntList with the basic
features of the vector data type from the Standard
Template Library

Features and abilities


 True object
 Can be passed by value and reference
 Can be assigned and copied
 Inspect and mutate individual elements
 Inspect list size
 Resize list
 Insert and extract a list
Sample IntList Usage
IntList A(5, 1);
IntList B(10, 2);
IntList C(5, 4);
for (int i = 0, i < A.size(); ++i) {
A[i] = C[i];
}
cout << A << endl; // [ 4 4 4 4 4 ]
A = B;
A[1] = 5;
cout << A << endl; // [ 5 2 2 2 2 2 2 2 2 2 ]
IntList Definition
class IntList {
public:
// constructors
IntList(int n = 10, int val = 0);
IntList(const int A[], int n);
IntList(const IntList &A);
// destructor
~IntList();
// inspector for size of the list
int size() const;
// assignment operator
IntList & operator=(const IntList &A);
IntList Definition (continued)

public:
// inspector for element of constant list
const int& operator[](int i) const;
// inspector/mutator for element of
// nonconstant list
int& operator[](int i);
// resize list
void resize(int n = 0, int val = 0);
// convenience for adding new last element
void push_back(int val);
IntList Definition (continued)

private:
// data members
int *Values; // pointer to elements
int NumberValues; // size of list
};

// IntList auxiliary operators -- nonmembers

ostream& operator<<(ostream &sout, const IntList &A);

istream& operator>>(istream &sin, IntList &A);


Default Constructor
IntList::IntList(int n, int val) {
assert(n > 0);
NumberValues = n;
Values = new int [n];
assert(Values);
for (int i = 0; i < n; ++i) {
Values[i] = val;
}
}
Gang of Three Rule
If a class has a data member that points to dynamic
memory then that class normally needs a class-defined
 Copy constructor
 Constructor that builds an object out of an object
of the same type
 Member assignment operator
 Resets an object using another object of the same
type as a basis
 Destructor
 Anti-constructor that typically uses delete the
operator on the data members that point to
dynamic memory
Why A Tailored Copy
Constructor
Suppose we use the default copy constructor
IntList A(3, 1);
3
IntList B(A);
A 1 2 1
And then
B 3
A[2] = 2;

Then
 B[2] is changed!
 Not what a client would expect

Implication
 Must use tailored copy constructor
Tailored Copy Constructor
IntList::IntList(const IntList &A) {
NumberValues = A.size();
Values = new int [size()];
assert(Values);
for (int i = 0; i < size(); ++i)
Values[i] = A[i];
}

What kind of subscripting is


being performed?
Gang Of Three
What happens when an IntList goes out of scope?
 If there is nothing planned, then we would have a

memory leak

Need to have the dynamic memory automatically


deleted
 Define a destructor

 A class object going out of scope automatically


Notice the tilde
has its destructor invoked

IntList::~IntList() {
delete [] Values;
}
First Assignment Attempt
Algorithm
 Return existing dynamic memory
 Acquire sufficient new dynamic memory
 Copy the size and the elements of the source object
to the target element
Initial Implementation
(Wrong)
IntList& operator=(const IntList &A) {
NumberValues = A.size();
delete [] Values;
Values = new int [NumberValues ];
assert(Values);
for (int i = 0; i < A.size(); ++i)
Values[i] = A[i];
return A;
}

Consider what happens with the code segment


IntList C(5,1);
C = C;
This Pointer
Consider
 this

Inside a member function or member operator this is a


pointer to the invoking object

IntList::size() {
return NumberValues;
}

or equivalently

IntList::size() {
return this->NumberValues;
}
Member Assignment
Operator
IntList& IntList::operator=(const IntList &A) {
if (this != &A) {
delete [] Values;
NumberValues = A.size();
Values = new int [A.size()];
assert(Values);
for (int i = 0; i < A.size(); ++i) {
Values[i] = A[i];
}
}
return *this; Notice the different uses
} of the subscript operator
Why the
asterisk?
Accessing List Elements
// Compute an rvalue (access constant element)
const int& IntList::operator[](int i) const {
assert((i >= 0) && (i < size()));
return Values[i];
}

// Compute an lvalue
int& IntList::operator[](int i) {
assert((i >= 0) && (i < size()));
return Values[i];
}
Stream Operators
Should they be members?

class IntList {
// ...
ostream& operator<<(ostream &sout);
// ...
};
Answer is based on the form we want the operation to
take

IntList A(5,1);
A << cout; // member form (unnatural)
cout << A; // nonmember form (natural)
Beware of Friends
If a class needs to
 Can provide complete access rights to a nonmember

function, operator, or even another class


 Called a friend

Declaration example

class IntList {
// ...
friend ostream& operator<< (
ostream &sout, const IntList &A);
// ...
};
Implementing Friend <<
ostream& operator<<(ostream &sout,
const IntList &A){
sout << "[ ";
for (int i = 0; i < A.NumberValues; ++i) {
sout << A.Values[i] << " ";
}
sout << "]";
Is there any need for
return sout; this friendship?
}
Proper << Implementation
ostream& operator<<(ostream &sout,
const IntList &A){
sout << "[ ";
for (int i = 0; i < A.size(); ++i) {
sout << A[i] << " ";
}
sout << "]";
return sout;
}
Inheritance
Mechanism for deriving new
classes from existing classes

JPC and JWD © 2002 McGraw-Hill, Inc.


Think of a Bicycle
Think of a Tandem Bike
Think of a Racing Bike
Think of a Mountain Bike
Thinking About Bicycles
A tandem bicycle is a kind of bicycle
 Bicycle with two seats

A mountain bicycle is a kind of bicycle


 Bicycle with shocks

A racing bicycle is a kind of bicycle


 Lightweight aerodynamic construction

Tandem, mountain, and racing bicycles are specialized


bicycles
Wouldn’t It Be Nice
Be able to create specialized program objects without
starting from scratch
 Blinking rectangles

 Moving bitmaps

 Arbitrary precision numbers

Inheritance is the object-oriented programming


mechanism for specialization
Inheritance
Ability to define new classes of objects using existing
classes as a basis
 The new class inherits the attributes and behaviors

of the parent classes


 New class is a

specialized version
of the parent class Bicycle
is-a relationships

Mountain Racing Tandem


Bikes Bikes Bikes
Inheritance
A natural way to reuse code
 Programming by extension rather than reinvention

 Object-oriented paradigm is well-suited for this style

of
programming
Terminology
 Base class (superclass) Bicycle

 Derived class (subclass) is-a relationships

Mountain Racing Tandem


Bikes Bikes Bikes
Before Inheritance
class RectangleShape {
public:
RectangleShape(SimpleWindow &W,
float XCoord, float YCoord, const color &Color,
float Width, float Height);
void Draw();
color GetColor() const;
void GetSize(float &Width, float &Height) const;
void GetPosition(float &x, float &y) const;
float GetWidth() const;
float GetHeight() const;
SimpleWindow& GetWindow() const;
void SetColor(const color &Color);
void SetPosition(float x, float y);
void SetSize(float Width, float Height);
private:
SimpleWindow &Window;
float XCenter;
float YCenter;
color Color;
float Width;
float Height;
};
Before Inheritance
class CircleShape {
public:
CircleShape(SimpleWindow &W, float x, float y,
const color &Color, float Diameter);
void Draw();
color GetColor() const;
float GetSize() const;
void GetPosition(float &x, float &y) const;
SimpleWindow& GetWindow() const;
void SetColor(const color &Color);
void SetPosition(float x, float y);
void SetSize(float Diameter);
private:
SimpleWindow &Window;
float XCenter;
float YCenter;
color Color;
float Diameter;
};
Shapes C: WindowObject
DM: Location, Window
MF: GetPosition(), GetWindow(), SetPosition()
Hierarchy
C: Shape
C: Label
DM: Color
MF: GetColor(), SetColor()

C: EllipseShape C: RectangleShape C: TriangleShape


DM: Width, Height DM: Width, Height DM: SideLength
MF: Draw(), MF: Draw(), GetWidth(), MF: Draw(),
GetWidth(), GetHeight(), SetSize() GetSideLength(),
GetHeight(), SetSize() SetSize()
Class WindowObject
class WindowObject {
public:
WindowObject(SimpleWindow &w,
const Position &p);
Position GetPosition() const;
SimpleWindow& GetWindow() const;
void SetPosition(const Position &p);
private:
SimpleWindow &Window;
Position Location;
};
WindowObject Constructor
WindowObject::WindowObject(SimpleWindow &w,
const Position &p) : Window(w), Location(p) {
// No body needed
}

Members are initialized


in class definition order
WindowObject Inspectors
Position WindowObject::GetPosition() const {
return Location;
}

SimpleWindow& WindowObject::GetWindow() const {


return Window;
}
WindowObject Mutator
void WindowObject::SetPosition(const Position &p) {
Location = p;
}
Defining a Derived Class
Access specifier
(usually public)
Class name of
Derived class name
base class

class DerivedClass : public BaseClass {


public:
// public section
...
private:
// private section
...
};
Declaring a Derived Class
Read this as Shape is a kind of WindowObject

class Shape : public WindowObject {


public:
Shape(SimpleWindow &w, Shape inherits WindowObject
const Position &p, members Window, Location,
const color &c = Red); GetPosition(), GetWindow(),
and SetPosition()
color GetColor() const;
void SetColor(const color &c);
private:
color Color;
};
Implementing A Derived
Class Constructor
Derived
class Base class
constructor Base constructor
Derived
parameter class parameter list
class
list name (sublist of PList)
name

DClass::DClass(PList) : BClass(BList), DMbrList {


// Body of derived class constructor
...
};
Derived cass data
member initialization list
(sublist of PList)
Implementing a Derived
Class
Shape::Shape(SimpleWindow &w, const Position &p,
const color &c) : WindowObject(w, p), Color(c) {
// No body needed
}
color Shape::GetColor() const {
return Color;
}
void Shape::SetColor(const color &c) {
assert(c >= 0 && c < MaxColors);
Color = c;
}
Basic Shapes
EllipseShape RectangleShape TriangleShape

WIdth Width SideLength

Height Height
TriangleShape
#include "shape.h"
class TriangleShape : public Shape {
public:
TriangleShape(SimpleWindow &w,
const Position &p, const color &c = Red,
float slen = 1);
float GetSideLength() const;
void SetSize(float slen);
void Draw();
private:
float SideLength;
};
#include "shape.h"
EllipseShape
class EllipseShape : public Shape {
public:
EllipseShape(SimpleWindow &w,
const Position &Center,
const color &c = Red, float Width = 1,
float Height = 2);
float GetWidth() const;
float GetHeight() const;
void Draw();
void SetSize(float Width, float Height);
private:
float Width;
float Height;
};
RectangleShape
#include "shape.h"
class RectangleShape : public Shape {
public:
RectangleShape(SimpleWindow &w,
const Position &Center, const color &c =
Red,
float Width = 1, float Width = 2);
float GetWidth() const;
float GetHeight() const;
void Draw();
void SetSize(float Width, float Height);
private:
float Width;
float Height;
};
TriangleShape::Draw()
void TriangleShape::Draw() {
const float Pi = 3.1415;
const Position Center = GetPosition();
const float SLength = GetSideLength();

// Compute c, distance from center of triangle


// to the top vertex, and a, the distance from
// the center to the base of the triangle
float c = SLength / (2.0 * cos(30 * Pi / 180.0));
float a = tan(30 * Pi / 180.0) * .5 * SLength;
TriangleShape::Draw()
// Create an array containing the positions of
// the vertices of the triangle
vector Position TrianglePoints[3];
TrianglePoints[0] = Center + Position(0, -c),
TrianglePoints[1] = Center
+ Position(-.5 * SLength, a);
TrianglePoints[2] = Center
+ Position(.5 * SLength, a);
// Draw the triangle
GetWindow().RenderPolygon(TrianglePoints, 3,
GetColor(), HasBorder());
}
#include "rect.h"
#include "ellipse.h"
#include "triangle.h"
Using Shapes
SimpleWindow Window("TestShapes", 17.0, 7.0,
Position(4.0, 4.0));
int ApiMain() {
Window.Open();
TriangleShape T(Window, Position(3.5, 3.5),
Red, 3.0);
T.Draw();
RectangleShape R(Window, Position(8.5, 3.5),
Yellow, 3.0, 2.0);
R.Draw();
EllipseShape E(Window, Position(13.5, 3.5),
Green, 3.0, 2.0);
E.Draw();
return 0;
}
Fun with Shapes
Cleaning Up

int ApiEnd()
TWindow.Close();
return 0;
}
Inheritance and Member
Access
class SomeClass {
public:
void MemberFunction();
int MyPublicData;
protected:
int MyProtectedData;
private:
int MyPrivateData;
};

void SomeClass::MemberFunction() {
MyPublicData = 1; // access allowed
MyProtectedData = 2; // access allowed
MyPrivateData = 3; // access allowed
}
Inheritance and Member
Access
void NonMemberFunction() {
SomeClass C;
C.MyPublicData = 1; // access allowed
C.MyProtectedData = 2; // illegal
C.MyPrivateData = 3; // illegal
}
Inheritance and Member
Access
class BaseClass {
public: int MyPublicData;
protected: int MyProtectedData;
private: int MyPrivateData;
};
class DerivedClass : public BaseClass {
public: void DerivedClassFunction();
// ...
};
void DerivedClass::DerivedClassFunction() {
MyPublicData = 1; // access allowed
MyProtectedData = 2; // access allowed
MyPrivateData = 3; // illegal
}
Controlling Inheritance
Inheritance Type Base class member Derived class
access member access
public public
public protected protected
private inaccessible
public protected
protected protected protected
private inaccessible
public private
private protected private
private inaccessible
Templates and
Polymorphism
Generic functions and classes

JPC and JWD © 2002 McGraw-Hill, Inc.


Polymorphic Functions
What are they?
 Generic functions that can act upon objects of

different types
 The action taken depends upon the types of the
 objects

Where have we seen them before?


before
 Function overloading

 Define functions or operators with the same name


 Rational addition operator +

 Function Min() for the various numeric types

 Primitive polymorphism
Polymorphic Functions
Templates
 Generate a function or class at compile time

Where have we seen them before?


 Standard Template Library

 Vector and other container classes

True polymorphism
 Choice of which function to execute is made during

run time
 C++ uses virtual functions
Function Templates
Current scenario
 We rewrite functions Min(), Max(), and

InsertionSort() for many different types


 There has to be a better way

Function template
 Describes a function format that when instantiated

with particulars generates a function definition


 Write once, use multiple times
An Example Function
Template
Indicates a template is being
defined
Indicates T is our formal
template parameter

template <class T>


T Min(const T &a, const T &b) {
if (a < b)
Instantiated
return a;
functions will Instantiated
return a value else functions require
whose type is the return b; two actual
actual template } parameters of
parameter the same type.
Their type will be
the actual value
for T
Min Template
Code segment
int Input1 = PromptAndRead();
int Input2 = PromptAndRead();
cout << Min(Input1, Input2) << endl;

Causes the following function to be generated from our


template
int Min(const int &a, const int &b) {
if (a < b)
return a;
else
return b;
}
Min Template
Code segment
double Value1 = 4.30;
double Value2 = 19.54;
cout << Min(Value1, Value2) << endl;

Causes the following function to be generated from our


template
double Min(const double &a, const double &b) {
if (a < b)
return a;
else
return b;
}
Min Template
Code segment
Rational r(6,21);
Rational s(11,29);
cout << Min(r, s) << endl;

Causes the following function to be generated from our


template
Rational Min(const Rational &a, const Rational &b) {
if (a < b) Operator < needs to be defined
return a; for for the actual template
else parameter type. If < is not
return b; defined, then a compile-time
error occurs
}
Function Templates Facts
Location in program files
 In current compilers

 Template definitions are part of header files

Possible template instantiation failure scenario


cout << min(7, 3.14); // different parameter
// types
Generic Sorting
template <class T>
void InsertionSort(T A[], int n) {
for (int i = 1; i < n; ++i) {
if (A[i] < A[i-1]) {
T val = A[i];
int j = i;
do { A[j] = A[j-1];
--j;
} while ((j > 0) && (val < A[j-1]));
A[j] = val;
}
}
}
STL’s Template Functions
STL provides template definitions for many
programming tasks
 Use them! Do not reinvent the wheel!

 Searching and sorting


 find(), find_if(), count(), count_if(),
min(), max(), binary_search(),
lower_bound(), upper_bound(), sort()
 Comparing
 equal()
 Rearranging and copying
 unique(), replace(), copy(), remove(),
reverse(), random_shuffle(), merge()
 Iterating

Class Templates
Rules
 Type template parameters

 Value template parameters


 Place holder for a value
 Described using a known type and an identifier
name

 Template parameters must be used in class


definition described by template

 Implementation of member functions in header file


 Compilers require it for now
A Generic Array
Representation
We will develop a class Array
 Template version of IntList

 Provides additional insight into container classes


of STL
Homegrown Generic Arrays
Array<int> A(5, 0); // A is five 0's
const Array<int> B(6, 1); // B is six 1's
Array<Rational> C; // C is ten 0/1's
A = B;
A[5] = 3;
A[B[1]] = 2;
cout << "A = " << A << endl; // [ 1 2 1 1 1 3 ]
cout << "B = " << B << endl; // [ 1 1 1 1 1 1 ]
cout << "C = " << D << endl;
// [ 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 ]
template <class T> Optional value is default
class Array { constructed
public:
Array(int n = 10, const T &val = T());
Array(const T A[], int n);
Array(const Array<T> &A);
~Array(); Inlined function
int size() const {
return NumberValues;
}
Array<T> & operator=(const Array<T> &A);
const T& operator[](int i) const;
T& operator[](int i);
private:
int NumberValues;
T *Values;
};
Auxiliary Operators
template <class T>
ostream& operator<<
(ostream &sout, const Array<T> &A);

template <class T>


istream& operator>>
(istream &sin, Array<T> &A);
Default Constructor
template <class T>
Array<T>::Array(int n, const T &val) {
assert(n > 0);
NumberValues = n;
Values = new T [n];
assert(Values);
for (int i = 0; i < n’ ++ i) {
Values[i] = A[i];
}
}
Copy Constructor
template <class T>
Array<T>::Array(const Array<T> &A) {
NumberValues = A.size();
Values = new T [A.size()];
assert(Values);
for (int i = 0; i < A.size(); ++i) {
Values[i] = A[i];
}
}
Destructor
template <class T>
Array<T>::~Array() {
delete [] Values;
}
Member Assignment
template <class T>
Array<T>& Array<T>::operator=(const Array<T> &A) {
if ( this != &A ) {
if (size() != A.size()) {
delete [] Values;
NumberValues = A.size();
Values = new T [A.size()];
assert(Values);
}
for (int i = 0; i < A.size(); ++i) {
Values[i] = A[i];
}
}
return *this;
}
Inspector for Constant Arrays
template <class T>
const T& Array<T>::operator[](int i) const {
assert((i >= 0) && (i < size()));
return Values[i];
}
Nonconstant
Inspector/Mutator
template <class T>
T& Array<T>::operator[](int i) {
assert((i >= 0) && (i < size()));
return Values[i];
}
Generic Array Insertion
Operator
template <class T>
ostream& operator<<(ostream &sout,
const Array<T> &A){
sout << "[ ";
for (int i = 0; i < A.size(); ++i) {
sout << A[i] << " ";
}
sout << "]";
return sout;
}

Can be instantiated for whatever type of Array we need


Specific Array Insertion
Operator
Suppose we want a different Array insertion operator for
Array<char> objects

ostream& operator<<(ostream &sout,


const Array<char> &A){
for (int i = 0; i < A.size(); ++i) {
sout << A[i];
}
return sout;
}
Scenario
Manipulate list of heterogeneous objects with common
base class
 Example: a list of graphical shapes to be drawn

// what we would like


for (int i = 0; i < n; ++i) {
A[i].Draw();
}

 Need
 Draw() to be a virtual function
 Placeholder in the Shape class with specialized

definitions in the derived class


Virtual Functions
For virtual functions
 It is the type of object to which the pointer refers

that determines which function is invoked

TriangleShape T(W, P, Red, 1);


RectangleShape R(W,P, Yellow, 3, 2);
CircleShape C(W, P, Yellow, 4);

Shape *A[3] = {&T, &R, &C};

for (int i = 0; i < 3; ++i) {


A[i]->Draw();
} When i is 0, a
TriangleShape’s Draw() is
used
Virtual Functions
For virtual functions
 It is the type of object to which the pointer refers

that determines which function is invoked

TriangleShape T(W, P, Red, 1);


RectangleShape R(W,P, Yellow, 3, 2);
CircleShape C(W, P, Yellow, 4);

Shape *A[3] = {&T, &R, &C};

for (int i = 0; i < 3; ++i) {


A[i]->Draw();
} When i is 1, a
RectangleShape’s Draw() is
used
Virtual Functions
For virtual functions
 It is the type of object to which the pointer refers

that determines which function is invoked

TriangleShape T(W, P, Red, 1);


RectangleShape R(W,P, Yellow, 3, 2);
CircleShape C(W, P, Yellow, 4);

Shape *A[3] = {&T, &R, &C};

for (int i = 0; i < 3; ++i) {


A[i]->Draw();
} When i is 2, a CircleShape’s
Draw() is used
A Shape Class with a Virtual
Draw
class Shape : public WindowObject {
public:
Shape(SimpleWindow &w, const Position &p,
const color c = Red);
color GetColor() const;
void SetColor(const color c);
virtual void Draw(); // virtual function!
private:
color Color;
};
Virtual Functions
Can be invoked via either a dereferenced pointer or a
reference object
 Actual function to be invoked is determined from the

type of object that is stored at the memory location


being accessed

Definition of the derived function overrides the


definition of the base class version

Determination of which virtual function to use cannot


always be made at compile time
 Decision is deferred by the compiler to run time

 Introduces overhead
Pure Virtual Function
 Has no implementation

 A pure virtual function is specified in C++ by assigning


the function the null address within its class definition

 A class with a pure virtual function is an abstract base


class
 Convenient for defining interfaces

 Base class cannot be directly instantiated


A Shape Abstract Base Class
class Shape : public WindowObject {
public:
Shape(SimpleWindow &w, const Position &p,
const color &c = Red);
color GetColor() const;
void SetColor(const color &c);
virtual void Draw() = 0; // pure virtual
// function!
private:
color Color;
};

Das könnte Ihnen auch gefallen