Basics Machine, software, and program design JPC and JWD © 2002 McGraw-Hill, Inc.

advertisement
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
Output
Devices
Input
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 is
the steps the CPU takes to
execute an instruction
Performing the action
specified by an instruction is
known as executing the
Fetch the instruction to
which the PC points
Increment the PC
instruction
The program counter (PC)
holds the memory address of
the next instruction
Execute the fetched
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
 Printer
Joystick
 Keyboard
Microphone
Scanner
CD-ROM
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
1280
element)
pixels
 Standard resolution
across
is 640 by 480
screen
 Many cards support
resolution of 1280 by
1024 or better
 Number of colors supported varies from 16 to billions
1024
pixels
down
screen
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
 Management of the running systems
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 to develop and maintain should not exceed profit
Adaptability
 System that is adaptive is easier to alter and expand
Reusability
 Improves reliability, maintainability, and profitability
Software Engineering Principles
Abstraction
 Extract the relevant properties while ignoring inessentials
Encapsulation
 Hide and protect essential information through a controlled
interface
Modularity
 Dividing an object into smaller modules so that it is easier to
understand and manipulate
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 standpoint
 Size of the oil filter, type of spark plugs, …
Price?
Oil change?
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
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 =
Binary
addition
00010
+ 01011
01101
2
+ 11
13
Equivalent
decimal
addition
2
Binary Arithmetic
Binary
multiplication
0101
× 0011
0101
0101
0000
0000
0001111
Equivalent decimal
multiplication
5
× 3
15
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
carry as we are
using a five bit
representation
01000 Add 8 and -7
+ 11001
100001
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
// Program: Display greetings
Preprocessor
// Author(s): Ima Programmer
directives
// 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
Insertion
Ends executions
Function
statement
of main() which ends
program
Greeting Output
#include <iostream>
using namespace std;
int main() {
// Extract length and width
cout << "Rectangle dimensions: ";
float Length;
float Width;
cin >> Length >> Width;
Area.cpp
Definitions
Extraction
// Compute and insert the area
float Area = Length * Width;
Definition with
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
 Character objects
Z
5 1.28345
1
P
3.14
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 integer
 40000L
 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 precision
0.15F
floating point value
Standard scientific notation
1.45E6
0.979e-3L
L or l indicates long double
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;
float Score;
float Temperature;
int i;
int n;
char c;
float x;
Objects are uninitialized with
this definition form
(Value of a object is
whatever is in its
assigned memory location)
Arithmetic Operators
Common
 Addition
+
 Subtraction
Write m*x + b
 Multiplication
*
not mx + b
 Division
/
 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
(4
((4
((4
((4
(20 -((4
(20 -((4
/
/
/
/
/
/
5)
5)
5)
5)
5)
5)
* 2
*
*
*
*
*
+
3 * 5
% 4
2)
2)
(3 * 5)
2)
((3 * 5) % 4)
2))
((3 * 5) % 4)
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
float y = 12.5;
y
12.5
1001
1002
1003
1004
Memory Depiction
float y = 12.5;
int Temperature = 32;
y
Temperature
12.5
32
1001
1002
1003
1004
1005
1006
Memory Depiction
float y = 12.5;
int Temperature = 32;
char Letter = 'c';
y
12.5
Temperature
Letter
32
'c'
1001
1002
1003
1004
1005
1006
1007
Memory Depiction
float y = 12.5;
y
int Temperature = 32;
char Letter = 'c';
Temperature
int Number;
Letter
Number
12.5
32
'c'
-
1001
1002
1003
1004
1005
1006
1007
1008
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;
int OldStudents = 21;
NewStudents
6
OldStudents
21
Definition
int NewStudents = 6;
int OldStudents = 21;
int TotalStudents;
NewStudents
6
OldStudents
21
TotalStudents
-
Assignment Statement
int NewStudents = 6;
int OldStudents = 21;
int TotalStudents;
NewStudents
6
OldStudents
21
TotalStudents
?
TotalStudents = NewStudents + OldStudents;
Assignment Statement
int NewStudents = 6;
int OldStudents = 21;
int TotalStudents;
NewStudents
6
OldStudents
21
TotalStudents
27
TotalStudents = NewStudents + OldStudents;
Assignment Statement
int NewStudents = 6;
int OldStudents = 21;
int TotalStudents;
NewStudents
6
OldStudents
?
TotalStudents
27
TotalStudents = NewStudents + OldStudents;
OldStudents = TotalStudents;
Assignment Statement
int NewStudents = 6;
int OldStudents = 21;
int TotalStudents;
NewStudents
6
OldStudents
27
TotalStudents
27
TotalStudents = NewStudents + OldStudents;
OldStudents = TotalStudents;
Consider
int Value1 = 10;
Value1
10
Consider
int Value1 = 10;
int Value2 = 20;
Value1
10
Value2
20
Consider
int Value1 = 10;
int Value2 = 20;
int Hold = Value1;
Value1
10
Value2
20
Hold
10
Consider
int Value1 = 10;
int Value2 = 20;
int Hold = Value1;
Value1 = Value2;
Value1
?
Value2
20
Hold
10
Consider
int Value1 = 10;
int Value2 = 20;
int Hold = Value1;
Value1 = Value2;
Value1
20
Value2
20
Hold
10
Consider
int Value1 = 10;
int Value2 = 20;
int Hold = Value1;
Value1 = Value2;
Value2 = Hold;
Value1
20
Value2
?
Hold
10
Consider
int Value1 = 10;
int Value2 = 20;
int Hold = Value1;
Value1
20
Value2
10
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 = i + 1;
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
int i =
int j =
i = y;
cout <<
y = j;
cout <<
= 2.7;
15;
10;
// i is now 2
i << endl;
// y is now 10.0
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
Programmers can also define their own 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
 color is an EzWindows type
RectangleShape Objects
Examples
SimpleWindow W1("My Window", 20, 20);
SimpleWindow W2("My Other Window", 15, 10);
RectangleShape
RectangleShape
RectangleShape
RectangleShape
R(W1,
S(W2,
T(W1,
U(W1,
4,
5,
3,
4,
2, Blue, 3, 2);
2, Red, 1, 1);
1, Black, 4, 5);
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;
cout << i << endl;
float a = 3.2;
a *= 2.0;
cout << a << endl;
// i is now 7
// a is now 6.4
Increment and Decrement
C++ has special operators for incrementing
object by one
Examples
int k = 4;
++k;
//
k++;
//
cout << k << endl;
int i = k++;
//
cout << i << " " << k << endl;
int j = ++k;
//
cout << j << " " << k << endl;
or decrementing an
k is 5
k is 6
i is 6, k is 7
j is 8, k is 8
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");
int k = Saying.find("its");
// 10
// ?
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
False
False
True
True
Q
False
True
False
True
P and Q
False
False
False
True
Boolean Algebra
Or truth table
P
False
False
True
True
Q
False
True
False
True
P or Q
False
True
True
True
Boolean Algebra
Not truth table
P
False
True
not P
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
False
False
True
True
Q
False
True
False
True
P and Q
False
False
False
True
not (P and Q)
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
bool
bool
bool
bool
bool
P
Q
R
S
T
U
=
=
=
=
=
=
true;
false;
true;
(P && Q);
((!Q) || R);
!(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
 bool q = (k
 bool r = (i
 bool s = (k
< 10);
> i);
>= 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
Action is either a single
statement or a group of
statements within braces
Action
false
Example
if (Value < 0) {
Value = -Value;
}
If Value is less than
zero then we need to
update its value to
that of its additive
inverse
Is our number negative?
Value < 0
true
Value = -Value
Our number is
now definitely
nonnegative
false
If Value is not less
than zero then our
number is fine as is
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
Rearrange value1
and value2 to
put their values
in the proper
order
Are the numbers
out of order
value2 < value1
fa lse
true
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
If Expression is true then execute
Action1 otherwise execute Action2
if (v == 0) {
cout << "v is 0";
}
else {
cout << "v is not 0";
}
Expression
true
false
Action1
Action2
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
Yes, it is . So Value2 is
larger than Value1. In
this case, Max is set
to Value2
Value1 < Value2
true
Max = Value2
Either case, Max is set
correctly
Is Value2 larger than Value1
No, its not. So Value1
is at least as large as
Value2. In this case,
Max is set to Value1
false
Max = Value1
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
case 'e': case
case 'i': case
case 'o': case
case 'u': case
cout << ch
break;
default:
cout << ch
}
'A':
'E':
'I':
'O':
'U':
<< " is a vowel" << endl;
<< " 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 it
it?
 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
whether the action is to be executed
Action to be iteratively
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
executed
true
Action
false
If Expression is
false, program
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
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;
4
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
int numberProcessed = 0;
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
0
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
0
int listSize = 4;
sum
int numberProcessed = 0;
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
0
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
0
int listSize = 4;
sum
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;
0
--
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
0
int listSize = 4;
sum
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;
0
1
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
0
int listSize = 4;
sum
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;
0
1
1
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
0
1
int listSize = 4;
sum
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;
1
1
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
1
int listSize = 4;
sum
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;
1
1
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
1
int listSize = 4;
sum
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;
1
--
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
1
int listSize = 4;
sum
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;
1
5
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
1
int listSize = 4;
sum
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;
1
6
5
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
1
2
int listSize = 4;
sum
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;
6
5
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
2
int listSize = 4;
sum
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;
6
5
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
2
int listSize = 4;
sum
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;
6
--
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
2
int listSize = 4;
sum
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;
6
3
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
2
int listSize = 4;
sum
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;
6
9
3
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
2
3
int listSize = 4;
sum
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;
9
3
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
3
int listSize = 4;
sum
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;
9
3
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
3
int listSize = 4;
sum
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;
9
--
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
3
int listSize = 4;
sum
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;
9
1
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
3
int listSize = 4;
sum
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;
10
9
1
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
3
4
int listSize = 4;
sum
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;
10
1
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
3
4
int listSize = 4;
sum
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;
10
1
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
3
4
int listSize = 4;
sum
int numberProcessed = 0;
average
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
10
2.5
Suppose input contains: 1 5 3 1 6
Execution Trace
listSize
4
numberProcessed
3
4
int listSize = 4;
sum
int numberProcessed = 0;
average
double sum = 0;
while (numberProcessed < listSize) {
double value;
cin >> value;
sum += value;
++numberProcessed;
}
double average = sum / numberProcessed ;
cout << "Average: " << average << endl;
10
2.5
Suppose input contains: 1 5 3 1 6
Execution Trace
Stays in stream until
extracted
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;
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
The value of the input
int numberProcessed = 0;
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
empty?
++numberProcessed;
}
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
execution
If ForExpr is
true, Action is
executed
After the Action
has completed,
the
PostExpression
is evaluated
ForInit
ForExpr
true
Action
PostExpr
After evaluating the
PostExpression, the next
iteration of the loop starts
The ForExpr is
evaluated at the
start of each
iteration of the
loop
false
If ForExpr is
false, program
execution
continues with
next statement
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
0
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
0
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
i is 0
0
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
i is 0
0
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
i is 0
1
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
1
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
i is 0
i is 1
1
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
i is 0
i is 1
1
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
i is 0
i is 1
2
Execution Trace
i
for (int i = 0; i < 3; ++i) {
cout << "i is " << i << endl;
}
cout << "all done" << endl;
i is 0
i is 1
2
Execution Trace
i
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
2
Execution Trace
i
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
2
Execution Trace
i
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
3
Execution Trace
i
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
3
Execution Trace
i
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
3
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
int
int
int
int
Counter1
Counter2
Counter3
Counter4
Counter5
=
=
=
=
=
0;
0;
0;
0;
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;
Only extracts
char c;
nonblank characters
while (cin >> c) {
++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;
File Processing
#include <iostream>
#include <fstream>
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;
}
}
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
 Execute Action
 If Expression is true then
execute Action again
 Repeat this process until
Expression evaluates to
false
Action is either a single
statement or a group of
statements within braces
Action
true
Expression
false
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 a;
double f(double x) {
cin >> a;
y = f(a);
double result =
cout << y;
x*x + 2*x + 5;
Value of a is given to x
return result;
}
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;
Activation record is large
x*x + 2*x + 5;
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;
Possibly a pointer to the
x*x + 2*x + 5;
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;
y = f(a);
double result =
cout << y;
x*x + 2*x + 5;
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;
y = f(a);
double result =
cout << y;
x*x + 2*x + 5;
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
the function returns
A description of the form the
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
the function returns
A description of the form the
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
Process
preprocessor
directives to
produce a
translation
unit
Check
translation
unit for legal
syntax and
compile it into
an object file
Link object file
with standard
object files
and other
object files to
produce an
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
 C++ has many other libraries
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>
Library header files
#include <cmath>
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();
sout.close();
// done with in1.txt
// 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();
sout.close();
// done with in2.txt
// 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
Local
object
definition
Function name
Formal parameter
float CircleArea (float r) {
const float Pi = 3.1415;
return Pi * r * r;
}
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
Activation record memory is automatically released at function
completion
Information to function
can come from
parameters or an input
stream
Parameters
Input stream
data
Function
Output stream
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;
{
int j = 10;
cout << i << j << endl;
i = 2;
cout << i << j << endl
}
cout << i << endl;
cout << j << endl;
}
// insert 1
// insert 1 10
// insert 2 10
// insert 2
// 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;
{
cout << i << endl;
char i = 'a';
cout << i << endl;
}
cout << i << endl;
}
cout << i << endl;
}
// insert 1
// insert 1
// insert a
// insert 1
// 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;
{
char i = 'a';
cout << i << endl;
::i = 2;
cout << i << endl;
cout << ::i << endl;
}
cout << i << endl;
return 0;
}
// insert 1
// insert a
// insert a
// insert 2
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 =
int j =
Swap(i,
int a =
int b =
Swap(b,
5;
6;
j);
7;
8;
a);
void Swap(int &a, int &b) {
int Temp = a;
a = b;
b = Temp;
return;
}
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
th argument in the function invocation,
 If there is no i
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"
Passed by reference, do not want
class RectangleShape {
a copy of the window
public:
// constructor
Access
RectangleShape(SimpleWindow &Window,
right
float XCoord, float YCoord, const color &c,
indicates
float Width, float Height);
no
// facilitator
limitations
void Draw();
on who
ezwin.h get us definitions of
can use
these
members
SimpleWindow and color
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
SimpleWindow &Window;
float thisXCenter;
float thisYCenter;
color thisColor;
float thisWidth;
float thisHeight;
A client cannot
directly access either
private or protected
data members
};
#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
Access
denied
Private access

