Sie sind auf Seite 1von 560

Basics

Machine, software, and program design

JPC and JWD 2002 McGraw-Hill, Inc.

Computer Organization
CPU - central processing unit Where decisions are made, computations are performed, and input/output requests are delegated Memory Stores information being processed by the CPU Input devices Allows people to supply information to computers Output devices Allows people to receive information from computers

Computer Organization
Memory 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 instruction The program counter (PC) holds the memory address of the next instruction Fetch the instruction to which the PC points

Increment the PC

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 User Simplicity Low

Complexity

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, P r ic e ? O il c h a n g e ?

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 radios 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 Ignition system Battery

Thermostat

Water pump

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 2

00010 = 0 24 + 0 23 + 0 22 + 1 21 + 0 20 =

Binary addition

00010 + 01011 01101

2 + 11 13

Equivalent decimal addition

Binary Arithmetic
Binary multiplication Equivalent decimal multiplication

0101 0011 0101 0101 0000 0000 0001111

5 3 15

Twos 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

Twos 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


Preprocessor // Program: Display greetings directives // Author(s): Ima Programmer // Date: 1/24/2001 Comments #include <iostream> #include <string> Provides simple access using namespace std; Function int main() { named cout << "Hello world!" << endl; main() return 0; indicates } start of program 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; // Compute and insert the area float Area = Length * Width;

Area.cpp
Definitions Extraction

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

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 / / / / / / 5) 5) 5) 5) 5) 5) * 2 + 3 * 5 % 4