Only class
members
have access
Access from
to the
outside of class
private
members
Private data
members and
member functions
Public data
members and
member functions
C: RectangleShape
DM: Window, Color,
XCenter, YCenter,
Width, Height
MF: Draw(), GetColor(), GetSize(),
GetWidth(), GetHeight(), GetPosition(),
GetWindow(), SetColor(),
SetPosition(),SetSize()
Instantiations
O: R1
DM: Window: &W,
Color: Cyan,
XCenter: 1, YCenter: 4
Width: 3, Height: 3
O: R2
DM: Window: &W,
Color: Red,
XCenter: 6, YCenter: 4
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
a c ad + bc
+ =
b d
bd

Subtraction
a c
ad - bc
=
b d
bd
Multiplication
a c ac
* =
b d bd
Division
a c ad
/ =
b d bc
Abstract Data Type
Consider
Rational a(1,2);
// a =
Rational b(2,3);
// b =
cout << a << " + " << b <<
Rational s;
// s =
Rational t;
// t =
cin >> s >> t;
cout << s << " * " << t <<
1/2
2/3
" = " << a + b;
0/1
0/1
" = " << 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
Rational a(1,2);
Object a
Attributes:
NumeratorValue(1)
DenominatorValue(2)
Instantiation
Rational b(2,3);
Object b
Attributes:
NumeratorValue(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
access to the class definition
and to auxiliary function
prototypes. The header file
does not provide member and
auxiliary definitions
#include <iostream>
using namespace std;
#include "rational.h"
int main() {
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 library file
Producing MyProgram.exe
MyProgram.cpp
Process
preprocessor
directives to
produce a
translation
unit
Check
translation unit
for legal syntax
and compile it
into object file
MyProgram.obj
Link object file
with standard
library files
and rational
library file to
produce
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 s;
r.Extract(cin);
s.Extract(cin);
Rational t = r.Add(s);
t.Insert(cout);
Rational r;
Rational s;
cin >> r;
cin >> s;
Rational t = r + s;
cout << t;
Natural look
Should << be a member?
 Consider
r << cout;
Const Power
const Rational OneHalf(1,2);
cout << OneHalf;
cin >> OneHalf;
// legal
// illegal
Rational Implementation
#include <iostream>
#include <string>
using namespace std;
#include "rational.h"
// Start of rational.cpp
Is this necessary?
// default constructor
Rational::Rational() {
SetNumerator(0);
SetDenominator(1);
}
Example
Rational r;
Which objects are
being referenced?
// 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);
Rational u(2);
// t = 2/3
// 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;
cout << t << endl;
// unnatural
// 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);
cin >> t;
// unnatural
// 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);
return *this;
}
a = b;
a = b = c;
*this is C++ syntax for the
object whose member
function was invoked
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
values in
list
Name
of list
Bracketed constant
expression
indicating number
of elements in list
double X [ 100 ] ;
// Subscripts are 0 through 99
Example Definitions
Suppose
const
const
const
const
int
int
int
int
N = 20;
M = 40;
MaxStringSize = 80;
MaxListSize = 1000;
Then the following are all correct array definitions
int A[10];
// array of
char B[MaxStringSize];
// array of
double C[M*N];
// array of
int Values[MaxListSize]; // array of
Rational D[N-15];
// array of
10 ints
80 chars
800 floats
1000 ints
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
A[10]
// does not exist
Array Elements
Suppose
int A[10];
A
// array of 10 uninitialized ints
----------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);
Could we just
int SmallestValueSoFar = A[0];
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;
int List[3];
List[0] = 9;
Notice no brackets
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;
vector<float> B;
vector<Rational> C;
// 0 ints
// 0 floats
// 0 Rationals
Construction
Basic construction
Container name
vector<T> List(SizeExpression);
Base element type
Example
vector<int> A(10);
//
vector<float> B(20);
//
vector<Rational> C(5); //
int n = PromptAndRead();
vector<int> D(n);
//
Number of
elements to be
default
constructed
10 ints
20 floats
5 Rationals
n ints
Construction
Basic construction
Container name
Initial value
vector<T> List(SizeExpression, Value);
Number of
elements to be
Base element type
default
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);
const vector<int> B(4, 0);
// A: 0 0 0 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;
++p;
cout << *p;
--p;
cout << *p;
reverse_iterator q = List.rbegin();
cout << *q;
++q;
cout << *q;
--q;
cout << *q;
// 100
// 101
// 100
// 102
// 101
// 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
IOEPTYURWQ
EOIPTYURWQ
EOIPTYURWQ
EIOPTYURWQ
EIOPTYURWQ
EIOPTYURWQ
EIOPQYURWT
EIOPQYURWT
EIOPQRTUWY
EIOPQRTUWY
EIOPQRTUWY
EIOPQRTUWY
EIOPQRTUWY
EIOPQRTUWY
9…9
8…9
7…9
5…9
4…9
7…6
5…5
4…3
0…9
2…2
1…2
0…2
1…0
0 … -1
8…7
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
}
of elements
else if (a == b) {
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
A[0]:
A[1]:
A[2]:
A[3]:
A[4]:
A[5]:
A[6]:
in the following manner:
"A"
"list"
"of"
"words"
"to"
"be"
"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
A[0]:
A[1]:
A[2]:
A[3]:
A[4]:
A[5]:
A[6]:
following manner
"A"
"list"
"of"
"words"
"to"
"be"
"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][3] M[1][0]
M[1][3]
M[0][0]
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
User start
C: S i m p l e W i n d o w
 Key down
Mouse click
 Key up
Timer tick
 Refresh
C: U s e r
User end
 Quit
 Timer
Handle messages by
registering a call back
Program
EzWindows Coordinate System
Use centimeters
 Metric
 Simpler to understand
than pixels
 Device independent
 Helps introduce notion
of information hiding
or encapsulation
X coordinate: dis tance
from left edge of
s creen (4 cm )
Y coordinate:
dis tance from top
of s creen (4 cm )
H eight of w indow (5 cm )
Length of w indow (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 coordinat e of t he
bounding box
Message
Second coordinat e of
t he 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 clicked
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
Rvalue expressions
 Represent objects that
Consider
int a;
vector<int> b(3);
int c[3];
a = 1;
c[0] = 2*a + b[0];
can be evaluated and modified
can only be evaluated
// a: lvalue
// 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
int *iPtr;
char *s;
Rational *rPtr;
Examples of initialized
int i = 1;
char c = 'y';
int *ptr = &i;
char *t = &c;
//
//
//
//
Indicates pointer object
iPtr is a pointer to an int
s is a pointer to a char
rPtr is a pointer to a
Rational
pointers
Indicates to take the address of the object
// ptr is a pointer to int i
// 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 = 2;
cout << i << endl;
// ptr points to i
// 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 = 3;
//
ptr = &j;
//
*ptr = 4;
//
cout << i << " "
ptr points to
contents of i
ptr points to
contents of j
<< j << endl;
location of i
are updated
location of j
are updated
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 points (r)
(*rPtr).Insert(cout);
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 used to
int main() {
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
parameters
 Object memory is
acquired automatically

Object memory is
returned automatically
when object goes out of
scope
Dynamic object
objects



Object memory is
acquired by program with
an allocation request
 new operation
Dynamic objects can
exist beyond the function
in which they were
allocated
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);
i pt r
rptr
10
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
R
—
5
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
And then
B 3
A[2] = 2;
Then

B[2] is changed!

Not what a client would expect
Implication
 Must use tailored copy constructor
1
2
1
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 has its
destructor invoked
Notice the tilde
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
Bikes
Racing
Bikes
Tandem
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
Bikes
Racing
Bikes
Tandem
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
Hierarchy
C: WindowObject
DM: Location, Window
MF: GetPosition(), GetWindow(), SetPosition()
C: Shape
DM: Color
MF: GetColor(), SetColor()
C: EllipseShape
DM: Width, Height
MF: Draw(),
GetWidth(),
GetHeight(), SetSize()
C: RectangleShape
DM: Width, Height
MF: Draw(), GetWidth(),
GetHeight(), SetSize()
C: Label
C: TriangleShape
DM: SideLength
MF: Draw(),
GetSideLength(),
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)
Derived class name
Class name of
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(),
color GetColor() const; and SetPosition()
void SetColor(const color &c);
private:
color Color;
};
Implementing A Derived Class
Constructor
Derived
class
name
Derived
class
constructor
parameter
list
Base
class
name
Base class
constructor
parameter list
(sublist of PList)
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
Width
WIdth
Height
TriangleShape
SideLength
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;
};
EllipseShape
#include "shape.h"
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"
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;
}
Using Shapes
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
public
protected
private
Base class member
access
Derived class
member access
public
public
protected
protected
private
inaccessible
public
protected
protected
protected
private
inaccessible
public
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 functions
return a;
will return a value
Instantiated functions
else
whose type is the
require two actual
return b;
actual template
parameters of the
}
parameter
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)
return a;
Operator < needs to be defined for
else
for the actual template parameter
type. If < is not defined, then a
return b;
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
 for_each()
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 constructed
class Array {
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
In C++ we can come close
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;
};
Download