(4 ((4 ((4 ((4 (20 -((4 (20 -((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; y int Temperature = 32; char Letter = 'c'; Temperature Letter
12.5 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
Basic form object = expression ; Target becomes source

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 OldStudents 6 21

Definition
int NewStudents = 6; int OldStudents = 21; int TotalStudents;
NewStudents OldStudents TotalStudents 6 21 -

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

TotalStudents = NewStudents + OldStudents;

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

TotalStudents = NewStudents + OldStudents;

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

TotalStudents = NewStudents + OldStudents; OldStudents = TotalStudents;

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

TotalStudents = NewStudents + OldStudents; OldStudents = TotalStudents;

Consider
int Value1 = 10;
Value1 10

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

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

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

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

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

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

We swapped the values of objects Value1 and Value2 using Hold as temporary holder for Value1s starting value!

Incrementing
int i = 1;
i 1

Incrementing
int i = 1;
i 1

i = i + 1;

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

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 object by one Examples int k = 4; ++k; k++; cout << k << int i = k++; cout << i << int j = ++k; cout << j << operators for incrementing or decrementing an

// k is 5 // k is 6 endl; // i is 6, k is 7 " " << k << endl; // j is 8, k is 8 " " << k << endl;

Class string
Some string member functions

size() determines number of characters in the string string Saying = "Rambling with Gambling"; cout << Saying.size() << endl; // 22 substr() determines a substring (Note first position has index 0) string Word = Saying.substr(9, 4); // with find() computes the position of a subsequence int j = Saying.find("it"); 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)) ((((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 If the Expression is true then execute Action

Expression

true Action

false

Action is either a single statement or a group of statements within braces

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
Value < 0 true false

Is our number negative?

Value = -Value

If Value is not less than zero then our number is fine as is

Our number is now definitely nonnegative

Sorting Two Numbers


cout << "Enter two integers: "; int Value1; int Value2; cin >> Value1 >> Value2; if (Value1 > Value2) { int RememberValue1 = Value1; Value1 = Value2; Value2 = RememberValue1; } cout << "The input in sorted order: " << Value1 << " " << Value2 << endl;

Semantics
Rearrange value1 and value2 to put their values in the proper order
value2 < value1 true

Are the numbers out of order

false

int rememberValue1 = value1 value1 = value2 value2 = rememberValue1

The numbers were rearranged into the proper order The numbers were initially in order The numbers are in order

What is the Output?


int m = 5; int n = 10; if (m < n) ++m; ++n; cout << " m = " << m << " n = " n << endl;

The If-Else Statement


Syntax if (Expression) Action1 else Action2 If Expression is true then execute Action1 otherwise execute Action2 if (v == 0) { cout << "v is 0"; } else { cout << "v is not 0"; } true

Expression 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

Is Value2 larger than Value1

No, its not. So Value is at least as large a Value2. In this case Max is set to Value
false

Max = Value2

Max = Value1

Either case, Max is set correctly

Selection
It is often the case that depending upon the value of an expression we want to perform a particular action Two major ways of accomplishing this choice

if-else-if statement if-else statements glued together Switch statement An advanced construct

An If-Else-If Statement
if ( nbr < 0 ){ cout << nbr << " is negative" << endl; } else if ( nbr > 0 ) { cout << nbr << " is positive" << endl; } else { cout << nbr << " is zero" << endl; }

A Switch Statement
switch (ch) { case 'a': case 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
L o g ic a l e x p r e s s io n t h a t d e t e rm in e s A c t io n to b e ite r a t iv e ly w h e t h e r t h e a c t i o n i s t o b e e x e c u t e dp e r f o r m e d u n t i l l o g i c a l e x p re s s io n is fa ls e

w h i l e ( E x p r e s s io n

) A c t io n

While Semantics

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

Expression

If Expression is true, Action is executed

true

false

Action

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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 0

numberProcessed 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 0 0

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 0 0

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 0 0 --

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 0 0 1

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 0 0 1 1

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 0 1 1 1

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 1 1 1

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 1 1 --

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 1 1 5

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 1 6 1 5

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 2 1 6 5

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 2 6 5

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 2 6 --

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 2 6 3

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 2 9 6 3

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 3 2 9 3

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 3 9 3

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 3 9 --

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 3 9 1

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 3 10 9 1

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 4 3 10 1

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 4 3 10 1

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 4 3 10 2.5

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace

listSize

4 4 3 10 2.5

numberProcessed 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;

Suppose input contains: 1 5 3 1 6

Execution Trace
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;

Stays in stream until extracted

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 ) { What if list is sum += value; 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

ForInit

The ForExpr is evaluated at the start of each iteration of the loop

If ForExpr is true, Action is executed After the Action has completed, the PostExpression is evaluated

ForExpr true false

Action

If ForExpr is false, program execution continues with next statement

PostExpr

After evaluating the PostExpression, the next iteration of the loop starts

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; 0

i is 0

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

i is 0

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

i is 0

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; 1

i is 0 i is 1

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

i is 0 i is 1

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

i is 0 i is 1

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

i is 0 i is 1

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

i is 0 i is 1 i is 2

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

i is 0 i is 1 i is 2

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

i is 0 i is 1 i is 2

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

i is 0 i is 1 i is 2

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

i is 0 i is 1 i is 2 all done

Table Revisiting
const int TableSize = 20; long Entry = 1; cout << "i" << "\t\t" << "2**i" << endl; for (int i = 0; i <= TableSize; ++i) { cout << i << "\t\t" << Entry << endl; Entry *= 2; }

Table Revisiting
const int TableSize = 20; long Entry = 1; cout << "i" << "\t\t" << "2**i" << endl; for (int i = 0; i < TableSize; ++i) { cout << i << "\t\t" << Entry << endl; Entry = 2 * Entry; } cout << "i is" << i << endl; // illegal The scope of i is limited to the loop!

Displaying a Diagonal
SimpleWindow W("One diagonal", 5.5, 2.25); W.Open(); for (int j = 1; j <= 3; ++j) { float x = j * 0.75 + 0.25; float y = j * 0.75 - 0.25; float Side = 0.4; RectangleShape S(W, x, y, Blue, Side, Side); S.Draw(); }

Sample Display

Displaying Three Diagonals


SimpleWindow W("Three diagonals", 6.5, 2.25); W.Open(); for (int i = 1; i <= 3; ++i) { for (int j = 1; j <= 3; ++j) { float x = i - 1 + j * 0.75 + 0.25; float y = j * 0.75 - 0.25; float Side = 0.4; RectangleShape S(W, x, y, Blue, Side, Side); S.Draw(); } The scope of i includes the inner loop. } The scope of j is just the inner loop.

Sample Display

int 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;

#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; } }

File Processing

Iteration Dos
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 Dont 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; double result = y = f(a); x*x + 2*x + 5; cout << y; return result; Value of a is given to x }

Invocation Process
Flow of control is temporarily transferred to the invoked function Local objects are also maintained in the invocations activation record. Even main() has a record
cout << "Enter number: "; double a; double f(double x) { cin >> a; y = f(a); double result = cout << y; x*x + 2*x + 5; Activation record is large enough to store values return result; associated with each object } that is defined by the function

Invocation Process
Flow of control is temporarily transferred to the invoked function Other information may also be maintained in the invocations activation record
cout << "Enter number: "; double a; double f(double x) { cin >> a; y = f(a); double result = cout << y; x*x + 2*x + 5; Possibly a pointer to the current statement being return result; executed and a pointer to } the invoking statement

Invocation Process
Flow of control is temporarily transferred to the invoked function Next statement executed is the first one in the invoked function
cout << "Enter number: "; double a; double f(double x) { cin >> a; double result = y = f(a); x*x + 2*x + 5; cout << y; return result; }

Invocation Process
Flow of control is temporarily transferred to the invoked function After function completes its action, flow of control is returned to the invoking function and the return value is used as value of invocation cout << "Enter number: "; double a; double f(double x) { cin >> a; double result = y = f(a); x*x + 2*x + 5; cout << y; return result;
}

Execution Process
Function body of invoked function is executed Flow of control then returns to the invocation statement The return value of the invoked function is used as the value of the invocation expression

Function Prototypes
Before a function can appear in an invocation its interface must be specified Prototype or complete definition
Type of value that 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: STLs 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 Function name Formal parameter float CircleArea (float r) { const float Pi = 3.1415; return Pi * r * r; } Function body

Local object definition

Return statement

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, Dont 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

Dont 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; }

Doesnt 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 parameters 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; Passed by reference -- in an return; 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

If there is no ith argument in the function invocation, pnamei is initialized to dvaluei

The parameter pnamei is an optional value parameter


Optional reference parameters are also permitted

Consider
void PrintChar(char c = '=', int n = 80) { for (int i = 0; i < n; ++i) cout << c; } What happens in the following invocations? PrintChar('*', 20); PrintChar('-'); PrintChar();

Default Parameters
Default parameters must appear after any mandatory parameters

Bad example void Trouble(int x = 5, double z, double y) { ... } Cannot come before mandatory parameters

Default Parameters
Consider bool GetNumber(int &n, istream &sin = cin) { return sin >> n ; } Some possible invocations int x, y, z; ifstream fin("Data.txt"); GetNumber(x, cin); GetNumber(y); GetNumber(z, fin); Design your functions for ease and reuse!

Function Overloading
A function name can be overloaded Two functions with the same name but with different interfaces Typically this means different formal parameter lists Difference in number of parameters Min(a, b, c) Min(a, b) Difference in types of parameters Min(10, 20) Min(4.4, 9.2)

Function Overloading
int Min(int a, int b) { cout << "Using int min()" << endl; if (a > b) return b; else return a; } double Min(double a, double b) { cout << "Using double min()" << endl; if (a > b) return b; else return a; }

Function Overloading
int main() { int a = 10; int b = 20; double x = 4.4; double y = 9.2; int c = Min(a, b); cout << "c is " << c << endl; int z = Min(x, y); cout << "z is " << z << endl; return 0; }

Function Overloading
Compiler uses function overload resolution to call the most appropriate function First looks for a function definition where the formal and actual parameters exactly match If there is no exact match, the compiler will attempt to cast the actual parameters to ones used by an appropriate function The rules for function definition overloading are very complicated Advice Be very careful when using this feature

Random Numbers
Generating a sequence of random numbers is often useful In a game, it ensures that a player does not see the same behavior each time In a simulation of a complex system, random numbers can be used to help generate random events Car crash in a simulation of a highway system Likelihood of a gene in cell mutation Weather simulation

Uniform Random Numbers


Uniform random number sequence A sequence of random numbers where Each value in the sequence is drawn from the same range of numbers In each position of the sequence, any value in the number range is equally likely to occur

Random Numbers
Examples Generate a uniform random number sequence in the range 1 to 6 Use a fair six-sided die Each roll represents a new random number

Generate a uniform random number sequence in the range 1 to 2 Use a fair coin Heads: 1, Tails: 2

Random Numbers
We can write an algorithm for generating what looks like random numbers 30 21 9 28 29 ...

Because its 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 limitations // facilitator 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 wont 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
private: // data members SimpleWindow &Window; float thisXCenter; float thisYCenter; color thisColor; float thisWidth; float thisHeight; }; #endif Close of #ifndef directive Access right A client cannot directly access either private or protected data members

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

Multiplication
a c ac * = b d bd

Subtraction
a c ad - bc = 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 b(2,3); Object b Attributes: NumeratorValue(2) DenominatorValue(3)

Instantiation Rational a(1,2); Object a Attributes: NumeratorValue(1) DenominatorValue(2)

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
#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; } 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

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 Link object file with standard library files and rational library file to produce executable unit

Process preprocessor directives to produce a translation unit

Check translation unit for legal syntax and compile it into object file MyProgram.obj

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" // default constructor Rational::Rational() { SetNumerator(0); SetDenominator(1); } Example Rational r; // r = 0/1 // Start of rational.cpp

Is this necessary?

Which objects are being referenced?

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; // unnatural cout << t << endl; // natural

Auxiliary Extraction Operator


// extracting a Rational istream& operator>>(istream &sin, Rational &r) { r.Extract(sin); return sin; } Why a reference return? We can do either t.Extract(cin); cin >> t; // unnatural // natural

Whats 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 Bracketed constant expression indicating number of elements in list

Name of list

double X [ 100 ] ;
// Subscripts are 0 through 99

Example Definitions
Suppose const int N = 20; const int M = 40; const int MaxStringSize = 80; const int MaxListSize = 1000; Then the following are all correct array definitions int A[10]; // array of 10 ints char B[MaxStringSize]; // array of 80 chars double C[M*N]; // array of 800 floats int Values[MaxListSize]; // array of 1000 ints Rational D[N-15]; // array of 5 Rationals

Subscripting
Suppose int A[10]; // array of 10 ints A[0], A[9] To access individual element must apply a subscript to list name A A subscript is a bracketed expression also known as the index First element of list has index 0 A[0] Second element of list has index 1, and so on A[1] Last element has an index one less than the size of the list A[9] Incorrect indexing is a common error 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
Basic construction vector<T> List; Base element type Example vector<int> A; vector<float> B; vector<Rational> C; Container name

// 0 ints // 0 floats // 0 Rationals

Construction
Basic construction Container name vector<T> List(SizeExpression); Base element type Number of elements to be default constructed

Example vector<int> A(10); // 10 ints vector<float> B(20); // 20 floats vector<Rational> C(5); // 5 Rationals int n = PromptAndRead(); vector<int> D(n); // n ints

Construction
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
99 89 79 59 49 43 09 12 02
0 -1

87 76

55

22

10

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[i] = toupper(t[i]); } cout << t << endl; // t: PEOPLE // t: people for (int i = 0; i < t.size(); ++i) {

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 os
The following counts number of os within A count = 0; for (int i Size of A = 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: SimpleWindow Key down Mouse click Key up Timer tick Refresh C: User end Quit Timer Handle messages by registering a call back

User Program

EzWindows Coordinate System


Use centimeters Metric Simpler to understand than pixels Device independent Helps introduce notion of information hiding or encapsulation
X c o o r d i n a te : d i s ta n c e Y c o o r d i n a te : fr o m le ft e d g e o f d i s ta n c e fr o m to p s c re e n (4 c m ) o f s c r e e n (4 c m )

H e ig h t o f w in d o w (5 c m )

L e n g th o f w in d o w (1 0 c m )

Class Position
For earlier objects, the position was specified by given both an x-coordinate and a y-coordinate We can now introduce a new object called Position and use it

Position
class Position { public: Position(float x = 0.0, float y = 0.0); float GetXDistance() const; float GetYDistance() const; Position Add(const Position &p) const; protected: void SetXDistance(float x); void SetYDistance(float y); private: float XDistance; float YDistance; }; Position operator+(const Position &x, const Position &y);

EzWindows Auxiliary Functions


long int GetMilliseconds() Returns the value of a timer that is ticking continuously. The resolution of the timer is milliseconds. void Terminate() Sends a terminate message to the EzWindows window manager.

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

Hello EzWindows
#include <assert.h> #include "ezwin.h" // Create a 10 x 4 window SimpleWindow HelloWindow("Hello EzWindows", 10.0, 4.0, Position(5.0, 6.0)); // ApiMain(): create a window and display greeting int ApiMain() { HelloWindow.Open(); assert(HelloWindow.GetStatus() == WindowOpen); // Get Center of Window Position Center = HelloWindow.GetCenter();

Hello EzWindows
// Create bounding box for text Position UpperLeft = Center + Position(-1.0, -1.0); Position LowerRight = Center + Position(1.0, 1.0); // Display the text HelloWindow.RenderText(UpperLeft, LowerRight, "Hello EzWindows", Black, White); } return 0;

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

Class SimpleWindow
Simple Window constructor SimpleWindow::SimpleWindow( const string &t = "Untitled float w = 8, float h = 8, const Position &p = Position(0,0) )

Bitmaps

Class BitMap
Uses BitMapStatus enum BitMapStatus { NoBitMap, BitMapOkay, NoWindow };

Class BitMap
Class BitMap can display .bmp files in a SimpleWindow window BitMaps 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 were 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 can be evaluated and modified Rvalue expressions Represent objects that can only be evaluated Consider int a; vector<int> b(3); int c[3]; a = 1; // a: lvalue c[0] = 2*a + b[0]; // c[0], a, b[0]: lvalues Observation Not all lvalues are the names of objects

Basics
Pointer Object whose value represents the location of another object

In C++ there are pointer types for each type of object


Pointers to int objects Pointers to char objects Pointers to RectangleShape objects

Even pointers to pointers


Pointers to pointers to int objects

Syntax
Examples of uninitialized pointers int *iPtr; char *s; Rational *rPtr; Indicates pointer object // iPtr is a pointer to an int // s is a pointer to a char // rPtr is a pointer to a // Rational Examples of initialized pointers int i = 1; Indicates to take the address of the object char c = 'y'; int *ptr = &i; // ptr is a pointer to int i char *t = &c; // t is a pointer to a char c

Memory Depiction
int i = 1; char c = 'y'; int *ptr = &i; char *t = &c

Indirection Operator
An asterisk has two uses with regard to pointers

In a definition, it indicates that the object is a pointer char *s; // s is of type pointer to char

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

int i = 1; int *ptr = &i; // ptr points to i *ptr = 2; cout << i << endl; // display a 2 * indicates indirection or dereferencing *ptr is an lvalue

Address Operator
& use is not limited to definition initialization int i = 1; int j = 2; int *ptr; ptr = &i; // *ptr = 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 Dynamic objects object

Object memory is returned automatically when object goes out of scope

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);

iptr 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 2/3 5 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 B 0 1 2 3 4

delete [] A; Locations do not belong to program A B

Memory Leak Pitfall


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

A = new int [5];


These locations cannot be accessed by program A 0 1 2 3 4

A Simple Dynamic List Type


What we want

An integer list data type IntList with the basic features of the vector data type from the Standard Template Library

Features and abilities

True object Can be passed by value and reference Can be assigned and copied Inspect and mutate individual elements Inspect list size Resize list Insert and extract a list

Sample IntList Usage


IntList A(5, 1); IntList B(10, 2); IntList C(5, 4); for (int i = 0, i < A.size(); ++i) { A[i] = C[i]; } cout << A << endl; // [ 4 4 4 4 4 ] A = B; A[1] = 5; cout << A << endl; // [ 5 2 2 2 2 2 2 2 2 2 ]

IntList Definition
class IntList { public: // constructors IntList(int n = 10, int val = 0); IntList(const int A[], int n); IntList(const IntList &A); // destructor ~IntList(); // inspector for size of the list int size() const; // assignment operator IntList & operator=(const IntList &A);

IntList Definition (continued)


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

IntList Definition (continued)


private: // data members int *Values; // pointer to elements int NumberValues; // size of list }; // IntList auxiliary operators -- nonmembers ostream& operator<<(ostream &sout, const IntList &A); istream& operator>>(istream &sin, IntList &A);

Default Constructor
IntList::IntList(int n, int val) { assert(n > 0); NumberValues = n; Values = new int [n]; assert(Values); for (int i = 0; i < n; ++i) { Values[i] = val; } }

Gang of Three Rule


If a class has a data member that points to dynamic memory then that class normally needs a class-defined

Copy constructor Constructor that builds an object out of an object of the same type Member assignment operator Resets an object using another object of the same type as a basis Destructor Anti-constructor that typically uses delete the operator on the data members that point to dynamic memory

Why A Tailored Copy Constructor


Suppose we use the default copy constructor IntList A(3, 1); 3 IntList B(A); A 1 And then B 3 A[2] = 2; Then B[2] is changed! Not what a client would expect Implication Must use tailored copy constructor

Tailored Copy Constructor


IntList::IntList(const IntList &A) { NumberValues = A.size(); Values = new int [size()]; assert(Values); for (int i = 0; i < size(); ++i) Values[i] = A[i]; } What kind of subscripting is being performed?

Gang Of Three
What happens when an IntList goes out of scope? If there is nothing planned, then we would have a memory leak Need to have the dynamic memory automatically deleted Define a destructor A class object going out of scope automatically 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

Wouldnt 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

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

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: Label

C: EllipseShape DM: Width, Height MF: Draw(), GetWidth(), GetHeight(), SetSize()

C: RectangleShape DM: Width, Height MF: Draw(), GetWidth(), GetHeight(), SetSize()

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 members Window, Location, const Position &p, GetPosition(), GetWindow(), const color &c = Red); and SetPosition() color GetColor() const; 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 TriangleShape

WIdth Height

Width Height

SideLength

TriangleShape
#include "shape.h" class TriangleShape : public Shape { public: TriangleShape(SimpleWindow &w, const Position &p, const color &c = Red, float slen = 1); float GetSideLength() const; void SetSize(float slen); void Draw(); private: float SideLength; };

#include "shape.h" 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; };

EllipseShape

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 Base class member access public public protected private public protected protected private public private protected private Derived class member access public protected inaccessible protected protected inaccessible 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 for the actual template parameter else 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; } } }

STLs 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 TriangleShapes } 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 RectangleShapes } 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 CircleShapes } Draw() is used

A Shape Class with a Virtual Draw


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

Virtual Functions
Can be invoked via either a dereferenced pointer or a reference object Actual function to be invoked is determined from the type of object that is stored at the memory location being accessed Definition of the derived function overrides the definition of the base class version Determination of which virtual function to use cannot always be made at compile time Decision is deferred by the compiler to run time Introduces overhead

Pure Virtual Function


Has no implementation A pure virtual function is specified in C++ by assigning the function the null address within its class definition A class with a pure virtual function is an abstract base class Convenient for defining interfaces Base class cannot be directly instantiated

A Shape Abstract Base Class


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

Das könnte Ihnen auch gefallen