Search for notes by fellow students, in your own course and all over the country.

Browse our notes for titles which look like what you need, you can preview any of the notes via a sample of the contents. After you're happy these are the notes you're after simply pop them into your shopping cart.

My Basket

You have nothing in your shopping cart yet.

Title: c++ easy learning
Description: C++ (pronounced as cee plus plus, /ˈsiː plʌs plʌs/) is a general-purpose programming language. It has imperative, object-oriented and generic programming features, while also providing facilities for low-level memory manipulation. It was designed with a bias toward system programming and embedded, resource-constrained and large systems, with performance, efficiency and flexibility of use as its design highlights.[3] C++ has also been found useful in many other contexts, with key strengths being software infrastructure and resource-constrained applications,[3] including desktop applications, servers (e.g. e-commerce, web search or SQL servers), and performance-critical applications (e.g. telephone switches or space probes).[4] C++ is a compiled language, with implementations of it available on many platforms and provided by various organizations, including the FSF, LLVM, Microsoft, Intel and IBM. C++ is standardized by the International Organization for Standardization (ISO), with the latest (and current) standard version ratified and published by ISO in December 2014 as ISO/IEC 14882:2014 (informally known as C++14).[5] The C++ programming language was initially standardized in 1998 as ISO/IEC 14882:1998, which was then amended by the C++03, ISO/IEC 14882:2003, standard. The current C++14 standard supersedes these and C++11, with new features and an enlarged standard library. Before the initial standardization in 1998, C++ was developed by Bjarne Stroustrup at Bell Labs since 1979, as an extension of the C language as he wanted an efficient and flexible language similar to C, which also provided high-level features for program organization. Many other programming languages have been influenced by C++, including C#, Java, and newer versions of C (after 1998)

Document Preview

Extracts from the notes are below, to see the PDF you'll receive please use the links above


C++ PROGRAMMING:
FROM PROBLEM ANALYSIS

TO

PROGRAM DESIGN

FIFTH EDITION

D
...
MALIK

Australia  Brazil  Japan  Korea  Mexico  Singapore  Spain  United Kingdom  United States

C++ Programming: From Problem Analysis
to Program Design, Fifth Edition
D
...
Malik
Executive Editor: Marie Lee
Acquisitions Editor: Amy Jollymore

For product information and technology assistance, contact us at
Cengage Learning Customer & Sales Support, 1-800-354-9706
For permission to use material from this text or product, submit
all requests online at www
...
com/permissions
Further permissions questions can be emailed to
permissionrequest@cengage
...
roycroftdesign
...
No part of this work
covered by the copyright herein may be
reproduced, transmitted, stored or used in any
form or by any means graphic, electronic, or
mechanical, including but not limited to
photocopying, recording, scanning, digitizing,
taping, Web distribution, information
networks, or information storage and retrieval
systems, except as permitted under Section
107 or 108 of the 1976 United States Copyright
Act, without the prior written permission of
the publisher
...

Any fictional data related to persons or companies or URLs used
throughout this book is intended for instructional purposes only
...

Course Technology, a part of Cengage Learning, reserves the
right to revise this publication and make changes from time to
time in its content without notice
...

They have been tested with care, but are not guaranteed
for any particular intent beyond educational purposes
...

Cengage Learning is a leading provider of customized
learning solutions with office locations around the globe,
including Singapore, the United Kingdom, Australia, Mexico,
Brazil and Japan
...
cengage
...

To learn more about Course Technology, visit
www
...
com/coursetechnology
Purchase any of our products at your local college store or at
our preferred online store www
...
com

Printed in the United States of America
1 2 3 4 5 6 7 16 15 14 13 12 11 10

TO
My Daughter

Shelly Malik

This page intentionally left blank

B RIEF C ONTENTS

1
...
Basic Elements of C++

1
27

3
...
Control Structures I (Selection)

175

5
...
User-Defined Functions I

319

7
...
User-Defined Simple Data Types, Namespaces,
and the string Type

433

9
...
Applications of Arrays (Searching and Sorting)
and the vector Type

563

11
...
Classes and Data Abstraction

649

13
...
Pointers, Classes, Virtual Functions, and Abstract Classes

793

15
...
Exception Handling

951

17
...
Linked Lists

1023

19
...
else
One-Way Selection

188
189

Two-Way Selection

191

Compound (Block of) Statements
Multiple Selections: Nested if

195
195

Comparing if
...
while Looping (Repetition) Structure
Choosing the Right Looping Structure

284
289

break and continue Statements
Nested Control Structures

291

Avoiding Bugs by Avoiding Patches

296

Debugging Loops

299

Quick Review

300

Exercises

301

Programming Exercises

6

289

313

USER-DEFINED FUNCTIONS I

319

Predefined Functions

320

User-Defined Functions

324

Value-Returning Functions
Syntax: Value-Returning Functions

324
326

Syntax: Formal Parameter List
Function Call

326
326

Syntax: Actual Parameter List

327

return Statement
Syntax: return Statement

327
327

Function Prototype
Syntax: Function Prototype

331
332

Value-Returning Functions: Some Peculiarity

333

More Examples of Value-Returning Functions
Flow of Execution

335
340

Programming Example: Largest Number

341

Programming Example: Cable Company

343

Quick Review

349

Exercises

350

Programming Exercises

356

Table of Contents

| xiii

361

Void Functions

362
367

Reference Variables as Parameters

368

Value and Reference Parameters
and Memory Allocation

372

Reference Parameters and Value-Returning Functions

382

Scope of an Identifier

382

Global Variables, Named Constants, and Side Effects

386

Static and Automatic Variables

391

Debugging: Using Drivers and Stubs

392

Function Overloading: An Introduction

395

Functions with Default Parameters

396

Programming Example: Classify Numbers

399

Programming Example: Data Comparison

404

Quick Review

414

Exercises

416

Programming Exercises

8

USER-DEFINED FUNCTIONS II

Value Parameters

7

424

USER-DEFINED SIMPLE DATA TYPES,
NAMESPACES, AND THE string TYPE

433

Enumeration Type

434

Declaring Variables

436

Assignment
Operations on Enumeration Types

436
437

Relational Operators
Input /Output of Enumeration Types

437
438

Functions and Enumeration Types

440

Declaring Variables When Defining the Enumeration Type

442

xiv

|

C++ Programming: From Problem Analysis to Program Design, Fifth Edition

Anonymous Data Types

442

typedef Statement

443

Programming Example: The Game of Rock,
Paper, and Scissors

444

Namespaces

452

string Type

458

Additional string Operations

461

Programming Example: Pig Latin Strings
Quick Review

475

Exercises

477

Programming Exercises

9

471

481

ARRAYS AND STRINGS

485

Arrays
Accessing Array Components

487
488

Processing One-Dimensional Arrays

491

Array Index Out of Bounds
Array Initialization During Declaration

494
495

Partial Initialization of Arrays During Declaration
Some Restrictions on Array Processing

496
496

Arrays as Parameters to Functions

497

Constant Arrays as Formal Parameters
Base Address of an Array and Array in Computer Memory

498
501

Functions Cannot Return a Value of the Type Array
Integral Data Type and Array Indices

503
506

Other Ways to Declare Arrays

507

Searching an Array for a Specific Item

507

C-Strings (Character Arrays)

510

String Comparison
Reading and Writing Strings

512
514

String Input
String Output

514
515

Table of Contents

|

xv

Specifying Input/Output Files at Execution Time

516

string Type and Input/Output Files

516

Parallel Arrays

517

Two- and Multidimensional Arrays
Accessing Array Components

518
520

Two-Dimensional Array Initialization During Declaration
Two-Dimensional Arrays and Enumeration Types

521
521

Initialization

524

Print
Input

525
525

Sum by Row
Sum by Column

525
526

Largest Element in Each Row and Each Column

526

Passing Two-Dimensional Arrays as Parameters to Functions 527
Arrays of Strings
530
Arrays of Strings and the string Type
Arrays of Strings and C-Strings (Character Arrays)

530
530

Another Way to Declare a Two-Dimensional Array

531

Multidimensional Arrays

532

Programming Example: Code Detection
Programming Example: Text Processing

540

Quick Review

547

Exercises

548

Programming Exercises

10

534

558

APPLICATIONS OF ARRAYS (SEARCHING AND SORTING)
AND THE Vector TYPE
563
List Processing

564

Searching
Bubble Sort

564
565

Selection Sort
Insertion Sort

569
572

Binary Search

576

xvi

|

C++ Programming: From Problem Analysis to Program Design, Fifth Edition

Performance of Binary Search

580

vector Type (class)
Programming Example: Election Results

585

Quick Review

601

Exercises

603

Programming Exercises

11

580

606

RECORDS ( structS)

611

Records (structs)

612

Accessing struct Members

614

Assignment
Comparison (Relational Operators)

616
617

Input /Output
struct Variables and Functions

618
618

Arrays versus structs

619

Arrays in structs
structs in Arrays

620
622

structs within a struct

624

Programming Example: Sales Data Analysis
Quick Review

642

Exercises

642

Programming Exercises

12

628

645

CLASSES AND DATA ABSTRACTION

649

Classes

650

Unified Modeling Language Class Diagrams
Variable (Object) Declaration

654
654

Accessing Class Members
Built-in Operations on Classes

655
656

Assignment Operator and Classes

657

Class Scope

657

Table of Contents

|

xvii

Functions and Classes
Reference Parameters and Class Objects (Variables)
Implementation of Member Functions

658
659

Accessor and Mutator Functions
Order of public and private Members of a Class

664
667

Constructors

669

Invoking a Constructor
Invoking the Default Constructor

671
671

Invoking a Constructor with Parameters
Constructors and Default Parameters

671
674

Classes and Constructors: A Precaution

674

Arrays of Class Objects (Variables) and Constructors
Destructors

675
677

Data Abstraction, Classes, and Abstract Data Types

678

A struct Versus a class

680

Information Hiding

681

Executable Code

685

Static Members of a Class

691

Programming Example: Candy Machine

697

Quick Review

711

Exercises

713

Programming Exercises

13

658

718

INHERITANCE AND COMPOSITION

723

Inheritance

724

Redefining (Overriding) Member Functions
of the Base Class

727

Constructors of Derived and Base Classes
Destructors in a Derived Class

734
742

Multiple Inclusions of a Header File

743

C++ Stream Classes
Protected Members of a Class

744
746

xviii

|

C++ Programming: From Problem Analysis to Program Design, Fifth Edition

Inheritance as public, protected, or private

746

(Accessing protected Members in the Derived Class)

747

Composition (Aggregation)

750

Object-Oriented Design (OOD) and
Object-Oriented Programming (OOP)

755

Identifying Classes, Objects, and Operations

757

Programming Example: Grade Report
Quick Review

779

Exercises

780

Programming Exercises

14

758

787

POINTERS, CLASSES, VIRTUAL FUNCTIONS,
AND ABSTRACT CLASSES

793

Pointer Data Type and Pointer Variables

794

Declaring Pointer Variables

794

Address of Operator (&)

795

Dereferencing Operator (*)

796

Classes, Structs, and Pointer Variables

800

Initializing Pointer Variables

803

Dynamic Variables
Operator new

803
804

Operator delete

805

Operations on Pointer Variables

807

Dynamic Arrays

809

Functions and Pointers
Pointers and Function Return Values

812
812

Dynamic Two-Dimensional Arrays

813

Shallow versus Deep Copy and Pointers

816

Classes and Pointers: Some Peculiarities

818

Destructor
Assignment Operator

818
820

Copy Constructor

821

Table of Contents

Inheritance, Pointers, and Virtual Functions
Classes and Virtual Destructors

| xix

828
835

Abstract Classes and Pure Virtual Functions
Address of Operator and Classes

844

Quick Review

846

Exercises

849

Programming Exercises

15

835

857

OVERLOADING AND TEMPLATES

861

Why Operator Overloading Is Needed

862

Operator Overloading

863

Syntax for Operator Functions
Overloading an Operator: Some Restrictions

864
864

Pointer this
Friend Functions of Classes

865
870

Operator Functions as Member Functions and Nonmember
Functions
Overloading Binary Operators

873
876

Overloading the Stream Insertion (<<) and Extraction (>>)
Operators

882

Overloading the Assignment Operator (=)

887

Overloading Unary Operators
Operator Overloading: Member versus Nonmember

895
901

Classes and Pointer Member Variables (Revisited)
Operator Overloading: One Final Word

902
902

Programming Example: Clock Type

902

Programming Example: Complex Numbers

911

Overloading the Array Index (Subscript) Operator ([])

916

Programming Example: Newstring

918

Function Overloading

924

xx

| C++ Programming: From Problem Analysis to Program Design, Fifth Edition

Templates
Function Templates
Class Templates

925
925
927

Quick Review
Exercises

937

Programming Exercises

16

935

942

EXCEPTION HANDLING

951

Handling Exceptions within a Program
C++ Mechanisms of Exception Handling

952
956

try/catch Block
Using C++ Exception Classes

956
963

Creating Your Own Exception Classes

967

Rethrowing and Throwing an Exception

973

Exception-Handling Techniques

978

Terminate the Program
Fix the Error and Continue

978
978

Log the Error and Continue

980

Stack Unwinding
Quick Review

984

Exercises

986

Programming Exercises

17

980

989

RECURSION

991

Recursive Definitions
Direct and Indirect Recursion

992
995

Infinite Recursion

995

Problem Solving Using Recursion
Tower of Hanoi: Analysis

996
1005

Recursion or Iteration?

1006

Table of Contents

| xxi

Programming Example: Converting a Number from
Binary to Decimal

1007

Programming Example: Converting a Number from
Decimal to Binary
Quick Review

1014

Exercises

1015

Programming Exercises

18

1011

1018

LINKED LISTS
Linked Lists

1023
1024

Linked Lists: Some Properties
Deletion

1025
1031

Building a Linked List

1032

Linked List as an ADT
Structure of Linked List Nodes

1037
1038

Member Variables of the class linkedListType

1038

Linked List Iterators
Print the List

1039
1045

Length of a List
Retrieve the Data of the First Node

1045
1046

Retrieve the Data of the Last Node

1046

Begin and End
Copy the List

1046
1047

Destructor
Copy Constructor

1048
1048

Overloading the Assignment Operator

1049

Unordered Linked Lists

1049

Search the List
Insert the First Node

1050
1051

Insert the Last Node
Header File of the Unordered Linked List

1052
1057

Ordered Linked Lists

1058

Search the List

1059

Insert a Node
Insert First and Insert Last

1060
1064

xxii |

C++ Programming: From Problem Analysis to Program Design, Fifth Edition

Delete a Node

1065

Header File of the Ordered Linked List

1066

Print a Linked List in Reverse Order (Recursion Revisited)
printList Reverse

1069
1071

Doubly Linked Lists

1072

Default Constructor
isEmptyList

1075
1075

Destroy the List

1075

Initialize the List
Length of the List

1076
1076

Print the List
Reverse Print the List

1076
1076

Search the List

1077

First and Last Elements

1077

Circular Linked Lists
Programming Example: Video Store

1084

Quick Review

1104

Exercises

1104

Programming Exercises

19

1083

1109

STACKS AND QUEUES

1115

Stacks
Stack Operations

1116
1118

Implementation of Stacks as Arrays

1120

Initialize Stack
Empty Stack

1123
1124

Full Stack

1124

Push
Return the Top Element

1124
1126

Pop
Copy Stack

1126
1128

Constructor and Destructor

1128

Copy Constructor

1129

Table of Contents

| xxiii

Overloading the Assignment Operator (=)

1129

Stack Header File

1130

Programming Example: Highest GPA

1134

Linked Implementation of Stacks
Default Constructor

1138
1141

Empty Stack and Full Stack
Initialize Stack

1141
1142

Push

1142

Return the Top Element
Pop

1144
1144

Copy Stack
Constructors and Destructors

1146
1147

Overloading the Assignment Operator (=)

1147

Stack as Derived from the
class unorderedLinkedList

1150

Application of Stacks: Postfix Expressions
Calculator
Main Algorithm

1151
1154

Function evaluateExpression

1154

Function evaluateOpr
Function discardExp

1156
1158

Function printResult

1158

Removing Recursion: Nonrecursive Algorithm
to Print a Linked List Backward

1161

Queues
Queue Operations

1165
1166

Implementation of Queues as Arrays
Linked Implementation of Queues

1168
1177

Queue Derived from the
class unorderedLinkedListType

1182

Application of Queues: Simulation
Designing a Queuing System
Customer
Server

1183
1184
1185
1188

xxiv

|

C++ Programming: From Problem Analysis to Program Design, Fifth Edition

Server List

1191

Waiting Customers Queue
Main Program

1196
1198

Quick Review

1203

Exercises

1204

Programming Exercises

1210

APPENDIX A: RESERVED WORDS

1215

APPENDIX B: OPERATOR PRECEDENCE

1217

APPENDIX C: CHARACTER SETS

1219

ASCII (American Standard Code for
Information Interchange)

1219

EBCDIC (Extended Binary Coded
Decimal Interchange Code)

1220

APPENDIX D: OPERATOR OVERLOADING

1223

APPENDIX E: ADDITIONAL C++ TOPICS

1225

Binary (Base 2) Representation of a
Nonnegative Integer
Converting a Base 10 Number to a
Binary Number (Base 2)
Converting a Binary Number (Base 2) to Base 10

1225
1225
1227

Converting a Binary Number (Base 2) to Octal (Base 8)
and Hexadecimal (Base 16)
More on File Input/Output
Binary Files
Random File Access
Naming Conventions of Header Files in
ANSI/ISO Standard C++ and Standard C++

1228
1230
1230
1236

1244

Table of Contents

|

xxv

APPENDIX F: HEADER FILES

1247

Header File cassert (assert
...
h)

1248

Header File cfloat (float
...
h)

1250

Header File cmath (math
...
h)
Header File cstring (string
...
Designed for a first Computer Science (CS1) C++ course, this text provides a
breath of fresh air to you and your students
...
My primary goal is to motivate and excite all CS1
students, regardless of their level
...
Motivation
and excitement are critical factors that lead to the success of the programming student
...

Warning: This text can be expected to create a serious reduction in the demand for
programming help during your office hours
...

C++ Programming: From Problem Analysis to Program Design started as a collection of brief
examples, exercises, and lengthy programming examples to supplement the books that were
in use at our university
...

The approach taken in this book is, in fact, driven by the students’ demand for clarity and readability
...
Most of the
examples in this book resulted from student interaction in the classroom
...
Cooking students practice their recipes
...
New programmers must practice solving
problems and writing code
...
We do not simply list the
C++ syntax followed by an example; we dissect the ‘‘why’’ behind all the concepts
...
This
technique offers a bridge to learning C++
...

Traditionally, a C++ programming neophyte needed a working knowledge of another
programming language
...
However,
some adequate mathematics background, such as college algebra, is required
...
Each of the Chapters 2 to 7 include a programming exercise which contains a
solution of a problem, however, the statements are in the incorrect order
...
This will allow the students
to learn how to read and debug programs written by someone else
...
In these sections, a
program with errors is included
...

We then show how to interpret the syntax errors and correct them
...
This edition also includes various new examples, such
as Examples 5-8, 7-8, 12-6, and 12-8
...
Chapter 8 includes additional string functions and virtual functions section of
Chapter 14 is rewritten with new examples
...
Numerous colleges and universities use C++ for their first programming language course
...

This book can be easily divided into two parts: structured programming and object-oriented
programming
...
However, only the first seven chapters are essential
to move on to the object-oriented portion
...
This book focuses on ANSI/
ISO Standard C++
...

Chapter 1 briefly reviews the history of computers and programming languages
...
This chapter contains a section on processing a C++
program
...

Chapter 2 discusses the basic elements of C++
...
Input/output is fundamental to any programming
language
...

Chapters 4 and 5 introduce control structures to alter the sequential flow of execution
...
It is recommended that readers with no prior
programming background spend extra time on Chapters 6 and 7
...


Preface

|

xxix

Chapter 8 discusses the user-defined simple data type (enumeration type), the namespace
mechanism of ANSI/ISO Standard C++, and the string type
...
Enumeration types have very limited use; their main
purpose is to make the program readable
...

Chapter 9 discusses arrays in detail
...
Chapter 11 introduces records
(structs)
...
This chapter is
optional; it is not a prerequisite for any of the remaining chapters
...

The first half of this chapter shows how classes are defined and used in a program
...
This chapter shows how classes in
C++ are a natural way to implement ADTs
...
It
explains how classes in C++ provide a natural mechanism for OOD and how C++ supports
OOP
...

Chapter 14 studies pointers in detail
...
Moreover, this chapter also discusses how to create and work with
dynamic two-dimensional arrays
...

Chapter 15 continues the study of OOD and OOP
...

The chapter specifically discusses two types of polymorphism—overloading and templates
...
Chapter 17 introduces and discusses recursion
...

Chapters 18 and 19 are devoted to the study of data structures
...
The programming code developed in
these chapters is generic
...

Appendix A lists the reserved words in C++
...
Appendix C lists the ASCII (American Standard Code
for Information Interchange) and EBCDIC (Extended Binary Coded Decimal Interchange
Code) character sets
...

Appendix E has three objectives
...
We then discuss binary and random access files in detail
...
Appendix F discusses some of the most widely used library
routines, and includes the names of the standard C++ header files
...
Appendix H gives an introduction to

xxx |

C++ Programming: From Problem Analysis to Program Design, Fifth Edition

the Standard Template Library, and Appendix I provides the answers to odd-numbered
exercises in the book
...
Figure 1 shows the dependency of the chapters
...
For example, Chapter 9
covers arrays in detail
...
However, if Chapter 12 is studied before
Chapter 9, then the section dealing with arrays in Chapter 12 can be skipped without any
discontinuation
...

It is recommended that the first seven chapters be covered sequentially
...
Chapter 8 can be studied any time after Chapter 7
...

2
...

4
...

16
...

16
...


More than 300
visual diagrams,
both extensive
and exhaustive,
illustrate difficult
concepts
...
The
programming code
in these examples is
followed by a
Sample Run
...


Notes highlight important
facts about the concepts
introduced in the chapter
...
Programming
Examples are where
everything in the
chapter comes
together
...

These examples teach
problem solving skills
and include the
concrete stages of
input, output,
problem analysis and
algorithm design,
class design, and a
program listing All
programs are
designed to be
methodical,
consistent, and userfriendly
...
Every
step of the algorithm
is coded in C++
...
We strongly recommend that students study the Programming
Examples carefully in order to learn C++ effectively
...
Further, programming examples reduce considerably the students’ need for help outside the classroom and
bolster the students’ self-confidence
...


Programming
Exercises challenge
students to write
C++ programs with
a specified
outcome
...

All instructor teaching tools are available with this book on a single CD-ROM
...




Solutions to all the end-of-chapter materials, including the Programming
Exercises
...

ExamView includes hundreds of questions that correspond to the topics covered in this
text, enabling students to generate detailed study guides that include page references for
further review
...


PowerPoint Presentations
This book comes with Microsoft PowerPoint slides for each chapter
...
Instructors can add their own
slides for additional topics that they introduce to the class
...
To access this material, visit www
...
com/webtutor
and search for your title
...
For students to access this material, they
must have purchased a WebTutor PIN-code specific to this title and your campus platform
...
For additional information, please contact your
sales representative
...
course
...
The input files needed to run some of the
programs are also included with the source code
...
course
...
The input files needed to run
some of the Programming Exercises are also included with the solution files
...
First, I would like to thank all the students who, during the preparation, were
spontaneous in telling me if certain portions needed to be reworded for better understanding
and clearer reading
...
I am thankful to Professors S
...
Cheng, Randall Crist, and
Vasant Raval for constantly supporting this project
...

I owe a great deal to the following reviewers who patiently read each page of every chapter of
the current version and made critical comments to improve on the book: Stefano Basagni,
Northeastern University; Jeff Ringenberg, University of Michigan; Colleen van Lent, University of Michigan; Tuan Vo, Mt
...
The reviewers will recognize that
their criticisms have not been overlooked and, in fact, made this a better book
...
All this would not have been possible without the careful
planning of Senior Product Manager Alyssa Pratt
...
I also thank Tintu Thomas of Integra
Software Services for assisting us in keeping the project on schedule
...

I am thankful to my parents for their blessings
...
She cheered me up whenever I was overwhelmed during the
writing of this book, and also made sure that the corrections were in place
...

I welcome any comments concerning the text
...
edu
D
...
Malik

1

CHAPTER

A N O VERVIEW OF
COMPUTERS AND
P ROGRAMMING
L ANGUAGES
I N T H I S C H A P T E R , YO U W I L L :


...


Explore the hardware and software components of a computer system


...


Learn about the evolution of programming languages


...


Discover what a compiler is and what it does


...


Explore how a C++ program is processed


...


Become aware of structured design and object-oriented design programming methodologies


...

Students in elementary school regularly ‘‘surf ’’ the Internet and use computers to design their
classroom projects
...
This is all made possible by the availability of different software, also
known as computer programs
...
Software is developed by using programming languages
...
Our main objective is to help you
learn how to write programs in the C++ programming language
...
We begin with an overview of the history of computers
...
The abacus was invented in
Asia but was used in ancient Babylon, China, and throughout Europe until the late middle
ages
...
In 1642,
the French philosopher and mathematician Blaise Pascal invented the calculating device
called the Pascaline
...
Both the abacus and Pascaline could perform only addition and subtraction operations
...
In 1819, Joseph Jacquard, a French weaver,
discovered that the weaving instructions for his looms could be stored on cards with holes
punched in them
...
A weaver could
rearrange the cards and change the pattern being woven
...
The weaving industry may seem to have little in common
with the computer industry
...

In the early and mid-1800s, Charles Babbage, an English mathematician and physical
scientist, designed two calculating machines—the difference engine and the analytical
engine
...
Babbage built a prototype of the difference engine, but the actual
device was never produced
...
However, the designs remained in blueprint stage
...
Augusta
is considered the first computer programmer
...
S
...
Herman Hollerith invented a calculating machine that ran on electricity
and used punched cards to store data
...

Hollerith founded the Tabulating Machine Company, which later became the computer
and technology corporation known as IBM
...
It was built, in 1944, jointly by IBM and
Harvard University under the leadership of Howard Aiken
...
The Mark I was 52 feet long, weighed 50 tons, and had 750,000 parts
...
It contained 18,000 vacuum tubes and weighed some 30 tons
...
His design included components such as an arithmetic logic unit, a control
unit, memory, and input/output devices
...
Von Neumann’s computer design makes it possible to store the programming
instructions and the data in the same memory space
...
S
...

In 1956, the invention of transistors resulted in smaller, faster, more reliable, and more
energy-efficient computers
...
In the next major technological advancement, transistors were replaced by tiny
integrated circuits, or ‘‘chips
...
They give computers tremendous processing speed
...
In 1977,
Stephen Wozniak and Steven Jobs designed and built the first Apple computer in their
garage
...
In the 1980s, clones of the
IBM PC made the personal computer even more affordable
...
Computers continue to become faster
and less expensive as technology advances
...
They can accept spoken-word
instructions and imitate human reasoning through artificial intelligence
...
Mobile computing applications are growing significantly
...
Cell phones permit you to check your e-mail,
make airline reservations, see how stocks are performing, and access your bank accounts
...


Elements of a Computer System
A computer is an electronic device capable of performing commands
...

In today’s market, personal computers are sold with descriptions such as a Pentium 4
Processor 2
...
These
descriptions represent two categories: hardware and software
...
80 GHz, 1GB RAM, 250 GB HD, VX750 19" Silver Flat CRT Color Monitor’’
fall into the hardware category; items such as ‘‘operating system, games, encyclopedias, and
application software’’ fall into the software category
...


Hardware
Major hardware components include the central processing unit (CPU); main memory
(MM), also called random access memory (RAM); input/output devices; and secondary
storage
...

Examples of output devices are the screen, printer, and secondary storage
...


Central Processing Unit and Main Memory
The central processing unit is the ‘‘brain’’ of the computer and the single most expensive
piece of hardware in a computer
...

Arithmetic and logical operations are carried out inside the CPU
...


Central
Processing
Unit (CPU)

Input
Device
Output
Device

Main Memory

Secondary Storage


...


...


...

2000
2001

...


...


...

54
A

...


...


...

Memory
(b)

Hardware components of a computer and main memory

Main memory, or random access memory, is connected directly to the CPU
...
Similarly, all
data must be brought into main memory before a program can manipulate it
...

Main memory is an ordered sequence of cells, called memory cells
...
These addresses help you access
the information stored in the cell
...


Elements of a Computer System

| 5

Today’s computers come with main memory consisting of millions to billions of cells
...
Moreover, this figure shows the data as numbers and
letters
...
The memory addresses are also expressed as sequences of 0s and 1s
...

The device that stores information permanently (unless the device becomes unusable or
you change the information by rewriting it) is called secondary storage
...
Examples of secondary storage are hard disks, flash
drives, floppy disks, ZIP disks, CD-ROMs, and tapes
...
The devices that feed data and programs into computers
are called input devices
...
The devices that the computer uses to display results are called output
devices
...

Figure 1-2 shows some input and output devices
...
For example, word processors
are programs that you use to write letters, papers, and even books
...
There are two types of programs: system programs and
application programs
...
The system program that loads first when you
turn on your PC is called the operating system
...
The operating system monitors the overall activity of the computer
and provides services
...
The operating system has a special program that
organizes secondary storage so that you can conveniently access information
...
Word processors, spreadsheets, and
games are examples of application programs
...


The Language of a Computer
When you press A on your keyboard, the computer displays A on the screen
...
Electrical signals are used inside the
computer to process information
...
Analog signals are continuous wave forms used to represent such things as
sound
...
Digital signals represent
information with a sequence of 0s and 1s
...
Digital signals are more reliable carriers of information than
analog signals and can be copied from one device to another with exact precision
...
On the other hand, when you copy a CD,
the copy is as good as the original
...

Because digital signals are processed inside a computer, the language of a computer, called
machine language, is a sequence of 0s and 1s
...
Sometimes a sequence of 0s and 1s is referred to as a binary code or a binary
number
...


A sequence of eight bits is called a byte
...
Table 1-1 summarizes the terms used to describe various numbers
of bytes
...
The most commonly used
encoding scheme on personal computers is the seven-bit American Standard Code
for Information Interchange (ASCII)
...
That is, in the ASCII data set, the position of the first character
is 0, the position of the second character is 1, and so on
...
In fact, A is the 66th character in the ASCII character code,
but its position is 65 because the position of the first character is 0
...
The character 3 is encoded as
0110011
...
It also follows that 0110011 is the
binary representation of 51
...

The number system that we use in our daily life is called the decimal system, or base 10
...
We
indicated in the preceding paragraph that the number 1000001 is the binary representation
of 65
...


8 |

Chapter 1: An Overview of Computers and Programming Languages

Inside the computer, every character is represented as a sequence of eight bits, that is, as
a byte
...
Note that we added 0
to the left of the seven-bit representation of 65 to convert it to an eight-bit representation
...

ASCII is a seven-bit code
...
This is accomplished by adding 0 to the left of the
seven-bit ASCII encoding of a character
...

There are other encoding schemes, such as EBCDIC (used by IBM) and Unicode,
which is a more recent development
...
To store a character belonging to Unicode, you need
two bytes
...
Even though most computers perform the same kinds of operations,
the designers of the computer may have chosen different sets of binary codes to perform
the operations
...
The only consistency among computers is that in any modern computer, all data is stored and manipulated as binary codes
...
To see how instructions are
written in machine language, suppose you want to use the equation:
wages = rate

Á

hours

to calculate weekly wages
...
In machine language, you
might need the following sequence of instructions to calculate weekly wages:
100100 010001
100110 010010
100010 010011

To represent the weekly wages equation in machine language, the programmer had to
remember the machine language codes for various operations
...

This need to remember specific codes made programming not only very difficult, but also
error-prone
...
In assembly
language, an instruction is an easy-to-remember form called a mnemonic
...


The Evolution of Programming Languages

| 9

TABLE 1-2 Examples of Instructions in Assembly Language and Machine Language

Assembly Language

Machine Language

LOAD

100100

STOR

100010

MULT

100110

ADD

100101

SUB

100011

Using assembly language instructions, you can write the equation to calculate the weekly
wages as follows:
LOAD
MULT
STOR

rate
hours
wages

As you can see, it is much easier to write instructions in assembly language
...
The instructions first
have to be translated into machine language
...

Assembler: A program that translates a program written in assembly language into an
equivalent program in machine language
...
The
next step toward making programming easier was to devise high-level languages that
were closer to natural languages, such as English, French, German, and Spanish
...
You
will learn the high-level language C++ in this book
...
As in the case of assembly language,
however, the computer cannot directly execute instructions written in a high-level
language
...
A program called a compiler translates instructions written in highlevel languages into machine code
...


1

10 |

Chapter 1: An Overview of Computers and Programming Languages

Processing a C++ Program
In the previous sections, we discussed machine language and high-level languages and
showed a C++ program
...

Consider the following C++ program:
#include
using namespace std;
int main()
{
cout << "My first C++ program
...
However,
if you run (execute) this program, it will display the following line on the screen:
My first C++ program
...
Therefore, in order to run
this program successfully, the code must first be translated into machine language
...

The following steps, as shown in Figure 1-3, are necessary to process a C++ program
...


2
...


You use a text editor to create a C++ program following the rules, or
syntax, of the high-level language
...
The program must be saved in a text file
that has the extension
...
For example, if you saved the preceding
program in the file named FirstCPPProgram, then its complete name
is FirstCPPProgram
...

Source program: A program written in a high-level language
...
In a C++ program, statements that begin with
the symbol # are called preprocessor directives
...

After processing preprocessor directives, the next step is to verify that the
program obeys the rules of the programming language—that is, the program
is syntactically correct—and translate the program into the equivalent
machine language
...
The equivalent machine language program is called an object
program
...


4
...


6
...
The IDE contains many
programs that are useful in creating your program
...
Therefore, if certain code is already available, you can use this code
rather than writing your own code
...
This prewritten code (program) resides in a place
called the library
...

Linker: A program that combines the object program with other programs
in the library and is used in the program to create the executable code
...
A program called a loader accomplishes this task
...

The final step is to execute the program
...


C++ Program
Editor

Step 1

Preprocessor

Step 2

Compiler

Syntax
Error

Step 3

Library
Linker
Loader

Step 5

Execution

FIGURE 1-3

Step 4

Step 6

Processing a C++ program

As a programmer, you need to be concerned only with Step 1
...


1

12 |

Chapter 1: An Overview of Computers and Programming Languages

As noted earlier, programs are developed using an IDE
...
NET (from Microsoft), C++ Builder (from Borland), and CodeWarrior (from
Metrowerks)
...

These IDEs are quite user friendly
...
Moreover, with just a simple command, the object code is linked with the resources used from
the IDE
...
Net is Build or Rebuild
...
) If the program is not yet
compiled, each of these commands first compiles the program and then links and produces
the executable code
...
microsoft
...
aspx contains a video that
explains how to use Visual C++ 2008 Express to write C++ programs
...
Different people use different techniques to
solve problems
...
They not
only solve the problem, but also give insight into how the solution was reached
...

To be a good problem solver and a good programmer, you must follow good problemsolving techniques
...

Algorithm: A step-by-step problem-solving process in which a solution is arrived at in a
finite amount of time
...

2
...


Analyze the problem, outline the problem and its solution requirements,
and design an algorithm to solve the problem
...

Maintain the program by using and modifying it if the problem domain changes
...


Programming with the Problem Analysis–Coding–Execution Cycle |

13

1

Problem

Analysis

Algorithm
Design

Coding

Preprocessor

Compiler
Library

Error

No Error
Linker

Loader

Execution

Error

No Error
Results

FIGURE 1-4

Problem analysis–coding–execution cycle

To develop a program to solve a problem, you start by analyzing the problem
...

Analyzing the problem is the first and most important step
...

2
...

Understand the problem requirements
...


Chapter 1: An Overview of Computers and Programming Languages

whether it produces output, and what the output looks like
...
That is, you need to look at sample data
...

If the problem is complex, divide the problem into subproblems and repeat
Steps 1 and 2
...


After you carefully analyze the problem, the next step is to design an algorithm to solve the
problem
...
Once you design an algorithm, you need to check it for correctness
...
At other times, you
might need to perform some mathematical analysis to test the algorithm’s correctness
...
You then use a text editor to enter the
programming code or the program into a computer
...
To verify the correctness of the syntax, you run
the code through a compiler
...

When all the syntax errors are removed, the compiler generates the equivalent machine
code, the linker links the machine code with the system’s resources, and the loader places
the program into main memory so that it can be executed
...
The compiler guarantees only that the program
follows the language’s syntax
...

During execution, the program might terminate abnormally due to logical errors, such as
division by zero
...
Under these circumstances, you may have to reexamine the code, the algorithm,
or even the problem analysis
...

Usually, you do this work on paper using a pen or pencil
...
It is much easier to discover errors in a program
that is well analyzed and well designed
...
Even the most experienced programmers
spend a considerable amount of time analyzing a problem and designing an algorithm
...
Each chapter provides several programming examples that discuss programming problems
...
To gain the full benefit of this book,
we recommend that you work through the programming examples at the end of each chapter
...


Programming with the Problem Analysis–Coding–Execution Cycle |

15

1

EXAMPLE 1-1
In this example, we design an algorithm to find the perimeter and area of a rectangle
...

The perimeter and area of the rectangle are then given by the following formulas:
perimeter = 2
area = length

Á
Á

(length + width)
width

The algorithm to find the perimeter and area of the rectangle is:
1
...

3
...

Get the width of the rectangle
...


Á

(length + width)

Find the area using the following equation:
area = length

Á

width

EXAMPLE 1-2
In this example, we design an algorithm that calculates the sales tax and the price of an item
sold in a particular state
...
5%
...

To calculate the price of the item, we need to calculate the state’s portion of the sales
tax, the city’s portion of the sales tax, and, if it is a luxury item, the luxury tax
...

To calculate the sales tax, we must know the selling price of the item and whether the item is
a luxury item
...
04
citySalesTax = salePrice Á 0
...
1
otherwise
luxuryTax = 0

Next, you can determine salesTax as follows:
salesTax = stateSalesTax + citySalesTax + luxuryTax

Finally, you can calculate amountDue as follows:
amountDue = salePrice + salesTax

The algorithm to determine salesTax and amountDue is, therefore:
1
...

3
...

Determine whether the item is a luxury item
...


Find the city’s portion of the sales tax using the formula:
citySalesTax = salePrice

5
...
04

Á

0
...
1
otherwise
luxuryTax = 0

6
...


Find amountDue using the formula:
amountDue = salePrice + salesTax

EXAMPLE 1-3
In this example, we design an algorithm that calculates the monthly paycheck of a salesperson
at a local department store
...
The salesperson also receives a bonus at the end of each
month, based on the following criteria: If the salesperson has been with the store for five years
or less, the bonus is $10 for each year that he or she has worked there
...
The salesperson can earn an additional bonus as follows: If the total sales made

Programming with the Problem Analysis–Coding–Execution Cycle |

17

by the salesperson for the month are at least $5,000 but less than $10,000, he or she receives a
3% commission on the sale
...

To calculate a salesperson’s monthly paycheck, you need to know the base salary, the number of
years that the salesperson has been with the company, and the total sales made by the salesperson for that month
...

You can determine the bonus as follows:
if (noOfServiceYears is less than or equal to five)
bonus = 10 Á noOfServiceYears
otherwise
bonus = 20 Á noOfServiceYears

Next, you can determine the additional bonus of the salesperson as follows:
if (totalSales is less than 5000)
additionalBonus = 0
otherwise
if (totalSales is greater than or equal to 5000 and
totalSales is less than 10000)
additionalBonus = totalSales Á (0
...
06)

Following the above discussion, you can now design the algorithm to calculate a salesperson’s
monthly paycheck:
1
...

3
...

Get noOfServiceYears
...

5
...

Calculate additionalBonus using the following formula:
if (totalSales is less than 5000)
additionalBonus = 0
otherwise
if (totalSales is greater than or equal to 5000 and
totalSales is less than 10000)
additionalBonus = totalSales Á (0
...
06)

1

18 |

6
...

The objective is to randomly generate an integer greater than or equal to 0 and less than 100
...
If the player guesses the number
correctly, output an appropriate message
...
If the guessed number is less than the random number
generated, output the message, ‘‘Your guess is lower than the number
...
Guess again!’’
...
The player is prompted to guess the random
number until the player enters the correct number
...
C++ provides the means to
do so, which is discussed in Chapter 5
...

After the player enters the guess, you can compare the guess with the random number as follows:
if (guess is equal to num)
Print "You guessed the correct number
...
Guess again!"
otherwise
Print "Your guess is higher than the number
...

2
...

Repeat the following steps until the player has guessed the correct number:
a
...

b
...
"
otherwise
if guess is less than num
Print "Your guess is lower than the number
...
Guess again!"

In Chapter 5, we use this algorithm to write a C++ program to play the guessing the number
game
...
Each student has taken five tests, and each test is worth 100
points
...
The grade is assigned as follows: If the average test score is greater than or equal
to 90, the grade is A; if the average test score is greater than or equal to 80 and less than 90,
the grade is B; if the average test score is greater than or equal to 70 and less than 80, the grade
is C; if the average test score is greater than or equal to 60 and less than 70, the grade is D;
otherwise, the grade is F
...

This is a problem that can be divided into subproblems as follows: There are five tests, so you
design an algorithm to find the average test score
...
The two subproblems are to determine the average test score and to determine the
grade
...
To find the average test
score, add the five test scores and then divide the sum by 5
...

2
...


Get the five test scores
...
Suppose sum stands for the sum of the test scores
...
Then:
average = sum / 5;

Next, you design an algorithm to determine the grade
...
The following algorithm determines the grade:
if average is greater than or equal to 90
grade = A
otherwise
if average is greater than or equal to 80 and less than 90
grade = B
otherwise
if average is greater than or equal to 70 and less than 80
grade = C
otherwise
if average is greater than or equal to 60 and less than 70
grade = D
otherwise
grade = F

You can use the solutions to these subproblems to design the main algorithm as follows:
(Suppose totalAverage stands for the sum of the averages of each student’s test average
...

2
...
Get student’s name
...
Use the algorithm as discussed above to find the average test score
...
Use the algorithm as discussed above to find the grade
...
Update totalAverage by adding the current student’s average test
score
...


Determine the class average as follows:
classAverage = totalAverage / 10

A programming exercise in Chapter 7 asks you to write a C++ program to determine the
average test score and grade for each student in a class
...


Structured Programming
Dividing a problem into smaller subproblems is called structured design
...
The solutions to all of
the subproblems are then combined to solve the overall problem
...
The structured-design
approach is also known as top-down design, bottom-up design, stepwise refinement,
and modular programming
...
In OOD, the
first step in the problem-solving process is to identify the components called objects, which
form the basis of the solution, and to determine how these objects interact with one another
...
The two main objects in this problem are the video and the customer
...
For example, for a video object, the
data might include:






movie name
starring actors
producer
production company
number of copies in stock

Some of the operations on a video object might include:
• checking the name of the movie
• reducing the number of copies in stock by one after a copy is rented
• incrementing the number of copies in stock by one after a customer returns a
particular video

Programming Methodologies |

21

This illustrates that each object consists of data and operations on that data
...
In OOD, the final program is
a collection of interacting objects
...
You will learn about the
many advantages of OOD in later chapters
...
In Chapter 2, you will learn the basic
data types of C++ and discover how to represent and manipulate data in computer
memory
...

To create operations, you write algorithms and implement them in a programming
language
...
After a brief introduction in
Chapters 2 and 3, you will learn the details of functions in Chapters 6 and 7
...
Other
algorithms might require certain statements to be repeated until certain conditions are
met, a process called repetition
...
You will learn about selection and repetition mechanisms, called control
structures, in Chapters 4 and 5
...

Finally, to work with objects, you need to know how to combine data and operations on
the data into a single unit
...
You will learn how classes work,
how to work with classes, and how to create classes in the chapter Classes and Data
Abstraction (later in this book)
...
To make this learning easier and more effective, this book purposely
divides control structures into two chapters (4 and 5) and user-defined functions into
two chapters (6 and 7)
...

Other problems will be better addressed by OOD
...
The C++
library supplies a wealth of functions that you can use effectively to manipulate
numbers
...
C++ was designed
especially to implement OOD
...


1

22 |

Chapter 1: An Overview of Computers and Programming Languages

Both the structured design and OOD approaches require that you master the basic components of a programming language to be an effective programmer
...
We illustrate
how these concepts work using the structured programming approach
...


ANSI/ISO Standard C++
The programming language C++ evolved from C and was designed by Bjarne
Stroustrup at Bell Laboratories in the early 1980s
...
Even though the fundamental
features of C++ in all compilers were mostly the same, the C++ language, referred
to in this book as Standard C++, was evolving in slightly different ways in different
compilers
...

To address this problem, in the early 1990s, a joint committee of the American National
Standard Institution (ANSI) and International Standard Organization (ISO) was established to standardize the syntax of C++
...
Most of today’s compilers comply with these new standards
...


QUICK REVIEW
1
...

3
...

5
...


7
...

9
...


A computer is an electronic device capable of performing arithmetic and
logical operations
...

The central processing unit (CPU) and the main memory are examples of
hardware components
...

When the power is switched off, everything in main memory is lost
...
Hard disks,
flash drives, floppy disks, ZIP disks, CD-ROMs, and tapes are examples of
secondary storage
...
Two common input devices
are the keyboard and the mouse
...

Software are programs run by the computer
...


Exercises

11
...

13
...

15
...

17
...

19
...

21
...

23
...

25
...

27
...


The most basic language of a computer is a sequence of 0s and 1s called machine
language
...

A bit is a binary digit, 0 or 1
...

A sequence of 0s and 1s is referred to as a binary code or a binary number
...

Assembly language uses easy-to-remember instructions called mnemonics
...

Compilers are programs that translate a program written in a high-level
language into machine code, called object code
...

Typically, six steps are needed to execute a C++ program: edit, preprocess,
compile, link, load, and execute
...

An algorithm is a step-by-step problem-solving process in which a solution is
arrived at in a finite amount of time
...

Programs written using the structured design approach are easier to understand,
easier to test and debug, and easier to modify
...
Each
subproblem is solved, and the solutions to all of the subproblems are then
combined to solve the problem
...

An object consists of data and operations on that data
...


EXERCISES
1
...

a
...


The first device known to carry out calculations was the Pascaline
...


|

23

1

24 |

Chapter 1: An Overview of Computers and Programming Languages

c
...

e
...

g
...

i
...

k
...

2
...

4
...

6
...

8
...

10
...


12
...

14
...


In ASCII coding, every character is coded as a sequence of 8 bits
...

The arithmetic operations are performed inside CPU, and if an error is
found, it outputs the logical errors
...

A linker links and loads the object code from main memory into the CPU
for execution
...

A program written in a high-level programming language is called a source
program
...

The first step in the problem-solving process is to analyze the problem
...


Name two input devices
...

Why is secondary storage needed?
What is the function of an operating system?
What are the two types of programs?
What are the differences between machine languages and high-level languages?
What is a source program?
Why do you need a compiler?
What kind of errors are reported by a compiler?
Why do you need to translate a program written in a high-level language into machine
language?
Why would you prefer to write a program in a high-level language rather than a
machine language?
What is linking?
What are the advantages of problem analysis and algorithm design over directly writing a
program in a high-level language?
Design an algorithm to find the weighted average of four test scores
...


For example, sample data is as follows:
75
95
85
65

0
...
35
0
...
30

Exercises

16
...


18
...

Given the radius, in inches, and price of a pizza, design an algorithm to find the
price of the pizza per square inch
...
He
travels by company car
...
Given the starting odometer reading (that is,
the odometer reading before he leaves on Monday) and the ending odometer
reading (the odometer reading after he returns home on Friday), design an
algorithm to find the average miles per gallon
...
75 16
...
95 20
...
00

19
...


21
...


23
...
Design an algorithm to find the selling price of an item sold at the
furniture store
...
Then the area of
the triangle can be calculated using the formula:
pffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffi

sðs À aÞðs À bÞðs À cÞ;
where s = (1/2)(a + b + c)
...
What information do you need to find the area?
Suppose that the cost of sending an international fax is calculated as follows:
Service charges $3
...
20 per page for the first 10 pages; and $0
...
Design an algorithm that asks the user to enter the number of
pages to be faxed
...

An ATM allows a customer to withdraw a maximum of $500 per day
...
If the customer does not have sufficient money in the account, the
ATM informs the customer about the insufficient fund and gives the option to
withdraw the money for a service charge of $25
...
If there is no money in the
account or if the account balance is negative, the ATM does not allow the
customer to withdraw any money
...
Write an algorithm that allows the customer to enter the
amount to be withdrawn
...

You are given a list of students’ names and their test scores
...

b
...

Determines and prints the names of all the students whose test scores are
below the average test score
...

d
...

Prints the names of all the students whose test scores are the same as the
highest test score
...
The second subproblem determines and prints the
names of all the students whose test scores are below the average test score
...
The fourth subproblem prints the names
of all the students whose test scores are the same as the highest test score
...
)

2

CHAPTER

B ASIC E LEMENTS

OF

C++

I N T H I S C H A P T E R , YO U W I L L :


...


Explore simple data types


...


Examine how a program evaluates arithmetic expressions


...


Become familiar with the string data type


...


Become familiar with the use of increment and decrement operators


...


Learn how to use preprocessor directives and why they are necessary


...


Explore how to properly structure a program, including using comments to document a program


...
As your objective is to learn the C++
programming language, two questions naturally arise
...
Programming is a process of
planning and creating a program
...
It may very well take an entire book to give a good and
satisfactory definition of programming
...
A recipe is also a program, and everyone with some cooking
experience can agree on the following:
1
...

3
...

5
...

There are good recipes and there are bad recipes
...

Some recipes produce reliable results and some do not
...

6
...

These same six points are also true about programming
...
Suppose you need to teach someone how to become a chef
...

Learning a programming language is like learning to become a chef or learning to play a
musical instrument
...
You cannot become
a good chef or even a poor chef just by reading recipes
...
The same is true of programming
...


A C++ Program
In this chapter, you will learn the basic elements and concepts of the C++ programming
language to create C++ programs
...
In this section, we provide an
example of a C++ program
...
You only need to know the effect of an output statement, which is
introduced in this program
...

EXAMPLE 2-1
//********************************************************
// This is a simple C++ program
...

//********************************************************
#include
using namespace std;
int main()
{
int num;
num = 6;
cout
cout
cout
cout
}

<<
<<
<<
<<

"My first C++ program
...
)
My first C++ program
...

cout
cout
cout
cout

<<
<<
<<
<<

"My first C++ program
...
Let us first consider the following statement:
cout << "My first C++ program
...
It causes the computer to evaluate the
expression after the pair of symbols << and display the result on the screen
...
For example, 7 + 8 is an arithmetic expression
...
For example, "My first C++ program
...
Typically, a
string evaluates to itself
...
Later in this chapter,
we explain how arithmetic expressions and strings are formed and evaluated
...
(On the screen, the insertion point is where the cursor is
...

My first C++ program
...

cout << "The sum of 2 and 3 = " << 5 << endl;

This output statement consists of two expressions
...
The expression "The sum of 2 and 3 = " is a string and evaluates to itself
...
) The second expression, which consists of the number 5
evaluates to 5
...

cout << "7 + 8 = " << 7 + 8 << endl;

In this output statement, the expression "7 + 8 = ", which is a string, evaluates to itself
...
This expression consists of the numbers 7
and 8 and the C++ arithmetic operator +
...
Thus, the output of the preceding statement is:
7 + 8 = 15

Finally, consider the statement:
cout << "Num = " << num << endl;

This statement consists of the string "Num = ", which evaluates to itself, and the word num
...
Therefore, the expression num, after
the second <<, evaluates to 6
...
We will
elaborate on this statement later in this chapter
...
After
finishing Chapter 2, you should be able to write C++ programs well enough to do some
computations and show results
...
A
C++ program is a collection of functions, one of which is the function main
...
The preceding program consists of the function main
...
The second line, which is
using namespace std;

allows you to use cout and endl without the prefix std::
...
We will elaborate on this later in this chapter
...
The eighth line consists of a left brace
...
The right brace (at the last line of the
program) matches this left brace and marks the end of the body of the function main
...

Note that in C++, << is an operator, called the stream insertion operator
...
Some
functions, called predefined or standard functions, are already written and are provided
as part of the system
...

Every C++ program has a function called main
...
Until Chapter 6, other than using some of the
predefined functions, you will mainly deal with the function main
...

If you have never seen a program written in a programming language, the C++ program in
Example 2-1 may look like a foreign language
...
The same is true of a programming language
...
The syntax rules tell you which statements
(instructions) are legal, or accepted by the programming language, and which are not
...

The programming language’s rules, symbols, and special words enable you to write programs
to solve problems
...

Programming language: A set of rules, symbols, and special words
...
Additional special symbols are introduced as other concepts are encountered in later chapters
...


Comments
The program that you write should be clear not only to you, but also to the reader of
your program
...

Typically, comments can be used to identify the authors of the program, give the date
when the program is written or modified, give a brief explanation of the program, and
explain the meaning of key statements in a program
...

Comments are for the reader, not for the compiler
...
Throughout this
book, comments are shown in green
...
It prints the sentence:
// Welcome to C++ Programming
...

Single-line comments begin with // and can be placed anywhere in the line
...
For example, consider the
following statement:
cout << "7 + 8 = " << 7 + 8 << endl;

You can put comments at the end of this line as follows:
cout << "7 + 8 = " << 7 + 8 << endl; //prints: 7 + 8 = 15

This comment could be meaningful for a beginning programmer
...
The compiler ignores anything
that appears between /* and */
...

*/

Special Symbols
The smallest individual unit of a program written in any language is called a token
...


The Basics of a C++ Program |

33

Following are some of the special symbols:
+

...
The second row consists of punctuation marks taken from English grammar
...
In C++, commas are used to separate items
in a list
...
Note that a blank, which is not
shown above, is also a special symbol
...
The third row consists of tokens made up of two characters
that are regarded as a single symbol
...


Reserved Words (Keywords)
A second category of tokens is word symbols
...
The letters that make up a reserved word are
always lowercase
...

Furthermore, word symbols cannot be redefined within any program; that is, they cannot
be used for anything other than their intended use
...

Throughout this book, reserved words are shown in blue
...
Identifiers are names of things that appear in
programs, such as variables, constants, and functions
...

Identifier: A C++ identifier consists of letters, digits, and the underscore character ( _ )
and must begin with a letter or underscore
...
In the C++ program in
Example 2-1, cout is a predefined identifier and num is a user-defined identifier
...
You have
already seen the effect of cout
...
Unlike reserved words, predefined identifiers can be redefined,
but it would not be wise to do so
...

C++ is case sensitive—uppercase and lowercase letters are considered different
...
Similarly, the identifiers
X and x are different
...

EXAMPLE 2-2
The following are legal identifiers in C++:
first
conversion
payRate
counter1

Table 2-1 shows some illegal identifiers and explains why they are illegal
...


Hello!

The exclamation mark cannot be used in an identifier
...


2nd

An identifier cannot begin with a digit
...

When the linker links the object program with the system resources provided by
the integrated development environment (IDE), certain errors could occur
...


Whitespaces
Every C++ program contains whitespaces
...
In a C++ program, whitespaces are used to separate special symbols, reserved
words, and identifiers
...
Proper utilization of whitespaces in a program is important
...


Data Types |

35

Data Types
The objective of a C++ program is to manipulate data
...
A program designed to calculate an employee’s paycheck will add, subtract,
multiply, and divide numbers, and some of the numbers might represent hours worked and
pay rate
...
You
wouldn’t expect a cherry pie recipe to help you bake cookies
...

Furthermore, you wouldn’t multiply or subtract names
...
Although at first it may seem confusing, by being so
type conscious, C++ has built-in checks to guard against errors
...


C++ data types fall into the following three categories and are illustrated in Figure 2-1:
1
...
Structured data type
3
...


Simple Data Types
The simple data type is the fundamental data type in C++ because it becomes a building
block for the structured data type, which you start learning about in Chapter 9
...
Integral, which is a data type that deals with integers, or numbers
without a decimal part
2
...
Enumeration, which is a user-defined data type
The enumeration type is C++'s method for allowing programmers to create their own
simple data types
...


2

36 |

Chapter 2: Basic Elements of C++

Integral data types are further classified into the following nine categories: char, short,
int, long, bool, unsigned char, unsigned short, unsigned int, and
unsigned long
...
For example, the char data type is used to represent integers
between –128 and 127
...

Note that the identifier num in Example 2-1 can be assigned any value belonging to the
int data type
...

In the early days of programming, computers and main memory were very expensive
...
As a result, programmers had to optimize the use of memory
...
Thus, to effectively use
memory, a programmer can look at the type of data used in a program and figure out which
data type to use
...
The integral data types that are used in this
book are int, bool, and char
...

TABLE 2-2

Values and Memory Allocation for Three Simple Data Types

Data Type

Values

Storage (in bytes)

int

-2147483648 to 2147483647

4

bool

true and false

1

char

-128 to 127

1

Use this table only as a guide
...
Check your compiler’s documentation
...
Furthermore, to find the maximum and
minimum values of these data types, you can run another program given in
Appendix F (Header File climits)
...
This discussion also applies to other integral data
types
...
Positive integers do not need a + sign in front of them
...
No commas are used within an integer
...
So 36,782 would be interpreted as
two integers: 36 and 782
...
Also, true and false are called
the logical (Boolean) values
...
Logical (Boolean) expressions will be formally defined and discussed
in detail in Chapter 4
...

char DATA TYPE
The data type char is the smallest integral data type
...
Thus, the char data type can
represent every key on your keyboard
...
Examples of values belonging to the
char data type include the following:
'A', 'a', '0', '*', '+', '$', '&', ' '

Note that a blank space is a character and is written as ' ', with a space between the single
quotation marks
...
Thus, the value 'abc' is not of the type char
...
All the individual symbols located on the keyboard that are
printable may be considered as possible values of the char data type
...
The most common are the
American Standard Code for Information Interchange (ASCII) and Extended BinaryCoded Decimal Interchange Code (EBCDIC)
...

The EBCDIC character set has 256 values and was created by IBM
...

Each of the 128 values of the ASCII character set represents a different character
...
Thus, each

2

38 |

Chapter 2: Basic Elements of C++

character has a predefined ordering, which is called a collating sequence, in the set
...
For example, the value representing 'B' is 66, so 'A' is smaller than 'B'
...

The 14th character in the ASCII character set is called the newline character and is
represented as '\n'
...
) Even though the
newline character is a combination of two characters, it is treated as one character
...
Furthermore, the first 32
characters in the ASCII character set are nonprintable
...
)

Floating-Point Data Types
To deal with decimal numbers, C++ provides the floating-point data type, which we
discuss in this section
...

You may be familiar with scientific notation
...
3872918 * 107

...
65 * 10-5
47
...
79832 * 101

{10 to the power of seven}
{10 to the power of minus five}
{10 to the power of one}

To represent real numbers, C++ uses a form of scientific notation called floating-point
notation
...
In the C++ floating-point notation,
the letter E stands for the exponent
...
924

7
...
18

1
...
0000453

4
...
482

-1
...
0

7
...
As in the case of integral data types, the data types float, double, and
long double differ in the set of values
...

Therefore, only the data types float and double are described here
...
4E+38 and 3
...
The memory allocated for a value of the float data type is

four bytes
...
7E+308 and 1
...
The memory allocated for a value of the double data type is

eight bytes
...
To find these values on a particular system, you can check your compiler’s
documentation or, alternatively, you can run a program given in Appendix F (Header
File cfloat)
...
The maximum number of significant digits—that is, the number of decimal
places—in float values is six or seven
...

For values of the double type, for better precision, some compilers might give more
than 15 significant digits
...


The maximum number of significant digits is called the precision
...
If you
are dealing with decimal numbers, for the most part you need only the float type; if you
need accuracy to more than six or seven decimal places, you can use the double type
...

Therefore, if you use the data type float to manipulate floating-point numbers in a
program, certain compilers might give you a warning message, such as ‘‘truncation
from double to float
...
For illustration purposes and to avoid such warning messages in programming examples, this book mostly uses the data type double to manipulate floatingpoint numbers
...
You can use the
standard arithmetic operators to manipulate integral and floating-point data types
...


2

40 |

Chapter 2: Basic Elements of C++

Arithmetic Operators: + (addition), - (subtraction or negation), * (multiplication), /
(division), % (mod, (modulus or remainder))
...

You use % with only the integral data type to find the remainder in ordinary division
...

That is, integral division truncates any fractional part; there is no rounding
...

ii
...

iv
...

vi
...
6 + 6
...
) Formally, an arithmetic
expression is constructed by using arithmetic operators and numbers
...
The numbers that are used to evaluate
an operator are called the operands for that operator
...
In this expression, – has only one operand
...

In expression (ii), the symbol – is used to subtract 7 from 8
...
Operators that have two operands are called binary operators
...

Binary operator: An operator that has two operands
...
In this
expression, the operator + has two operands and is a binary operator
...
Here, + has
only one operand and so acts as a unary operator
...
However, as arithmetic operators, *, /, and % are binary and so
must have two operands
...
As you can see from these examples, the operator / represents the
quotient in ordinary division when used with integral data types
...
Therefore, 5 / 2 with the integral
operands evaluates to the quotient, which is 2
...
Therefore, 34 % 5 evaluates to the
remainder, which is 4
...
Therefore, 4 % 6 evaluates to the
remainder, which is 4
...

#include
using namespace std;
int main()
{
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
}

"2 + 5 = " << 2 + 5 << endl;
"13 + 89 = " << 13 + 89 << endl;
"34 - 20 = " << 34 - 20 << endl;
"45 - 90 = " << 45 - 90 << endl;
"2 * 7 = " << 2 * 7 << endl;
"5 / 2 = " << 5 / 2 << endl;
"14 / 7 = " << 14 / 7 << endl;
"34 % 5 = " << 34 % 5 << endl;
"4 % 6 = " << 4 % 6 << endl;

return 0;

Sample Run:
2 + 5 =
13 + 89
34 - 20
45 - 90
2 * 7 =

7
= 102
= 14
= -45
14

42 |

Chapter 2: Basic Elements of C++

5 / 2 = 2
14 / 7 = 2
34 % 5 = 4
4 % 6 = 4

You should be careful when evaluating the mod operator with negative integer
operands
...
For example, -34 % 5 = -4,
because in the division –34 / 5, the quotient is –6 and the remainder is -4
...
Also, -34 % -5 = -4, because in the division –34 / –5,
the quotient is 6 and the remainder is –4
...

EXAMPLE 2-4
The following C++ program evaluates various floating-point expressions
...
)
// This program illustrates how floating-point expressions
// are evaluated
...
0 + 3
...
0 + 3
...
0 + 9
...
0 + 9
...
3 - 5
...
3 - 5
...
2 * 2
...
2 * 2
...
0 / 2
...
0 / 2
...
5 / 6
...
5 / 6
...
5 / 6
...
5 / 6
...
0 + 3
...
5
3
...
4 = 12
...
3 - 5
...
1
4
...
5 = 10
...
0 / 2
...
5
34
...
0 = 5
...
5 / 6
...
30769

Arithmetic Operators and Operator Precedence

|

43

Order of Precedence
When more than one arithmetic operator is used in an expression, C++ uses the operator
precedence rules to evaluate the expression
...
Similarly, the
operators + and - have the same level of precedence
...
To avoid confusion, you can use parentheses to group arithmetic expressions
...
Note that this is an integer division
...
You can also use parentheses to override the order of precedence rules (see
Example 2-5)
...
Therefore, the result of this expression is 23
...


Because arithmetic operators are evaluated from left to right, unless parentheses are
present, the associativity of the arithmetic operators is said to be from left to right
...
However, you should use this
ability carefully
...
The
integer value of 8 is 8
...

When evaluating arithmetic expressions, 8 + 7 = 15; '8' + '7' = 56 + 55, which yields
111; and '8' + 7 = 56 + 7, which yields 63
...

These examples illustrate that many things can go wrong when you are performing
character arithmetic
...


Expressions
To this point, we have discussed only arithmetic operators
...
Arithmetic expressions were introduced in the last section
...
If all operands in an expression are floating-point numbers, the
expression is called a floating-point or decimal expression
...

Looking at some examples will help clarify these definitions
...
Variables are discussed later in this chapter
...
8 * 17
...
50
x * 10
...
2

Here, x and y represent variables of the floating-point type; that is, they can hold
floating-point values
...


Expressions

|

45

Evaluating an integral or a floating-point expression is straightforward
...
You
can always use parentheses to group operands and operators to avoid confusion
...
A
mixed expression contains both integers and floating-point numbers
...
5
6 / 4 + 3
...
4 * 2 - 13
...
In the second expression, both operands for the operator / are integers, the first
operand of + is the result of 6 / 4, and the second operand of + is a floating-point
number
...
The obvious question is: How does C++ evaluate mixed expressions?
Two rules apply when evaluating a mixed expression:
1
...


If the operator has the same types of operands (that is, either both
integers or both floating-point numbers), the operator is evaluated
according to the type of the operands
...

b
...
The result is a floatingpoint number
...
The entire expression is evaluated according to the precedence rules;
the multiplication, division, and modulus operators are evaluated
before the addition and subtraction operators
...
Grouping is
allowed for clarity
...
If the operator to be evaluated has
operands of the same data type, evaluate the operator using Rule 1(a)
...
If the operator to be evaluated has one integer
operand and one floating-point operand, before evaluating this operator, convert the
integer operand to a floating-point number with the decimal part of 0
...


2

46 |

Chapter 2: Basic Elements of C++

EXAMPLE 2-8
Mixed Expression

Evaluation

Rule Applied

3 / 2 + 5
...
5
= 6
...
6 / 2 + 5

= 7
...
5
= 1
...
5 (Rule 1(b))
= 6
...
6 / 2
= 15
...
0 (Rule 1(b))
= 7
...
8 + 5
= 7
...
0 (Rule1(b))
= 12
...
0 = 5
...
0 (Rule1(b))
= 2
...
5 = 4
...
5 (Rule1(b))
= 6
...
5 = 13
...
5 (Rule 1(b))
= -12
...
8

4 + 5 / 2
...
5
= 6
...
5

= 12+7/5 – 25
...
5
= 13 – 25
...
5

The following C++ program evaluates the preceding expressions:
// This program illustrates how mixed expressions are evaluated
...
5 = " << 3 / 2 + 5
...
6 / 2 + 5 = " << 15
...
0 = " << 4 + 5 / 2
...
5 = "
4 * 3 + 7 / 5 - 25
...
5 = 6
...
6 / 2 + 5 = 12
...
0 = 6
...
5 = -12
...


Type Conversion (Casting)

|

47

Type Conversion (Casting)
In the previous section, you learned that when evaluating an arithmetic expression, if the
operator has mixed operands, the integer value is changed to a floating-point value with
the zero decimal part
...
As the examples in the
preceding section illustrate, if you are not careful about data types, implicit type coercion
can generate unexpected results
...
The cast operator, also called type conversion or type casting,
takes the following form:
static_cast(expression)

First, the expression is evaluated
...
In C++, static_cast is a reserved word
...
That is, the floating-point
number is truncated
...
Be sure you understand why the last two expressions evaluate as they do
...
9)
static_cast(3
...
0
= static_cast(8) = 8
...
0 / 2
(because static_cast (15) = 15
...
0 / 2
...
5
= static_cast(7) (because 15 / 2 = 7)
= 7
...
8 +
static_cast(15) / 2)
static_cast(7
...
8 + 7
...
3)
= 15
= static_cast(7
...
0)
= static_cast(14
...

#include
using namespace std;
int main()
{
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
}

"static_cast(7
...
9)
endl;
"static_cast(3
...
3)
endl;
"static_cast(25) = "
static_cast(25)
endl;
"static_cast(5 + 3) = "
static_cast(5 + 3)
endl;
"static_cast(15) / 2 = "
static_cast(15) / 2
endl;
"static_cast(15 / 2) = "
static_cast(15 / 2)
endl;
"static_cast(7
...
8 + static_cast(15) / 2)
endl;
"static_cast(7
...
8 + static_cast(15 / 2))
endl;

return 0;

Sample Run:
static_cast(7
...
3) = 3
static_cast(25) = 25
static_cast(5 + 3) = 8
static_cast(15) / 2 = 7
...
8 + static_cast(15) / 2) = 15
static_cast(7
...
0
...
0
...

Chapter 3 explains how to output decimal numbers in a desired format
...


string Type | 49

In C++, the cast operator can also take the form dataType(expression)
...
For example, double(5) = 5
...
6) = 17
...


2
You can also use cast operators to explicitly convert char data values into int data values
and int data values into char data values
...
For example, in the ASCII character
set, static_cast('A') is 65 and static_cast('8') is 56
...

Earlier in this chapter, you learned how arithmetic expressions are formed and evaluated
in C++
...
There are many reasons to save the value of an
expression
...
By calculating the values once and saving them for further
use, you not only save computer time and create a program that executes more quickly,
you also avoid possible typographical errors
...
That is, unless it is saved, the value of an expression
cannot be used in later calculations
...

Before leaving the discussion of data types, let us discuss one more data type—string
...
It is not directly available for
use in a program like the simple data types discussed earlier
...
The data type string is a feature of ANSI/ISO Standard C++
...
Compiler vendors often supplied their own programmer-defined
string type, and the syntax and semantics of string operations often varied from vendor
to vendor
...
Strings in C++ are enclosed in double
quotation marks
...
The
following are examples of strings
...

"William Jacob"
"Mickey"
""

Every character in a string has a relative position in the string
...
The length of a string is
the number of characters in it
...

the first 'i' is 1
...

'J' is 8
...


13

"Mickey"

Position
Position
Position
Position
Position
Position

of
of
of
of
of
of

'M'
'i'
'c'
'k'
'e'
'y'

is
is
is
is
is
is

0
...

2
...

4
...


6

When determining the length of a string, you must also count any spaces in the string
...

"It is a beautiful day
...
It provides
many operations to manipulate strings
...
You will learn about this
data over the next few chapters
...
Recall that data must be loaded into main memory before it can be
manipulated
...

Storing data in the computer’s memory is a two-step process:
1
...

2
...


Allocating Memory with Constants and Variables
When you instruct the computer to allocate memory, you tell it not only what names to
use for each memory location, but also what type of data to store in those memory
locations
...
As you saw earlier, knowing
what data type you have is crucial for performing accurate calculations
...

Some data must stay the same throughout a program
...
A conversion formula that converts inches into

Input |

51

centimeters is fixed, because 1 inch is always equal to 2
...
When stored
in memory, this type of data needs to be protected from accidental changes during
program execution
...

Named constant: A memory location whose content is not allowed to change during

program execution
...
The syntax to declare a
named constant is:
const dataType identifier = value;

In C++, const is a reserved word
...
54;
const int NO_OF_STUDENTS = 20;
const char BLANK = ' ';

The first statement tells the compiler to allocate memory (eight bytes) to store a value
of type double, call this memory space CONVERSION, and store the value 2
...

Throughout a program that uses this statement, whenever the conversion formula is
needed, the memory space CONVERSION can be accessed
...

Note that the identifier for a named constant is in uppercase letters
...
Moreover, if the name of a named constant is a combination of more than one word, called a run-together word, then the words are separated
using an underscore
...

As noted earlier, the default type of floating-point numbers is double
...
54f;
Otherwise, the compiler will generate a warning message
...
54f says that it is
a float value
...
Because memory size is of little concern these days, as indicated earlier,
we will mostly use the type double to work with floating-point values
...
If the fixed data changes, you do not need to edit the entire
program and change the old value to the new value wherever the old value is used
...
In addition, by storing a value and
referring to that memory location whenever the value is needed, you avoid typing
the same value again and again and prevent accidental typos
...

In some programs, data needs to be modified during program execution
...
Similarly, after each
pay increase, the employee’s salary changes
...
In C++, memory cells
whose contents can be modified during program execution are called variables
...


The syntax for declaring one variable or multiple variables is:
dataType identifier, identifier,
...
The second and third statements have similar
conventions
...
The fifth statement tells the compiler
to allocate memory space to store a string and call it name
...

However, C++ programmers typically use lowercase letters to declare variables
...
(For example, see the variable amountDue in the
preceding example
...


Input |

53

In C++, you must declare all identifiers before you can use them
...
Therefore, to use either a named constant or
a variable, you must first declare it
...
A data type is called simple if
the variable or named constant of that type can store only one value at a time
...


Putting Data into Variables
Now that you know how to declare variables, the next question is: How do you put data
into those variables? In C++, you can place data into a variable in two ways:
1
...

2
...


Assignment Statement
The assignment statement takes the following form:
variable = expression;

In an assignment statement, the value of the expression should match the data type of
the variable
...

A variable is said to be initialized the first time a value is placed in the variable
...

EXAMPLE 2-13
Suppose you have the following variable declarations:
int num1, num2;
double sale;
char first;
string str;

Now consider the following assignment statements:
num1 = 4;
num2 = 4 * 5 - 11;
sale = 0
...
";

2

54 |

Chapter 2: Basic Elements of C++

For each of these statements, the computer first evaluates the expression on the right
and then stores that value in a memory location named by the identifier on the left
...
00 in sale, and the fourth statement stores the
character D in first
...
"
in the variable str
...

#include
#include
using namespace std;
int main()
{
int num1, num2;
double sale;
char first;
string str;
num1 = 4;
cout << "num1 = " << num1 << endl;
num2 = 4 * 5 - 11;
cout << "num2 = " << num2 << endl;
sale = 0
...
";
cout << "str = " << str << endl;
}

return 0;

Sample Run:
num1 = 4
num2 = 9
sale = 20
first = D
str = It is a sunny day
...
Let us take a look at the
output statement:
cout << " num1 = " << num1 << endl;

This output statement consists of the string " num1 = ", the operator <<, and the variable
num1
...
The meaning of the other output statements is similar
...
’’ The expression on the right side must be evaluated first; that value is then
assigned to the memory location specified by the variable on the left side
...
Note that if num has not been initialized, the statement num = num + 2
might give unexpected results and/or the complier might generate a warning message
indicating that the variable has not been initialized
...
’’ Reading the statement as ‘‘num equals 5’’ is incorrect, especially for statements such
as num = num + 2;
...

EXAMPLE 2-14
Suppose that num1, num2, and num3 are int variables and the following statements are
executed in sequence
...

2
...

4
...


num1 = 18;
num1 = num1 + 27;
num2 = num1;
num3 = num2 / 5;
num3 = num3 / 4;

The following table shows the values of the variables after the execution of each
statement
...
The orange color in a box shows
that the value of that variable is changed
...

This value is assigned to num1, which
replaces the old value of num1
...


Before Statement 1

After Statement 1

After Statement 2

45

45

?

num1

num2

num3

45

45

9

num1

num2

num3

After Statement 3

After Statement 4

45

45

2

num1

num2

num3

After Statement 5

num2 / 5 = 45 / 5 = 9
...
So num3
= 9
...
This
value is assigned to num3, which
replaces the old value of num3
...

Tracing values through a sequence, called a walk-through, is a valuable tool to learn and
practice
...
You will learn more about how to walk through a
sequence of C++ statements later in this chapter
...
The following is a legal statement in C++:

x = y = z;
In this statement, first the value of z is assigned to y, and then the new value of y is
assigned to x
...


Saving and Using the Value of an Expression
Now that you know how to declare variables and put data into them, you can learn
how to save the value of an expression
...
To save the value of an expression and use it in a later
expression, do the following:
1
...
For example, if the
result of the expression is an integer, declare an int variable
...
Assign the value of the expression to the variable that was declared,
using the assignment statement
...

3
...
The following example further illustrates this concept
...

Because the expression b2 – 4ac appears in both expressions, you can first calculate
the value of this expression and save its value in d
...
You also learned
that after declaring a variable, you can use an assignment statement to initialize it
...
Before we discuss how to
use an input (read) statement, we address this important issue
...
In
other words, C++ may not automatically initialize variables
...

This does not mean, however, that there is no value in a variable after its declaration
...

Recall from Chapter 1 that main memory is an ordered sequence of cells, and each cell is
capable of storing a value
...
Therefore, data in a memory cell is a sequence of bits
...
The state of these bits depends on how the system functions
...


2

58 |

Chapter 2: Basic Elements of C++

During data manipulation, the computer takes the value stored in particular cells and
performs a calculation
...

If you only declare a variable and do not instruct the computer to put data into the variable,
the value of that variable is garbage
...
Using a variable in an expression without initializing it produces erroneous
results
...
For example, consider the following C++ statements in which variables are first
declared and then initialized:
int first, second;
char ch;
double x;
first = 13;
second = 10;
ch = ' ';
x = 12
...
6;

The first C++ statement declares two int variables, first and second, and stores 13 in
first and 10 in second
...

In reality, not all variables are initialized during declaration
...
The key point is that all variables must be initialized before
they are used
...
In
this section, you will learn how to put data into variables from the standard input device,
using C++’s input (or read) statements
...


When the computer gets the data from the keyboard, the user is said to be acting interactively
...
The syntax of cin together with >> is:
cin >> variable >> variable
...
In C++, >> is called the stream extraction
operator
...
Furthermore,
throughout this book, the syntax is enclosed in yellow boxes
...
Further suppose that the input is
73
...
Consider the following statements:
cin >> miles;

This statement causes the computer to get the input, which is 73
...
That is, after this statement executes, the
value of the variable miles is 73
...

Example 2-17 further explains how to input numeric data into a program
...
Notice that when these numbers are entered via the keyboard,
they are separated with a blank
...


2

60 |

Chapter 2: Basic Elements of C++

The following C++ program shows the effect of the preceding input statements:
// This program illustrates how input statements work
...

Enter two integers separated by spaces: 23 7
Feet = 23
Inches = 7

The C++ program in Example 2-18 illustrates how to read strings and numeric data
...

#include
#include
using namespace std;
int main()
{
string firstName;
string lastName;
int age;
double weight;
cout << "Enter first name, last name, age, "
<< "and weight, separated by spaces
...

Enter first name, last name, age, and weight, separated by spaces
...
5
Name: Sheila Mann
Age: 23
Weight: 120
...
The statement in Line 5 is an output statement and tells the user what to
do
...
) As shown in the sample run, the
input to the program is:
Sheila Mann 23 120
...
Next, the statement in Line 7 first skips the blank after
Mann and reads and stores 23 into the variable age and then skips the blank after 23
and reads and stores 120
...

The statements in Lines 8, 9, and 10 produce the third, fourth, and fifth lines of the
sample run
...
Alternately, one value per line can be entered
...
Consider the following declaration:
int feet;
int inches;

2

62 |

Chapter 2: Basic Elements of C++

Consider the following two sets of code:

(a)

feet = 35;
inches = 6;
cout << "Total inches = "
<< 12 * feet + inches;

(b)

cout << "Enter feet: ";
cin >> feet;
cout << endl;
cout << "Enter inches: ";
cin >> inches;
cout << endl;
cout << "Total inches = "
<< 12 * feet + inches;

In (a), feet and inches are initialized using assignment statements, and in (b), these
variables are initialized using input statements
...
On the other hand, in (b), each time the
program runs, you are prompted to enter values for feet and inches
...

Sometimes it is necessary to initialize a variable by using an assignment statement
...

Recall that C++ does not automatically initialize variables when they are declared
...

When the program is compiled, some of the newer IDEs might give warning messages
if the program uses the value of a variable without first properly initializing that variable
...


Suppose you want to store a character into a char variable using an input statement
...
For example, suppose that ch is a char variable
...
Similarly, if you want to store a string into a string variable using an
input statement, during program execution, you enter only the string without the
double quotes
...
Consider the following declarations:
int firstNum, secondNum;
double z;
char ch;
string name;

Also, suppose that the following statements execute in the order given:
1
...

3
...

5
...

7
...

9
...

11
...


firstNum = 4;
secondNum = 2 * firstNum + 6;
z = (firstNum + 1) / 2
...
3 Jenny D

This line has four values, 8, 16
...

Let’s now determine the values of the declared variables after the last statement
executes
...
(In
the following figures, a question mark [?] in a box indicates that the value in the box
is unknown
...


?

?

?

?

firstNum

FIGURE 2-2

?
secondNum

z

ch

name

Variables before statement 1 executes

2

64 |

Chapter 2: Basic Elements of C++

Next, we show the values of the variables after the execution of each statement
...


Values of the Variables

Explanation

4

?

secondNum

z

ch

name

14

?

?

?

secondNum

z

ch

name

4

14

2
...
5

A

?

firstNum

4

?

firstNum

3

?

4

2

?

firstNum

1

secondNum

z

ch

name

4

2
...
3

A

?

firstNum

6

8

firstNum

5

secondNum

z

ch

name

10

16
...
3

A

Jenny

secondNum

z

ch

name

32

9

16
...
3

D

Jenny

firstNum

secondNum

z

ch

name

Store 4 into firstNum
...

Store 14 into secondNum
...
0
= (4 + 1) / 2
...
0
= 2
...
Store 2
...

Store 'A' into ch
...
This statement
replaces the old value of
secondNum with this new
value
...
3)
and store this number into z
...

2 * secondNum +
static_cast(z) =
2 *8 þ
static_cast (16
...
Store 32 into
firstNum
...

Read the next input, Jenny,
from the keyboard and store it
into name
...

Store 9 into secondNum
...
This statement replaces
the old value of ch with the new
value
...


Values of the Variables

100

9

16
...
7

D

Jenny

firstNum

12

65

Explanation

firstNum

11

|

secondNum

z

ch

name

firstNum +
static_cast(ch) =
32 + static_cast
('D') = 32 + 68 = 100
...

firstNum – z = 100 – 16
...
0 – 16
...
7
...
7 into z
...
Example 2-19 illustrates how to do a walk-through
of your program
...
The Web site
accompanying this book contains a C++ program that shows the effect of the
12 statements listed at the beginning of Example 2-19
...
cpp
...
In this
case, the compiler most likely will issue a warning message about the implicit
type conversion
...
These operators are used frequently by C++ programmers and are useful
programming tools
...
The statement:
count = count + 1;

increments the value of count by 1
...
It then assigns this value to
the variable on the left, which is count
...
To expedite the execution of such statements,
C++ provides the increment operator, ++, which increases the value of a variable by
1, and the decrement operator, ––, which decreases the value of a variable by 1
...
The syntax of the
increment operator is:
Pre-increment: ++variable
Post-increment: variable++
The syntax of the decrement operator is:
Pre-decrement: ––variable
Post-decrement: variable––
Let’s look at some examples
...
Similarly, the statement:
––count;

or:
count––;

decrements the value of count by 1
...

Now, both the pre- and post-increment operators increment the value of the variable by 1
...

What is the difference between the pre and post forms of these operators? The difference
becomes apparent when the variable using these operators is employed in an expression
...
If ++x is used in an expression, first the value of x is
incremented by 1, and then the new value of x is used to evaluate the expression
...
The following example clarifies
the difference between the pre- and post-increment operators
...
Consider the following statements:
x = 5;
y = ++x;

The first statement assigns the value 5 to x
...
After the second statement executes, both x and y have the value 6
...
In the second statement, the post-increment
operator is applied to x
...
Finally, the
value of the expression, which is 5, is stored in y
...

The following example further illustrates how the pre and post forms of the increment
operator work
...
To execute the second statement, first the expression
2 +(++a) is evaluated
...
Then 2 is added to 6 to get 8, which is then assigned to b
...

On the other hand, after the execution of the following statements:
a = 5;
b = 2 + (a++);

the value of a is 6 while the value of b is 7
...
That is, the variable using the increment or decrement operator
will not be part of any expression
...
We also used certain output statements to show the
results on the standard output device
...

The standard output device is usually the screen
...
The general syntax of cout together with << is:
cout << expression or manipulator << expression or manipulator
...
In C++, << is called the stream insertion
operator
...
The expression is evaluated, and its value is printed at the current
insertion point on the output device
...
A manipulator is used to format the output
...

On the screen, the insertion point is where the cursor is
...
In an output statement, a
string or an expression involving only one variable or a single value evaluates to itself
...

For example, suppose ch is a char variable and ch = 'A';
...


EXAMPLE 2-21
Consider the following statements
...

Statement
1
2
3
4

cout
cout
cout
cout

<<
<<
<<
<<

Output
29 / 4 << endl;
"Hello there
...

12
4 + 7

Output |

5
6
7
8
9

cout
cout
cout
cout
cout

<<
<<
<<
<<
<<

4 + 7 << endl;
'A' << endl;
"4 + 7 = " << 4 + 7 << endl;
2 + 3 * 5 << endl;
"Hello \nthere
...


Look at the output of statement 9
...

Therefore, when \n appears in a string in an output statement, it causes the insertion
point to move to the beginning of the next line on the output device
...
are printed on separate lines
...


Recall that all variables must be properly initialized; otherwise, the value stored in them
may not make much sense
...

If num is an int variable, then the output of the C++ statement:
cout << num << endl;

is meaningful provided that num has been given a value
...

EXAMPLE 2-22
Consider the following C++ program
...

#include
using namespace std;
int main()
{
int a, b;
a = 65;
b = 78;

//Line
//Line

1
2

2

70 |

Chapter 2: Basic Elements of C++

cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
cout
}

<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<

//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line

29 / 4 << endl;
3
...
\n";
7 << endl;
3 + 5 << endl;
"3 + 5";
endl;
a << endl;
"a" << endl;
(a + 5) * 6 << endl;
2 * b << endl;

3
4
5
6
7
8
9
10
11
12
13

return 0;

In the following output, the column marked ‘‘Output of Statement at’’ and the line
numbers are not part of the output
...

Output of Statement at
7
1
...

7
8
3 + 5
65
a
420
156

Line
Line
Line
Line
Line
Line
Line
Line
Line
Line

3
4
5
6
7
8
10
11
12
13

For the most part, the output is straightforward
...
The statement in Line 7 outputs the result of 3 + 5, which is 8, and
moves the insertion point to the beginning of the next line
...
Note that the statement in Line 8 consists only of the string 3 + 5
...

The output statement in Line 9 contains only the manipulator endl, which moves
the insertion point to the beginning of the next line
...
Note that in
this output, the column ‘‘Output of Statement at’’ does not contain Line 9
...
It simply
moves the insertion point to the beginning of the next line
...
The manipulator endl then moves the insertion
point to the beginning of the next line
...


2
Let us now take a close look at the newline character, '\n'
...
";
cout << "My name is James
...
My name is James
...
\n";
cout << "My name is James
...

My name is James
...
Note also that \n may appear anywhere in the string
...
\nMy name is James
...

My name is James
...
\n";
cout << "My name is James
...
" << endl;
cout << "My name is James
...
\nMy name is James
...
";
cout << "\nMy name is James
...
";
cout << endl << "My name is James
...

My name is James
...
\n
...
2\n
...
" << endl << "
...
2" << endl << "
...


...
2

...
We can go golfing
...
However, in the
programming code, this statement may not fit in one line as part of the output statement
...
";
cout << "We can go golfing
...
Also, note that there is no manipulator endl at
the end of the first statement
...
Equivalently, you can use the following output statement to
output this sentence:
cout << "It is sunny, warm, and not a windy day
...
" << endl;

In this statement, note that there is no semicolon at the end of the first line, and the
identifier cout does not appear at the beginning of the second line
...
Also, note the double quotation marks at the beginning and end of the sentences
on each line
...

If a string appearing in an output statement is long and you want to output the string in
one line, you can break the string by using either of the previous two methods
...

We can go golfing
...

That is, in programming code, a string cannot be broken into more than one line by using
the return (Enter) key on your keyboard
...
There are many escape sequences in C++, which allow you
to control the output
...

TABLE 2-4

Commonly Used Escape Sequences
Escape
Sequence

Description

\n

Newline

Cursor moves to the beginning of the next line

\t

Tab

Cursor moves to the next tab stop

\b

Backspace

Cursor moves one space to the left

\r

Return

Cursor moves to the beginning of the current line (not
the next line)

\\

Backslash

Backslash is printed

\'

Single quotation

Single quotation mark is printed

\"

Double quotation

Double quotation mark is printed

2

74 |

Chapter 2: Basic Elements of C++

The following example shows the effect of some of these escape sequences
...

Therefore, the preceding statement is equivalent to the following output statement:
cout << "The tab character is represented as '\\t'" << endl;

The output of the statement:
cout << "The string \"Sunny\" contains five characters
...


The Web site accompanying this text contains the C++ program that shows
the effect of the statements in Example 2-26
...
cpp
...
The next
section explains what this header file is, how to include a header file in a program, and
why you need header files in a program
...


Preprocessor Directives |

75

Preprocessor Directives
Only a small number of operations, such as arithmetic and assignment operations, are
explicitly defined in C++
...
Every library has a name and is
referred to by a header file
...
Similarly, the
descriptions of some very useful mathematical functions, such as power, absolute, and
sine, are contained in the header file cmath
...
You
use preprocessor directives and the names of header files to tell the computer the
locations of the code provided in libraries
...

Preprocessor directives are commands supplied to the preprocessor that cause the preprocessor to modify the text of a C++ program before it is compiled
...
There are no semicolons at the end of preprocessor commands
because they are not C++ statements
...

The general syntax to include a header file (provided by the IDE) in a C++ program is:
#include

For example, the following statement includes the header file iostream in a C++ program:
#include

Preprocessor directives to include header files are placed as the first line of a program so
that the identifiers declared in those header files can be used throughout the program
...
)
Certain header files are required to be provided as part of C++
...
Individual programmers can also create their
own header files, which is discussed in the chapter Classes and Data Abstraction, later in
this book
...

From Figure 1-3 (Chapter 1), we can conclude that a C++ system has three basic
components: the program development environment, the C++ language, and the C++
library
...
The program
development environment consists of the six steps shown in Figure 1-3
...


2

76 |

Chapter 2: Basic Elements of C++

namespace and Using cin and cout in a Program
Earlier, you learned that both cin and cout are predefined identifiers
...
The name of this namespace is std
...
For now, you need to know
only how to use cin and cout and, in fact, any other identifier from the header file
iostream
...
One way to use
cin and cout is to refer to them as std::cin and std::cout throughout the program
...
You can then refer
to cin and cout without using the prefix std::
...
That is, to use cin and cout in a program, the programs
will contain the following two statements:
#include
using namespace std;

In C++, namespace and using are reserved words
...
As you learn more
C++ programming, you will become aware of other header files
...

Similarly, the header file iomanip contains the specifications of many useful functions
and manipulators that help you format your output in a specific manner
...

The name of the namespace in each of these header files is std
...
Moreover, to simplify the accessing of
identifiers in programs, the statement using namespace std; will be included
...
This using
statement typically appears after all the header files
...
To use the string data type, you need to access its
definition from the header file string
...

You are now ready to create a complete C++ program
...

Therefore, if a C++ program consists of only one function, then it must be the function
main
...

Until Chapter 6, you will deal mainly with the function main
...
The
statements to declare named constants are usually placed outside of the function main
...


...

statement_n
}

return 0;

In the syntax of the function main, each statement (statement_1,
...
The statement return 0;
must be included in the function main and must be the last statement
...
The meaning of the statement return 0; will be
discussed in Chapter 6
...

A C++ program might use the resources provided by the IDE, such as the necessary code
to input the data, which would require your program to include certain header files
...
The preprocessor directives tell the compiler which header files to include in
the program
...
Taken
together, the preprocessor directives and the program statements constitute the C++
source code
...
cpp
...
cpp
...

When the program is compiled, the compiler generates the object code, which is saved in
a file with the file extension
...
When the object code is linked with the system
resources, the executable code is produced and saved in a file with the file extension

...
Typically, the name of the file containing the object code and the name of the file
containing the executable code are the same as the name of the file containing the source

2

78 |

Chapter 2: Basic Elements of C++

code
...
cpp, the
name of the file containing the object code is firstProg
...
exe
...
cpp,
...
exe—are
system dependent
...
The
name of the project and the name of the source file need not be the same
...
exe
...

Because the programming instructions are placed in the function main, let us elaborate on
this function
...
The first line of the
function main, that is:
int main()

is called the heading of the function main
...
The body of the function main contains two types of statements:



Declaration statements
Executable statements

Declaration statements are used to declare things, such as variables
...

EXAMPLE 2-27
The following statements are examples of variable declarations:
int a, b, c;
double x, y;

Executable statements perform calculations, manipulate data, create output, accept
input, and so on
...

EXAMPLE 2-28
The following statements are examples of executable statements:
a = 4;
cin >> b;
cout << a << " " << b << endl;

//assignment statement
//input statement
//output statement

Creating a C++ Program |

79

In skeleton form, a C++ program looks like the following:
//comments, if needed
preprocessor directives to include header files

2

using statement
named constants, if necessary
int main()
{
statement_1

...


...


EXAMPLE 2-29
//***************************************************************
// Author: D
...
Malik
//
// This program shows where the include statements, using
// statement, named constants, variable declarations, assignment
// statements, and input and output statements typically appear
...

Line 9: firstNum = 18
Line 10: Enter an integer: 15
Line 13: secondNum = 15
Line 15: The new value of firstNum = 60

The preceding program works as follows: The statement in Line 1 includes the
header file iostream so that program can perform input/output
...
The statement in Line 3 declares the named constant NUMBER and
sets its value to 12
...
The
statements in Lines 6 and 7 declare the variables firstNum and secondNum
...
Next, the statement in Line 10 prompts the user to
enter an integer
...
The statement in Line 12 positions the
cursor on the screen at the beginning of the next line
...
The statement in Line 14 evaluates the expression:
firstNum + NUMBER + 2 * secondNum

and assigns the value of this expression to the variable firstNum, which is 60 in the
sample run
...
The statement
in Line 16 contains the return statement
...


Debugging: Understanding and Fixing Syntax
Errors
The previous sections of this chapter described the basic components of a C++ program
...

Therefore, when you compile a program, the compiler will identify the syntax error
...


Debugging: Understanding and Fixing Syntax Errors

|

81

Consider the following C++ program:
1
...

3
...

5
...
{
7
...

9
...

11
...

13
...

return ;
15
...
}
(Note that the numbers 1 to 16 on the left side are not part of the program
...
) This program contains syntax errors
...
)
Example2_Syntax_Errors
...
cpp(9) : error C2146: syntax error :
missing ';' before identifier 'num'
c:\chapter 2 source code\example2_syntax_errors
...
cpp(13) : error C2065: 'tempNum' :
undeclared identifier
c:\chapter 2 source code\example2_syntax_errors
...
cpp(13) : error C2568: '<<' : unable to
resolve function overload
c:\program files\microsoft visual studio 9
...
0\vc\include\ostream(966): or
'std::basic_ostream<_Elem,_Traits> &std::endl(std::basic_ostream<_Elem,_Traits> &)'
with
[
_Elem=char,
_Traits=std::char_traits
]

2

82 |

Chapter 2: Basic Elements of C++

c:\program files\microsoft visual studio 9
...
cpp(15) : error C2561: 'main' : function
must return a value
f:\cs1 c++ fifth edition\chapter 2\chapter 2 source code and prog ex\chapter 2
source code\example2_syntax_errors
...
htm"
Proj1 - 6 error(s), 0 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

First, consider the following error:
c:\chapter 2 source code\example2_syntax_errors
...
cpp(9) indicates that there is an error in
Line 9
...
If we look at Line 7, we find that there is a missing semicolon at the end of
the statement int num
...

Next, consider the second error:
c:\chapter 2 source code\example2_syntax_errors
...

When we look at the code, we find that this identifier has not been declared
...

The error:
c:\chapter 2 source code\example2_syntax_errors
...
As in the
previous error, we must declare tempNum
...

The next error is:
c:\chapter 2 source code\example2_syntax_errors
...
For a beginner, this error is somewhat hard to understand
...
) However, as you practice, you
will learn how to interpret and correct syntax errors
...
cpp(13) : error C2568: '<<' :
unable to resolve function overload

Debugging: Understanding and Fixing Syntax Errors

|

83

It tells us that this error has something to do with the operator <<
...

So we must correct this error
...
cpp(15) : error C2561: 'main' :
function must return a value
c:\chapter 2 source code\example2_syntax_errors
...
However, at this point, the explanation given,
especially for a beginner, is somewhat unclear
...
We can effectively use this information to fix syntax error
...
It is possible that the list of errors reported by the compiler is
longer than the program itself
...
In situations like this, correct the syntax errors in the order they

2

84 |

Chapter 2: Basic Elements of C++

are listed and compile your program, if necessary, after each correction
...
The important thing is not to panic
...


Program Style and Form
In previous sections, you learned enough C++ concepts to write meaningful programs
...
Using the proper structure for a C++ program makes it easier to
understand and subsequently modify the program
...

In addition, every C++ program must satisfy certain rules of the language
...
It must also follow the syntax rules, which, like
grammar rules, tell what is right and what is wrong and what is legal and what is illegal in
the language
...

The following sections are designed to help you learn how to use the C++ programming
elements you have learned so far to create a functioning program
...


Syntax
The syntax rules of a language tell what is legal and what is not legal
...
For example, consider the following C++ statements:
int x;
int y
double z;

//Line 1
//Line 2
//Line 3

y = w + x;

//Line 4

When these statements are compiled, a compilation error will occur at Line 2 because the
semicolon is missing after the declaration of the variable y
...

As discussed in Chapter 1, you enter a program into the computer by using a text editor
...
Therefore, when the program is
compiled, you are most likely to see syntax errors
...
It is very
common for the omission of a single character to cause four or five error messages
...
Therefore, you should
correct syntax errors in the order in which the compiler lists them
...
Also, compilers not only discover syntax errors, but also hint and sometimes tell the
user where the syntax errors are and how to fix them
...
Blanks are
also used to separate reserved words and identifiers from each other and from other
symbols
...


Use of Semicolons, Brackets, and Commas
All C++ statements must end with a semicolon
...

Note that curly braces, { and }, are not C++ statements in and of themselves, even
though they often appear on a line with no other code
...
Brackets have other uses, which will be explained later
...
For example, you use commas
when you declare more than one variable following a data type
...
For example, the
order-of-precedence rules for arithmetic operators are semantic rules
...
What happens when a
program contains semantic errors? It is quite possible to eradicate all syntax errors in a
program and still not have it run
...

For example, the following two lines of code are both syntactically correct expressions,
but they have different meanings:
2 + 3 *5

and:
(2 + 3) * 5

If you substitute one of these lines of code for the other in a program, you will not get the
same results—even though the numbers are the same, the semantics are different
...


Naming Identifiers
Consider the following two sets of statements:
const double A = 2
...
54;
double centimeters;
double inches;
centimeters = inches * CENTIMETERS_PER_INCH;

The identifiers in the second set of statements, such as CENTIMETERS_PER_INCH, are
usually called self-documenting identifiers
...

Consider the self-documenting identifier annualsale
...
In using self-documenting identifiers, you may inadvertently include
run-together words, which may lessen the clarity of your documentation
...
For example, you could use
either annualSale or annual_sale to create an identifier that is more clear
...
For example, an identifier used to name a named constant is
all uppercase
...


Prompt Lines
Part of good documentation is the use of clearly written prompts so that users will
know what to do when they interact with a program
...
Prompt lines are executable
statements that inform the user what to do
...

If the program contained only the second statement, users would have no idea that they
must enter a number, and the computer would wait forever for the input
...

In a program, whenever input is needed from users, you must include the necessary
prompt lines
...
For example, the preceding prompt line not

Program Style and Form

|

87

only tells the user to input a number, but also informs the user that the number
should be between 1 and 10
...
Therefore, you must properly document your programs
...
You use comments to document programs
...


Form and Style
You might be thinking that C++ has too many rules
...
For example, consider the following two ways of
declaring variables:
int feet, inch;
double x, y;

and:
int feet,inches;double x,y;

The computer would have no difficulty understanding either of these formats, but the
first form is easier to read and follow
...

What about blank spaces? Where are they significant and where are they meaningless?
Consider the following two statements:
int a,b,c;

and:
int

a,

b,

c;

Both of these declarations mean the same thing
...
On the other hand, consider the following
statement:
inta,b,c;

This statement contains a syntax error
...

The clarity of the rules of syntax and semantics frees you to adopt formats that are pleasing
to you and easier to understand
...

EXAMPLE 2-30
Consider the following C++ program:
//An improperly formatted C++ program
...
However, this program is very hard to read
...
Note the difference when the
program is reformatted:
//A properly formatted C++ program
...
Your programs should be properly
indented and formatted
...
Also, always put a space before and after an operator
...


More on Assignment Statements
The assignment statements you have seen so far are called simple assignment
statements
...

Corresponding to the five arithmetic operators +, -, *, /, and %, C++ provides five
compound operators: +=, -=, *=, /=, and %=, respectively
...
For example, using
the compound operator +=, you can rewrite the simple assignment statement:
variable = variable + (expression);

as:
variable += expression;

The compound assignment statement allows you to write simple assignment statements
in a concise fashion by combining an arithmetic operator with the assignment operator
...

Simple Assignment Statement

Compound Assignment Statement

i = i + 5;
counter = counter + 1;
sum = sum + number;
amount = amount * (interest + 1);
x = x / ( y + 5);

i += 5;
counter += 1;
sum += number;
amount *= interest + 1;
x /= y + 5;

Any compound assignment statement can be converted into a simple assignment statement
...
For example, consider the following simple assignment statement:

x = x * y + z – 5;
To write this statement as a compound assignment statement, the variable x must be a
common factor in the right side, which is not the case
...
In fact, the equivalent
compound assignment statement is:

x *
=

y + (z – 5)/x;

which is more complicated than the simple assignment statement
...
We recommend avoiding such compound
expressions
...
So
statements such as a = a + b; are written as a += b;
...
The
program should then convert and output the lengths in centimeters
...

Input
Output
PROBLEM
ANALYSIS
AND
ALGORITHM
DESIGN

Length in feet and inches
...


The lengths are given in feet and inches, and you need to find the equivalent length
in centimeters
...
54 centimeters
...
Then, you can
use the conversion formula, 1 inch = 2
...
To convert the length from feet and inches to inches, you multiply
the number of feet by 12, as 1 foot is equal to 12 inches, and add the given inches
...
You then find the total inches
as follows:
totalInches = (12 * feet) + inches
= 12 * 5 + 7
= 67

You can then apply the conversion formula, 1 inch = 2
...

centimeters = totalInches * 2
...
54
= 170
...

2
...

4
...

Convert the length into total inches
...

Output centimeters
...
Thus,

you need two variables: one to store feet and the other to store inches
...
You also need a variable to store the equivalent length in
centimeters
...
54
...
54 directly in the program, you will

declare this value as a named constant
...
Instead of using 12 directly in the
program, you will also declare this value as a named constant
...

const double CENTIMETERS_PER_INCH = 2
...
We also determined the necessary variables and named constants
...

1
...
(Without a prompt line, the user
will be staring at a blank screen and will not know what to do
...
Get the data
...
Echo the input—that is, output what the program read as input
...
)
4
...

5
...

6
...

7
...


Putting It Now that the problem has been analyzed and the algorithm has been designed, the
Together next step is to translate the algorithm into C++ code
...

The program will begin with comments that document its purpose and functionality
...

In other words, the program will use input statements to get data into the program and
output statements to print the results
...
Thus, the first statement of the program, after the comments as
described above, will be the preprocessor directive to include this header file
...
Typically, named constants hold special data, such as
CENTIMETERS_PER_INCH
...
If a named constant is to be

Programming Example: Convert Length |

93

used throughout the program, then it is typically placed before the function main
...
Until then, usually, we will place named
constants before the function main so that they can be used throughout the program
...
In addition, the program needs variables to
manipulate data, and these variables will be declared in the body of the function
main
...
The body of the function main will also contain the C++
statements that implement the algorithm
...

2
...

4
...

Include header files, if any are used in the program
...

Write the definition of the function main
...
S
...
54 centimeters
...
54;
const int INCHES_PER_FOOT = 12;

2

94 |

Chapter 2: Basic Elements of C++

int main ()
{
//Declare variables
int feet, inches;
int totalInches;
double centimeter;
//Statements: Step 1 - Step 7
cout << "Enter two integers, one for feet and "
<< "one for inches: ";
cin >> feet >> inches;
cout << endl;
cout << "The numbers you entered are " << feet
<< " for feet and " << inches
<< " for inches
...

Enter two integers, one for feet, one for inches: 15 7
The numbers you entered are 15 for feet and 7 for inches
...
98

PROGRAMMING EXAMPLE:

Make Change

Write a program that takes as input any change expressed in cents
...
For example, 483 cents should be returned as 9 halfdollars, 1 quarter, 1 nickel, and 3 pennies
...


Output

Equivalent change in half-dollars, quarters, dimes, nickels, and pennies
...
To find the number of half-dollars, you
divide 646 by 50, the value of a half-dollar, and find the quotient, which is 12, and
the remainder, which is 46
...

Next, divide the remaining change by 25 to find the number of quarters
...
This process
continues for dimes and nickels
...

Applying this discussion to 646 cents yields the following calculations:
1
...

3
...

5
...

7
...

9
...

2
...

4
...

6
...

8
...


Get the change in cents
...

Calculate the remaining change
...

Calculate the remaining change
...

Calculate the remaining change
...

Calculate the remaining change, which is the number of pennies
...
However, the numbers
of half-dollars, quarters, and so on are not used in later calculations, so the program can
simply output these values without saving each of them in a variable
...
Because these data are special and the program uses these values

more than once, it makes sense to declare them as named constants
...

2
...

4
...

6
...

8
...

10
...

12
...

Get input
...

Compute and print the number of half-dollars
...

Compute and print the number of quarters
...

Compute and print the number of dimes
...

Compute and print the number of nickels
...

Print the remaining change
...
S
...

//************************************************************
//Header file
#include
using namespace std;
//Named constants
const int HALF_DOLLAR = 50;
const int QUARTER = 25;
const int DIME = 10;
const int NICKEL = 5;

Programming Example: Make Change |

int main()
{
//Declare variable
int change;
//Statements: Step 1 – Step 12
cout << "Enter change in cents: ";
cin >> change;
cout << endl;
cout << "The change you entered is " << change
<< endl;

2
//Step 1
//Step 2

//Step 3

cout << "The number of half-dollars to be returned "
<< "is " << change / HALF_DOLLAR
<< endl;
//Step 4
change = change % HALF_DOLLAR;

//Step 5

cout << "The number of quarters to be returned is "
<< change / QUARTER << endl;
//Step 6
change = change % QUARTER;

//Step 7

cout << "The number of dimes to be returned is "
<< change / DIME << endl;
//Step 8
change = change % DIME;

//Step 9

cout << "The number of nickels to be returned is "
<< change / NICKEL << endl;
//Step 10
change = change % NICKEL;

//Step 11

cout << "The number of pennies to be returned is "
<< change << endl;
//Step 12
}

return 0;

Sample Run: In this sample run, the user input is shaded
...

2
...

4
...

6
...

8
...

10
...

12
...

14
...

16
...

18
...

20
...


22
...

Every C++ program has a function called main
...

Multiline comments are enclosed between /* and */
...

Reserved words cannot be used as identifiers in a program
...

In C++, identifiers are names of things
...

Whitespaces include blanks, tabs, and newline characters
...

C++ data types fall into the following three categories: simple, structured,
and pointers
...

Integral data types are classified into nine categories: char, short, int,
long, bool, unsigned char, unsigned short, unsigned int, and
unsigned long
...

The data type bool has only two values: true and false
...

The collating sequence of a character is its preset number in the character
data set
...

The data type float is used in C++ to represent any real number between
À3
...
4E + 38
...

The data type double is used in C++ to represent any real number
between À1
...
7E + 308
...

The arithmetic operators in C++ are addition (+), subtraction (-), multiplication (*), division (/), and modulus (%)
...

24
...

26
...


28
...

30
...

32
...

34
...

36
...

38
...

40
...

42
...

44
...

46
...


The modulus operator, %, takes only integer operands
...

All operands in an integral expression, or integer expression, are integers,
and all operands in a floating-point expression are decimal numbers
...

When evaluating an operator in an expression, an integer is converted to a
floating-point number, with a decimal part of 0, only if the operator has
mixed operands
...

A string is a sequence of zero or more characters
...

A string containing no characters is called a null or empty string
...
The position of
the first character is 0, the position of the second character is 1, and so on
...

During program execution, the contents of a named constant cannot be
changed
...

A named constant is initialized when it is declared
...

C++ does not automatically initialize variables
...

When a new value is assigned to a variable, the old value is lost
...

In C++, >> is called the stream extraction operator
...

When data is input in a program, the data items, such as numbers, are
usually separated by blanks, lines, or tabs
...

Output of the program to the standard output device is accomplished by
using cout and the stream insertion operator <<
...


99

2

100 |

48
...

50
...

52
...

54
...

56
...

58
...

60
...

The character \ is called the escape character
...

All preprocessor commands start with the symbol #
...

The preprocessor command #include instructs the preprocessor to include the header file iostream in the program
...

All C++ statements end with a semicolon
...

A C++ system has three components: environment, language, and the
standard libraries
...
They contain functions
to perform operations, such as mathematical operations
...
cpp
...

Corresponding to the five arithmetic operators +, -, *, /, and %,
C++ provides five compound operators: +=, -=, *=, /=, and %=, respectively
...


Mark the following statements as true or false
...

b
...

d
...

f
...

h
...

In C++, there is no difference between a reserved word and a predefined identifier
...

The operands of the modulus operator must be integers
...

In the statement cin >> y;, y can only be an int or a double variable
...

The following is a legal C++ program:
int main()
{
return 0;
}

Exercises

i
...


k
...


e
...

j
...

6
...

h
...


quiz7

Const

b
...


Char

d
...


int

f
...
20 - 12 / 4 * 2
18
...
28 - 5 / 2
...
0 + 3
...
0 / 5
...

g
...
3 - 5 % 7
17 + 5 % 2 - 3

If x = 5, y = 6, z = 4, and w = 3
...
If it is not possible, state the reason
...

e
...


myFirstProgram
b
...
C++Program2
ProgrammingLecture2
f
...
Update Grade
i
...

a
...


In a mixed expression, all the operands are converted to floating-point
numbers
...
After the statement y = x++; executes, y is 5 and
x is 6
...
After the statement ++a; executes, the value of a is still
5 because the value of the expression is not saved in another variable
...


4
...


3
...

f
...

g
...
(x + y) * w
(x *z) % y
h
...

When not given, assume that each variable is declared
...


num1 = 35;

b
...


num1 = 5; num2 = 2 + num1; num1 = num2 / 3;

d
...


x = 12 * num1 - 15
...


num1 * 2 = newNum + num2;

g
...


newNum = static_cast (x) % 5;

j
...

9
...
0;

i
...
6 / 2);

Do a walk-through to find the value assigned to e
...

a
b
c
d
e

10
...

n = 12;
char letter = ;
int one = 5, two;
double x, y, z;

11
...

a
...


//Line
//Line
//Line
//Line

i = i + 5;

b
...


x = 2
...


percent = 10%;

Write C++ statement(s) that accomplish the following
...

b
...

d
...


f
...


h
...

j
...
Initialize x to 25 and y to 18
...

Update the value of an int variable x by adding 5 to it
...
50
...

Swap the contents of the int variables x and y
...
)
Suppose x and y are double variables
...

Declare a char variable grade and set the value of grade to 'A'
...

Copy the value of a double variable z to the nearest integer into an
int variable x
...


32 times a plus b
The character that represents 8
The string that represents the name Julie Nelson
...

c
...

e
...


(-b + (b2 - 4ac)) / 2a

Suppose x, y, z, and w are int variables
...


Suppose x, y, and z are int variables and w and t are double variables
...


=
=
=
=
=
=

17;
15;
x + y / 4;
x % 3 + 4;
17 / 3 + 6
...
0 + 15 % 4 - 3
...
What is
the output of each of the following statements?
a
...


cout << "x + y = " << x + y << endl;

c
...


cout << "z / x = " << z / x << endl;

e
...


103

Write each of the following as a C++ expression
...


14
...
5
...

b
...

d
...

f
...
3 + b / a << endl;
cout << static_cast(c) % 5 + a – b
<< endl;
cout << 13
...
0 * 3
...


Write C++ statements that accomplish the following
...

b
...


19
...

Output the tab character
...


Which of the following are correct C++ statements?
a
...


cout << "Hello";
<< " There!" << endl;

c
...

20
...

a
...

c
...

e
...


variable
variable
variable
variable
variable

to
to
to
to
to

store
store
store
store
store

the
the
the
the
the

first name of a student
...

number of juice bottles
...

highest test score
...

a
...

c
...


22
...

Prompt the user to input two numbers
...

Output num1, num2, and 2 times num1 minus num2
...


The following program has syntax mistakes
...
On each successive line, assume that any preceding error has been corrected
...
35
main()
{
int one, two;
double first, second;
one = 18;
two = 11;
first = 25;
second = first * three;

Exercises

|

105

second = 2 * SECRET_NUM;
SECRET_NUM = SECRET_NUM + 3;
cout << first << " " << second << SECRET_NUM << endl;
paycheck = hoursWorked * PAY_RATE

}
23
...
Correct them
...

const char = STAR = '*'
const int PRIME = 71;
int main
{
int count, sum;
double x;

}
24
...
67;
newNum = count * ONE + 2;
sum + count = sum;
x = x + sum * COUNT;
cout << " count = " << count << ", sum = " << sum
<< ", PRIME = " << Prime << endl;

The following program has syntax errors
...
On each successive
line, assume that any preceding error has been corrected
...

26
...


What action must be taken before a variable can be used in a program?
Preprocessor directives begin with which of the following symbols:
a
...
#
c
...
!
e
...

Write equivalent compound statements if possible
...

d
...


x = 2 *x
b
...
sum = sum + num;
z = z * x + 2 * z;
e
...

a
...


29
...

x -= z + y - t;

y * 2 * x + 5 - z;
=
sum += num;

a
__
__
__

b
__
__
__

c
__
__
__

Suppose a, b, and sum are int variables and c is a double variable
...
1
...


w += 2 * z + 4;

Suppose a, b, and c are int variables and a = 5 and b = 6
...

a = (b++) + 3;
c = 2 * a + (++b);
b = 2 * (++c) - (a++);

30
...


e
...
5;
int main()
{
int a, b;
double z;

Exercises

|

107

char grade;
a = 25;
cout << "a = " << a << endl;
cout << "Enter two integers: ";
cin >> a >> b;
cout << endl;
cout << "The numbers you entered are "
<< a << " and " << b << endl;
z = X + 2 * a - b;
cout << "z = " << z << endl;
grade = 'A';
cout << "Your grade is " << grade << endl;
a = 2 * NUM + z;
cout << "The value of a = " << a << endl;
}
32
...


return 0;

Rewrite the following program so that it is properly formatted
...
45; const int Y=34;
const char BLANK= ' ';
int main()
{string firstName,lastName;int num;
double salary;
cout<<"Enter first name: "; cin>> firstName; cout<cout<<"Enter last name: "; cin
>>lastName;cout<cout<<"Enter a positive integer less than 70:";
cin>>num;cout<X;
cout<<"Name: "<<<"Wages: $"<cin >> length;
cout << endl;
int length;
area = length * width;
return 0;
int width;
cin>> width;
cout << "Enter the width: "
cout << endl;
cout << "Area = " << area << endl;
cout << "Perimeter = " << perimeter << endl;

}
6
...


b
...


d
...


|

111

Write C++ statements that include the header files iostream and
string
...

Write C++ statements that declare the following variables: name of type
string and studyHours of type double
...

Write a C++ statement that outputs the values of name and studyHours
with the appropriate text
...
5, the output is:

Hello, Donald! on Saturday, you need to study 4
...

f
...


8
...


Write a program that prompts the user to input a decimal number and
outputs the number rounded to the nearest integer
...


b
...


d
...


//return statement

Write C++ statements that include the header files iostream and
string
...

Write C++ statements that declare and initialize the following named
constants: SECRET of type int initialized to 11 and RATE of type
double initialized to 12
...

Write C++ statements that declare the following variables: num1, num2,
and newNum of type int; name of type string; and hoursWorked and
wages of type double
...


2

112 |

f
...
For example, if num1 is 8
and num2 is 5, then the output is:
The value of num1 = 8 and the value of num2 = 5
...


h
...


j
...


l
...
Then, write a
C++ statement that outputs the value of newNum
...
Then, write a C++
statement that outputs the value of newNum with an appropriate
message
...

Write C++ statements that prompt the user to enter a decimal number
between 0 and 70 and then store the number entered into hoursWorked
...

Write C++ statements that produce the following output:
Name:
Pay Rate: $
Hours Worked:
Salary: $

//output the value
//output the value
//output the value
//hoursWorked
//output the value

of the variable name
of the variable rate
of the variable
of the variable wages

For example, if the value of name is "Rainbow" and hoursWorked is
45
...
50
Hours Worked: 45
...
75
m
...
Place the statements at the appropriate place
in the previous C++ program segment
...


b
...


num1 = 13, num2 = 28; name = "Jacobson"; hoursWorked =
48
...

num1 = 32, num2 = 15; name = "Crawford"; hoursWorked =
58
...


Write a program that prompts the user to enter five test scores and then prints
the average test score
...
)

Programming Exercises

10
...


Write a program that prompts the user to input five decimal numbers
...

Write a program that does the following:
a
...

c
...

e
...


13
...


15
...


Prompts the user to input five decimal numbers
...

Converts each decimal number to the nearest integer
...

Prints the sum and average of the five integers
...
The program
outputs the number of miles the automobile can be driven without refueling
...
The program then outputs the elapsed time in hours,
minutes, and seconds
...
)
Write a C++ program that prompts the user to input the elapsed time for
an event in hours, minutes, and seconds
...

To make a profit, a local store marks up the prices of its items by a certain
percentage
...
The program then
outputs the original price of the item, the percentage of the mark-up, the store’s
selling price of the item, the sales tax rate, the sales tax, and the final price of the
item
...
)
Write a program that prompts the user to input a length expressed in centimeters
...

For example, suppose the input for centimeters is 312
...
123 inches would thus be output as:
3 yard(s), 1 feet (foot), and 3 inch(es)
...


18
...
(You may assume that the value of p = 3
...

In your program, declare a named constant PI to store this value
...
78 liters of milk
...
The cost of producing one liter of
milk is $0
...
27
...


b
...

d
...


20
...

c
...

e
...


23
...

Outputs the number of milk cartons needed to hold milk
...
)
Outputs the cost of producing milk
...


Redo Programming Exercise 18 so that the user can also input the cost of
producing one liter of milk and the profit on each carton of milk
...
It pays, say, $15
...
Suppose that the total tax you pay on your summer job
income is 14%
...
After buying clothes and school
supplies, you use 25% of the remaining money to buy savings bonds
...
50 to buy additional savings bonds for you
...
The program then outputs the
following:
a
...


Chapter 2: Basic Elements of C++

Your income before and after taxes from your summer job
...

The money you spend on school supplies
...

The money your parents spend to buy additional savings bonds for
you
...
For example, some of the permutations of these objects
are abc, bca, and cab
...

Suppose that these three objects are strings
...
The program then outputs the six permutations of those strings
...
The program then outputs the total value of the coins in
pennies
...
The value of k is approximately 6
...
cm2/g2
...


25
...
The program then outputs the force between
the bodies
...
Write a program that
prompts the user to input the amount of rice, in pounds, in a bag
...

Cindy uses the services of a brokerage firm to buy and sell stocks
...
5% service charges on the total amount for each transaction, buy
or sell
...
Write a program that allows Cindy to input
the number of shares sold, the purchase price of each share, and the selling
price of each share
...


|

115

2

This page intentionally left blank

3

CHAPTER

I NPUT /O UTPUT
I N T H I S C H A P T E R , YO U W I L L :


...


Explore how to read data from the standard input device


...


Explore how to use the input stream functions get, ignore, putback, and peek


...


Learn how to write data to the standard output device


...


Learn how to perform input and output operations with the string data type


...


Become familiar with file input and output

118 |

Chapter 3: Input/Output

In Chapter 2, you were introduced to some of C++’s input/output (I/O) instructions,
which get data into a program and print the results on the screen
...
Because I/O operations are fundamental to
any programming language, in this chapter, you will learn about C++’s I/O operations
in more detail
...
You will then
learn how to format output using manipulators
...


I/O Streams and Standard I/O Devices
A program performs three basic operations: it gets data, it manipulates the data, and it
outputs the results
...
In later chapters, you will learn how to manipulate nonnumeric
data
...
In this chapter, you will learn about various I/O
operations that can greatly enhance the flexibility of your programs
...
The bytes are usually characters, unless the program requires other
types of information, such as a graphic image or digital speech
...
There are
two types of streams:
Input stream: A sequence of characters from an input device to the computer
...


Recall
output
output
header

that the standard input device is usually the keyboard, and the standard
device is usually the screen
...
This
file contains, among other things, the definitions of two data types,
istream (input stream) and ostream (output stream)
...

These variable declarations are similar to the following C++ statements:
istream cin;
ostream cout;

To use cin and cout, every C++ program must use the preprocessor directive:
#include

I/O Streams and Standard I/O Devices

|

119

From Chapter 2, recall that you have been using the statement using namespace std;
in addition to including the header file iostream to use cin and cout
...
In Chapter 8, you will learn about the meaning of the statement using
namespace std; in detail
...
A stream variable is either an input stream
variable or an output stream variable
...

The variable cin has access to operators and functions that can be used to extract data
from the standard input device
...
The next section describes in detail how the
extraction operator >> works
...


cin and the Extraction Operator >>
In Chapter 2, you saw how to input data from the standard input device by using cin and
the extraction operator >>
...
Consider the following C++ statement:
cin >> payRate;

When the computer executes this statement, it inputs the next number typed on
the keyboard and stores this number in payRate
...
50, the
value stored in payRate is 15
...

The extraction operator >> is binary and thus takes two operands
...
Because the purpose of an input statement
is to read and store values in a memory location and because only variables refer to
memory locations, the right-side operand is a variable
...
Therefore, the right-side operand of the extraction operator >> is a variable
of the simple data type
...
You will learn this mechanism in the chapter entitled
Overloading and Templates, later in this book
...
;

3

120 |

Chapter 3: Input/Output

As you can see in the preceding syntax, a single input statement can read more than one
data item by using the operator >> several times
...
For example, you can read both payRate and
hoursWorked via a single input statement by using the following code:
cin >> payRate >> hoursWorked;

There is no difference between the preceding input statement and the following two
input statements
...

cin >> payRate;
cin >> hoursWorked;

How does the extraction operator >> work? When scanning for the next input, >> skips
all whitespace characters
...
Thus, whether you
separate the input data by lines or blanks, the extraction operator >> simply finds the
next input data in the input stream
...
Consider the following input statement:
cin >> payRate >> hoursWorked;

Whether the input is:
15
...
30

or:
15
...
30

or:
15
...
30

the preceding input statement would store 15
...
30 in
hoursWorked
...

Now suppose that the input is 2
...
If the right-side operand is a variable of the data type
char, the input 2 is treated as the character 2 and, in this case, the ASCII value of 2 is
stored
...

Next, consider the input 25 and the statement:
cin >> a;

where a is a variable of some simple data type
...
If a is of the data type int, 25 is stored in a
...
0
...

TABLE 3-1

Valid Input for a Variable of the Simple Data Type

Data Type of a

Valid Input for a

char

One printable character except the blank

int

An integer, possibly preceded by a + or - sign

double

A decimal number, possibly preceded by a + or - sign
...


When reading data into a char variable, after skipping any leading whitespace characters,
the extraction operator >> finds and stores only the next character; reading stops after a
single character
...


EXAMPLE 3-1
Suppose you have the following variable declarations:
int a, b;
double z;
char ch;

The following statements show how the extraction operator >> works
...
35

a = 48
a = 46,
...
35
39
65
...
35
z = 39
...
78, a = 38

3

122 |

Chapter 3: Input/Output

Statement
8
9

Input

Value Stored in Memory

cin >> a >> b;
cin >> a >> z;

4 60
46 32
...
4, 68 is
held for later input

EXAMPLE 3-2
Suppose you have the following variable declarations:
int a;
double z;
char ch;

The following statements show how the extraction operator >> works
...
9

2

cin >> a >> ch >> z;

3

cin >> a >> ch >> z;

4

cin >> a >> ch >> z;

57 A
26
...
9
57A26
...
9
57, ch = 'A',
26
...
9

a = 57, ch = 'A',
z = 26
...
For statement 1, data is entered on the same line separated by
blanks
...
For statement 3, all
three input values are separated by lines, and for statement 4, all three input values are on
the same line, but there is no space between them
...
These statements work as follows
...
Let us look at statement 4
...
Then, the extraction operator >> extracts the character 'A' from the input
stream and stores it in ch
...
9 is extracted and stored in z
...


I/O Streams and Standard I/O Devices

|

123

EXAMPLE 3-3
Suppose you have the following variable declarations:
int a, b;
double z;
char ch, ch1, ch2;

The following statements show how the extraction operator >> works
...
78B34

2

cin >> z >> ch >> a;

36
...
49
256
256

7

cin >> ch1 >> ch2;

A B

5

36
...
78, ch = 'B',
34
11, b = 34,

computer waits for the next
number

cin >> a >> z;
cin >> ch >> a;
cin >> a >> ch;

4

=
=
=
=
=

a = 78, z = 0
...
78 is extracted from the input stream, and the value 36
...

Next, 'B' is extracted and stored in ch
...

Statement 2 works similarly
...
In this case, the computer waits (and waits, and
waits
...
The computer does not continue to execute
until the next value is entered
...
49
...
Therefore, the operator >> stores 78 into a
...
Therefore, the operator >> stores the value

...
49 into z
...

The character '2' is stored in the variable ch
...


3

124 |

Chapter 3: Input/Output

In statement 6, the first right-side operator of the extraction operator >> is an int
variable, so the first data item, 256, is extracted from the input stream and stored in a
...

In statement 7, 'A' is stored into ch1
...


Recall that during program execution, when entering character data such as letters, you
do not enter the single quotes around the character
...
When you
enter data for processing, the data values should correspond to the data types of the
variables in the input statement
...
If the input
number is an integer and has no decimal part, it is converted to a decimal value
...
For example, entering
a char value into an int or double variable causes serious errors, called input failure
...

The extraction operator, when scanning for the next input in the input stream, skips
whitespace such as blanks and the newline character
...
For example, if you are processing
text in a line-by-line fashion, you must know where in the input stream the newline
character is located
...
The next few sections
teach you how to input data into a program using the input functions, such as get,
ignore, putback, and peek
...
I/O functions, such as get, are typically
called stream member functions or stream functions
...
You will study functions in detail and learn how to write your own
in Chapters 6 and 7
...
When
a function executes, it accomplishes something
...
Other functions execute

Using Predefined Functions in a Program |

125

only when they are activated—that is, called
...
In this section, you will learn how
to use some predefined functions that are provided as part of the C++ system
...

Recall from Chapter 2 that predefined functions are organized as a collection of libraries,
called header files
...
Therefore, to
use a particular function, you need to know the name of the function and a few other
things, which are described shortly
...
That is, pow(x, y) pffiffiffiffiffiffiffiffi
...
0, 3
...
03
...
0 and
= xy
0
...
0, 0
...
0
= 4:0 = 2
...
The numbers x and y that you use in the
function pow are called the arguments or parameters of the function pow
...
0, 3
...
0 and 3
...

An expression such as pow(2
...
0) is called a function call, which causes the code
attached to the predefined function pow to execute and, in this case, computes 2
...
0
...

To use a predefined function in a program, you need to know the name of the header
file containing the specification of the function and include that header file in the
program
...
You must also be aware
of what the function is going to do
...
The function pow has two parameters, which are decimal
numbers
...
(Appendix F describes some commonly used header files and predefined
functions
...
More specifically, we use some math functions, from the header file cmath, and
the string function length, from the header file string
...

EXAMPLE 3-4
// How to use predefined functions
...
0, 6
...
5;
v = 3
...
0) << endl;

//Line 5

u = pow(8
...
5);
cout << "Line 7: u = " << u << endl;

//Line 6
//Line 7

str = "Programming with C++";

//Line 8

cout << "Line 9: Length of str = "
<< str
...
5 to the power of 3 = 1953
...
89898
u = 181
...
The statement in Line 1 uses the function pow
to determine and output 26
...
5, and the statement in
Line 3 sets v to 3
...
The statement in Line 4 determines and outputs uv
...
0
...
02
...

The statement in Line 7 outputs the value of u
...
The
statement in Line 9 uses the string function length to determine and output the
length of str
...
Later in this chapter, we
explain the meaning of expressions such as str
...


Because I/O is fundamental to any programming language and because writing instructions
to perform a specific I/O operation is not a job for everyone, every programming language
provides a set of useful functions to perform specific I/O operations
...
As a programmer,
you must pay close attention to how these functions are used so that you can get the most
out of them
...


Using Predefined Functions in a Program |

127

cin and the get Function
As you have seen, the extraction operator skips all leading whitespace characters when
scanning for the next input value
...

However, what if you intended to store 'A' in ch1, the blank in ch2, and 25 in num? It is
clear that you cannot use the extraction operator >> to input this data
...
For example, suppose
you want to process the entered data on a line-by-line basis
...

The variable cin can access the stream function get, which is used to read character
data
...

The function get comes in many forms
...

The syntax of cin, together with the get function to read a character, follows:
cin
...
get statement, varChar is a char variable
...
The effect of the preceding statement would be to store the next input character
in the variable varChar
...
get(ch1);
cin
...
Notice that you cannot use the get function to read data into the
variable num because num is an int variable
...

The preceding set of cin
...
get(ch2);
cin >> num;

The function get has other forms, one of which you will study in Chapter 9
...


cin and the ignore Function
When you want to process only partial data (say, within a line), you can use the stream
function ignore to discard a portion of the input
...
ignore(intExp, chExp);

Here, intExp is an integer expression yielding an integer value, and chExp is a char
expression yielding a char value
...

Suppose intExp yields a value of, say 100
...
To be specific, consider the following statement:
cin
...
For example,
if the next 120 characters do not contain the newline character, then only the first
100 characters are discarded and the next input data is the character 101
...
Similarly, the execution of the
statement:
cin
...


Using Predefined Functions in a Program |

129

EXAMPLE 3-5
Consider the declaration:
int a, b;

and the input:
25 67 89 43 72
12 78 34

Now consider the following statements:
cin >> a;
cin
...
The second statement,
cin
...
The
third statement, cin >> b;, stores 12 (from the next line) in b
...
My name is Mickey
...


Consider the following statements:
cin >> ch1;
cin
...
');
cin >> ch2;

The first statement, cin >> ch1;, stores 'H' in ch1
...
ignore(100, '
...
(period)
...
(Remember that the extraction operator >> skips all leading whitespace
characters
...
[period] and
stores 'M' in ch2
...
Suppose that we have the following statement:
cin >> ch1;
cin
...
');
cin >> ch2;

3

130 |

Chapter 3: Input/Output

The first statement, cin >> ch1;, stores 'H' in ch1
...
ignore(5, '
...

The third statement, cin >> ch2;, stores the character 't' (from the same line) in ch2
...
For example, the following statement will skip the very next character:
cin
...


The putback and peek Functions
Suppose you are processing data that is a mixture of numbers and characters
...
You have also looked at many sets of
sample data and cannot determine whether the next input is a character or a number
...
If a digit is found, you could then read the remaining digits of the number and
somehow convert these characters into numbers
...
Fortunately, C++ provides two very useful stream functions that
can be used effectively in these types of situations
...
The stream function peek looks
into the input stream and tells you what the next character is without removing it from
the input stream
...
You do not have to read the digits of the number as
characters and then convert these characters to that number
...
putback(ch);

Here, istreamVar is an input stream variable, such as cin, and ch is a char variable
...
In other words, the function peek looks into the input stream
and checks the identity of the next input character
...
That is, when you use the peek function, the
next input character stays the same, even though you now know what it is
...
peek();

Here, istreamVar is an input stream variable, such as cin, and ch is a char variable
...
First, the function peek is used in an assignment
statement
...
Second, the
function peek has empty parentheses
...

The following example illustrates how to use the peek and putback functions
...
get(ch);
cout << endl;
cout << "Line 4: After first cin
...
get(ch);
cout << "Line 6: After second cin
...
putback(ch);
cin
...
get(ch); ch = " << ch << endl;

//Line 4

//Line 6
//Line 7
//Line 8
//Line 9

ch = cin
...
peek(); ch = "
<< ch << endl;
cin
...
get(ch); ch = "
<< ch << endl;
}

//Line 10

//Line 12

return 0;

Sample Run: In this sample run, the user input is shaded
...
get(ch); ch = a
Line 6: After second cin
...
get(ch); ch = b
Line 11: After cin
...
get(ch); ch = c

The user input, abcd, allows you to see the effect of the functions get, putback, and
peek in the preceding program
...

In Line 2, the statement cin
...
So after Line 2 executes, the value of ch is 'a'
...
The statement cin
...

At this point, the value of ch is 'b'
...
The cin
...
Therefore, the next character to be extracted from the input stream is 'b'
...
get(ch); statement in Line 8 extracts the next character from the input
stream, which is still 'b', and stores it in ch
...
The cout
statement in Line 9 outputs the value of ch as 'b'
...
peek(); checks the next character in the input stream,
which is 'c', and stores it in ch
...
The cout statement in Line
11 outputs the value of ch
...
get(ch); statement in Line 12 extracts the next
character from the input stream and stores it in ch
...

Note that the statement ch = cin
...
The output of Lines 11 and
13 demonstrates this functionality
...
You also learned how to use the functions get, ignore, peek, and
putback
...
For example, to
use the get function, you used statements such as the following:
cin
...
For example, in the statement:
cin
...
In the statement:
cinget(ch);

Input Failure |

133

cinget becomes a new identifier
...
Similarly,
missing parentheses, as in cin
...
Also, remember that you
must use the input functions together with an input stream variable
...
’’ For example, the
statement get(ch); could result in a syntax error
...
Recall that the functions get, ignore, and so on are members of the data type
istream
...
In fact, in C++, the dot is an operator called the
member access operator
...
The data types
istream and ostream are called classes
...
Therefore, cin is called an istream object, and cout is called an
ostream object
...
You will learn these
concepts in the chapter entitled Inheritance and Composition later in this book
...
A program that is syntactically
correct might produce incorrect results
...

What about an attempt to read invalid data? For example, what would happen if you tried
to input a letter into an int variable? If the input data did not match the corresponding
variables, the program would run into problems
...
Consider the following
statements:
int a, b, c;
double x;

If the input is:
W 54

then the statement:
cin >> a >> b;

3

134 |

Chapter 3: Input/Output

would result in an input failure, because you are trying to input the character 'W' into
the int variable a
...
93 48

then the input statement:
cin >> a >> x > >b;

would result in storing 35 in a, 67
...

Now consider the following read statement with the previous input (the input with three
values):
cin >> a >> b >> c;

This statement stores 35 in a and 67 in b
...
(the decimal point)
...
into c,
which is an error
...

What actually happens when the input stream enters the fail state? Once an input stream
enters the fail state, all further I/O statements using that stream are ignored
...
The program in Example 3-8 illustrates an input
failure
...


EXAMPLE 3-8
//Input Failure program
#include
using namespace std;
int main()
{
int a =
int b =
int c =
int d =

cout << "Line 5:
cin >> a >> b >>
cout << endl;
cout << "Line 8:
<< endl;
cout << "Line 9:
<< ", c = "
}

//Line
//Line
//Line
//Line

10;
20;
30;
40;

return 0;

Enter four integers: ";
c >> d;

1
2
3
4

//Line 5
//Line 6
//Line 7

The numbers you entered are:"
//Line 8
a = " << a << ", b = " << b
<< c << ", d = " << d << endl;

//Line 9

Input Failure |

135

Sample Runs: In these sample runs, the user input is shaded
...
The statement in Line 5 prompts the user to
enter four integers; the statement in Line 6 inputs these four integers into variables a,
b, c, and d
...
The cin statement tries to
input this character into the variable b
...
Note that the values of b, c, and d are unchanged, as shown by
the output of the statement in Line 9
...
89 23 76
Line 8: The numbers you entered are:
Line 9: a = 37, b = 653, c = 30, d = 40

In this sample run, the cin statement in Line 6 inputs 37 into a and 653 into b and
then tries to input the decimal point into c
...
In this sample
run, the values of c and d are unchanged, as shown by the output of the statement
in Line 9
...
You can use the stream function clear to restore the input stream to a
working state
...
clear();

Here, istreamVar is an input stream variable, such as cin
...
This can be accomplished by
using the function ignore
...


3

136 |

Chapter 3: Input/Output

EXAMPLE 3-9
//Input failure and the clear function
#include
using namespace std;
int main()
{
int a = 23;
int b = 34;
cout << "Line 3: Enter a
<< " by a character:
cin >> a >> b;
cout << endl << "Line 5:
<< ", b = " << b <<
cin
...
ignore(200,'\n');

//Clear the buffer; Line 7

cout << "Line 8: Enter two numbers: ";
cin >> a >> b;
cout << endl << "Line 10: a = " << a
<< ", b = " << b << endl;
}

//Line 3
//Line 4

//Line 8
//Line 9
//Line 10

return 0;

Sample Run: In this sample run, the user input is shaded
...
The statement in Line 3 prompts the user to enter a number followed by a
character; the statement in Line 4 inputs this number into the variable a and then tries to
input the character into the variable b
...
The value of b is
unchanged, as shown by the output of the statement in Line 5
...
The statement in Line 8 again prompts
the user to input two numbers; the statement in Line 9 stores these two numbers into a
and b
...


Output and Formatting Output

|

137

Output and Formatting Output
Other than writing efficient programs, generating the desired output is one of a programmer’s highest priorities
...
More precisely, you learned how to
use the insertion operator << and the manipulator endl to display results on the standard
output device
...
Sometimes, floatingpoint numbers must be output in a specific way
...
Also, you might like to align the numbers in specific columns or fill the empty
space between strings and numbers with a character other than the blank
...
In this section, you will learn about
various output functions and manipulators that allow you to format your output in a
desired way
...
;

Here, expression is evaluated, its value is printed, and manipulator is used to format
the output
...

Other output manipulators that are of interest include setprecision, fixed, showpoint,
and setw
...


setprecision Manipulator
You use the manipulator setprecision to control the output of floating-point numbers
...
Some
integrated development environments (IDEs) might use a maximum of six decimal
places for the default output of floating-point numbers
...
To print
floating-point output to two decimal places, you use the setprecision manipulator to
set the precision to 2
...


3

138 |

Chapter 3: Input/Output

You use the setprecision manipulator with cout and the insertion operator
...
Notice that the number of decimal places, or the
precision value, is passed as an argument to setprecision
...
Thus, the following include statement is required:
#include

fixed Manipulator
To further control the output of floating-point numbers, you can use other manipulators
...
The following statement sets the output of floating-point numbers in a fixed
decimal format on the standard output device:
cout << fixed;

After the preceding statement executes, all floating-point numbers are displayed in the fixed
decimal format until the manipulator fixed is disabled
...
For example, to disable the manipulator fixed on the standard output device, you use the following statement:
cout
...
The manipulator scientific is used to output floating-point
numbers in scientific format
...
In this case, you can use cin
...
setf(ios::scientific); in place of cin >> scientific;
...

EXAMPLE 3-10
//Example: scientific and fixed
#include
using namespace std;

Output and Formatting Output

|

139

int main()
{
double hours = 35
...
00;
double tolerance = 0
...
45, rate = 15, pay = 531
...
01
Scientific notation:
hours = 3
...
500000e+001, pay = 5
...
000000e-002
Fixed decimal notation:
hours = 35
...
000000, pay = 531
...
010000

The sample run shows that when the value of rate and tolerance are printed without
setting the scientific or fixed manipulators, the trailing zeros are not shown and, in the
case of rate, the decimal point is also not shown
...
In the next section, we describe the manipulator
showpoint to force the system to show the decimal point and trailing zeros
...


showpoint Manipulator
Suppose that the decimal part of a decimal number is zero
...
To force the output to show the decimal point and

3

140 |

Chapter 3: Input/Output

trailing zeros, you use the manipulator showpoint
...


EXAMPLE 3-11
//Example: setprecision, fixed, showpoint
#include
#include

//Line 1
//Line 2

using namespace std;

//Line 3

const double PI = 3
...
67;
double height = 12
...
67
height = 12
...
80
PI = 3
...
670
height = 12
...
797
PI = 3
...
6700
height = 12
...
7969
PI = 3
...
670, 12
...
14159

In this program, the statement in Line 2 includes the header file iomanip, and the
statement in Line 4 declares the named constant PI and sets the value to eight decimal
places
...
The statement in Line
10 sets the output of floating-point numbers in a fixed decimal format with a decimal
point and trailing zeros
...

The statements in Lines 16, 17, 18, and 19 output the values of radius, height,
the volume, and PI to three decimal places
...

The statement in Line 25 outputs the value of radius to three decimal places, the value
of height to two decimal places, and the value of PI to five decimal places
...
The value of
radius printed in Line 16 contains a trailing 0
...
In a similar
manner, the value of height is printed in Lines 12, 17, and 22
...

Note that the value of PI printed in Line 24 is rounded
...
After printing the
value of radius, the statement in Line 25 sets the output of floating-point numbers to
two decimal places and then outputs the value of height to two decimal places
...

If you omit the statement in Line 9 and recompile and run the program, you will see the
default output of the decimal numbers
...


setw
The manipulator setw is used to output the value of an expression in a specific number of
columns
...
The expression
setw(n) outputs the value of the next expression in n columns
...
Thus, if you specify the number of columns to be 8, for example, and the output
requires only four columns, the first four columns are left blank
...
For example, if x is an int variable, the following statement outputs the value
of x in five columns on the standard output device:
cout << setw(5) << x << endl;

To use the manipulator setw, the program must include the header file iomanip
...

EXAMPLE 3-12
//Example: setw
#include
#include

Output and Formatting Output

|

143

using namespace std;
int main()
{
int x = 19;
int a = 345;
double y = 76
...
38
19
19
345 76
...
384, respectively
...

The output of the statement in Line 5 shows the column positions when the specific
values are printed; it is the first line of output
...
Because x has only two
digits, only two columns are needed to output its value
...
The statement in Line 7 outputs the value of a in
the first five columns, the string "Hi" in the next five columns, and then the value of x in the
following five columns
...
See

3

144 |

Chapter 3: Input/Output

the third line of output
...

The statement in Line 8 sets the output of floating-point numbers to two decimal places
...
The output
of the statement in Line 10 (which is the sixth line of output) is similar to the output of
the statement in Line 9
...
The seventh line of output is blank because the manipulator
endl appears twice in the statement in Line 10
...
Note that the manipulator setw in the statement in Line 11 controls only the output of
a
...

In the cout statement in Line 12, only two columns are assigned to output the value of a
...
The
value of x is then printed in four columns
...
Therefore, because four columns
are allocated to output the value of x, the first two columns are left blank (see the ninth line
of output)
...
Even though these manipulators are adequate
to produce an elegant report, in some situations, you may want to do more
...


setfill Manipulator
Recall that in the manipulator setw, if the number of columns specified exceeds the number
of columns required by the expression, the output of the expression is right-justified and the
unused columns to the left are filled with spaces
...

The syntax to use the manipulator setfill is:
ostreamVar << setfill(ch);

where ostreamVar is an output stream variable and ch is a character
...

To use the manipulator setfill, the program must include the header file iomanip
...

EXAMPLE 3-13

3

//Example: setfill
#include
#include
using namespace std;
int main()
{
int x = 15;
int y = 7634;

//Line 1
//Line 2

cout << "12345678901234567890" << endl;
cout << setw(5) << x << setw(7) << y
<< setw(8) << "Warm" << endl;

//Line 3

cout << setfill('*
');
cout << setw(5) << x << setw(7) << y
<< setw(8) << "Warm" << endl;

//Line 5
//Line 6

cout << setw(5) << x << setw(7) << setfill('#')
<< y << setw(8) << "Warm" << endl;

//Line 7

cout <<
<<
<<
<<
cout <<
cout <<
<<
}

setw(5) << setfill('@') <<
setw(7) << setfill('#') <<
setw(8) << setfill('^') <<
endl;
setfill(' ');
setw(5) << x << setw(7) <<
setw(8) << "Warm" << endl;

//Line 4

x
y
"Warm"
//Line 8
//Line 9
y
//Line 10

return 0;

Sample Run:
12345678901234567890
15
7634
Warm
***15***7634****Warm
***15###7634####Warm
@@@15###7634^^^^Warm
15
7634
Warm

The statements in Lines 1 and 2 declare and initialize the variables x and y to 15 and 7634,
respectively
...
The
statement in Line 4 outputs the value of x in five columns, the value of y in seven columns,
and the string "Warm" in eight columns
...

The statement in Line 5 sets the filling character to *
...
Because x is a two-digit number and five columns are assigned to
output its value, the first three columns are unused by x and are, therefore, filled by the
filling character *
...
Similarly, to print
the value of the string "Warm", eight columns are assigned; the string "Warm" has only
four characters, so the filling character fills the first four columns
...

The output of the statement in Line 7—the fourth line of output—is similar to the output
of the statement in Line 6, except that the filling character for y and the string "Warm" is
#
...
The manipulator setfill sets these filling characters
...
The statement in Line 10
outputs the values of x, y, and the string "Warm" using the filling character blank, as
shown in the sixth line of output
...

Sometimes, you might want the output to be left-justified
...

The syntax to set the manipulator left is:
ostreamVar << left;

where ostreamVar is an output stream variable
...
The syntax
to disable the manipulator left is:
ostreamVar
...
Disabling the manipulator left returns
the output to the settings of the default output format
...
unsetf(ios::left);

The syntax to set the manipulator right is:

3

ostreamVar << right;

where ostreamVar is an output stream variable
...

In this case, you can use cin
...
setf(ios::right); in place of cin >> right;
...

EXAMPLE 3-14
//Example: left justification
#include
#include
using namespace std;
int main()
{
int x = 15;
int y = 7634;

//Line 1
//Line 2

cout << left;

//Line 3

cout << "12345678901234567890" << endl;
cout << setw(5) << x << setw(7) << y
<< setw(8) << "Warm" << endl;

//Line 4

cout << setfill('*
');

//Line 6

cout << setw(5) << x << setw(7) << y
<< setw(8) << "Warm" << endl;

//Line 7

//Line 5

cout << setw(5) << x << setw(7) << setfill('#')
<< y << setw(8) << "Warm" << endl;
//Line 8
cout << setw(5) << setfill('@') << x
<< setw(7) << setfill('#') << y

148 |

Chapter 3: Input/Output

<< setw(8) << setfill('^') << "Warm"
<< endl;

//Line 9

cout << right;
cout << setfill(' ');
cout << setw(5) << x << setw(7) << y
<< setw(8) << "Warm" << endl;
}

//Line 10
//Line 11
//Line 12

return 0;

Sample Run:
12345678901234567890
15
7634
Warm
15***7634***Warm****
15***7634###Warm####
15@@@7634###Warm^^^^
15
7634
Warm

The output of this program is the same as the output of Example 3-11
...

You are encouraged to do a walk-through of this program
...
To use stream
functions such as get, ignore, fill, and clear in a program, the program must
include the header file iostream
...

Manipulators with parameters are called parameterized stream manipulators
...
On the
other hand, manipulators such as endl, fixed, scientific, showpoint, and
left do not have parameters
...
Manipulators without parameters are part of the iostream header file and,
therefore, do not require inclusion of the header file iomanip
...
For example, if the input
is the string "Shelly", the following code stores this input into the string
variable name:
string name;
cin >> name;

//variable declaration
//input statement

Debugging: Understanding Logic Errors and Debugging with cout Statements |

149

Recall that the extraction operator skips any leading whitespace characters and that
reading stops at a whitespace character
...
For example, suppose that the variable name
is defined as noted above
...

To read a string containing blanks, you can use the function getline
...
The
reading is delimited by the newline character '\n'
...
The newline
character is also read but not stored in the string variable
...
How are you?

where b represents a blank, after the statement:
getline(cin, myString);

the value of myString is:
myString =

"

Hello there
...

Similarly, you can use an output stream variable, such as cout, and the insertion operator
<< to output the contents of a variable of the data type string
...
As we have seen, syntax errors are reported by the compiler, and the compiler not
only reports syntax errors, but also gives some explanation about the errors
...
In this section, we illustrate how to spot and

3

150 |

Chapter 3: Input/Output

correct logic errors using cout statements
...
The formula to convert the temperature is: Celsius ¼ 5 / 9 * (Fahrenheit – 32)
...
" << endl;
}

//Line 7
//Line 8
//Line 9

//Line 11

return 0;

//Line 12
//Line 13

Sample Run 1: In this sample run, the user input is shaded
...


Sample Run 2: In this sample run, the user input is shaded
...


The result shown in the first calculation looks correct
...
It means the value of celsius calculated in Line 10 is incorrect
...
So we should
look at this expression closely
...
This can be accomplished by
temporarily inserting an output statement as shown in the following program:
#include

//Line 1

using namespace std;

//Line 2

int main()
{
int fahrenheit;
int celsius;

//Line
//Line
//Line
//Line

3
4
5
6

Debugging: Understanding Logic Errors and Debugging with cout Statements |

cout << "Enter temperature in Fahrenheit: ";
cin >> fahrenheit;
cout << endl;

//Line 9a

celsius = 5 / 9 * (fahrenheit - 32);

//Line 10

cout << fahrenheit << " degree F = "
<< celsius << " degree C
...

Enter temperature in Fahrenheit: 110
5 / 9 = 0; fahrenheit - 32 = 78
110 degree F = 0 degree C
...
We see that the value of 5 / 9 = 0 and the value of
fahrenheit - 32 = 78
...
Now let us look at the expression 5 / 9
...
Because both of the operands, 5 and 9, of the operator / are integers,
using integer division, the value of the expression is 0
...
So by the precedence of the operators, the value of the
expression 5 / 9 * (fahrenheit - 32) will always be 0 regardless of the value of
fahrenheit
...
We can replace the expression
5 / 9 with 5
...
In this case, the value of the expression 5
...
Because fahrenheit and celsius are int variables, we can use
the cast operators to convert this value to an integer, that is, we use the following expression:
celsius = static_cast (5
...
5);

(Note that in the preceding expression, we added 0
...
)
The revised program is:
#include

//Line 1

using namespace std;

//Line 2

int main()
{
int fahrenheit;
int celsius;

//Line
//Line
//Line
//Line

3
4
5
6

152 |

Chapter 3: Input/Output

cout << "Enter temperature in Fahrenheit: ";
cin >> fahrenheit;
cout << endl;
celsius = static_cast
(5
...
5);

//Line 10

cout << fahrenheit << " degree F = "
<< celsius << " degree C
...

Enter temperature in Fahrenheit: 110
110 degree F = 43 degree C
...
After
correcting the problem, the temporary cout statements are removed
...
Using
cout statements to print the values of expressions and/or variables to see the results of a
calculation is an effective way to find and correct logic errors
...
However, getting input
from the keyboard and sending output to the screen have several limitations
...
Sending
output to the screen works well if the amount of data is small (no larger than the size of the
screen) and you do not want to distribute the output in a printed format to others
...
In addition to the inconvenience of typing large amounts
of data, typing can generate errors, and unintentional typos cause erroneous results
...
By using alternative
sources of data, you can prepare the data before running a program, and the program can
access the data each time it runs
...
Distributing printed
copies of the program output is a better approach than showing the output on a screen
...
Furthermore, output must sometimes be saved so that the output
produced by one program can be used as an input to other programs
...
C++ allows a program to get

File Input/Output |

153

data directly from and save output directly to secondary storage
...
Formally, a file is defined as follows:
File: An area in secondary storage used to hold information
...

In addition, C++ provides a header file called fstream, which is used for file I/O
...

The variables cin and cout are already defined and associated with the standard input/
output devices
...
These same operators and
functions are also available for file I/O, but the header file fstream does not declare variables
to use them
...
You then use these
variables together with >>, <<, or other functions for I/O
...
Once you declare the fstream variables, you
must associate these file variables with the input/output sources
...

2
...

4
...


Include the header file fstream in the program
...

Associate the file stream variables with the input/output sources
...

Close the files
...
A skeleton program then shows how the
steps might appear in a program
...
The following
statement accomplishes this task:
#include

Step 2 requires you to declare file stream variables
...
The second
statement declares outData to be an output file stream variable
...
This
step is called opening the files
...

The syntax for opening a file is:
fileStreamVariable
...

Suppose you include the declaration from Step 2 in a program
...
dat
...
dat and outData with prog
...
That is, the file prog
...
out is opened for outputting data
...
open("prog
...
open("prog
...
Net manage programs in the form of projects
...
The statement in Line 1 assumes
that the file prog
...
However, if this
is in a different directory (subdirectory), then you must specify the path where the file is
located, along with the name of the file
...
dat is on a
flash memory in drive H
...
open("h:\\prog
...
Recall from Chapter 2 that in C++, \ is the escape
character
...
(To be absolutely sure
about specifying the source where the input file is stored, such as the drive h:\\, check
your system’s documentation
...


Suppose that a program reads data from a file
...


We typically use
...
out, or
...
You can also use
your IDE’s editor, if any, to create
...
(To be absolutely sure about it, check
you IDE’s documentation
...
You use the file stream variables with >>, <<, or other
input/output functions
...
Instead of using cin and cout, however,
you use the file stream variable names that were declared
...
dat and stores it in the variable payRate
...
78—in the file prog
...
This statement
assumes that the pay was calculated as 565
...

Once the I/O is complete, Step 5 requires closing the files
...
Once
these variables are freed, they can be reused for other file I/O
...
You close files by using the stream function close
...
close();
outData
...
When the program terminates,
the files are closed automatically
...
Also, if you want to use the same file stream variable to open another file,
you must close the first file opened with that file stream variable
...


...

//Open the files
inData
...
dat"); //open the input file
outData
...
out"); //open the output file
//Code for data manipulation
//Close files
inData
...
close();
}

return 0;

3

156 |

Chapter 3: Input/Output

Recall that Step 3 requires the file to be opened for file I/O
...
In the case of an input file, the file must exist before the open statement executes
...
An output file does not have to exist before it is opened; if the output file does not
exist, the computer prepares an empty file for output
...

To add the output at the end of an existing file, you can use the option ios::app as follows
...
out
...
open("firstProg
...
out does not exist, then the system creates an empty file
...


PROGRAMMING EXAMPLE:

Movie Tickets Sale and Donation to Charity
A movie in a local theater is in great demand
...
This example designs and implements a program that prompts the
user to input the movie name, adult ticket price, child ticket price, number of adult
tickets sold, number of child tickets sold, and percentage of the gross amount to be
donated to the charity
...

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Movie Name:
...

2650
Gross Amount:
...
00
Percentage of Gross Amount Donated:
10
...
$ 915
...
$ 8235
...


Programming Example: Movie Tickets Sale and Donation to Charity |

157

Input

Output
PROBLEM
ANALYSIS
AND
ALGORITHM
DESIGN

The input to the program consists of the movie name, adult ticket price, child
ticket price, number of adult tickets sold, number of child tickets sold, and
percentage of the gross amount to be donated to the charity
...


To calculate the amount donated to the local charity and the net sale, you first need to
determine the gross amount
...
That is:
grossAmount = adultTicketPrice * noOfAdultTicketsSold
+ childTicketPrice * noOfChildTicketsSold;

Next, you determine the percentage of the amount donated to the charity and then
calculate the net sale amount by subtracting the amount donated from the gross
amount
...
This analysis leads to the following algorithm:
1
...

3
...

5
...

7
...

Get the price of an adult ticket
...

Get the number of adult tickets sold
...

Get the percentage of the gross amount donated to the charity
...
Calculate the amount donated to the charity using the following formula:
amountDonated = grossAmount * percentDonation / 100;

9
...
Therefore, the
following variables are needed:
string movieName;
double adultTicketPrice;
double childTicketPrice;
int noOfAdultTicketsSold;
int noOfChildTicketsSold;

3

158 |

Chapter 3: Input/Output

double
double
double
double

percentDonation;
grossAmount;
amountDonated;
netSaleAmount;

Because movieName is declared as a string variable, you need to include the header
file string
...
Therefore, when printing a value in the first column,
the manipulator left is used; before printing a value in the second column, the
manipulator right is used
...
In the lines showing the gross amount, amount donated,
and net sale amount, the space between the $ sign and the number is filled with
blank spaces
...
The following statements accomplish the desired output:
cout <<
<<
cout <<
<<
cout <<
<<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
MAIN
ALGORITHM

"-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
"-*-*-*-*-*-*-*-*-*-*-*-*-*" << endl;
setfill('
...
') << left << setw(35) << "Gross Amount: "
setfill(' ') << right << " $"
setw(8) << grossAmount << endl;
setfill('
...
') << left << setw(35) << "Amount Donated: "
setfill(' ') << right << " $"
setw(8) << amountDonated << endl;
setfill('
...
We also determined the necessary variables and named constants
...


Programming Example: Movie Tickets Sale and Donation to Charity |

1
...

2
...

Include the header file iomanip
...
Prompt the user to enter a movie name
...
Input (read) the movie name
...

5
...

6
...

7
...

8
...

9
...

10
...

11
...

12
...

13
...

14
...

15
...

16
...

17
...

18
...

COMPLETE PROGRAM LISTING
//************************************************************
// Author: D
...
Malik
//
// Program: Movie Tickets Sale
// This program determines the money to be donated to a
// charity
...

//************************************************************
#include
#include
#include
using namespace std;

159

3

160 |

Chapter 3: Input/Output

int main()
{
//Step 1
string movieName;
double adultTicketPrice;
double childTicketPrice;
int noOfAdultTicketsSold;
int noOfChildTicketsSold;
double percentDonation;
double grossAmount;
double amountDonated;
double netSaleAmount;
cout << fixed << showpoint << setprecision(2);

//Step 2

cout << "Enter the movie name: ";
getline(cin, movieName);
cout << endl;

//Step 3
//Step 4

cout << "Enter the price of an adult ticket: "; //Step 5
cin >> adultTicketPrice;
//Step 6
cout << endl;
cout << "Enter the price of a child ticket: ";
cin >> childTicketPrice;
cout << endl;
cout << "Enter the number of adult tickets "
<< "sold: ";
cin >> noOfAdultTicketsSold;
cout << endl;
cout << "Enter the number of child tickets "
<< "sold: ";
cin >> noOfChildTicketsSold;
cout << endl;
cout << "Enter the percentage of donation: ";
cin >> percentDonation;
cout << endl << endl;

//Step 7
//Step 8
//Step 9
//Step 10

//Step 11
//Step 12
//Step 13
//Step 14

//Step 15
grossAmount = adultTicketPrice * noOfAdultTicketsSold +
childTicketPrice * noOfChildTicketsSold;
//Step 16
amountDonated = grossAmount * percentDonation / 100;
netSaleAmount = grossAmount - amountDonated;
//Step 18: Output results
cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
<< "-*-*-*-*-*-*-*-*-*-*-*-*-*" << endl;

//Step 17

Programming Example: Movie Tickets Sale and Donation to Charity |

cout <<
<<
cout <<
<<
<<
<<
cout <<
<<
<<
<<
cout <<
<<
<<
<<
cout <<
<<
<<
<<
cout <<
<<
<<
}

161

setfill('
...
') << left << setw(35)
"Gross Amount: "
setfill(' ') << right << " $"
setw(8) << grossAmount << endl;
setfill('
...
') << left << setw(35)
"Amount Donated: "
setfill(' ') << right << " $"
setw(8) << amountDonated << endl;
setfill('
...

Enter movie name: Journey to Mars
Enter the price of an adult ticket: 4
...
00
Enter number of adult tickets sold: 800
Enter number of child tickets sold: 1850
Enter the percentage of donation: 10
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Movie Name:
...

2650
Gross Amount:
...
00
Percentage of Gross Amount Donated:
10
...
$ 915
...
$ 8235
...


3

162 |

Chapter 3: Input/Output

PROGRAMMING EXAMPLE:

Student Grade

Write a program that reads a student name followed by five test scores
...

Output the average test score with two decimal places
...
txt
...
out
...
A sample input is:
Andrew Miller 87
...
75 37 98
...


To find the average of the five test scores, you add the five test scores and divide the
sum by 5
...
Therefore, you must read the student name first and then read the five
test scores
...

2
...

4
...

Output the student name and the five test scores
...

Output the average
...

Variables The program needs to read a student’s first and last name and five test scores
...

To find the average, you must add the five test scores and then divide the sum by 5
...
Furthermore, because the
input data is in a file, you need an ifstream variable to open the input file
...
The program, therefore, needs at least the following variables:
ifstream inFile;
ofstream outFile;

//input file stream variable
//output file stream variable

double test1, test2, test3, test4, test5; //variables to
//read the five test scores
double average;
//variable to store the average test score
string firstName; //variable to store the first name
string lastName;
//variable to store the last name
MAIN
ALGORITHM

In the preceding sections, we analyzed the problem and determined the formulas to
perform the calculations
...
We can now expand the previous algorithm to solve the problem given at
the beginning of this programming example:
1
...

2
...

3
...

4
...
Also, to output the floating-point numbers with
two decimal places, set the precision to two decimal places
...
Read the student name
...
Output the student name
...
Read the five test scores
...
Output the five test scores
...
Find the average test score
...
Output the average test score
...
Close the input and output files
...
Because the program outputs the average test score to two decimal
places, you need to set the precision to two decimal places
...

Because firstName and lastName are string variables, we must include the header file
string
...

COMPLETE PROGRAM LISTING
//************************************************************
// Author: D
...
Malik
//
// Program to calculate the average test score
...
The student's name, the
// five test scores, and the average test score are stored in
// the file testavg
...
The data is input from the file
// test
...

//************************************************************
#include
#include
#include
#include






using namespace std;

3

164 |

Chapter 3: Input/Output

int main()
{
//Declare variables;
ifstream inFile;
ofstream outFile;

Step 1

double test1, test2, test3, test4, test5;
double average;
string firstName;
string lastName;
inFile
...
txt");
outFile
...
out");

//Step 2
//Step 3

outFile << fixed << showpoint;
outFile << setprecision(2);

//Step 4
//Step 4

cout << "Processing data" << endl;
inFile >> firstName >> lastName;
outFile << "Student name: " << firstName
<< " " << lastName << endl;

//Step 5
//Step 6

inFile >> test1 >> test2 >> test3
>> test4 >> test5;
//Step 7
outFile << "Test scores: " << setw(6) << test1
<< setw(6) << test2 << setw(6) << test3
<< setw(6) << test4 << setw(6) << test5
<< endl;
//Step 8
average = (test1 + test2 + test3 + test4
+ test5) / 5
...
close();
outFile
...
txt):
Andrew Miller 87
...
75 37 98
...
out):
Student name: Andrew Miller
Test scores: 87
...
00 65
...
00 98
...
55

Quick Review |

165

The preceding program uses five variables—test1, test2, test3, test4,
and test5—to read the five test scores and then find the average test score
...
The program is named
Ch3_AverageTestScoreVersion2
...


QUICK REVIEW
1
...

3
...

5
...


7
...

9
...

11
...

13
...

15
...

An input stream is a stream from a source to a computer
...

cin, which stands for common input, is an input stream object, typically
initialized to the standard input device, which is the keyboard
...

When the binary operator >> is used with an input stream object, such as cin, it
is called the stream extraction operator
...

When the binary operator << is used with an output stream object, such as
cout, it is called the stream insertion operator
...

When inputting data into a variable, the operator >> skips all leading
whitespace characters
...

The function get is used to read data on a character-by-character basis and
does not skip any whitespace characters
...

The function putback puts the last character retrieved by the function get
back into the input stream
...

Attempting to read invalid data into a variable causes the input stream to
enter the fail state
...


3

166 |

16
...

18
...

20
...

22
...

24
...

26
...


Chapter 3: Input/Output

The manipulator setprecision formats the output of floating-point
numbers to a specified number of decimal places
...

The manipulator showpoint outputs floating-point numbers with a
decimal point and trailing zeros
...

If the number of columns specified in the argument of setw is less than the
number of columns needed to print the value of the expression, the output
is not truncated and the output of the expression expands to the required
number of columns
...

If the number of columns specified in the setw manipulator exceeds the
number of columns required by the next expression, the output is rightjustified
...

To use the stream functions get, ignore, putback, peek, clear, and unsetf
for standard I/O, the program must include the header file iostream
...

The header file fstream contains the definitions of ifstream and ofstream
...
You must also do the following: declare
variables of type ifstream for file input and of type ofstream for file output
and use open statements to open input and output files
...

To close a file as indicated by the ifstream variable inFile, you use the
statement inFile
...
To close a file as indicated by the ofstream
variable outFile, you use the statement outFile
...


EXERCISES
1
...

a
...

c
...


The extraction operator >> skips all leading whitespace characters when
searching for the next data in the input stream
...

The statement cin >> x >> y; requires the input values for x and y to
appear on the same line
...


Exercises

e
...

2
...
Consider the
following input:
What value (if any) is assigned to x, y, and ch after each of the following
statements executes? (Use the same input for each statement
...


cin >> x >> y >> ch;

b
...


cin >> x >> ch >> y;

d
...
get(ch);

Suppose x and y are int variables and z is a double variable
...
56 32

What value (if any) is assigned to x, y, and z after each of the following
statements executes? (Use the same input for each statement
...


cin >> x >> y >> z;

b
...

4
...

The function ignore is used to skip certain input in a line
...


|

cin >> z >> x >> y;

Suppose x and y are int variables and ch is a char variable
...
)
a
...
ignore(50, '\n');
cin >> ch;

b
...
ignore(50, '\n');
cin >> y;
cin
...
get(ch);

c
...
ignore(50, '\n');
cin >> x >> ch;

3

168 |

d
...


Chapter 3: Input/Output

cin
...
ignore(50, '\n');
cin >> x;
cin
...


Suppose that x and y are int variables, z is a double variable, and ch is a
char variable
...

b
...

9
...


86 32A 92
...

7
...
78
12
...
Write the input statement
to read and store the input Brenda Clinton in name
...
)
Write a C++ statement that uses the manipulator setfill to output a line
containing 35 stars, as in the following line:
***********************************

11
...
What are
the values of age and name after the following input statements execute:
cin >> age;
getline(cin, name);

if the input is:
a
...


12
...
What are the values of age and name after the following
input statements execute:

Exercises

|

169

cin >> age;
cin
...

b
...


23 Lance Grant
23
Lance Grant

The following program is supposed to read two numbers from a file named
input
...
dat
...
Rewrite the program so that it accomplishes what
it is intended to do
...
)
#include
#include
using namespace std;
int main()
{
int num1, num2;
ifstream infile;

}
14
...


16
...


outfile
...
dat");
infile >> num1 >> num2;
outfile << "Sum = " << num1 + num2 << endl;
return 0;

What may cause an input stream to enter the fail state? What happens when
an input stream enters the fail state?
Which header file needs to be included in a program that uses the data types
ifstream and ofstream?
Suppose that infile is an ifstream variable and employee
...
Write the C++ statement that opens
this file using the variable infile
...
dat and, after doing
some calculations, writes the results to a file called outFile
...
Answer
the following questions:
a
...


c
...


After the program executes, what are the contents of the file
inputFile
...
dat if
this file was empty before the program executed?
After the program executes, what are the contents of the file outFile
...
dat did not exist before the
program executed?

3

170 |

18
...


Chapter 3: Input/Output

Suppose that infile is an ifstream variable and it is associated with the
file that contains the following data: 27306 savings 7503
...
Write the
C++ statement(s) that reads and stores the first input in the int variable
acctNumber, the second input in the string variable accountType, and
the third input in the double variable balance
...

b
...


d
...


Open the file travel
...

Write the statement to format your output to two decimal places in
fixed form
...
dat
...
dat
...


Consider the following incomplete C++ program:
#include
int main()
{

...


b
...


d
...

Write statements that declare inFile to be an ifstream variable and
outFile to be an ofstream variable
...
txt and write output
to the file outData
...
Write statements to open both of these files,
associate inFile with inData
...
txt
...
txt contains the following data:
10
...
35
15
...
5
A

Programming Exercises

|

171

The numbers in the first line represent the length and width, respectively, of
a rectangle
...

The third line contains the first name, last name, and the age of a person
...
(Assume
that p ¼ 3
...
) The fifth line contains an uppercase letter between A and
Y (inclusive)
...
txt are as shown below
...
Your statements should be general enough so that if the
content of the input file changes and the program is run again (without
editing and recompiling), it outputs the appropriate results
...
20, width = 5
...
57, parameter = 31
...
60, area = 764
...
02
Name: Randy Gill, age: 31
Beginning balance = $18500
...
50
Balance at the end of the month = $18553
...

f
...


Write statements that close the input and output files
...


Consider the following program in which the statements are in the incorrect
order
...
Format the output to two decimal places
...
0)* height << endl;
cout << "Enter the height of the cylinder: ";
cin >> radius;
cout << endl;
return 0;
double radius;

3

172 |

Chapter 3: Input/Output

cout << "Surface area: "
<< 2 * radius * + 2 * PI * pow(radius, 2
...
14159;
using namespace std;
3
...


Write a program that prompts the user to enter the weight of a person in
kilograms and outputs the equivalent weight in pounds
...
(Note that 1 kilogram ¼ 2
...
) Format your output with two decimal places
...
The nursery carries different
types of vegetable fertilizers in various bag sizes
...
The following program prompts the user to
enter the size of the fertilizer bag, in pounds, the cost of the bag, and the
area, in square feet, that can be covered by the bag
...
However, the program contains logic errors
...

//Logic errors
...


"The cost of the fertilizer per pound is: $"
bagSize / cost << endl;
"The cost of fertilizing per square foot is: $"
area / cost << endl;

return 0;

The manager of a football stadium wants you to write a program that
calculates the total ticket sales after each game
...
After each game,
data is stored in a file in the following form:
ticketPrice

...


5750
28000
35750
18750

The first line indicates that the ticket price is $250 and that 5750 tickets were
sold at that price
...

Format your output with two decimal places
...
The net pay is calculated after taking the following deductions:
Federal Income Tax: 15%
State Tax: 3
...
75%
Medicare/Medicaid Tax: 2
...
00

Your program should prompt the user to input the gross amount and the
employee name
...
Format your output to
have two decimal places
...
$3575
...
$ 536
...
$ 125
...

Medicare/Medicaid Tax:
...

Health Insurance:
...


7
...


$ 205
...
31
$ 178
...
00
$2356
...

Redo Programming Exercise 21, in Chapter 2, so that each string can store
a line of text
...
You are
given a file, say Ch3_Ex8Data
...
87 5
Green Sheila 75892
...
50 6
...


10
...
For example, in the first input line, the last name of
the employee is Miller, the first name is Andrew, the current salary is
65789
...
Write a program that reads data from
the specified file and stores the output in the file Ch3_Ex8Output
...

For each employee, the data must be output in the following form:
firstName lastName updatedSalary
...

Write a program that accepts as input the mass, in grams, and density, in
grams per cubic centimeters, and outputs the volume of the object using the
formula: density ¼ mass / volume
...

Interest on a credit card’s unpaid balance is calculated using the average daily
balance
...
Then, the average
daily balance is:
averageDailyBalance ¼ ðnetBalance à d1 À payment à d2Þ=d1
If the interest rate per month is, say, 0
...
The program outputs the interest
...


4

CHAPTER

CONTROL S TRUCTURES I
(S ELECTION )
I N T H I S C H A P T E R , YO U W I L L :


...


Examine relational and logical operators


...


Discover how to use the selection control structures if, if
...


Learn how to avoid bugs by avoiding partially understood concepts


...
The programs you have examined so far were simple
and straightforward
...

In this chapter and Chapter 5, you will learn how to tell a computer that it does
not have to follow a simple sequential order of statements; it can also make
decisions and repeat certain statements over and over until certain conditions
are met
...
Figure 4-1
illustrates the first three types of program flow
...
) The programming examples in Chapters 2 and 3 included simple sequential
programs
...
No choices are made; there is no repetition
...
The two most common control structures are selection and repetition
...

In repetition, the program repeats particular statements a certain number of times based on
some condition(s)
...
Sequence

FIGURE 4-1

Flow of execution

b
...
Repetition

statement

Relational Operators

|

177

Before you can learn about selection and repetition, you must understand the nature
of conditional statements and how to use them
...
if (score is greater than or equal to 90)
grade is A

2
...
5 *(rate *(hours – 40))

3
...
You can see that certain
statements are to be executed only if certain conditions are met
...
For example, in statement 1:
score is greater than or equal to 90

is true if the value of score is greater than or equal to 90; it is false otherwise
...
Similarly, if the
value of score is 86, the statement evaluates to false
...
Furthermore, in certain situations, the truth or falsity of a
statement could depend on more than one condition
...

As you can see, for the computer to make decisions and repeat statements, it must be able
to react to conditions that exist when the program executes
...


Relational Operators
To make decisions, you must be able to express conditions and make comparisons
...
If the balance is less than some minimum balance, not
only is the interest rate lower, but there is also usually a service charge
...
The premium on an
insurance policy is also determined by stating conditions and making comparisons
...
Nonsmokers (the condition) receive lower premiums than
smokers
...
Certain items are compared

4

178 |

Chapter 4: Control Structures I (Selection)

for equality against a particular condition; others are compared for inequality (greater than
or less than) against a particular condition
...
An expression that
has a value of either true or false is called a logical (Boolean) expression
...
Suppose i and j are integers
...
The
symbol > is called a relational operator
...

C++ includes six relational operators that allow you to state conditions and make
comparisons
...

TABLE 4-1

Relational Operators in C++

Operator

Description

==

equal to

!=

not equal to

<

less than

<=

less than or equal to

>

greater than

>=

greater than or equal to

In C++, the symbol ==, which consists of two equal signs, is called the equality operator
...
Remember that the equality
operator, ==, determines whether two expressions are equal, whereas the assignment
operator, =, assigns the value of an expression to a variable
...

Because the result of a comparison is true or false, expressions using these operators
evaluate to true or false
...
In the following
example, the expressions use both integers and real numbers:

Relational Operators

|

179

EXAMPLE 4-1
Expression

Meaning

Value

8 < 15
6 != 6
2
...
8
5
...
5

8 is less than 15
6 is not equal to 6
2
...
8
5
...
5

true
false
false
true

4

Comparing Characters
For char values, whether an expression using relational operators evaluates to true or false
depends on a machine’s collating sequence
...

Now, because 32 < 97, and the ASCII value of ' ' is 32 and the ASCII value of 'a' is
97, it follows that ' ' < 'a' is true
...
For
example, the following expression compares an integer and a character:
8 < '5'

In this expression, on a particular machine, 8 would be compared with the collating
sequence of '5', which is 53
...

Expressions such as 4 < 6 and 'R' > 'T' are examples of logical (Boolean) expressions
...
In C++, any
nonzero value is treated as true
...
Recall that the data type bool has two values,
true and false
...
The identifier
true is set to 1, and the identifier false is set to 0
...


Relational Operators and the string Type
The relational operators can be applied to variables of type string
...
The character-by-character comparison continues until
either a mismatch is found or the last characters have been compared and are equal
...

EXAMPLE 4-2
Suppose that you have the statements:
string
string
string
string
string

str1
str2
str3
str4
str5

=
=
=
=
=

"Hello";
"Hi";
"Air";
"Bill";
"Big";

The following expressions show how string relational expressions evaluate
...
The first characters
of str1 and str2 are the same, but the second character 'e'
of str1 is less than the second character 'i' of str2
...


Relational Operators

|

181

str1 > "Hen"

false
str1 = "Hello"
...
Therefore,
str1 > "Hen" is false
...
The first characters of str3 and "An" are
the same, but the second character 'i' of "Air" is less than
the second character 'n' of "An"
...


str1 == "hello"

false
str1 = "Hello"
...

Therefore, str1 == "hello" is false
...
The first character
'A' of str3 is less than the first character 'B' of str4
...


str2 > str4

true
str2 = "Hi" and str4 = "Bill"
...

Therefore, str2 > str4 is true
...

Expression

Value/Explanation

str4 >= "Billy"

false
str4 = "Bill"
...
Therefore, str4 is the shorter string
...
Therefore, str4 >= "Billy" is false
...
It has three characters, and "Bigger"
has six characters
...

All three characters of str5 are the same as the
corresponding first three characters of "Bigger",
and "Bigger" is the larger string
...


4

182 |

Chapter 4: Control Structures I (Selection)

The program Chapter4_StringComparisons
...


Logical (Boolean) Operators and Logical Expressions
This section describes how to form and evaluate logical expressions that are combinations of other logical expressions
...
C++ has three logical (Boolean) operators, as shown in
Table 4-2
...
The operator ! is unary, so it has only one operand
...
Tables 4-3, 4-4, and 4-5 define these operators
...
When you use the ! operator, !true is false
and !false is true
...

TABLE 4-3

The ! (Not) Operator

Expression

!(Expression)

true (nonzero)

false (0)

false (0)

true (1)

EXAMPLE 4-3
Expression

Value

Explanation

!('A' > 'B')
!(6 <= 7)

true
false

Because 'A' > 'B' is false, !('A' > 'B') is true
...


Logical (Boolean) Operators and Logical Expressions | 183

Table 4-4 defines the operator && (and)
...

TABLE 4-4

The && (And) Operator

Expression1

Expression2

Expression1 && Expression2

true (nonzero)

true (nonzero)

true (1)

true (nonzero)

false (0)

false (0)

false (0)

true (nonzero)

false (0)

false (0)

false (0)

false (0)

EXAMPLE 4-4
Expression

Value

Explanation

(14 >= 5) && ('A' < 'B')

true

(24 >= 35) && ('A' < 'B')

false

Because (14 >= 5) is true, ('A' <
'B') is true, and true && true is
true, the expression evaluates to true
...


Table 4-5 defines the operator || (or)
...

TABLE 4-5

The || (Or) Operator

Expression1

Expression2

Expression1 || Expression2

true (nonzero)

true (nonzero)

true (1)

true (nonzero)

false (0)

true (1)

false (0)

true (nonzero)

true (1)

false (0)

false (0)

false (0)

4

184 |

Chapter 4: Control Structures I (Selection)

EXAMPLE 4-5
Expression

Value

Explanation

(14 >= 5) || ('A' > 'B')

true

(24 >= 35) || ('A' > 'B')

false

('A' <= 'a') || (7 != 7)

true

Because (14 >= 5) is true, ('A' >
'B') is false, and true || false is
true, the expression evaluates to true
...

Because ('A' <= 'a') is true,
(7 != 7) is false, and true || false
is true, the expression evaluates to true
...
Consider the following logical
expression:
11 > 5 || 6 < 15 && 7 >= 8

This logical expression yields different results, depending on whether || or && is evaluated
first
...
If && is evaluated first, the
expression evaluates to true
...
Table 4-6 shows the order of precedence of some C++ operators,
TABLE 4-6

Precedence of Operators

Operators

Precedence

!, +, - (unary operators)

first

*, /, %

second

+, -

third

<, <=, >=, >

fourth

==, !=

fifth

&&

sixth

||

seventh

=

(assignment operator)

last

Logical (Boolean) Operators and Logical Expressions | 185

including the arithmetic, relational, and logical operators
...
)
In C++, & and | are also operators
...
Using & in place of && or | in place of ||—as might result from a
typographical error—would produce very strange results
...
Because relational and logical operators are evaluated from left to right, the
associativity of these operators is said to be from left to right
...

EXAMPLE 4-6
Suppose you have the following declarations:
bool found = true;
int age = 20;
double hours = 45
...
00;
int count = 20;
char ch = 'B';

Consider the following expressions:
Expression

Value / Explanation

!found

false
Because found is true, !found is false
...
00

!age

true
Because hours is 45
...
30 > 40
...
00 evaluates to
true
...

Therefore, !age is false
...

Therefore,!found && (age >= 18) is false &&
true, which evaluates to false
...
Therefore, !(found &&
(age >= 18)) is !true, which evaluates to false
...
00

Value / Explanation
true
Because hours + overTime is 45
...
00 =
60
...
30 <= 75
...
00 evaluates to true
...
Because 20 >= 0 is true,
count >= 0 is true
...
Therefore, (count >=
0) && (count <= 100) is true && true,
which evaluates to true
...
Because 'A' <= 'B' is true,
'A' <= ch evaluates to true
...

Therefore, ('A' <= ch && ch <= 'Z') is true
&& true, which evaluates to true
...
Note
that if a logical expression evaluates to true, the corresponding output is 1; if the logical
expression evaluates to false, the corresponding output is 0, as shown in the output at the
end of the program
...
)
//Chapter 4 Logical operators
#include
#include
using namespace std;
int main()
{
bool found = true;
int age = 20;
double hours = 45
...
00;
int count = 20;
char ch = 'B';
cout << fixed << showpoint << setprecision(2);
cout << "found = " << found << ", age = " << age
<< ", hours = " << hours << ", overTime = " << overTime
<< "," << endl << "count = " << count
<< ", ch = " << ch << endl << endl;
cout
cout
cout
cout

<<
<<
<<
<<
<<

"!found evaluates to " << !found << endl;
"hours > 40
...
00) << endl;
"!age evaluates to " << !age << endl;
"!found && (hours >= 0) evaluates to "
(!found && (hours >= 0)) << endl;

Logical (Boolean) Operators and Logical Expressions | 187

cout <<
<<
cout <<
<<
cout <<
<<
cout <<
<<
}

"!(found && (hours >= 0)) evaluates to "
(!(found && (hours >= 0))) << endl;
"hours + overTime <= 75
...
00) << endl;
"(count >= 0) && (count <= 100) evaluates to "
((count >= 0) && (count <= 100)) << endl;
"('A' <= ch && ch <= 'Z') evaluates to "
('A' <= ch && ch <= 'Z') << endl;

return 0;

Sample Run:
found = 1, age = 20, hours = 45
...
00,
count = 20, ch = B
!found evaluates to 0
hours > 40
...
00 evaluates to 1
(count >= 0) && (count <= 100) evaluates to 1
('A' <= ch && ch <= 'Z') evaluates to 1

You can insert parentheses into an expression to clarify its meaning
...
Using the standard order of precedence, the expression:
11 > 5 || 6 < 15 && 7 >= 8

is equivalent to:
11 > 5 || (6 < 15 && 7 >= 8)

In this expression, 11 > 5 is true, 6 < 15 is true, and 7 >= 8 is false
...
Therefore, the expression 11 > 5 || (6 < 15 && 7 >= 8) evaluates to true
...
The following sections describe
these methods
...
Because logical expressions evaluate to either 1 or 0, the value of
a logical expression was stored in a variable of the data type int
...


4

188 |

Chapter 4: Control Structures I (Selection)

Recall that nonzero values are treated as true
...

The assignment statement:
legalAge = (age >= 21);

assigns the value 1 to legalAge if the value of age is greater than or equal to 21
...


bool Data Type and Logical (Boolean) Expressions
More recent versions of C++ contain a built-in data type, bool, that has the logical
(Boolean) values true and false
...
Recall that in C++, bool, true, and false are
reserved words
...
Now, consider the following declaration:
bool legalAge;
int age;

The statement:
legalAge = true;

sets the value of the variable legalAge to true
...
This
statement assigns the value false to legalAge if the value of age is less than 21
...

Similarly, if the value of age is 16, the value assigned to legalAge is false—that is, 0
...
For the purpose of clarity, this book uses bool variables to store the values of
logical expressions
...
else
Although there are only two logical values, true and false, they turn out to be extremely
useful because they permit programs to incorporate decision making that alters the
processing flow
...
else

|

189

into a program
...
This section discusses how if and if
...
The switch structure is discussed later in this chapter
...
That is, if the account balance is below the
required minimum balance, it should send a notice to the customer; otherwise, it should
do nothing
...
Both of these
examples involve one-way selection
...
The syntax of one-way selection is:
if (expression)
statement

Note the elements of this syntax
...
Note that
the parentheses around the expression are part of the syntax
...
The expression is usually a logical expression
...
If the value is false,
the statement does not execute and the computer goes on to the next statement in
the program
...
Figure 4-2 shows the flow of execution of the if statement
(one-way selection)
...
If the expression evaluates to false, the statements (if any)
following the if structure execute
...


EXAMPLE 4-8
The following C++ program finds the absolute value of an integer
...

Line 1: Enter an integer: -6734
Line 7: The absolute value of -6734 is 6734

The statement in Line 1 prompts the user to enter an integer; the statement in Line 2
inputs the number into the variable number
...
If
number is negative, the statement in Line 6 changes number to a positive number
...
Note that because we want

Selection: if and if
...


EXAMPLE 4-9
Consider the following statement:
if score >= 60
grade = 'P';

//syntax error

4

This statement illustrates an incorrect version of an if statement
...


Putting a semicolon after the parentheses following the expression in an if statement
(that is, before the statement) is a semantic error
...

EXAMPLE 4-10
Consider the following C++ statements:
if (score >= 60);
grade = 'P';

//Line 1
//Line 2

Because there is a semicolon at the end of the expression (see Line 1), the if statement in
Line 1 terminates
...
Hence, the statement in Line 2 executes regardless
of how the if statement evaluates
...
For example, if a part-time employee works overtime, the paycheck is
calculated using the overtime payment formula; otherwise, the paycheck is calculated
using the regular formula
...
To choose between
two alternatives—that is, to implement two-way selections—C++ provides the if
...
Two-way selection uses the following syntax:
if (expression)
statement1
else
statement2

192 |

Chapter 4: Control Structures I (Selection)

Take a moment to examine this syntax
...
Statements 1 and 2 are any valid
C++ statements
...
If the value of the expression is false, statement2 executes
...
else statement (two-way selection)
...
0)
wages = 40
...
5 * rate * (hours - 40
...
0, the wages include overtime
payment
...
The expression in the if statement, in Line 1,
evaluates to true, so the statement in Line 2 executes
...
In this case, the program skips the statement in Line 2 and executes the
statement in Line 4—that is, the statement following the reserved word else executes
...
If the if statement ends with a semicolon,
statement1 is no longer part of the if statement, and the else part of the
if
...
There is no stand-alone else statement in C++
...


Selection: if and if
...

if (hours > 40
...
0 * rate +
1
...
0); //Line 2
else
//Line 3
wages = hours * rate;
//Line 4

The semicolon at the end of the if statement (see Line 1) ends the if statement, so the
statement in Line 2 separates the else clause from the if statement
...
Because there is no stand-alone else statement in C++, this code generates a
syntax error
...


EXAMPLE 4-13
The following program determines an employee’s weekly wages
...

//Program: Weekly wages
#include
#include
using namespace std;
int main()
double wages, rate, hours;
cout << fixed << showpoint << setprecision(2);
//Line 1
cout << "Line 2: Enter working hours and rate: "; //Line 2
cin >> hours >> rate;
//Line 3
if (hours > 40
...
0 * rate +
1
...
0);
else
wages = hours * rate;
cout << endl;
cout << "Line 9: The wages are $" << wages
<< endl;
}

//Line 4

//Line 8

return 0;

//Line 5
//Line 6
//Line 7

//Line 9

4

194 |

Chapter 4: Control Structures I (Selection)

Sample Run: In this sample run, the user input is shaded
...
45 12
...
44

The statement in Line 1 sets the output of the floating-point numbers in a fixed decimal format,
with a decimal point, trailing zeros, and two decimal places
...
The statement in Line 3 inputs these
values into the variables hours and rate, respectively
...
0
...
0, then the
wages are calculated by the statement in Line 5, which includes overtime payment
...
The statement in Line 9 outputs the wages
...

EXAMPLE 4-14
Consider the following statements:
if (score >= 60)
cout << "Passing" << endl;
cout << "Failing" << endl;

//Line 1
//Line 2
//Line 3

If the expression (score >= 60) evaluates to false, the output statement in Line 2 does
not execute
...
That is, this set of statements performs the
same action as an if
...
It will execute the output statement in Line 3
rather than the output statement in Line 2
...
For example, if the
value of score is 70, these statements will output the following lines:
Passing
Failing

The if statement controls the execution of only the statement in Line 2
...

The correct code to print Passing or Failing, depending on the value of score, is:
if (score >= 60)
cout << "Passing" << endl;
else
cout << "Failing" << endl;

Selection: if and if
...
else structures control only one statement at a time
...
else statement evaluates to true
...
A
compound statement takes the following form:
{
statement_1
statement_2

...


...
In an if or if
...
Thus, instead of having a simple two-way selection similar to the
following code:
if (age >= 18)
cout << "Eligible to vote
...
" << endl;

you could include compound statements, similar to the following code:
if (age >= 18)
{
cout << "Eligible to vote
...
" << endl;
}
else
{
cout << "Not eligible to vote
...
" << endl;
}

The compound statement is very useful and will be used in most of the structured
statements in this chapter
...
Some problems require the implementation of more than two alternatives
...
99, the interest rate is
5%; if the balance is between $1,000 and $24,999
...
This particular problem has four alternatives—that is, multiple
selection paths
...
else structure if the action statement itself is an if or if
...
When
one control statement is located within another, it is said to be nested
...
else
structure
...
The following
statements determine the interestRate depending on the value of the balance
...
00)
interestRate = 0
...
00)
interestRate = 0
...
00)
interestRate = 0
...
00;

//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line

1
2
3
4
5
6
7
8
9
10

A nested if
...
Every else must be paired with an if
...

Using this rule, in Example 4-15, the else in Line 3 is paired with the if in Line 1
...

To avoid excessive indentation, the code in Example 4-15 can be rewritten as follows:
if (balance > 50000
...
07;
else if (balance >= 25000
...
05;
else if (balance >= 1000
...
03;
else
interestRate = 0
...


Selection: if and if
...
Based on the value of score, the following
code outputs the grade
...
" << endl;
is B
...
" << endl;
is D
...
" << endl;

EXAMPLE 4-17
Assume that all variables are properly declared, and consider the following statements:
if (temperature >= 50)
if (temperature >= 80)
cout << "Good day for swimming
...
" << endl;
else
cout << "Good day to play tennis
...
Note that the else in Line 4 cannot be paired with the if in
Line 1
...
Also, the
statements in Lines 2 though 5 form the statement part of the if in Line 1
...


EXAMPLE 4-18
Assume that all variables are properly declared, and consider the following statements:
if (temperature >= 70)
if (temperature >= 80)
cout << "Good day for swimming
...
" << endl;

//Line
//Line
//Line
//Line
//Line

1
2
3
4
5

198 |

Chapter 4: Control Structures I (Selection)

In this code, the else in Line 4 is paired with the if in Line 2
...
In this code, the if in Line 1 has no
else and is a one-way selection
...


EXAMPLE 4-19
Assume that all variables are properly declared, and consider the following statements:
if (gender == 'M')
if (age < 21 )
policyRate
else
policyRate
else if (gender ==
if (age < 21 )
policyRate
else
policyRate

= 0
...
035;
'F')
= 0
...
03;

//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line

1
2
3
4
5
6
7
8
9
10

In this code, the else in Line 4 is paired with the if in Line 2
...
The else in Line 6 is paired
with the if in Line 1
...
Once again,
the indentation does not determine the pairing, but it communicates the pairing
...
else Statements with a Series of if Statements
Consider the following C++ program segments, all of which accomplish the same task
...


if (month == 1)
cout << "January" << endl;
else if (month == 2)
cout << "February" << endl;
else if (month == 3)
cout << "March" << endl;
else if (month == 4)
cout << "April" << endl;
else if (month == 5)
cout << "May" << endl;
else if (month == 6)
cout << "June" << endl;

b
...
else

|

199

if (month == 4)
cout << "April" << endl;
if (month == 5)
cout << "May" << endl;
if (month == 6)
cout << "June" << endl;

Program segment (a) is written as a sequence of if
...
Both program segments accomplish the same
thing
...
If month is 1, then in
program segment (a), the expression in the if statement in Line 1 evaluates to true
...
In program segment (b), the computer has to evaluate the expression in
each if statement because there is no else statement
...


Short-Circuit Evaluation
Logical expressions in C++ are evaluated using a highly efficient algorithm
...
This expression evaluates to true if either the operand (x > y)
is true or the operand (x == 5) is true
...
As soon as the value of the entire
logical expression is known, the evaluation stops
...
Therefore, the value of
the operand (x == 5) has no bearing on the final outcome
...
If the operand (a == b) evaluates to false, then the entire expression
evaluates to false because false && true is false and false && false is false
...

EXAMPLE 4-20
Consider the following expressions:
(age >= 21) || ( x == 5)
(grade == 'A') && (x >= 7)

//Line 1
//Line 2

4

200 |

Chapter 4: Control Structures I (Selection)

For the expression in Line 1, suppose that the value of age is 25
...
Due to short-circuit evaluation, the computer does not evaluate the expression
(x == 5)
...
Because ('B' == 'A') is false and the logical operator used in the
expression is &&, the expression evaluates to false
...


Comparing Floating-Point Numbers for Equality: A Precaution
Comparison of floating-point numbers for equality may not behave as you would expect
...
0;
double y = 3
...
0 + 2
...
0 + 2
...
0;
cout << fixed << showpoint << setprecision(17);
cout << "3
...
0 + 2
...
0 + 2
...
0 = "
<< 3
...
0 + 2
...
0 + 2
...
0 << endl;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
if (x == y)
cout << "x and y are the same
...
" << endl;
if (fabs(x
cout <<
<<
else
cout <<
<<
}

return 0;

- y) < 0
...
000001
...
000001
...
else

|

201

Sample Run:
3
...
0 + 2
...
0 + 2
...
0 = 0
...
00000000000000000
y = 0
...

x and y are the same within the tolerance 0
...


In this program, x is initialized to 1
...
0 / 7
...
0 / 7
...
0 / 7
...
Now, due to rounding, as shown by the output, this expression
evaluates to 0
...
Therefore, the expression (x == y) evaluates
to false
...
0 / 7
...
0 / 7
...
0 /
7
...
0 / 7
...
0 / 7
...
0 / 7
...
0 + 2
...
0) / 7
...
0 / 7
...
0
...
0
...
One way to check whether two floating-point
numbers are equal is to check whether the absolute value of their difference is less than
a certain tolerance
...
000001
...
000001
...

Therefore, the expression fabs(x – y) < 0
...
000001
...

#include
using namespace std;
int main()
{
int num;
cout << "Enter an integer: ";
cin >> num;
cout << endl;
if (0 <= num <= 10)
cout << num << " is within 0 and 10
...
" << endl;
}

return 0;

4

202 |

Chapter 4: Control Structures I (Selection)

Sample Runs: In these sample runs, the user input is shaded
...


Sample Run 2:
Enter an integer: 20
20 is within 0 and 10
...


Clearly, Sample Run 1 is correct and Sample Runs 2 and 3 are incorrect
...
So, let us look at this expression, which is:
0 <= num <= 10

Although this statement is a legal C++ expression, you do not get the desired result
...
Suppose that the value of num is 5
...
Then:
0 <= num <= 10

= 0 <= 20 <= 10
= (0 <= 20) <= 10

(Because relational operators are
evaluated from left to right)

= 1 <= 10

(Because 0 <= 20 is true, 0
<= 20 evaluates to 1)

= 1

(true)

Now, you can see why the expression evaluates to true when num is 20
...
In fact, this expression will
always evaluate to true, no matter what num is
...
So what is

Selection: if and if
...
A correct
way to write this expression in C++ is:
0 <= num && num <= 10

You must take care when formulating logical expressions
...


Avoiding Bugs by Avoiding Partially Understood Concepts
and Techniques
The debugging sections in Chapters 2 and 3 illustrated how to understand and fix syntax
and logic errors
...

The programs that you have written until now should have illustrated that a small
error such as omission of a semicolon at the end of a variable declaration or using a
variable without properly declaring it can prevent a program from successfully compiling
...
Recall that the condition associated with an if statement must
be enclosed in parentheses
...

if score >= 90

Example 4-12 illustrates that an unintended semicolon following the condition of the
following if statement:
if (hours > 40
...

The approach that you take to solve a problem must use concepts and techniques
correctly; otherwise, your solution will be either incorrect or deficient
...
The problem of using partially understood concepts and techniques can be
illustrated by the following program
...
If the GPA is
greater than or equal to 3
...
If the GPA is less
than 2
...
So, consider the following program:
//GPA program with bugs
...
0)
if (gpa >= 3
...
" << endl;
else
cout << "The GPA is below the graduation "
<< "requirement
...
" << endl;
}

//Line 4
//Line 5

//Line
//Line
//Line
//Line

return 0;

9
10
11
12

//Line 13
//Line 14
//Line 15

Sample Runs: In these sample runs, the user input is shaded
...
91
Dean's Honor List
...
8
The GPA is below the graduation requirement
...


Sample Run 3:
Enter the GPA: 1
...
Clearly, the output in Sample Run 1 is correct
...
8 and the output indicates that this GPA is below the
graduation requirement
...
8 would graduate with
some type of honor
...
In Sample Run 3, the
input is 1
...
Therefore, the output
in Sample Run 3 is also incorrect
...
else statement in Lines 9 to 13
is incorrect
...
0)
if (gpa >= 3
...
" << endl;
else
cout << "The GPA is below the graduation "
<< "requirement
...
" << endl;

//Line
//Line
//Line
//Line

9
10
11
12

//Line 13

Selection: if and if
...
In other words, using the correct indentation, the code is:
if (gpa >= 2
...
9)
cout << "Dean\'s Honor List
...
\nSee your "
<< "academic advisor
...
Therefore, if the
input number is less than 2
...
Now, suppose the input is 3
...
Then, the expression in Line 9 evaluates to
true, so the expression in Line 10 is evaluated, which evaluates to false
...

In fact, the program should print the warning message only if the GPA is less than 2
...


if the GPA is greater than or equal to 3
...

To achieve that result, the else in Line 12 needs to be paired with the if in Line 9
...
0)
{
if (gpa >= 3
...
" << endl;
}
else
cout << "The GPA is below the graduation "
<< "requirement
...
" << endl;

//Line 9
//Line 10
//Line 11
//Line 12
//Line 13

The correct program is as follows:
//Correct GPA program
...
0)
{
if (gpa >= 3
...
" << endl;
}
else
cout << "The GPA is below the graduation "
<< "requirement
...
" << endl;
}

return 0;

//Line
//Line
//Line
//Line
//Line
//Line

9
10
11
12
13
14

//Line 15
//Line 16
//Line 17

Sample Runs: In these sample runs, the user input is shaded
...
91
Dean’s Honor List
...
8

Sample Run 3:
Enter the GPA: 1
...

See your academic advisor
...
The else in Line 14 cannot be paired with
the if in Line 11 because the if statement in Line 11 is enclosed within braces, and the
else in Line 14 cannot look inside those braces
...

In this book, the C++ programming concepts and techniques are presented in a logical
order
...
Understanding a concept or
technique completely before using it will save you an enormous amount of debugging
time
...
Once an input stream enters a fail state, all subsequent input statements associated
with that input stream are ignored, and the computer continues to execute the program,
which produces erroneous results
...


Selection: if and if
...
Two additional common causes of input failure are the following:



Attempting to open an input file that does not exist
Attempting to read beyond the end of an input file

One way to address these causes of input failure is to check the status of the
input stream variable
...
If the last input succeeded, the input stream
variable evaluates to true; if the last input failed, it evaluates to false
...
" << endl;

prints:
Input is OK
...
Similarly, if infile is an
ifstream variable, the statement:
if (!infile)
cout << "Input failed
...


if the last input associated with the stream variable infile failed
...
If
the input file does not exist, you can use the value of the input stream variable, in
conjunction with the return statement, to terminate the program
...

A value of 0 indicates that the program terminated normally and that no error occurred
during program execution
...
The return of any value other than 0,
however, indicates that something went wrong during program execution
...
Whenever a return
statement executes, it immediately exits the function in which it appears
...
You
can use these properties of the return statement to terminate the function main
whenever the input stream fails
...
Consider the following statements:

4

208 |

Chapter 4: Control Structures I (Selection)

ifstream infile;
infile
...
dat");

//open inputdat
...
"
<< "The program terminates
...
dat does not exist
...
As a logical expression, the file stream
variable infile then evaluates to false
...
The message:
Cannot open the input file
...


is printed on the screen, and the return statement terminates the program by returning a
value of 1 to the operating system
...
Recall that this program
calculates the average test score based on data from an input file and then outputs the
results to another file
...

//Program to calculate the average test score
...
open("test
...
else

|

209

{

}

cout << "Cannot open the input file
...
" << endl;
return 1;

outFile
...
out");

//open the output file

outFile << fixed << showpoint;
outFile << setprecision(2);
cout << "Processing data" << endl;
inFile >> firstName >> lastName;
outFile << "Student name: " << firstName
<< " " << lastName << endl;
inFile >> test1 >> test2 >> test3
>> test4 >> test5;
outFile << "Test scores: " << setw(4) << test1
<< setw(4) << test2 << setw(4) << test3
<< setw(4) << test4 << setw(4) << test5
<< endl;
average = (test1 + test2 + test3 + test4 + test5) / 5
...
close();
outFile
...
In addition, the expression is usually a logical
expression
...
Consider the following statement:
if (x = 5)
cout << "The value is five
...
The
expression x = 5 is called an assignment expression because the operator = appears in
the expression and there is no semicolon at the end
...
First, the right side of the operator = is evaluated,
which evaluates to 5
...
Moreover, the value 5—that is, the

4

210 |

Chapter 4: Control Structures I (Selection)

new value of x—also becomes the value of the expression in the if statement—that is, the
value of the assignment expression
...

No matter how experienced a programmer is, almost everyone makes the mistake of
using = in place of == at one time or another
...
Thus,
experience with other programming languages can create confusion
...

Despite the fact that an assignment expression can be used as an expression, using the
assignment operator in place of the equality operator can cause serious problems in a
program
...
A driving record of 1 means that the driver is accident-free and
receives a 25% discount on the policy
...
" << endl;

outputs:
The discount on the policy is 25%
...
However, the statement:
if (drivingCode = 1)
cout << "The discount on the policy is 25%
...


because the right side of the assignment expression evaluates to 1, which is nonzero and so
evaluates to true
...
Also, the
value 1 is assigned to the variable drivingCode
...
After the if statement executes, not
only is the output wrong, but the new value also replaces the old driving code
...
It is not a syntax error, so the
compiler does not warn you of an error
...

Using = in place of == can cause serious problems, especially if it happens in a looping
statement
...


The appearance of the equality operator in place of the assignment operator can also cause
errors in a program
...
The statement:
x = y + z;

Selection: if and if
...
The statement:
x == y + z;

compares the value of the expression y + z with the value of x; the value of x remains the
same, however
...
The compiler provides feedback
only about syntax errors, not logic errors
...


4
Conditional Operator (?:)
The reader can skip this section without any discontinuation
...
else statements can be written in a more concise way by using C++’s
conditional operator
...
The syntax for using the conditional operator is:
expression1 ? expression2 : expression3

This type of statement is called a conditional expression
...
Otherwise, the result of the conditional expression is expression3
...
else statement
as follows:
max = (a >= b) ? a : b;

Program Style and Form (Revisited): Indentation
In the section ‘‘Program Style and Form’’ of Chapter 2, we specified some guidelines to
write programs
...

As you write programs, typos and errors are unavoidable
...
Typically, the IDE that you use will automatically indent your program
...

Proper indentation can show the natural grouping of statements
...
In this book, the statements
inside braces, the statements of a selection structure, and an if statement within an if
statement are all indented four spaces to the right
...
You can also use four spaces for indentation
...
In this book, we place braces
on a line by themselves
...

This style of placing braces easily shows the grouping of the statements and also
matches left and right braces
...

In the second style of placing braces, the left brace need not be on a line by itself
...
This style might save
some space
...

No matter what style of indentation you use, you should be consistent within your
programs, and the indentation should show the structure of the program
...
One method involves using an informal
mixture of C++ and ordinary language, called pseudocode or just pseudo
...
When you are constructing programs that involve complex nested
control structures, pseudo can help you quickly develop the correct structure of the
program and avoid making common errors
...
If x and y are integers,
using pseudo, you can quickly write the following:
a
...


if (y > x) then
y is larger

Using Pseudocode to Develop, Test, and Debug a Program |

213

If the statement in (a) is true, then x is larger
...
However, for this code to work in concert to determine the larger of two integers,
the computer needs to evaluate both expressions:
(x > y)

and

(y > x)

even if the first statement is true
...

Let’s rewrite this pseudo as follows:
if (x > y) then
x is larger
else
y is larger

4

Here, only one condition needs to be evaluated
...

#include
using namespace std;
int main()
{
if (x > y)

Wait
...
The variables
were not declared, which is a very common oversight, especially for new programmers
...
Let’s start the program code
again:
#include
using namespace std;
int main()
{
int num1, num2, larger;
if

(num1 > num2);
larger = num1;
else
larger = num2;
}

return

//Line 1
//Line
//Line
//Line
//Line

2; error
3
4
5

0;

Compiling this program will result in the identification of a common syntax error
(in Line 2)
...
else statement
...

The variables have not been initialized, which is another common error
...

Because there are so many mistakes in the program, you should try a walk-through to see
whether it works at all
...
For example, does
this program work if one number is zero, if one number is negative and the other number is
positive, if both numbers are negative, or if both numbers are the same? Examining the
program, you can see that it does not check whether the two numbers are equal
...

#include
using namespace std;
int main()
int num1, num2;
cout << "Enter any two integers: ";
cin >> num1 >> num2;
cout << endl;
cout << "The two integers entered are " << num1
<< " and " << num2 << endl;
if (num1 > num2)
cout << "The larger number is " << num1 << endl;
else if (num2 > num1)
cout << "The larger number is " << num2 << endl;
else
cout << "Both numbers are equal
...

Enter any two integers: 78 90
The two integers entered are 78 and 90
The larger number is 90

One thing you can learn from the preceding program is that you must first develop a
program using paper and pencil
...
On paper, it is easier to spot errors and improve the program, especially with large
programs
...
The first selection
structure, which is implemented with if and if
...
The second selection structure, which does
not require the evaluation of a logical expression, is called the switch structure
...

A general syntax of the switch statement is:
switch (expression)
{
case value1:
statements1
break;
case value2:
statements2
break;

...


...
In a switch
structure, first the expression is evaluated
...
Recall that in a syntax, shading indicates an optional part of the
definition
...
Whether it is an
identifier or an expression, the value can be only integral
...
Its value determines which statement is selected for
execution
...
One or more statements
may follow a case label, so you do not need to use braces to turn multiple
statements into a single compound statement
...
Figure 4-4 shows the flow of execution of the
switch statement
...
When the value of the expression is matched against a case
value (also called a label), the statements execute until either a
break statement is found or the end of the switch structure is
reached
...
If the value of the expression does not match any of the case values,
the statements following the default label execute
...

3
...


switch Structures | 217

EXAMPLE 4-21
Consider the following statements, in which grade is a variable of type char
...
0
...
0
...
0
...
0
...
0
...
";

In this example, the expression in the switch statement is a variable identifier
...
The possible values of grade
are 'A', 'B', 'C', 'D', and 'F'
...
If the value of grade is 'A', the output is:
The grade point is 4
...


EXAMPLE 4-22
The following program illustrates the effect of the break statement
...

//Program: Effect of break statements in a switch structure
#include
using namespace std;
int main()
{
int num;
cout << "Enter an integer between 0 and 7: ";
cin >> num;
cout << endl;

//Line 1
//Line 2
//Line 3

218 |

Chapter 4: Control Structures I (Selection)

cout << "The number you entered is " << num
<< endl;
switch(num)
{
case 0:
case 1:
cout <<
case 2:
cout <<
case 3:
cout <<
break;
case 4:
break;
case 5:
cout <<
case 6:
case 7:
cout <<
break;
default:
cout <<
}

//Line 4
//Line 5

//Line
//Line
"Learning to use ";
//Line
//Line
"C++'s ";
//Line
//Line
"switch structure
...
" << endl;
//Line
//Line
//Line
"The number is out of range
...
" << endl;
}

//Line 24

return 0;

//Line 25

Sample Runs: These outputs were obtained by executing the preceding program several
times
...

Sample Run 1:
Enter an integer between 0 and 7: 0
The number you entered is 0
Learning to use C++'s switch structure
...


Sample Run 2:
Enter an integer between 0 and 7: 2
The number you entered is 2
C++'s switch structure
...


Sample Run 3:
Enter an integer between 0 and 7: 4
The number you entered is 4
Out of the switch structure
...

Out of the switch structure
...

Out of the switch structure
...

Out of the switch structure
...
If the value of num is 0,
the value of the switch expression matches the case value 0
...

The first break statement appears in Line 13, just before the case value of 4
...

When the value of the switch expression matches a case value, all statements execute
until a break is encountered, and the program skips all case labels in between
...
If the value of num is
4, it matches the case value of 4
...


EXAMPLE 4-23
Although a switch structure’s case values (labels) are limited, the switch statement
expression can be as complex as necessary
...
" << endl;

Assume that score is an int variable with values between 0 and 100
...
If the value of score is between
0 and 59, the grade is 'F'
...
Each of these values corresponds to the grade 'F'
...
Rather than write the statement grade =
'F'; followed by the break statement for each of the case values of 0, 1, 2, 3, 4, and 5,
you can simplify the programming code by first specifying all of the case values (as shown
in the preceding code) and then specifying the desired action statement
...

In addition to being a variable identifier or a complex expression, the switch expression
can evaluate to a logical value
...
" << endl;
"Old enough to vote
...
" << endl;
"Not old enough to vote
...
If
the expression evaluates to 1, the statements following the case label 1 execute
...


switch Structures | 221

You can use true and false, instead of 1 and 0, respectively, in the case labels, and
rewrite the preceding switch statement as follows:
switch (age
{
case true:
cout <<
cout <<
break;
case false:
cout <<
cout <<
}

>= 18)

"Old enough to be drafted
...
" << endl;

"Not old enough to be drafted
...
" << endl;

4

As you can see from the preceding examples, the switch statement is an elegant way to
implement multiple selections
...
Even though no fixed rules exist that can be applied
to decide whether to use an if
...
If multiple selections involve a range of values, you should use either an if
...

For instance, in Example 4-23, the value of grade depends on the value of score
...
Because score is an int variable, 60 values
correspond to the grade of 'F'
...
However, dividing by 10 reduces these 60 values to only 6
values: 0, 1, 2, 3, 4, and 5
...
else structure
...
However, you can use the expression static_cast(score) / 10
and still reduce this infinite number of values to just six values
...
In this section, we give another example to
illustrate the problem of using partially understood concepts and techniques
...
Next,
consider the following program that assigns a grade based on a test score
...

#include

//Line 1

using namespace std;

//Line 2

222 |

Chapter 4: Control Structures I (Selection)

int main()
{
int testScore;

//Line 3
//Line 4
//Line 5

cout << "Enter the test score: ";
cin >> testScore;
cout << endl;
switch (testScore / 10)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
cout << "The grade is
case 6:
cout << "The grade is
case 7:
cout << "The grade is
case 8:
cout << "The grade is
case 9:
case 10:
cout << "The grade is
default:
cout << "Invalid test
}
}

//Line 6
//Line 7
//Line 8
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//LIne
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line

F
...
" << endl;
C
...
" << endl;

A
...
" << endl;

return 0;

Sample Runs: In these sample runs, the user input is shaded
...


Sample Run 2:
Enter the test score: -70
Invalid test score
...

B
...

score
...
Can you
see why?
As in Sample Run 3, suppose that the value of testScore is 75
...
So, as we indented, it should print The grade is C
...

The grade is B
...

Invalid test score
...

The problem is a result of having only a partial understanding of how the switch
structure works
...
Therefore, after executing the statement(s) associated with the matching case
label, execution continues with the statement(s) associated with the next case label,
resulting in the printing of four unintended lines
...
We leave it as an exercise for you to
modify this program so that it outputs correct results
...
Therefore, taking time to understand each concept and technique completely
will save you hours of debugging time
...
For
example, division by zero can be difficult to catch using any of the programming
techniques you have examined so far
...
In the case of
division by zero, you can use the assert function to ensure that a program terminates
with an appropriate error message indicating the type of error and the program location
where the error occurred
...
quotient = numerator / denominator;
2
...
50))
wages = rate * hours;

3
...
During execution, however, the computer would try to perform the division
...

The second statement is designed to compute wages only if hours is greater than 0 and
rate is positive and less than or equal to 15
...
The third statement is designed to
execute certain statements only if ch is an uppercase letter
...
You could handle
these types of situations by including output and return statements in your program
...

The syntax to use the assert function is:
assert(expression);

Here, expression is any logical expression
...
If expression evaluates to false, the program terminates and indicates
where in the program the error occurred
...
Therefore,
for a program to use the assert function, it must include the following statement:
#include

A statement using the assert function is sometimes called an assert statement
...
Because quotient should
be calculated only if denominator is nonzero, you include an assert statement before
the assignment statement as follows:
assert(denominator);
quotient = numerator / denominator;

Now, if denominator is 0, the assert statement halts the execution of the program
with an error message similar to the following:
Assertion failed: denominator, file c:\temp\assert
function\assertfunction
...
The error message
also gives the name of the file containing the source code and the line number where the
assertion failed
...
50));
if (hours > 0 && (0 < rate && rate <= 15
...
50), file
c:\temp\assertfunction\assertfunction
...
As you can see, the assert statement not only halts the
program, but also identifies the expression where the assertion failed, the name of the file
containing the source code, and the line number where the assertion failed
...
Therefore, after you have developed and
tested a program, you might want to remove or disable the assert statements
...
In addition, if you plan to modify a
program in the future, you might like to keep the assert statements
...
You can disable assert
statements by using the following preprocessor directive:
#define NDEBUG

This preprocessor directive #define NDEBUG must be placed before the directive
#include
...
There are two types of customers: residential and business
...
For residential customers, the following rates apply:




Bill processing fee: $4
...
50
Premium channels: $7
...


4

226 |

Chapter 4: Control Structures I (Selection)

For business customers, the following rates apply:




Bill processing fee: $15
...
00 for first 10 connections, $5
...
00 per channel for any number of
connections

The program should ask the user for an account number (an integer) and a customer
code
...

Customer’s account number and the billing amount
...
To calculate
the billing amount, you need to know the customer for whom the billing amount is
calculated (whether the customer is residential or business) and the number of
premium channels to which the customer subscribes
...
Other data needed to calculate the bill, such as the bill
processing fees and the cost of a premium channel, are known quantities
...
This problem analysis translates into the following algorithm:
1
...

2
...

3
...
If the customer type is R or r,
i
...

ii
...

iii
...

b
...
Prompt the user for the number of basic service connections
and number of premium channels
...
Compute the bill
...
Print the bill
...
Also, because the
program will calculate the billing amount, you need a variable to store the billing
amount
...


Although these values are constants in the program, the cable company can change
them with little warning
...
Based on the problem analysis, you need to declare the following
named constants:
//Named constants – residential customers
const double RES_BILL_PROC_FEES = 4
...
50;
const double RES_COST_PREM_CHANNEL = 7
...
00;
double BUS_BASIC_SERV_COST = 75
...
00;
double BUS_COST_PREM_CHANNEL = 50
...
To compute

the residential bill, you need to know only the number of premium channels to
which the user subscribes
...

amountDue = RES_BILL_PROC_FEES + RES_BASIC_SERV_COST
+ numOfPremChannels * RES_COST_PREM_CHANNEL;

To compute the business bill, you need to know the number of basic service
connections and the number of premium channels to which the user subscribes
...
If the number of basic service connections
exceeds 10, you must add the cost for each connection over 10
...

if (numOfBasicServConn <= 10)
amountDue = BUS_BILL_PROC_FEES + BUS_BASIC_SERV_COST
+ numOfPremChannels * BUS_COST_PREM_CHANNEL;
else
amountDue = BUS_BILL_PROC_FEES + BUS_BASIC_SERV_COST
+ (numOfBasicServConn - 10)
* BUS_BASIC_CONN_COST
+ numOfPremChannels * BUS_COST_PREM_CHANNEL;
MAIN
ALGORITHM

Based on the preceding discussion, you can now write the main algorithm
...
To output floating-point numbers in a fixed decimal format with
a decimal point and trailing zeros, set the manipulators fixed and
showpoint
...
Recall
that to use these manipulators, the program must include the
header file iomanip
...
Prompt the user to enter the account number
...
Get the customer account number
...
Prompt the user to enter the customer code
...
Get the customer code
...
If the customer code is r or R,
a
...

b
...

c
...

d
...

7
...
Prompt the user to enter the number of basic service connections
...
Get the number of basic service connections
...
Prompt the user to enter the number of premium channels
...
Get the number of premium channels
...
Calculate the billing amount
...
Print the account number and the billing amount
...
If the customer code is something other than r, R, b, or B, output an
error message
...


Programming Example: Cable Company Billing

|

229

COMPLETE PROGRAM LISTING
//***********************************************************
// Author: D
...
Malik
//
// Program: Cable Company Billing
// This program calculates and prints a customer's bill for
// a local cable company
...

//***********************************************************
#include
#include
using namespace std;
//Named constants – residential customers
const double RES_BILL_PROC_FEES = 4
...
50;
const double RES_COST_PREM_CHANNEL = 7
...
00;
double BUS_BASIC_SERV_COST = 75
...
00;
double BUS_COST_PREM_CHANNEL = 50
...
" << endl;
cout << "Enter account number (an integer): ";
cin >> accountNumber;
cout << endl;
cout <<
<<
<<
cin >>
cout <<

"Enter customer type: "
"R or r (Residential), "
"B or b (Business): ";
customerType;
endl;

//Step 1
//Step 1

//Step 2
//Step 3

//Step 4
//Step 5

4

230 |

Chapter 4: Control Structures I (Selection)

switch (customerType)
{
case 'r':
case 'R':
cout << "Enter the number"
<< " of premium channels: ";
cin >> numOfPremChannels;
cout << endl;
amountDue = RES_BILL_PROC_FEES
+ RES_BASIC_SERV_COST
+ numOfPremChannels *
RES_COST_PREM_CHANNEL;
cout <<
<<
<<
cout <<
<<
<<
break;

"Account number: "
accountNumber
endl;
"Amount due: $"
amountDue
endl;

case 'b':
case 'B':
cout << "Enter the number of basic "
<< "service connections: ";
cin >> numOfBasicServConn;
cout << endl;
cout << "Enter the number"
<< " of premium channels: ";
cin >> numOfPremChannels;
cout << endl;
if (numOfBasicServConn<= 10)
amountDue = BUS_BILL_PROC_FEES
+ BUS_BASIC_SERV_COST
+ numOfPremChannels *
BUS_COST_PREM_CHANNEL;

//Step 6
//Step 6a
//Step 6b
//Step 6c

//Step 6d
//Step 6d
//Step 7
//Step 7a
//Step 7b

//Step 7c
//Step 7d
//Step 7e

else
amountDue = BUS_BILL_PROC_FEES
+ BUS_BASIC_SERV_COST
+ (numOfBasicServConn - 10) *
BUS_BASIC_CONN_COST
+ numOfPremChannels *
BUS_COST_PREM_CHANNEL;
cout <<
<<
cout <<
<<
break;

"Account number: "
accountNumber << endl;
"Amount due: $" << amountDue
endl;

//Step 7f
//Step 7f

Quick Review |

default:
cout << "Invalid customer type
...

This program computes a cable bill
...
00

QUICK REVIEW
1
...

3
...

5
...

7
...

9
...

11
...


Control structures alter the normal flow of control
...

Selection structures incorporate decisions in a program
...

Including a space between the relational operators ==, <=, >=, and ! =
creates a syntax error
...

Logical expressions evaluate to 1 (or a nonzero value) or 0
...

In C++, int variables can be used to store the value of a logical expression
...

In C++, the logical operators are ! (not), && (and), and || (or)
...

One-way selection takes the following form:
if (expression)
statement

If expression is true, the statement executes; otherwise, the computer
executes the statement following the if statement
...


Chapter 4: Control Structures I (Selection)

Two-way selection takes the following form:
if (expression)
statement1
else
statement2

14
...

16
...

18
...


20
...

22
...

24
...

The expression in an if or if
...

Including a semicolon before the statement in a one-way selection creates
a semantic error
...

Including a semicolon before statement1 in a two-way selection creates a
syntax error
...
Every else has a related if
...

A sequence of statements enclosed between curly braces, {and }, is called a
compound statement or block of statements
...

You can use the input stream variable in an if statement to determine the
state of the input stream
...
This can cause serious errors in the program
...

The execution of a break statement in a switch statement immediately
exits the switch structure
...


EXERCISES
1
...

a
...


c
...


The result of a logical expression cannot be assigned to an int variable
...

Every if statement must have a corresponding else
...


Exercises

e
...


evaluates to false if either ch < 'A' or ch >= 'Z'
...
The output of the code:
cin >> num;
if (num > 5)
cout << num;
num = 0;
else
cout << "Num is zero" << endl;
is: Num is zero

g
...

i
...


2
...

The expression !(x > 0) is true only if x is a negative number
...

The order in which statements execute in a program is called the flow of
control
...

a
...


if ('a' > 'b' || 66 > static_cast('A'))
cout << "# *#" << endl;

outputs the following:
(i) # *#
(ii) #
(iii) *

(iv) none of these

*
#
c
...
0
d
...


if (5 < 3)
cout << " *";
else if (7 == 8)
cout << "&";
else
cout << "$";

outputs the following:
(i) *
(ii) &
(iii) $
3
...

Determine whether the following expressions evaluate to true or false
...

b
...


(x != 5) && (y != z)

d
...

4
...

Evaluate the following expressions
...

b
...


str3 < str2

d
...


str1 >= str2

str2 >= "Chemistry"

Suppose that x, y, z, and w are int variables, and x = 3, y = 4, z = 7, and w = 1
...

b
...


cout << "y == z - 3: " << (y == z - 3) << endl;

d
...

6
...


Correct the following code so that it prints the correct message
...
" << endl;
else;
cout << "You fail
...


9
...

What is the output of the following program?
#include
using namespace std;
int main()
{
int myNum = 10;
int yourNum = 30;
if (yourNum % myNum == 3)
{
yourNum = 3;
myNum = 1;
}
else if (yourNum % myNum == 2)
{
yourNum = 2;
myNum = 2;
}
else
{
yourNum = 1;
myNum = 3;
}
cout << myNum << " " << yourNum << endl;
}

10
...


b
...


return 0;

What is the output of the program in Exercise 9, if myNum = 5 and
yourNum = 12?
What is the output of the program in Exercise 9, if myNum = 30 and
yourNum = 33?

Suppose that sale and bonus are double variables
...
else
statement that assigns a value to bonus as follows: If sale is greater than
$20,000, the value assigned to bonus is 0
...
05; otherwise, the value assigned to bonus is 0
...


13
...
Assign the value
to fine as follows: If 0 < overSpeed <= 5, the value assigned to fine is
$20
...
00 if
10 < overSpeed <= 15, the value assigned to fine is $150
...
00 plus $20
...

Suppose that score is an int variable
...

b
...


What is the output if the value of score is 95? Justify your answer
...


Suppose that score is an int variable
...


if (score == 70)
cout << "Grade is C
...


if (score = 70)
cout << "Grade is C
...


b
...


What is the output in (i) and (ii) if the value of score is 70? What is
the value of score after the if statement executes?
What is the output in (i) and (ii) if the value of score is 80? What is
the value of score after the if statement executes?

Rewrite the following expressions using the conditional operator
...
)
a
...


if (hours >= 40
...
50 + 1
...
5 * (hours - 40);
else
wages = hours * 7
...


16
...
else statement
...
)

Exercises

a
...


(fuel >= 10) ? drive = 150 : drive = 30;

c
...


|

(booksBought >= 3) ? discount = 0
...
0;

Suppose that you have the following conditional expression
...
)
(0 < backyard && backyard <= 5000) ? fertilizingCharges = 40
...
00 + (backyard - 5000) * 0
...


b
...


18
...
If not, explain
why
...

a
...
" << endl;
break;
case 1:
cout << "Win
...
" << endl;
break;
}

b
...
" << endl;
break;
case 1,
case 2:
cout << "middle
...
" << endl;
}

c
...


19
...
What is the value of alpha after the following C++
code executes?
cin >> alpha;
switch (alpha)
{
case 1:
case 2:
alpha = alpha + 2;
break;
case 4:
alpha++;
case 5:
alpha = 2 * alpha;
case 6:
alpha = alpha + 5;
break;
default:
alpha--;
}

20
...
What is the value of beta after the following C++
code executes?
cin >> beta;
switch (beta)
{
case 3:
beta = beta + 3;

Exercises

|

239

case 1:
beta++;
break;
case 5:
beta = beta + 5;
case 4:
beta = beta + 4;
}
21
...
What is the value of a after the following C++ code
executes?
cin >> a;
if (a > 0)
switch (a)
{
case 1:
a = a + 3;
case 3:
a++;
break;
case 6:
a = a + 6;
case 8:
a = a * 8;
break;
default:
a--;
}
else
a = a + 2;

22
...

include
main ()
{
int a, b;
bool found;
cout << "Enter two integers: ;
cin >> a >> b;
if

a > a *b && 10 < b
found = 2 * a > b;

else
{
found = 2 * a < b;
if found
a = 3;
c = 15;
if b

4

240 |

Chapter 4: Control Structures I (Selection)

{

}
23
...
Correct them so that the program
will run and output w = 21
...


cout << "w = " << w << endl;

Write the missing statements in the following program so that it prompts
the user to input two numbers
...
If
the first number is greater than the second number, it outputs the first
number divided by the second number; if the first number is less than the
second number, it outputs the second number divided by the first number;
otherwise, it outputs the product of the numbers
...


2
...


4
...
The program
should then output the number and a message saying whether the number is
positive, negative, or zero
...
The program
should then output the numbers in ascending order
...
If
the number is less than or equal to 9, the program should output the number;
otherwise, it should output A for 10, B for 11, C for 12
...
(Hint:
Use the cast operator, static_cast( ), for numbers >= 10
...
Rearrange
the statements so that they prompt the user to input the shape type
(rectangle, circle, or cylinder) and the appropriate dimension of the
shape
...
After rearranging the statements, you program should be properly
indented
...
0) << endl;
cout << "Circumference of the circle: "
<< 2 * PI * pow(radius, 2
...
0) << endl;
}
else if (shape == "circle")
{
cout << "Enter the radius of the circle: ";
cin >> radius;
cout << endl;
cout << "Volume of the cylinder = "
<< PI * pow(radius, 2
...
1416;
cout << "Area of the rectangle = "
<< length * width << endl;
else
cout << "The program does not handle " << shape << endl;
cout << fixed << showpoint << setprecision(2);
}
5
...


#include

Write a program to implement the algorithm you designed in Exercise 21 of
Chapter 1
...
Write a program that
prompts the user to enter the lengths of three sides of a triangle and then
outputs a message indicating whether the triangle is a right triangle
...


8
...
Write a program that prompts the user to enter the total
number of cookies, the number of cookies in a box, and the number of
cookie boxes in a container
...
Note that each
box must contain the specified number of cookies, and each container
must contain the specified number of boxes
...
Similarly, if the last container
contains less than the number of specified boxes, you can discard it and
output the number of leftover boxes
...


pffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffi
b2 À 4ac
2a

In this formula, the term b2 À 4ac is called the discriminant
...
If b2 À 4ac > 0, the
equation has two real roots
...
Write a program that prompts the user to input the
value of a (the coefficient of x2), b (the coefficient of x), and c (the
constant term) and outputs the type of roots of the equation
...
(Hint: Use the function pow from the header file
cmath to calculate the square root
...
)
Write a program that mimics a calculator
...
It should then output the
numbers, the operator, and the result
...
) Some sample outputs follow:
3 + 4 = 7
13 * 5 = 65

10
...


Redo Exercise 9 to handle floating-point numbers
...
)
Redo Programming Exercise 19 of Chapter 2, taking into account that your
parents buy additional savings bonds for you as follows:
a
...


If you do not spend any money to buy savings bonds, then because you
had a summer job, your parents buy savings bonds for you in an
amount equal to 1% of the money you save after paying taxes and
buying clothes, other accessories, and school supplies
...
25 for each dollar you spend to buy savings bonds,

|

243

4

244 |

c
...


Chapter 4: Control Structures I (Selection)

plus money equal to 1% of the money you save after paying taxes and
buying clothes, other accessories, and school supplies
...
40 for each dollar you spend to buy savings
bonds, plus money equal to 2% of the money you save after paying
taxes and buying clothes, other accessories, and school supplies
...

The bank offers two types of accounts: savings and checking
...
If a customer’s balance falls below the
minimum balance, there is a service charge of $10
...
00 for checking accounts
...

b
...

Checking accounts with balances of up to $5,000 more than the
minimum balance receive 3% interest; otherwise, the interest is 5%
...
The program should then
output the account number, account type, current balance, and an appropriate message
...


14
...

The number of lines that can be printed on a paper depends on the paper size,
the point size of each character in a line, whether lines are double-spaced or
single-spaced, the top and bottom margin, and the left and right margins of
the paper
...
Note that 1 inch = 72 points
...
For
example, if the length of the paper is 11 inches and width is 8
...
5 inches
...

b
...

d
...


Premium service:
a
...


17
...
The company offers two types of service: regular and premium
...
The rates are computed as
follows:
Regular service:

16
...
00 plus first 50 minutes are free
...
20 per minute
...
00 plus:

For calls made from 6:00 a
...
to 6:00 p
...
, the first 75 minutes are free;
charges for more than 75 minutes are $0
...

For calls made from 6:00 p
...
to 6:00 a
...
, the first 100 minutes are
free; charges for more than 100 minutes are $0
...


Your program should prompt the user to enter an account number, a
service code (type char), and the number of minutes the service was used
...
Treat any other character as an error
...

For the premium service, the customer may be using the service during the
day and the night
...

Write a program to implement the algorithm that you designed in Exercise
22 of Chapter 1
...
txt
...
Also save the account balance after
withdrawal in the file Ch4_Ex16_Output
...

You have several pictures of different sizes that you would like to frame
...

The frames are available in white and can be ordered in any color the
customer desires
...
The cost of
coloring the frame is $0
...
The cost of a regular frame is $0
...
25 per inch
...
02 per square inch, and the cost
of putting glass on top of the picture is $0
...
The customer
can also choose to put crowns on the corners, which costs $0
...

Write a program that prompts the user to input the following information
and then output the cost of framing the picture:
a
...

c
...


The length and width, in inches, of the picture
The type of the frame
Customer’s choice of color to color the frame
If the user wants to put the crowns, then the number of crowns

4

246 |

18
...


Chapter 4: Control Structures I (Selection)

Samantha and Vikas are looking to buy a house in a new development
...
The builder gave them the base price and the
finished area in square feet of the three models
...
Write a program that accepts as
input the base price and the finished area in square feet of the three models
...

One way to determine how healthy a person is by measuring the body fat
of the person
...
732) + 8
...
140
A3 ¼ waist measurement (at navel) Â 0
...
249
A5 ¼ forearm measurement (at fullest point) Â 0
...
082) + 94
...
15
B ¼ A1 – A2
Body fat ¼ body weight – B
Body fat percentage ¼ body fat  100 / body weight

Write a program to calculate the body fat of a person
...


Learn about repetition (looping) control structures


...


Examine break and continue statements


...


Learn how to avoid bugs by avoiding patches


...
In this chapter, you
learn how repetitions are incorporated in programs
...
From what you have learned
so far, you could proceed as follows (assume that all variables are properly declared):
cin >> num1 >> num2 >> num3 >> num4 >> num5;
sum = num1 + num2 + num3 + num4 + num5;
average = sum / 5;

//read five numbers
//add the numbers
//find the average

But suppose you want to add and average 100, 1000, or more numbers
...
This takes an exorbitant amount of space and time
...

Suppose you want to add the following numbers:
5 3 7 9 4

Consider the following statements, in which sum and num are variables of type int:
1
...
cin >> num;
3
...
Let us execute statements 2 and 3
...
After statement
3, the value of sum is 5
...
After statement 2 (after the programming code reads the
next number):
num = 3

After statement 3:
sum = sum + num = 5 + 3 = 8

At this point, sum contains the sum of the first two numbers
...
After statement 2 (after the code reads the next number):
num = 7

After statement 3:
sum = sum + num = 8 + 7 = 15

Now, sum contains the sum of the first three numbers
...


while Looping (Repetition) Structure

|

249

If you want to add 10 numbers, you can repeat statements 2 and 3 ten times
...
In either case, you do not
have to declare any additional variables, as you did in the first code
...

There are many other situations in which it is necessary to repeat a set of statements
...

C++ has three repetition, or looping, structures that let you repeat statements over and over
until certain conditions are met
...
The next section discusses the first repetition structure, called the while loop
...
One way to repeat a set of statements is to type the set of statements in the
program over and over
...
However, this solution of
repeating a set of statements is impractical, if not impossible
...
As noted earlier, C++ has three repetition, or looping,
structures that allow you to repeat a set of statements until certain conditions are met
...

The general form of the while statement is:
while (expression)
statement

In C++, while is a reserved word
...
The expression acts as a decision maker and is usually a
logical expression
...
Note that the
parentheses around the expression are part of the syntax
...


expression
false

FIGURE 5-1

while loop

true

statement

5

250 |

Chapter 5: Control Structures II (Repetition)

The expression provides an entry condition
...
The loop condition—the expression—is then reevaluated
...
The statement (body of the loop)
continues to execute until the expression is no longer true
...
To avoid an infinite loop, make sure that the loop’s
body contains statement(s) that assure that the exit condition—the expression in the while
statement—will eventually be false
...
)
i = 0;

//Line 1

while (i <= 20)
{
cout << i << " ";
i = i + 5;
}

//Line 2
//Line 3
//Line 4

cout << endl;

Sample Run:
0 5 10 15 20

In Line 1, the variable i is set to 0
...
Because the expression i <= 20 evaluates to true, the body of
the while loop executes next
...
The statement in Line 3 outputs the value of i, which is 0
...
After executing the statements in Lines 3 and 4, the
expression in the while loop (Line 2) is evaluated again
...

This process of evaluating the expression and executing the body of the while loop
continues until the expression, i <= 20 (in Line 2), no longer evaluates to true
...

Note the following from Example 5-1:
a
...

b
...


while Looping (Repetition) Structure

|

251

c
...
If the statement:
i = 0;

(in Line 1) is omitted, the loop may not execute at all
...
)
d
...
For example, consider
the following statements:
i = 0;
while (i <= 20)
{
i = i + 5;
cout << i << " ";
}
cout << endl;

Here, the output is:
5 10 15 20 25

Typically, this would be a semantic error because you rarely want a
condition to be true for i <= 20 and yet produce results for i > 20
...
If you put a semicolon at the end of the while loop, (after the logical
expression), then the action of the while loop is empty or null
...

i = 0;
while (i <= 20);
{
i = i + 5;
cout << i <<
}

" ";

cout << endl;

The statements within the braces do not form the body of the while loop
...
Typically, the expression checks whether a
variable(s), called the loop control variable (LCV), satisfies certain conditions
...
The LCV must be properly initialized before the while loop, and it should

5

252 |

Chapter 5: Control Structures II (Repetition)

eventually make the expression evaluate to false
...
Therefore, typically, while loops
are written in the following form:
//initialize the loop control variable(s)
while (expression) //expression tests the LCV
{

...


...


...

}

For instance, in Example 5-1, the statement in Line 1 initializes the LCV i to 0
...

EXAMPLE 5-2
Consider the following C++ program segment:
i = 20;
while (i < 20)
{
cout << i << " ";
i = i + 5;
}
cout << endl;

//Line 1
//Line 2
//Line 3
//Line 4
//Line 5

It is easy to overlook the difference between this example and Example 5-1
...
Because i is 20, the expression i < 20 in the while statement (Line 2)
evaluates to false
...
Hence, no values are output, and the value of i remains 20
...


Case 1: Counter-Controlled while Loops
Suppose you know exactly how many times certain statements need to be executed
...

In such cases, the while loop assumes the form of a counter-controlled while loop
...
You can set up a counter

while Looping (Repetition) Structure

|

253

(initialized to 0 before the while statement) to track how many items have been read
...
If
counter < N, the body of the while statement executes
...
Thus, inside the body of the
while statement, the value of counter increments after it reads a new item
...


...

counter++;
//update the loop control variable

...


...
The program can prompt you to specify the number of items in the file; an
input statement can read the value; or you can specify the first item in the file as the number
of items in the file, so that you need not remember the number of input values (items)
...
Consider Example 5-3
...
Consider the following
program:
//Program: Counter-Controlled Loop
#include
using namespace std;
int main()
{
int limit;
int number;
int sum;
int counter;

//store the number of data items
//variable to store the number
//variable to store the sum
//loop control variable

cout << "Line 1: Enter the number of "
<< "integers in the list: ";
cin >> limit;
cout << endl;

//Line 1
//Line 2
//Line 3

5

254 |

Chapter 5: Control Structures II (Repetition)

sum = 0;
counter = 0;

//Line 4
//Line 5

cout << "Line 6: Enter " << limit
<< " integers
...
" << endl;

return 0;

//Line 7
//Line 8
//Line 9
//Line 10

//Line 11
//Line 12
//Line 13
//Line 14
//Line 15
//Line 16

}

Sample Run: In this sample run, the user input is shaded
...

8 9 2 3 90 38 56 8 23 89 7 2
Line 11: The sum of the 12 numbers = 335
Line 13: The average = 27

This program works as follows
...
The statement in Line 2 reads the next input line and stores it in the
variable limit
...
The statements
in Lines 4 and 5 initialize the variables sum and counter to 0
...
) The statement in Line 6 prompts the user to input numbers
...
) The while statement in Line 7
checks the value of counter to determine how many items have been read
...
The statement in Line 8
reads the next number and stores it in the variable number
...
The statement in Line 11 outputs the sum of
the numbers; the statements in Lines 12 through 15 output the average
...
In Line 9, after reading a number at
Line 8, the program adds it to the sum of all the numbers scanned before the current number
...
To find the average, divide sum by counter
...

Therefore, before dividing sum by counter, you must check whether or not counter is 0
...

The expression counter < limit in Line 7 evaluates whether counter is less than
limit
...


Case 2: Sentinel-Controlled while Loops
You do not always know how many pieces of data (or entries) need to be read, but you
may know that the last entry is a special value, called a sentinel
...
If this item does not equal the sentinel, the
body of the while statement executes
...
Such a while loop is called a sentinelcontrolled while loop
...


...

cin >> variable;
//update the loop control variable

...


...
Suppose the number -999 marks the end of the
data
...

//Program:

Sentinel-Controlled Loop

#include
using namespace std;
const int SENTINEL = -999;
int main()
{
int number;
int sum = 0;
int count = 0;

//variable to store the number
//variable to store the sum
//variable to store the total
//numbers read

5

256 |

Chapter 5: Control Structures II (Repetition)

cout << "Line 1: Enter integers ending with "
<< SENTINEL << endl;
cin >> number;
while (number != SENTINEL)
{
sum = sum + number;
count++;
cin >> number;
}
cout << "Line 7: The sum of the " << count
<< " numbers is " << sum << endl;
if (count != 0)
cout << "Line 9: The average is "
<< sum / count << endl;
else
cout << "Line 11: No input
...

Line 1:
34 23 9
Line 7:
Line 9:

Enter integers
45 78 0 77 8 3
The sum of the
The average is

ending with -999
5 -999
10 numbers is 282
28

This program works as follows
...
The statement in Line 2 reads the first number and stores it
in number
...
(The variable number is the loop control variable
...
The statement in Line 4 updates the
value of sum by adding number to it
...
The
statements in Lines 4 through 6 repeat until the program reads the SENTINEL
...

Notice that the statement in Line 2 initializes the LCV number
...

The statement in Line 6 reinitializes the LCV number
...
In this example, the
user is prompted to enter the value to be processed
...


while Looping (Repetition) Structure

|

257

EXAMPLE 5-5

Telephone Digits
The following program reads the letter codes A to Z and prints the corresponding
telephone digit
...
To stop the
program, the user is prompted for the sentinel, which is #
...
else, switch, and the while loop are nested
...
This
// program converts uppercase letters to their corresponding
// telephone digits
...
" << endl;

//Line 2

cout << "To stop the program enter #
...
" << endl;

//Line 27
//Line 28

"\nEnter another uppercase "
"letter to find its "
"corresponding telephone digit
...
"
endl;

cout << "Enter a letter: ";
cin >> letter;
cout << endl;
}//end while
}

return 0;

//Line 29
//Line 30
//Line 31
//Line 32
//Line 33

while Looping (Repetition) Structure

|

259

Sample Run: In this sample run, the user input is shaded
...

To stop the program enter #
...

To stop the program enter #
...

To stop the program enter #
...
The statements in Lines 2 and 3 tell the user what to do
...
The while loop in Line 7 checks that the letter is #
...
The statement in
Line 8 outputs the letter entered by the user
...
The statement part of the if statement is the
switch statement (Line 11)
...
The
statements in Lines 12 through 26 determine the corresponding telephone digit
...
The statement in Line 31 prompts the user to enter a letter; the
statement in Line 32 reads and stores that letter into the variable letter
...
) After the statement in
Line 33 (at the end of the while loop) executes, the control goes back to the top of the while
loop and the same process begins again
...

Notice that in this program, the variable letter is the loop control variable
...
The
expression in Line 7 checks whether letter is #
...
(See Programming Exercise 3 at the end of this chapter
...
Suppose
found is a bool variable
...


...

if (expression)
found = true; //update the loop control variable

...


...

Example 5-6 further illustrates the use of a flag-controlled while loop
...
The program then prompts the user to guess the number
...
Otherwise, the
program checks whether the guessed number is less than the random number
...
Guess again!’’; otherwise, the
program outputs the message ‘‘Your guess is higher than the number
...
The
program then prompts the user to enter another number
...

To generate a random number, you can use the function rand of the header file
cstdlib
...
Therefore, the statement:
cout << rand() << ", " << rand() << endl;

will output two numbers that appear to be random
...
This is because the function
rand uses an algorithm that produces the same sequence of random numbers each time the
program is executed on the same system
...
The
function srand takes as input an unsigned int, which acts as the seed for the algorithm
...
To specify a different seed, you can
use the function time of the header file ctime, which returns the number of seconds
elapsed since January 1, 1970
...
Note how the function time is used
...

The program uses the bool variable isGuessed to control the loop
...
It is set to true when the user guesses the correct
number
...

//Number guessing game
...
" << endl;
//Line
isGuessed = true;
//Line
}
//Line
else if (guess < num)
//Line
cout << "Your guess is lower than the "
<< "number
...
\n Guess again!"
<< endl;
} //end while

//Line 16
//Line 17
//Line 18

return 0;
}

Sample Run: In this sample run, the user input is shaded
...

Guess again!
Enter an integer greater than or equal to 0 and less than 100: 20
Your guess is lower than the number
...

Guess again!
Enter an integer greater than or equal to 0 and less than 100: 28
Your guess is lower than the number
...


The preceding program works as follows: The statement in Line 2 creates an integer
greater than or equal to 0 and less than 100 and stores this number in the variable num
...
The expression in
the while loop at Line 4 evaluates the expression !isGuessed
...

The statement in Line 6 prompts the user to enter an integer greater than or equal to 0
and less than 100
...
The expression in the if statement in Line 9 determines whether
the value of guess is the same as num, that is, if the user guessed the number correctly
...


The statement in Line 12 sets the variable isGuessed to true
...
Because done is true, !isGuessed is false and the while loop
terminates
...


while Looping (Repetition) Structure

|

263

Case 4: EOF-Controlled while Loops
If the data file is frequently altered (for example, if data is frequently added or deleted), it’s
best not to read the data with a sentinel value
...
Also, it can be difficult at times to select a good sentinel value
...

Until now, we have used an input stream variable, such as cin, and the extraction
operator, >>, to read and store data into variables
...
If the program has reached the end of the input data, the input stream
variable returns the logical value false
...
If the program reads any faulty data (such as a char value into an int
variable), the input stream enters the fail state
...
Unfortunately, the computer does
not halt the program or give any error messages
...
In
this case, the input stream variable returns the value false
...
In cases other than (1) and (2), the input stream variable returns the
logical value true
...
Because the input stream variable returns the
logical value true or false, in a while loop, it can be considered a logical expression
...


...

cin >> variable; //update the loop control variable

...


...


eof Function
In addition to checking the value of an input stream variable, such as cin, to determine
whether the end of the file has been reached, C++ provides a function that you can use
with an input stream variable to determine the end-of-file status
...
Like the I/O functions—such as get, ignore, and peek, discussed in Chapter 3—
the function eof is a member of the data type istream
...
eof()

in which istreamVar is an input stream variable, such as cin
...
Consider the expression:
infile
...
The value of this expression is true if the program has
read past the end of the input file, infile; otherwise, the value of this expression is false
...
The earlier method of determining the end-of-file status works
best if the input consists of numeric data
...
open("inputDat
...

infile
...
eof())
{
cout << ch;
infile
...
eof()

is false and so the expression:
!infile
...
When the program reads past the end of the input file,
the expression:
infile
...
eof()

in the while statement becomes false and the loop terminates
...
In the UNIX environment, the end-of-file marker is
entered using Ctr+d (hold the Ctrl key and press d)
...
Each line in the file consists of a student name followed by
the test score
...
The program also needs to output the average test score for
the class
...
The program outputs each student's
name followed by the test score followed by the grade
...


#include
#include
#include
#include






using namespace std;

//Line
//Line
//Line
//Line

1
2
3
4

//Line 5

5

266 |

Chapter 5: Control Structures II (Repetition)

int main()
{
//Declare variables to manipulate data
string firstName;
string lastName;
double testScore;
char grade = ' ';
double sum = 0;
int count = 0;

//Line 6
//Line 7
//Line
//Line
//Line
//Line
//Line
//Line

8
9
10
11
12
13

//Declare stream variables
ifstream inFile;
ofstream outFile;

//Line 14
//Line 15

//Open input file
inFile
...
txt");

//Line 16

if (!inFile)
{
cout << "Cannot open input file
...
open("Ch5_stData
...
" << endl;
}//end switch

//Line 53
//Line 54
//Line 55

outFile <<
<<
<<
<<

//Line 56

left << setw(12) << firstName
setw(12) << lastName
right << setw(4) << testScore
setw(2) << grade << endl;

49
50
51
52

5

inFile >> firstName >> lastName; //read the name Line 57
inFile >> testScore;
//read the test score Line 58
}//end while
//Line 59
outFile << endl;

//Line 60

if (count != 0)
outFile << "Class Average: " << sum / count
<else
outFile << "No data
...
close();
outFile
...
5
Randy Brown 85
...
5
Samir Mann 73
Samantha McCoy 88
...
00

89
...
50
85
...
50
73
...
50

B
A
B
C
C
B

268 |

Chapter 5: Control Structures II (Repetition)

The preceding program works as follows
...
The statement in Lines 14 and 15 declares
inFile to be an ifstream variable and outFile to be an ofstream variable
...
If the input file does
not exist, the statements in Lines 17 to 21 output an appropriate message and terminate
the program
...

The statement in Line 23 sets the output of floating-point numbers to two decimal places
in a fixed form with trailing zeros
...
Specifically, the statement in Lines 24 and 57 reads the first and last
name; the statement in Lines 25 and 58 reads the test score
...
(After reading all the data, the value of sum stores the sum of all
the test scores
...
(The variable
count stores the number of students in the class
...
The
statement in Line 56 outputs a student’s first name, last name, test score, and grade
...
else statement in Lines 61 to 64 outputs the class average and the statements
in Lines 65 and 66 close the files
...


More on Expressions in while Statements
In the examples of the previous sections, the expression in the while statement is quite
simple
...
However, there
are situations when the expression in the while statement may be more complex
...
However, the program gives as many tries as the user
needs to guess the number
...
If the user does not guess the number correctly within five tries, then
the program outputs the random number generated by the program as well as a message
that you have lost the game
...
You guessed the correct number
...
\n"
<< "Guess again!" << endl;
else
cout << "Your guess is higher than the number
...

if (!isGuessed)
cout << "You lose! The correct number is " << num << endl;

Programming Exercise 16 at the end of this chapter asks you to write a complete C++
program to implement the Number Guessing Game in which the user has, at most, five
tries to guess the number
...
The main objective of a while loop is to repeat certain statement(s) until
certain conditions are met
...
Recall that in C++, while loops are
used when a certain statement(s) must be executed repeatedly until certain conditions are
met
...

Consider the following sequence of numbers:
1, 1, 2, 3, 5, 8, 13, 21, 34,
...


5

270 |

Chapter 5: Control Structures II (Repetition)

Such a sequence is called a Fibonacci sequence
...
However, given any first two numbers, using this process, you can
determine the nth number, an,n >= 3, of the sequence
...
Suppose a2 = 6 and a1 = 3
...

Input
Output
PROBLEM
ANALYSIS
AND
ALGORITHM
DESIGN

The first two Fibonacci numbers and the desired Fibonacci number
...


To find, say, the tenth Fibonacci number of a sequence, you must first find a9 and a8,
which requires you to find a7 and a6, and so on
...
, a9
...
Get the first two Fibonacci numbers
...
Get the desired Fibonacci number
...

3
...

4
...

5
...

Note that the program assumes that the first number of the Fibonacci sequence is less
than or equal to the second number of the Fibonacci sequence, and both numbers are
nonnegative
...
(See Programming Exercise 12 at the end of this chapter
...
The number of
times that Step 2 of the algorithm repeats depends on the position of the Fibonacci
number you are calculating
...
(Remember—the user gives
the first two numbers of the Fibonacci sequence
...
You also need a variable to track
the number of times Step 3 has executed, the loop control variable
...
To calculate the fourth Fibonacci number, add the value
of the second Fibonacci number (that is, previous2) and the value of the third Fibonacci
number (that is, current)
...
Instead of declaring additional variables, which
could be too many, after calculating a Fibonacci number to determine the next Fibonacci
number, current becomes previous2 and previous2 becomes previous1
...

This process is repeated until the desired Fibonacci number is calculated
...
From the preceding discussion, it follows that you need five variables
...
Prompt the user for the first two numbers—that is, previous1 and
previous2
...
Read (input) the first two numbers into previous1 and previous2
...
Output the first two Fibonacci numbers
...
)
4
...

5
...

6
...
if (nthFibonacci == 1)
the desired Fibonacci number is the first Fibonacci number
...

b
...

Copy the value of previous2 into current
...
else calculate the desired Fibonacci number as follows:
Because you already know the first two Fibonacci numbers of
the sequence, start by determining the third Fibonacci number
...
1
...
2
...

Calculate the next Fibonacci number, as follows:

c
...

c
...

c
...


Assign the value of previous2 to previous1
...

Increment counter
...
2 through c
...

The following while loop executes Steps c
...
5 and determines the
nth Fibonacci number
...
Output the nthFibonacci number, which is current
...
S
...

//*************************************************************
#include
using namespace std;
int main()
{
int
int
int
int
int

//Declare variables
previous1;
previous2;
current;
counter;
nthFibonacci;

cout << "Enter the first two Fibonacci "
<< "numbers: ";
//Step 1
cin >> previous1 >> previous2;
//Step 2
cout << endl;
cout << "The first two Fibonacci numbers are "
<< previous1 << " and " << previous2
<< endl;
//Step 3
cout << "Enter the position of the desired "
<< "Fibonacci number: ";
//Step 4
cin >> nthFibonacci;
//Step 5
cout << endl;
if (nthFibonacci == 1)
current = previous1;

//Step 6
...
c
...
c
...
b
//Step 6
...
c
...
c
...
c
...
c
...
c
...

Sample Run 1:
Enter the first two Fibonacci numbers: 12 16
The first two Fibonacci numbers are 12 and 16
Enter the position of the desired Fibonacci number: 10
The Fibonacci number at position 10 is 796

Sample Run 2:
Enter the first two Fibonacci numbers: 1 1
The first two Fibonacci numbers are 1 and 1
Enter the position of the desired Fibonacci number: 15
The Fibonacci number at position 15 is 610

for Looping (Repetition) Structure
The while loop discussed in the previous section is general enough to implement
most forms of repetitions
...
Its primary purpose is to simplify the writing of counter-controlled
loops
...


274 |

Chapter 5: Control Structures II (Repetition)

The general form of the for statement is:
for (initial statement; loop condition; update statement)
statement

The initial statement, loop condition, and update statement (called for
loop control statements) enclosed within the parentheses control the body (statement)
of the for statement
...


initial
statement

loop
condition

true

statement

update
statement

false

FIGURE 5-2

for loop

The for loop executes as follows:
1
...

2
...
If the loop condition evaluates
to true:
i
...

ii
...

3
...

The initial statement usually initializes a variable (called the for loop control, or
for indexed, variable)
...

As the name implies, the initial statement in the for loop is the first statement to
execute; it executes only once
...
Next, the loop
condition, i < 10, is evaluated
...
The update statement, i++, then executes, which sets the value of i to 1
...
When i
becomes 10, the loop condition evaluates to false, the for loop terminates, and
the statement following the for loop executes
...

The following examples further illustrate how a for loop executes
...
The following for loop outputs Hello! and a star (on separate lines)
five times:
for (i = 1; i <= 5; i++)
{
cout << "Hello!" << endl;
cout << "* << endl;
"
}

2
...
Note that
the for loop controls only the first output statement because the two
output statements are not made into a compound statement
...
After the for loop executes, the second output
statement executes only once
...


5

276 |

Chapter 5: Control Structures II (Repetition)

EXAMPLE 5-11
The following for loop executes five empty statements:
for (i = 0; i < 5; i++);
cout << "* << endl;
"

//Line 1
//Line 2

The semicolon at the end of the for statement (before the output statement, Line 1)
terminates the for loop
...


The preceding examples show that care is required in getting a for loop to perform the
desired action
...

The update expression, when executed, changes the value of the
loop control variable (initialized by the initial expression), which eventually sets the value of the loop condition to false
...

C++ allows you to use fractional values for loop control variables of the
double type (or any real data type)
...

A semicolon at the end of the for statement (just before the body of the
loop) is a semantic error
...

In the for statement, if the loop condition is omitted, it is assumed
to be true
...
The following is a legal for loop:
for (;;)
cout << "Hello" << endl;

This is an infinite for loop, continuously printing the word Hello
...

EXAMPLE 5-12
You can count backward using a for loop if the for loop control expressions are set correctly
...
After each iteration of the loop, i is
decremented by 1
...


EXAMPLE 5-13
You can increment (or decrement) the loop control variable by any fixed number
...
This for loop outputs the first 10 positive odd integers
...

1
...
Because initially the loop
condition (i <= 9) is false, nothing happens
...
Consider the following for loop:
for (i = 9; i >= 10; i--)
cout << i << " ";
cout << endl;

In this for loop, the initial statement sets i to 9
...

3
...
The loop condition (i <= 10)
evaluates to true, so the output statement in Line 2 executes, which outputs 10
...
Now the loop condition evaluates to false and the for loop terminates
...

4
...
The semicolon at the
end of the for statement terminates the for loop; the action of the for loop is thus
empty
...

5
...
This is an infinite loop
...

Consider the following program code, in which i, newNum, sum, and average are
int variables
...
The variable
sum is initialized to 0 before the for loop
...


for Looping (Repetition) Structure

|

279

The syntax of the for loop, which is:
for (initial expression; logical expression; update expression)

statement
is functionally equivalent to the following while statement:
initial expression
while (expression)
{
statement
update expression
}
For example, the following for and while loops are equivalent:
for (int i = 0; i < 10; i++)
cout << i << " ";
cout << endl;

5

int i = 0;
while (i < 10)
{
cout << i <<
i++;

" ";

}
cout << endl;
If the number of iterations of a loop is known or can be determined in advance, typically
programmers use a for loop
...
You can replace the while
loop with an equivalent for loop as follows:
for (counter = 3; counter <= nthFibonacci; counter++)
{
current = previous2 + previous1;
previous1 = previous2;
previous2 = current;
counter++;
}//end for

The complete program listing of the program that uses a for loop to determine the
desired Fibonacci number is given at the Web site accompanying this book
...
cpp
...


280 |

Chapter 5: Control Structures II (Repetition)

EXAMPLE 5-17
The following C++ program finds the sum of the first n positive integers
...

#include
using namespace std;
int main()
{
int counter;
int sum;
int n;

//loop control variable
//variable to store the sum of numbers
//variable to store the number of
//first positive integers to be added

cout << "Line 1: Enter the number of positive "
<< "integers to be added: ";
//Line 1
cin >> n;
//Line 2
sum = 0;
//Line 3
cout << endl;
//Line 4
for (counter = 1; counter <= n; counter++)
sum = sum + counter;
cout << "Line 7: The sum of the first " << n
<< " positive integers is " << sum
<< endl;
}

//Line 5
//Line 6

//Line 7

return 0;

Sample Run: In this sample run, the user input is shaded
...

The statement in Line 2 stores the number entered by the user in n, and the statement in Line
3 initializes sum to 0
...
In the for loop, counter is
initialized to 1 and is incremented by 1 after each iteration of the loop
...
Each time through the loop, the value of counter is added to sum
...
Therefore, after the for loop executes, sum contains
the sum of the first n values, which in the sample run is 100 positive integers
...
The
following programming example demonstrates a simple instance of nesting
...


Programming Example: Classifying Numbers

PROGRAMMING EXAMPLE:

|

281

Classifying Numbers

This program reads a given set of integers and then prints the number of odd and
even integers
...

The program reads 20 integers, but you can easily modify it to read any set of
numbers
...

Input

20 integers—positive, negative, or zeros
...


5
PROBLEM
ANALYSIS
AND
ALGORITHM
DESIGN

After reading a number, you need to check whether it is even or odd
...
Divide number by 2 and check the remainder
...
Increment the even count and then check whether
number is 0
...
If the remainder is not 0, increment
the odd count
...

Suppose that number is odd
...
If number is even, dividing by 2 gives
the remainder 0 whether number is positive or negative
...
For example:
6 % 2 = 0; -4 % 2 = 0; -7 % 2 = -1; 15 % 2 = 1

Repeat the preceding process of analyzing a number for each number in the list
...
For each number in the list:
a
...

b
...

c
...

2
...

Variables

Because you want to count the number of zeros, even numbers, and odd numbers,
you need three variables of type int—say, zeros, evens, and odds—to track the
counts
...

Therefore, you need the following variables in the program:

282 |

int
int
int
int
int

Chapter 5: Control Structures II (Repetition)

counter;
number;
zeros;
evens;
odds;

//loop control variable
//variable to store the
//variable to store the
//variable to store the
//variable to store the

number read
zero count
even count
odd count

Clearly, you must initialize the variables zeros, evens, and odds to zero
...

MAIN
ALGORITHM

1
...

2
...

3
...
Read the number
...
Output the number (echo input)
...
If the number is even:
{

i
...

ii
...

}
otherwise
Increment the odd count
...
Print the results
...
It will be
much easier for you to then write the instructions in C++
...
Initialize the variables
...

2
...

3
...
In pseudocode, this step is written as follows:
for (counter = 1; counter <= 20; counter++)
{
read the number;
output number;
switch (number % 2)
// check the remainder
{
case 0:
increment even count;
if (number == 0)
increment zero count;
break;

Programming Example: Classifying Numbers

|

283

case 1:
case –1:
increment odd count;
}//end switch
}//end for

4
...
Output the value of the variables zeros, evens,
and odds
...
S
...

// The program also counts the number of zeros
...
"
<< endl;

//Step 2

cout << "The numbers you entered are:" << endl;
for (counter = 1; counter <= N; counter++)
{
cin >> number;
cout << number << " ";
//Step 3c
switch (number % 2)

//Step 3
//Step 3a
//Step 3b

5

284 |

Chapter 5: Control Structures II (Repetition)

{
case 0:
evens++;
if (number == 0)
zeros++;
break;
case 1:
case -1:
odds++;
} //end switch
} //end for loop
cout << endl;
cout <<
<<
<<
cout <<
<<
}

//Step 4
"There are " << evens << " evens, "
"which includes " << zeros << " zeros
...

Please enter 20 integers, positive, negative, or zeros
...

The number of odd numbers is: 7

We recommend that you do a walk-through of this program using the above sample
input
...
while Looping (Repetition) Structure
This section describes the third type of looping or repetition structure, called a do
...
The general form of a do
...
If it is a
compound statement, enclose it between braces
...
while loop
...
while Looping (Repetition) Structure

|

285

statement

expression

true

false

5

FIGURE 5-3

do
...

The statement executes first, and then the expression is evaluated
...
As long as the expression in a
do
...
To avoid an infinite loop, you
must, once again, make sure that the loop body contains a statement that ultimately makes
the expression false and assures that it exits properly
...


286 |

Chapter 5: Control Structures II (Repetition)

In a while and for loop, the loop condition is evaluated before executing the body of
the loop
...
On the other hand,
the loop condition in a do
...
Therefore, do
...

Because the while and for loops both have entry conditions, these loops may never
activate
...
while loop, on the other hand, has an exit condition and therefore
always executes the statement at least once
...


i = 11;
while (i <= 10)
{
cout << i << " ";
i = i + 5;
}
cout << endl;

b
...
In (b), the do
...

A do
...
Suppose that a program prompts a user
to enter a test score, which must be greater than or equal to 0 and less than or equal to 50
...
The following do
...
while Looping (Repetition) Structure

|

287

EXAMPLE 5-20

Divisibility Test by 3 and 9
Suppose that m and n are integers and m is nonzero
...

Let n ¼ akak-1ak-2
...
Let s = ak + ak-1 + ak-2 + Á Á Á + a1 + a0 be the sum of the
digits of n
...
In other words,
an integer is divisible by 3 and 9 if and only if the sum of its digits is divisible by 3 and 9
...
Then s = 2 + 7 + 1 + 9 + 3 + 2 + 5 + 7 = 36
...

Next, we write a program that determines whether a positive integer is divisible by 3 and 9
by first finding the sum of its digits and then checking whether the sum is divisible by 3 and 9
...
Consider the number 951372
...
Also note that 951372 / 10 = 95137; that is, when the number is
divided by 10, it removes the last digit
...
Of course, we need to add the extracted digits
...
We
thus have the following algorithm to find the sum of the digits:
sum = 0;
do
{
sum = sum + num % 10; //extract the last digit
//and add it to sum
num = num / 10;
//remove the last digit

}
while (num > 0);

Using this algorithm, we can write the following program that uses a do
...

//Program: Divisibility test by 3 and 9
#include
using namespace std;
int main()
{
int num, temp, sum;
cout << "Enter a positive integer: ";
cin >> num;

5

288 |

Chapter 5: Control Structures II (Repetition)

cout << endl;
temp = num;
sum = 0;
do
{
sum = sum + num % 10; //extract the last digit
//and add it to sum
num = num / 10;
//remove the last digit

}
while (num > 0);

cout << "The sum of the digits = " << sum << endl;
if (sum % 3 == 0)
cout << temp << " is divisible by 3" << endl;
else
cout << temp << " is not divisible by 3" << endl;

}

if (sum % 9 == 0)
cout << temp << " is divisible by 9" << endl;
else
cout << temp << " is not divisible by 9" << endl;

Sample Run: In these sample runs, the user input is shaded
...
If you know, or the program can determine in
advance, the number of repetitions needed, the for loop is the correct choice
...
If you do not know, and
the program cannot determine in advance the number of repetitions needed, and it is at
least one, the do
...


break and continue Statements
The break statement, when executed in a switch structure, provides an immediate
exit from the switch structure
...
while loops
...
The break statement
is typically used for two purposes:



To exit early from a loop
...


After the break statement executes, the program continues to execute with the first
statement after the structure
...
The following C++ code segment helps illustrate this idea
...
)
sum = 0;
isNegative = false;
cin >> num;
while (cin && !isNegative)
{
if (num < 0)
//if num is negative, terminate the loop
//after this iteration
{
cout << "Negative number found in the data
...
If the data set
contains a negative number, the loop terminates with an appropriate error message
...
The
variable isNegative is initialized to false before the while loop
...
If num is negative, an error message appears on
the screen and isNegative is set to true
...
(Note that because isNegative is true, !isNegative is false
...
" << endl;
break;
}

}

sum = sum + num;
cin >> num;

In this form of the while loop, when a negative number is found, the expression in the
if statement evaluates to true; after printing an appropriate message, the break
statement terminates the loop
...
)
The break statement is an effective way to avoid extra variables to control a loop and
produce an elegant code
...
An excessive use of these statements in a loop will produce spaghetti-code
(loops with many exit conditions) that can be very hard to understand and manage
...
If you’re not sure, don’t
use break statements
...
while structures
...
In a while and do
...
In a for structure, the update statement is executed after the continue
statement, and then the loop condition (that is, the loop-continue test) executes
...
If you want to discard the negative number and read the next number rather than
terminate the loop, replace the break statement with the continue statement, as shown
in the following example:
sum = 0;
cin >> num;

Nested Control Structures |

291

while (cin)
{
if (num < 0)
{
cout << "Negative number found in the data
...
The execution of a continue statement, however, is where the
while and do
...
When the continue
statement is executed in a while or a do
...
In a for structure, the update statement always executes
...

EXAMPLE 5-21
Suppose you want to create the following pattern:
*
**
***
****
*****

Clearly, you want to print five lines of stars
...
Because five lines will be printed, start with the
following for statement:
for (i = 1; i <= 5; i++)

The value of i in the first iteration is 1, in the second iteration it is 2, and so on
...
A little more thought produces the
following code:
for (i = 1; i <= 5; i++)
{
for (j = 1; j <= i; j++)
cout << "*
";
cout << endl;
}

//Line
//Line
//Line
//Line
//Line
//Line

1
2
3
4
5
6

5

292 |

Chapter 5: Control Structures II (Repetition)

A walk-through of this code shows that the for loop in Line 1 starts with i = 1
...
Then i becomes 2, the inner for loop outputs two stars, and the output
statement in Line 5 moves the insertion point to the next line, and so on
...

What pattern does this code produce if you replace the for statement in Line 1 with the
following?
for (i = 5; i >= 1; i--)

EXAMPLE 5-22
Suppose you want to create the following multiplication table:
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
5 10 15 20

5
10
15
20
25

6
12
18
24
30

7
14
21
28
35

8
16
24
32
40

9
18
27
36
45

10
20
30
40
50

The multiplication table has five lines
...
Notice that the first line starts with
1 and when this line is printed, i is 1
...
If i is 1, i * 1 is 1; if i is 2, i * 2 is 2;
and so on
...
That is, consider the following for loop:
for (j = 1; j <= 10; j++)
cout << setw(3) << i * j;

Let us take a look at this for loop
...
Then we are printing the first line of
the multiplication table
...
Similarly, if i is
2, we are printing the second line of the multiplication table
...

A little more thought produces the following nested loops to output the desired grid:
for (i = 1; i <= 5; i++)
{
for (j = 1; j <= 10; j++)
cout << setw(3) << i * j;
cout << endl;
}

//Line
//Line
//Line
//Line
//Line
//Line

1
2
3
4
5
6

Nested Control Structures |

293

EXAMPLE 5-23
Consider the following data:
65
87
23
62

78
34
99
35

65
89
98
78

89
99
97
99

25
26
26
12

98
78
78
93

-999
64 34 -999
100 63 87 23 -999
19 -999

The number -999 at the end of each line acts as a
of the data
...
Moreover, assume that this data is
Exp_5_23
...
We assume that the input file has
stream variable infile
...
So we can use a for loop or a countercontrolled while loop to process each line of data
...
It follows that the while loop takes the following form:
counter = 0;
while (counter < 4)
{
//process the line

}

//Line
//Line
//Line
//Line

1
2
3
4

//output the sum
counter++;

Let us now concentrate on processing a line
...
For example, the first line has six numbers, the second line has eight numbers, and
so on
...
(Remember how a sentinel-controlled loop
works
...
The Boolean expression num != -999 in Line 6 checks
whether the number is -999
...

The statement in Line 8 updates the value of sum; the statement in Line 9 reads and stores the
next number into num
...

It now follows that the nested loop to process the data is as follows
...
)

5

294 |

Chapter 5: Control Structures II (Repetition)

counter = 0;
while (counter < 4)
{
sum = 0;
infile >> num;
while (num != -999)
{
sum = sum + num;
infile >> num;
}

}

cout << "Line " << counter + 1
<< ": Sum = " << sum << endl;
counter++;

//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line

1
2
3
4
5
6
7
8
9
10

//Line 11
//Line 12
//Line 13

EXAMPLE 5-24
Suppose that we want to process data similar to the data in Example 5-23, but the input
file is of an unspecified length
...

Because we do not know the number of input lines, we must use an EOF-controlled
while loop to process the data
...
(Assume that
all variables are properly declared and the input file has been opened using the input file
stream variable infile
...
The only reason to do so is
because we want to print the line number with the sum of each line
...


98 -999

78 64 34 -999

78 100 63 87 23 -999

5
93 19 -999

The number -999 at the end of a line acts as a sentinel and therefore is not part of the data
...

For each candidate, the data is in the following form:
ID
Name
Votes

The objective is to find the total number of votes received by the candidate
...
txt of unknown size
...

Because the input file is of an unspecified length, we use an EOF-controlled while loop
...

To read the ID, we use the extraction operator >>; to read the name, we use the stream
function getline
...
Therefore, after reading the ID, the reading
marker is after the ID and before the newline character (of the line containing the ID)
...
Therefore, if we read the name
immediately after reading the ID, then what is stored in the variable name is the newline
character (after the ID)
...

Therefore, the statements to read the ID and name are as follows:
infile >> ID;
infile
...
) The general loop to process the data is:
//Line
//Line
//Line
//Line
//Line

infile >> ID;
while (infile)
{
infile
...
get(ch);
getline(infile, name);
sum = 0;
infile >> num;
while (num != -999)
{
sum = sum + num;
infile >> num;
}
cout << "Name: " << name
<< ", Votes: " << sum
<< endl;
}

infile >> ID;

//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line
//Line

1
2
3
4
5
6
7; read the first number
8
9
10; update sum
11; read the next number

//Line 12

//Line 13; begin processing the next line

Avoiding Bugs by Avoiding Patches
Debugging sections in the previous chapters illustrated how to debug syntax and logical
errors, and how to avoid partially understood concepts
...
A software patch is a piece of code written on top
of an existing piece of code and intended to fix a bug in the original code
...
txt
...
For each line, output the
numbers together with their sum
...
open("Ch5_LoopWithBugsData
...
Also, the number 56 in the last line
repeats four times
...
Some
programmers, especially some beginners, address the symptom of the problem by adding
a software patch
...


5

298 |

Chapter 5: Control Structures II (Repetition)

A beginning programmer might fix the code by adding a software patch as shown in the
following modified program
...
open("Ch5_LoopWithBugsData
...

As we can see, the programmer merely observed the symptom and addressed the problem by
adding a software patch
...
It appears that
the programmer does not have a good grasp of why the earlier program produced four lines
rather than three
...
The programmer must resolve why the program produced four lines
...
The values assigned to loop control variable i are 1, 2, 3, and 4
...
(In an ‘‘off-by-one problem,’’ either the loop executes
one too many or one too few times
...
For example, we can rewrite the loops as follows:
for (i = 1; i <= 3; i++)
{
sum = 0;
for (j = 1; j <= 4; j++)
{
infile >> num;
cout << num << " ";
;
sum = sum + num;
}
cout << "sum = " << sum << endl;
}

This code fixes the original problem without using a software patch
...
The complete modified program is available at the Web site
accompanying this book and is named Ch5_LoopWithBugsCorrectedProgram
...


Debugging Loops
As we have seen in the earlier debugging sections, no matter how careful a program is
designed and coded, errors are likely to occur
...
However, if there are logical errors, we must carefully look at the code or
even maybe at the design and try to find the errors
...

Once an algorithm is written, the next step is to verify that it works properly
...
Typically, loops are harder to debug
...
A loop invariant is a set of statements that
remains true each time the loop body is executed
...
Then p && q remains true before each iteration of the
loop and p && not(q) is true after the loop terminates
...
However, you can learn about loop invariants in the book:
Discrete Mathematical Structures: Theory and Applications, D
...
Malik and M
...
Sen, Course
Technology, 2004
...

As discussed in the previous section, the most common error associated with loops is offby-one
...
Check the logical expression carefully
and see if you have reversed an inequality, an assignment statement symbol appears in place
of the equality operator, or && appears in place of ||
...

The debugging sections in this book are designed to help you understand the debugging
process
...
If your
program is very bad, do not debug
...


QUICK REVIEW
1
...


C++ has three looping (repetition) structures: while, for, and
do
...

The syntax of the while statement is:
while (expression)
statement

3
...


5
...

7
...


9
...

11
...


13
...

15
...

In the while statement, the parentheses around the expression (the
decision maker) are important; they mark the beginning and end of the
expression
...

The body of the while loop must contain a statement that eventually sets
the expression to false
...

In a counter-controlled while loop, you must initialize the counter before
the loop, and the body of the loop must contain a statement that changes
the value of the counter variable
...
The
sentinel must be similar to, yet differ from, all the data items
...
The while loop continues to execute until the sentinel is read
...

In the Windows console environment, the end-of-file marker is entered using
Ctrl+z (hold the Ctrl key and press z)
...

A for loop simplifies the writing of a counter-controlled while loop
...

The syntax of the for loop is:
for (initialize statement; loop condition; update statement)
statement

statement is called the body of the for loop
...

17
...
In this case, the action of the for loop is empty
...
while statement is:
do
statement
while (expression);

18
...

20
...

22
...


statement is called the body of the do
...

Both while and for loops are called pretest loops
...
while loop is
called a posttest loop
...
while loop
always executes at least once
...

Executing a continue statement in the body of a loop skips the loop’s
remaining statements and proceeds with the next iteration
...
while loop,
the expression update statement in the body of the loop may not execute
...


EXERCISES
1
...

a
...

c
...


In a counter-controlled while loop, it is not necessary to initialize the
loop control variable
...

In an infinite while loop, the while expression (the decision maker) is
initially false, but after the first iteration it is always true
...


f
...


terminates if j > 10
...

A loop is a control structure that causes certain statements to execute
over and over
...


5

302 |

h
...


Chapter 5: Control Structures II (Repetition)

When a while loop terminates, the control first goes back to the
statement just before the while statement, and then the control goes
to the statement immediately following the while loop
...


What is the output of the following C++ code?
int num = 5;
while (num > 5)
num = num + 2;
cout << num << endl;

4
...


When does the following while loop terminate?
ch = 'D';
while ('A' <= ch && ch <= 'Z')
ch = static_cast(static_cast(ch) + 1);

6
...
What is the output of the
following code? Assume all variables are properly declared
...


Suppose that the input is 38 35 71 14 -1
...

cin >> sum;
cin >> num;
while (num != -1)

Exercises

|

303

{
sum = sum + num;
cin >> num;

}
cout << "Sum = " << sum << endl;
8
...
What is the output of the
following code? Assume all variables are properly declared
...


Suppose that the input is 38 35 71 14 -1
...

sum = 0;
cin >> num;
while (num != -1)
{
sum = sum + num;
cin >> num;
}
cout << "Sum = " << sum << endl;

10
...

sum = 0;
while (count < 20)
cin >> num;
sum = sum + num;
count++;

11
...


return 0;

Suppose that the input is:
58

23

46

75

98

150

12

176

145 -999

What is the output of the following program?
#include
using namespace std;
int main()
{
int num;
cin >> num;
while (num != -999)
{
cout << num % 25 << "
cin >> num;
}

";

cout << endl;
}
13
...
It asks the user if he/she would like to run the program
...
After adding the
numbers and displaying the results, it again asks the user if he/she would
like to add more numbers
...
Correct the
program so that it works properly
...
" << endl;
cout << "Would you like to run the program: (Y/y) ";
cin >> response;
cout << endl;

Exercises

|

305

cout << fixed << showpoint << setprecision(2);
while (response == 'Y' && response == 'y')
{
cout << "Enter two numbers: ";
cin >> num1 >> num2;
cout << endl;
cout << num1 << " + " << num2 << " = " << (num1 - num2)
<< endl;
cout << "Would you like to add again: (Y/y) ";
cin >> response;
cout << endl;
}
return 0;
}
14
...
" << endl;

15
...


What is the output of the following program segment?
int count = 5;
while (count-- > 0)
cout << count << " ";
cout << endl;

17
...


What type of loop, such as counter-control and sentinel-control, will you
use in each of the following situations?
a
...
+ (10 / 9)

b
...


Sum the following numbers, except the last number: 17, 32, 62, 48, 58, -1
A file contains an employee’s salary
...


5

306 |

19
...


In this for loop, identify the loop control variable, the initialization statement, the
loop condition, the update statement, and the statement that updates the value of s
...
(Assume all variables are properly
declared
...


Given that the following code is correctly inserted into a program, state its
entire output as to content and form
...
)
j = 2;
for (i = 0; i <= 5; i++)
{
cout << j << " ";
j = 2 * j + 3;
}
cout << j << " " << endl;

22
...


b
...


What is the final value of s?
(i) 11
(ii) 4
(iii) 26
(iv) none of these
If a semicolon is inserted after the right parenthesis in the for loop
statement, what is the final value of s?
(i) 0
(ii) 1
(iii) 2
(iv) 5
(v) none of these
If the 5 is replaced with a 0 in the for loop control expression, what is
the final value of s?
(ii) 1
(iii) 2
(iv) none of these
(i) 0

Exercises

23
...


for (i = 2; i >= 1; i++)
cout << "*";
cout << endl;

c
...


for (i = 12; i >= 9; i--)
cout << "*";
cout << endl;

e
...


25
...

What is the output of the following code? Is there a relationship between
the variables x and y? If yes, state the relationship? What is the output?
int x = 19683;
int i;
int y = 0;
for (i = x; i >= 1; i = i / 3)
y++;
cout << "x = " << x << ", y = " << y << endl;

26
...
What is the output of the following code?
Assume all variables are properly declared
...


307

State what output, if any, results from each of the following statements:
a
...


|

What is the output of the following C++ program segment? Assume all
variables are properly declared
...


if (j != 7)
cout << (j + 1) * 25 - 1 << endl;
else
cout << (j + 1) * 25 << endl;

Suppose that the input is 38 35 71 44 -1
...

sum = 0;
cin >> num;
j
for (j = 1; j <= 3; j++)
{
cin >> num;
sum = sum + num;
}
cout << "Sum = " << sum << endl;

29
...
while
loop only? To both?
a
...

c
...

30
...

The body of the loop executes at least once
...

The body of the loop may not execute at all
...
Correct all such mistakes
...

32
...


x = 5; y = 80;
do
x = x * 2;
while (x < y);
cout << x << " " << y << endl;

c
...


x = 5; y = 35;
while (x < y)
x = x + 10;
cout << x << " " << y << endl;

e
...


34
...


33
...

Rewrite the following as a for loop
...

36
...
while loop
...
while loop in the following program is supposed to read some
numbers until it reaches a sentinel (in this case, -1)
...
If the data looks like:
12

5

30

48

-1

the program does not add the numbers correctly
...

#include
using namespace std;
int main()
{
int total = 0,
count = 0,
number;
do
{
cin >> number;
total = total + number;
count++;
}
while (number != -1);
cout << "The number of data read is " << count << endl;
cout << "The sum of the numbers entered is " << total
<< endl;
}
37
...
Correct it
...


Using the same data as in Exercise 36, the following loop also fails
...

cin >> number;
while (number != -1)
{
cin >> number;
total = total + number;
}
cout << endl;
cout << total << endl;

39
...
while loop that have the same output
...


|

311

Given the following program segment:
j = 2;
for (i = 1; i <= 5; i++);
{
cout << setw(4) << j;
j = j + 5;
}
cout << endl;

41
...
while loop that have the same output
...


return 0;

To learn how nested for loops work, do a walk-through of the following
program segments and determine, in each case, the exact output
...


int i, j;
for (i = 1; i <= 5; i++)
{
for (j = 1; j <= 5; j++)
cout << setw(3) << i;
cout << endl;
}

b
...


int i, j;
for (i = 1; i <= 5; i++)
{
for (j = 1; j <= i; j++)
cout << setw(3) << j;
cout << endl;
}

d
...


int i, j;
for (i = 1; i <= 9; i++)
{
for (j = 1; j <= (9 - i); j++)
cout << " ";
for (j = 1; j <= i; j++)
cout << setw(1) << j;
for (j = (i - 1); j >= 1; j--)
cout << setw(1) << j;
cout << endl;
}

43
...


What is the output of the following code?
int num = 12;
while (num >= 0)
{
if (num % 5 == 0)
break;
cout << num << " ";
num = num - 2;
}
cout << endl;

Programming Exercises

45
...


What does a break statement do in a loop?

PROGRAMMING EXERCISES
1
...


Write a program that prompts the user to input an integer and then outputs
both the individual digits of the number and the sum of the digits
...

The value of p can be approximated by using the following series:


1 1 1
1
1
 ¼ 4 1 À þ À þ ÁÁÁ þ
þ
:
3 5 7
2n À 1 2n þ 1
The following program uses this series to find the approximate value of p
...

Rearrange the statements and also find and remove the bug so that this program can
be used to approximate p
...


4
...


6
...


8
...
Replace the statements from Line 10 to Line 28 so that the program uses only a switch
structure to find the digit that corresponds to an uppercase letter
...
Rewrite the program so that it processes both
uppercase and lowercase letters and outputs the corresponding telephone
digit
...

To make telephone numbers easier to remember, some companies use letters
to show their telephone number
...
In some cases, to make a
telephone number meaningful, companies might use more than seven letters
...
Write a program that prompts the user to enter a telephone number
expressed in letters and outputs the corresponding telephone number in digits
...

Also output the – (hyphen) after the third digit
...
Moreover, your
program should process as many telephone numbers as the user wants
...

Write a program that prompts the user to input a positive integer
...
(Note: An
even number is prime if it is 2
...
)
Let n = akak-1ak-2
...
It
is known that n is divisible by 11 if and only if t is divisible by 11
...
Then, t = 4 - 0 + 2 - 4 + 8 - 7 + 8 =
11
...

If n ¼ 54063297, then t = 7 - 9 + 2 - 3 + 6 - 0 + 4 - 5 = 2
...


b
...


d
...


f
...

12
...


14
...


315

divisible by 11, 54063297 is not divisible by 11
...

Write a program that uses while loops to perform the following steps:
a
...


|

Prompt the user to input two integers: firstNum and secondNum
(firstNum must be less than secondNum)
...

Output the sum of all even numbers between firstNum and
secondNum
...

Output the sum of the square of the odd numbers between firstNum
and secondNum
...


Redo Exercise 9 using for loops
...
while loops
...
Also,
the program does not check whether the user entered a valid value for the
position of the desired number in the Fibonacci sequence
...

The population of a town A is less than the population of town B
...
Write a program that prompts the user to enter the
population and growth rate of each town
...
(A sample input is: Population of town A ¼ 5000, growth
rate of town A ¼ 4%, population of town B ¼ 8000, and growth rate of
town B ¼ 2%
...

Define a0 ¼ x; an+1 ¼ an/2 if an is even; an+1 ¼ 3 Â an + 1 if an is odd
...
Write a program that
prompts the user to input the value of x
...
, ak
...
, a14, respectively, are
75, 226, 113, 340, 170, 85, 256, 128, 64, 32, 16, 8, 4, 2, 1
...

Enhance your program from Exercise 14 by outputting the position of the
largest number and the largest number of the sequence a0, a1, a2,
...

(For example, the largest number of the sequence 75, 226, 113, 340, 170,

5

316 |

16
...


Chapter 5: Control Structures II (Repetition)

85, 256, 128, 64, 32, 16, 8, 4, 2, 1 is 340, and its position is 4
...

The program in Example 5-6 implements the Number Guessing Game
...
Rewrite the program so that the user has no more than
five tries to guess the correct number
...

Example 5-6 implements the Number Guessing Game program
...
Modify the program as follows: Suppose
that the variables num and guess are as declared in Example 5-6 and diff
is an int variable
...
If diff
is 0, then guess is correct and the program outputs a message indicating
that the user guessed the correct number
...
Then the
program outputs the message as follows:
a
...


c
...


If diff is greater than or equal to 50, the program outputs the message
indicating that the guess is very high (if guess is greater than num) or
very low (if guess is less than num)
...

If diff is greater than or equal to 15 and less than 30, the program
outputs the message indicating that the guess is moderately high (if guess
is greater than num) or moderately low (if guess is less than num)
...


As in Programming Exercise 16, give the user no more than five tries to
guess the number
...
The function abs is from the header file
cstdlib
...


A high school has 1000 students and 1000 lockers, one locker for each
student
...
She then asks the
second student to go and close all the even-numbered lockers
...
If it is open, the student closes
it; if it is closed, the student opens it
...
If it is open, the student closes it; if it is closed, the
student opens it
...
In general, the
nth student checks every nth locker
...
After all the students have taken their
turn, some of the lockers are open and some are closed
...
After the
game is over, the program outputs the number of lockers that are opened
...
Do
you see any pattern developing?

19
...


21
...


(Hint: Consider locker number 100
...
These are the positive divisors
of 100
...
Notice that if the number of positive divisors of a locker
number is odd, then at the end of the game, the locker is opened
...
)
When you borrow money to buy a house, a car, or for some other purpose,
you repay the loan by making periodic payments over a certain period of time
...
Every
periodic payment consists of the interest on the loan and the payment toward
the principal amount
...
2% per year and the payments are monthly
...
Now, the interest is 7
...
2/12 ¼ 0
...
The first month’s
interest on $1000 is 1000 Â 0
...
Because the payment is $25 and
interest for the first month is $6, the payment toward the principal amount is
25 – 6 ¼ 19
...
For the second payment, the interest is calculated on $981
...
006 ¼ 5
...
89
...
89 ¼ 19
...
11 ¼ 961
...
This process is repeated until the loan is paid
...
(Enter the interest rate as a percentage
...
2% per year, then enter 7
...
) The program
then outputs the number of months it would take to repay the loan
...
In this case, the program
must warn the borrower that the monthly payment is too low, and with
this monthly payment, the loan amount could not be repaid
...
Your last payment might be more than the remaining
loan amount and interest on it
...
Also, output the
total interest paid
...

Write a complete program to test the code in Example 5-22
...

24
...

26
...

Write a complete program to test the code in Example 5-24
...

(The conical paper cup problem) You have been given the contract for
making little conical cups that come with bottled water
...
By closing the remaining part of the
circle, a conical cup is made
...


r

x

4
h

FIGURE 5-4

27
...
The program should then output the length of the removed
sector so that the resulting cup is of maximum volume
...

(Apartment problem) A real estate office handles, say, 50 apartment units
...
However,
for each, say, $40 increase in rent, one unit becomes vacant
...

How many units should be rented to maximize the profit?
Write a program that prompts the user to enter:
a
...

c
...

The increase in rent that results in a vacant unit
...


The program then outputs the number of units to be rented to maximize the profit
...


Learn about standard (predefined) functions and discover how to use them in a program


...


Examine value-returning functions, including actual and formal parameters


...
One such
function is main
...
This technique,
however, is good only for short programs
...
You must learn to break the problem into manageable
pieces
...

Let us imagine an automobile factory
...

Some parts are made by the company itself; others, by different companies
...
They let you divide complicated programs into
manageable pieces
...

• Different people can work on different functions simultaneously
...

• Using functions greatly enhances the program’s readability because it
reduces the complexity of the function main
...
They are like miniature programs; you can put
them together to form a larger program
...
This ability is less apparent with predefined functions
because their programming code is not available to us
...


Predefined Functions
Before formally discussing predefined functions in C++, let us review a concept from a
college algebra course
...
Thus, if f(x) = 2x + 5, then f(1) = 7, f(2) = 9, and
f(3) = 11, where 1, 2, and 3 are the arguments of f, and 7, 9, and 11 are the
corresponding values of the function f
...
For example, every function has a name and, depending on the
values specified by the user, it does some computation
...


Predefined Functions |

321

Some of the predefined mathematical functions are pow(x, y), sqrt(x), and
floor(x)
...

For example, pow(2, 3)= 23 = 8
...
5, 3)= 2
...
625
...
Moreover, x and y
are called the parameters (or arguments) of the function pow
...

The square root function, sqrt(x), calculates the nonnegative square root of x for
x >= 0
...
For example, sqrt(2
...
5
...

The floor function, floor(x), calculates the largest whole number that is less than or
equal to x
...
79) is 48
...
The function floor is of type
double and has only one parameter
...
For example, the
header file iostream contains I/O functions, and the header file cmath contains
math functions
...
The function type is the data type of the final
value returned by the function
...
)
TABLE 6-1

Predefined Functions

Function

Header File

Purpose

Parameter(s)
Result
Type

abs(x)



Returns the absolute value
of its argument: abs(-7) = 7

int
(double)

int
(double)

ceil(x)



Returns the smallest whole
number that is not less than
x: ceil(56
...
0

double

double

cos(x)



Returns the cosine of angle:
x: cos(0
...
0

double
(radians)

double

exp(x)



double

double

fabs(x)



double

double

Returns ex, where e = 2
...
0) = 2
...
67) = 5
...
67) = 45
...
16, 0
...
4

sqrt(x)



Returns the nonnegative
square root of x; x must be
nonnegative: sqrt(4
...
0

tolower(x)



Returns the lowercase value
of x if x is uppercase;
otherwise, it returns x

int

int

toupper(x)



Returns the uppercase value
of x if x is lowercase;
otherwise, it returns x

int

int

To use predefined functions in a program, you must include the header file that contains
the function’s specification via the include statement
...


Predefined Functions |

323

EXAMPLE 6-1
//How to
#include
#include
#include

use predefined functions
...
2;
v = 3
...
0 to the power of 4 = "
<< pow(5
...
0, 3);
cout << "Line 7: u = " << u << endl;

//Line 6
//Line 7

x = -15;
cout << "Line 9: Absolute value of " << x
<< " = " << abs(x) << endl;

//Line 8

}

//Line 9

return 0;

Sample Run:
Line
Line
Line
Line
Line

1:
4:
5:
7:
9:

Uppercase a is A
4
...
088
5
...
2
Absolute value of -15 = 15

This program works as follows
...
Note that the function toupper returns an int value
...

To print A rather than 65, you need to apply the cast operator, as shown in the statement in
Line 1
...
In C++ terminology,
it is said that the function pow is called with the parameters u and v
...
The other statements have similar meanings
...


6

324 |

Chapter 6: User-Defined Functions I

User-Defined Functions
As Example 6-1 illustrates, using functions in a program greatly enhances the program’s
readability because it reduces the complexity of the function main
...
For instance, in
Example 6-1, the function pow is used more than once
...

User-defined functions in C++ are classified into two categories:


Value-returning functions—functions that have a return type
...

• Void functions—functions that do not have a return type
...

The remainder of this chapter discusses value-returning functions
...
Chapter 7
describes void functions
...
These are examples of value-returning functions
...
You need to include this header file in your program using the
include statement and know the following items:
1
...

3
...


The name of the function
The number of parameters, if any
The data type of each parameter
The data type of the value computed (that is, the value returned) by the
function, called the type of the function

Because the value returned by a value-returning function is unique, the natural
thing for you to do is to use the value in one of three ways:
• Save the value for further calculation
...

• Print the value
...

• As a parameter in a function call
...

That is, a value-returning function is used (called) in an expression
...
In addition to the four properties described
previously, one more thing is associated with functions (both value-returning and void):
5
...
Together, these
five properties form what is called the definition of the function
...
Thus, the formal parameter of abs is number
...
That
is, in C++ terminology, the function pow is called several times
...

Suppose that the heading of the function pow is:
double pow(double base, double exponent)

From the heading of the function pow, it follows that the formal parameters of pow are
base and exponent
...
5;
double v = 3
...
0, 3
...
1;
cout << u << " to the power of 7 = " <<

pow(u, 7) << endl;

//Line 1
//Line 2
//Line 3

6

326 |

Chapter 6: User-Defined Functions I

In Line 1, the function pow is called with the parameters u and v
...
In fact, the value of u is copied into base, and
the value of v is copied into exponent
...
In Line 2, the
function pow is called with the parameters 2
...
2
...
0 is
copied into base, and 3
...
Moreover, in this call of the
function pow, the actual parameters are 2
...
2, respectively
...
0 is copied into exponent
...

Actual Parameter: A variable or expression listed in a call to a function
...

Software companies do not give out the actual source code, which is the body of the
function
...


Syntax: Value-Returning function
The syntax of a value-returning function is:
functionType functionName(formal parameter list)
{
statements
}

in which statements are usually declaration statements and/or executable statements
...
The
functionType is also called the data type or the return type of the value-returning
function
...


Syntax: Formal Parameter List
The syntax of the formal parameter list is:
dataType identifier, dataType identifier,
...


(In this syntax, expression can be a single constant value
...

A function’s formal parameter list can be empty
...
The function heading of the value-returning
function thus takes, if the formal parameter list is empty, the following form:
functionType functionName()

If the formal parameter list of a value-returning function is empty, the actual parameter is
also empty in a function call
...
Thus, a call to a value-returning
function with an empty formal parameter list is:
functionName()

In a function call, the number of actual parameters, together with their data types, must
match with the formal parameters in the order given
...
(Chapter 7 discusses functions with default
parameters
...
The expression
can be part of either an assignment statement or an output statement, or a parameter in a
function call
...


return Statement
Once a value-returning function computes the value, the function returns this value via
the return statement
...


Syntax: return Statement
The return statement has the following syntax:
return expr;

in which expr is a variable, constant value, or expression
...
The data type of the value that expr computes must match the
function type
...

When a return statement executes in a function, the function immediately terminates
and the control goes back to the caller
...
When a return statement executes in
the function main, the program terminates
...
Because the function compares two numbers, it follows that this
function has two parameters and that both parameters are numbers
...
Because the larger
number is of type double, the function’s data type is also double
...
The only thing you need to complete this function is the body of the
function
...
Figure 6-1
describes various parts of the function larger
...
Also suppose that num1 = 45
...
50
...


Function call

Actual parameters

num = larger(23
...
80);
Function call

Actual parameters

num = larger(num1, num2);
Function call

Actual parameters

num = larger(34
...

1
...


2
...
Recall that once a
return statement executes, all subsequent statements are skipped
...


6

330 |

Chapter 6: User-Defined Functions I

EXAMPLE 6-2
Now that the function larger is written, the following C++ code illustrates how to use it
...
00;
double two = 36
...
45, 56
...
When the expression larger(5, 6) executes, 5 is
copied into x, and 6 is copied into y
...

• The expression larger(one, two) in Line 2 is a function call
...
When the expression larger(one, two)
executes, the value of one is copied into x, and the value of two is copied
into y
...

• The expression larger(one, 29) in Line 3 is also a function call
...
Therefore, the statement in Line 3
outputs the larger of one and 29
...
45, 56
...
In this
call, the actual parameters are 38
...
78
...


In a function call, you specify only the actual parameter, not its data type
...
However, the following statements contain incorrect
calls to the function larger and would result in syntax errors
...
)

x = larger(int one, 29);
y = larger(int one, int 29);
cout << larger(int one, int two);

//illegal
//illegal
//illegal

Value-Returning Functions |

331

Once a function is written, you can use it anywhere in the program
...
Let us now write
another function that uses this function to determine the largest of three numbers
...

double compareThree(double x, double y, double z)
{
return larger(x, larger(y, z));
}

In the function heading, x, y, and z are formal parameters
...
This expression has two calls to the
function larger
...
It follows that, first, the expression
larger(y, z) is evaluated; that is, the inner call executes first, which gives the larger of y
and z
...
(Notice that t is either y or z
...
Finally, the return statement returns
the largest number
...
For example, the actual parameter larger(y, z) of the outer call evaluates first
...
Here, we are merely illustrating that once you have written a function,
you can use it to write other functions
...


Function Prototype
Now that you have some idea of how to write and use functions in a program, the next
question relates to the order in which user-defined functions should appear in a program
...

In reality, C++ programmers customarily place the function main before all other userdefined functions
...
For example, if
the function main is placed before the function larger, the identifier larger is
undefined when the function main is compiled
...

Function Prototype: The function heading without the body of the function
...
)
For the function larger, the prototype is:
double larger(double x, double y);
When writing the function prototype, you do not have to specify the variable name in the
parameter list
...

You can rewrite the function prototype of the function larger as follows:

double larger(double, double);

FINAL PROGRAM
You now know enough to write the entire program, compile it, and run it
...

//Program: Largest of three numbers
#include
using namespace std;
double larger(double x, double y);
double compareThree(double x, double y, double z);
int main()
{
double one, two;

//Line 1

cout << "Line 2: The larger of 5 and 10 is "
<< larger(5, 10) << endl;

//Line 2

cout << "Line 3: Enter two numbers: ";
cin >> one >> two;
cout << endl;

//Line 3
//Line 4
//Line 5

cout << "Line 6: The larger of " << one
<< " and " << two << " is "
<< larger(one, two) << endl;

//Line 6

Value-Returning Functions |

cout <<
<<
<<
<<
}

333

"Line 7: The largest of 43
...
00, "
"and 12
...
48, 34
...
65)
endl;
//Line 7

return 0;

double larger(double x, double y)
{
double max;
if (x >= y)
max = x;
else
max = y;
}

return max;

6

double compareThree (double x, double y, double z)
{
return larger(x, larger(y, z));
}

Sample Run: In this sample run, the user input is shaded
...
6 73
...
6 and 73
...
85
Line 7: The largest of 43
...
00, and 12
...
48
In the previous program, the function prototypes of the functions larger and
compareThree appear before their function definitions
...


Value-Returning Functions: Some Peculiarity
A value-returning function must return a value
...
If the value of the parameter, x, is greater than 5, it
returns twice the value of x; otherwise, the value of x remains unchanged
...

Suppose the value of x is 10
...
So
the return statement in Line 2 returns the value 20
...
The

334 |

Chapter 6: User-Defined Functions I

expression x > 5 in Line 1 now evaluates to false
...
However, there are no more statements
to be executed in the body of the function
...
It thus follows that if the value of x is less than or equal to 5, the function does not
contain any valid return statements to return the value of x
...
On the other hand, if the value of x is, say
10, the return statement in Line 2 executes, which returns the value 20 and also
terminates the function
...

Consider the following return statement:
return x, y;

//only the value of y will be returned

This is a legal return statement
...
However, this is not the case
...
If a return statement contains more than one expression, only
the value of the last expression is returned
...
The following program further illustrates this
concept
...

#include
using namespace std;
int funcRet1();
int funcRet2(int z);
int main()
{
int num = 4;
cout << "Line 1: The value returned by funcRet1: "
<< funcRet1() << endl;

// Line 1

Value-Returning Functions |

cout << "Line 2: The value returned by funcRet2: "
<< funcRet2(num) << endl;
}

335

// Line 2

return 0;

int funcRet1()
{
int x = 45;
}

return 23, x;

//only the value of x is returned

int funcRet2(int z)
{
int a = 2;
int b = 3;
}

return 2 * a + b, z + b; //only the value of z + b is returned

Sample Run:
Line 1: The value returned by funcRet1: 45
Line 2: The value returned by funcRet2: 7

Even though a return statement can contain more than one expression, a return
statement in your program should contain only one expression
...


More Examples of Value-Returning Functions
EXAMPLE 6-3
In this example, we write the definition of function courseGrade
...
(We assume that the test score is a value between 0 and 100
inclusive
...
else structure to determine the course grade
...
We also want to know the number of times the dice are rolled
to get the desired sum
...
So the smallest sum of
the numbers rolled is 2, and the largest sum of the numbers rolled is 12
...

int
int
int
int

die1;
die2;
sum;
rollCount = 0;

We use the random number generator, discussed in Chapter 5, to randomly generate a
number between 1 and 6
...

die1 = rand() % 6 + 1;

Similarly, the following statement randomly generates a number between 1 and 6 and
stores that number into die2, which becomes the number rolled by die2
...
If sum does not contain the desired sum, then we roll the dice again
...
while loop
...
)
do
{
die1 = rand() % 6 + 1;
die2 = rand() % 6 + 1;
sum = die1 + die2;
rollCount++;

}
while (sum != num);

We can now write the function rollDice that takes as a parameter the desired sum of
the numbers to be rolled and returns the number of times the dice are rolled to roll the
desired sum
...

//Program: Roll dice
#include
#include
#include
using namespace std;
int rollDice(int num);

6

338 |

Chapter 6: User-Defined Functions I

int main()
{
cout <<
<<
cout <<
<<
}

"The
"get
"The
"get

number of times the dice are rolled to "
the sum 10 = " << rollDice(10) << endl;
number of times the dice are rolled to "
the sum 6 = " << rollDice(6) << endl;

return 0;

int rollDice(int num)
{
int die1;
int die2;
int sum;
int rollCount = 0;
srand(time(0));
do
{
die1 = rand() % 6 + 1;
die2 = rand() % 6 + 1;
sum = die1 + die2;
rollCount++;
}
while (sum != num);
}

return rollCount;

Sample Run:
The number of times the dice are rolled to get the sum 10 = 11
The number of times the dice are rolled to get the sum 6 = 7

We leave it as an exercise for you to modify this program so that it allows the user to
enter the desired sum of the numbers to be rolled
...
)
Following is an example of a function that returns a Boolean value
...
A nonnegative integer

Value-Returning Functions |

339

is a palindrome if it reads forward and backward in the same way
...

Suppose num is a nonnegative integer
...
Suppose num >= 10
...
If the first and the last digits of num are
not the same, it is not a palindrome, so the function should return false
...
Repeat this process as long as the number is >= 10
...
Because the first and last digits of 18281
are the same, remove the first and last digits to get the number 828
...
Once again, the first and last digits are the
same
...
Thus, 18281 is a palindrome
...
The highest power of 10 that divides
18281 is 4, that is, pwr = 4
...

Also, because 8281 / 10 = 828, the last digit is removed
...
To remove
the last digit, divide the number by 10
...
The following algorithm implements this discussion:
1
...

2
...
To see if num is a palindrome:
Find the highest power of 10 that divides num and call it pwr
...

b
...


a
...
1
...
Return false
...
2
...
2
...
Remove the first and last digits of num
...
2
...
Decrement pwr by 2
...
Return true
...
a
while (num / static_cast(pow(10
...
b
{
int tenTopwr = static_cast(pow(10
...
b
...
b
...
b
...
1
//Step 2
...
2
...
b
...
2

return true;
}//end else

In the definition of the function isNumPalindrome, the function pow from the
header file cmath is used to find the highest power of 10 that divides the number
...


Flow of Execution
As stated earlier, a C++ program is a collection of functions
...
The only thing that you have to remember is that you must declare
an identifier before you can use it
...
Thus, if the function main appears before any other user-defined
functions, it is compiled first
...

Function prototypes appear before any function definition, so the compiler translates
these first
...
However, when the

Programming Example: Largest Number

|

341

program executes, the first statement in the function main always executes first, regardless
of where in the program the function main is placed
...

A function call statement transfers control to the first statement in the body of the function
...
A value-returning function returns a
value
...
The
execution continues at the point immediately following the function call
...
Suppose that the program calls funcA
...


6
PROGRAMMING EXAMPLE:

Largest Number

In this programming example, the function larger is used to determine the largest
number from a set of numbers
...
You can easily enhance this
program to accommodate any set of numbers
...

The largest of 10 numbers
...
Because this is the only number read to this
point, you may assume that it is the largest number so far and call it max
...
Now compare max and num and store the larger
number into max
...
Read the
third number
...
At this
point, max contains the largest of the first three numbers
...
Repeat this process for each
remaining number in the data set
...
This discussion translates into the following algorithm:
1
...
Because this is the only number that you
have read so far, it is the largest number so far
...


342 |

Chapter 6: User-Defined Functions I

2
...
Read the next number
...

b
...
If max < num, then num is the new
largest number, so update the value of max by copying num into
max
...

3
...

To find the larger of two numbers, the program uses the function larger
...
S
...

//********************************************************
#include
using namespace std;
double larger(double x, double y);
int main()
{
double num; //variable to hold the current number
double max; //variable to hold the larger number
int count; //loop control variable
cout << "Enter 10 numbers
...

Enter 10 numbers
...
In that
program, all of the programming instructions are packed in the function main
...
The problem analysis phase shows how to divide a complex
problem into smaller subproblems
...

Input to and output of the program are the same as before
...
Both functions calculate the billing amount and
then return the billing amount to the function main
...
Let us call the function that calculates the residential bill residential
and the function that calculates the business bill business
...

As in Chapter 4, data such as the residential bill processing fee, the cost of residential
basic service connection, and so on are special
...


Function
residential

To compute the residential bill, you need to know the number of premium channels
to which the customer subscribes
...
After calculating the billing amount, the function
returns the billing amount using the return statement
...
Prompt the user for the number of premium channels
...
Read the number of premium channels
...
Calculate the bill
...
Return the amount due
...
Other
items needed to calculate the billing amount, such as the cost of basic service connection
and bill-processing fees, are defined as named constants (before the definition of the
function main)
...
This function, therefore, has no parameters
...
This
function needs only two local variables to calculate the billing amount:
int noOfPChannels;
double bAmount;

//number of premium channels
//billing amount

The definition of the function residential can now be written as follows:
double residential()
{
int noOfPChannels; //number of premium channels
double bAmount;
//billing amount
cout << "Enter the number of premium "
<< "channels used: ";
cin >> noOfPChannels;
cout << endl;
bAmount = RES_BILL_PROC_FEES +
RES_BASIC_SERV_COST +
noOfPChannels * RES_COST_PREM_CHANNEL;
}
Function
business

return bAmount;

To compute the business bill, you need to know the number of both the basic service
connections and the premium channels to which the customer subscribes
...
The billing amount is then
returned using the return statement
...

b
...

d
...

f
...

Read the number of basic service connections
...

Read the number of premium channels
...

Return the amount due
...
The function also contains
statements to input the number of basic service connections and premium channels
(Steps b and d)
...
It follows that to calculate the billing
amount, this function does not need to get any values from the function main
...

Local
Variables
(Function
business)

From the preceding discussion, it follows that the function business requires
variables to store the number of basic service connections and premium channels, as
well as the billing amount
...


2
...

4
...

6
...


To output floating-point numbers in a fixed decimal format with
the decimal point and trailing zeros, set the manipulators fixed and
showpoint
...

Prompt the user for the account number
...

Prompt the user to enter the customer type
...

a
...
Call the function residential to calculate the bill
...
Print the bill
...
If the customer type is B or b:
i
...

ii
...

c
...


COMPLETE PROGRAM LISTING
//***********************************************************
// Author: D
...
Malik
//
// Program: Cable Company Billing
// This program calculates and prints a customer's bill for
// a local cable company
...

//***********************************************************
#include
#include
using namespace std;
//Named constants – residential customers
const double RES_BILL_PROC_FEES = 4
...
50;
const double RES_COST_PREM_CHANNEL = 7
...
00;
double BUS_BASIC_SERV_COST = 75
...
00;
double BUS_COST_PREM_CHANNEL = 50
...
"
<< endl;
cout << "Enter account number: ";
//Step 3
cin >> accountNumber;
//Step 4
cout << endl;
cout << "Enter customer type: R, r "
<< "(Residential), B, b (Business): ";
cin >> customerType;
cout << endl;
switch (customerType)
{
case 'r':
case 'R':
amountDue = residential();
cout << "Account number = "
<< accountNumber << endl;
cout << "Amount due = $"
<< amountDue << endl;
break;
case 'b':
case 'B':
amountDue = business();
cout << "Account number = "
<< accountNumber << endl;
cout << "Amount due = $"
<< amountDue << endl;
break;
default:
cout << "Invalid customer type
...
i
//Step 7a
...
ii
//Step 7b
//Step 7b
...
ii
//Step 7b
...

This program computes a cable bill
...
00

QUICK REVIEW
1
...

3
...


Functions are like miniature programs and are called modules
...

The C++ system provides the standard (predefined) functions
...

ii
...


5
...

7
...

9
...


11
...


There are two types of user-defined functions: value-returning functions
and void functions
...

Expressions, variables, or constant values used in a function call are called
actual parameters
...

To call a function, use its name together with the actual parameter list
...
Therefore, a value-returning
function is used (called) in either an expression or an output statement or as
a parameter in a function call
...


13
...
Statements enclosed
between braces ({ and }) are called the body of the function
...


6

350 |

14
...

16
...

18
...

20
...

22
...

24
...

26
...

28
...

A value-returning function returns its value via the return statement
...
However, whenever a return statement executes in a function, the remaining statements
are skipped and the function exits
...

A function prototype is the function heading without the body of the
function; the function prototype ends with the semicolon
...

In a function prototype, the names of the variables in the formal parameter
list are optional
...

In a program, function prototypes are placed before every function definition, including the definition of the function main
...

When the program executes, the execution always begins with the first
statement in the function main
...

A call to a function transfers control from the caller to the called
function
...

When a function exits, the control goes back to the caller
...


Mark the following statements as true or false
...


b
...


d
...


To use a predefined function in a program, you need to know only the
name of the function and how to use it
...

Parameters allow you to use different values each time the function is
called
...

A value-returning function returns only integer values
...


static_cast(toupper('b'))

b
...


static_cast(toupper('K'))

d
...


static_cast(tolower('D'))

f
...


static_cast(tolower('h'))

h
...

a
...
fabs(10
...
fabs(-2
...
pow(2
...
sqrt(25
...
sqrt(6
...
pow(3
...
0) / abs(-9)
4
...


351

Determine the value of each of the following expressions
...


3
...
pow(3
...
floor(28
...
ceil(35
...
(The expression in (e) denotes the absolute value of x + 2
...
)
pffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffi
pffiffiffiffiffiffiffiffiffiffiffi
Àb þ b2 À 4ac
5
...
u
a
...
0
b
...

e
...


double func();

ii
...

6
...


func(double x, int y, string name);

Consider the following program:
#include
#include
using namespace std;
int main()
{
int num1;
int num2;
cout << "Enter two integers: ";
cin >> num1 >> num2;
cout << endl;

6

352 |

Chapter 6: User-Defined Functions I

if (num1 != 0 && num2 != 0)
cout << sqrt(fabs(num1 + num2 + 0
...
0) << endl;
else if (num2 != 0)
cout << ceil(num2 + 0
...

b
...

d
...


return 0;

What
What
What
What

is
is
is
is

the
the
the
the

output
output
output
output

if
if
if
if

the
the
the
the

input
input
input
input

is
is
is
is

12 4?
3 27?
25 0?
0 49?

Consider the following statements:
double num1, num2, num3;
int int1, int2, int3;
int value;
num1 = 5
...
0; num3 = 3
...

a
...


cout << cube(num1, num3, num2) << endl;

c
...
0, 8
...
5) << endl;

d
...


value = cube(num1, int2, num3);

f
...

8
...
0, num3);

value = cube(int1, int2, int3);

Consider the following functions:
int secret(int x)
{
int i, j;
i = 2 * x;
if (i > 10)
j = x / 2;

Exercises

|

353

else
j = x / 3;
}

return j - 1;

int another(int a, int b)
{
int i, j;
j = 0;
for (i = a; i <= b; i++)
j = j + i;
}

return j;

What is the output of each of the following program segments? Assume
that x, y, and k are int variables
...


b
...


x = 10; k = secret(x);
cout << x << " " << k << " " << another(x, k) << endl;

d
...


x = 10;
cout << secret(x) << endl;

x = 5; y = 8;
cout << another(y, x) << endl;

Consider the following function prototypes:
int test(int, char, double, int);
double two(double, double);
char three(int, int, char, double);

Answer the following questions
...


b
...


d
...


How many parameters does the function test have? What is the type
of the function test ?
How many parameters does function two have? What is the type of
function two?
How many parameters does function three have? What is the type of
function three ?
How many actual parameters are needed to call the function test?
What is the type of each actual parameter, and in what order should
you use these parameters in a call to the function test?
Write a C++ statement that prints the value returned by the function
test with the actual parameters 5, 5, 7
...


6

354 |

Chapter 6: User-Defined Functions I

Write a C++ statement that prints the value returned by function two
with the actual parameters 17
...
3, respectively
...
Write a C++ statement that prints the next character returned by
function three
...
)
Why do you need to include function prototypes in a program that contains
user-defined functions?
Write the definition of a function that takes as input a char value and
returns true if the character is uppercase; otherwise, it returns false
...


10
...


12
...

b
...
7, 'v') << endl;

c
...


cout << mystery(5, 4
...
9, 'D') << endl;

Consider the following function:
int secret(int one)
{
int i;
int prod = 1;

}
a
...

ii
...

14
...

The function returns true if the first number to the power of the second
number equals the third number; otherwise, it returns false
...
)

Exercises

15
...
0)), 2) == counter)
cout << counter << " ";
cout << endl;
}

16
...


Write the definition of a function that takes as input three numbers and
returns the sum of the first two numbers multiplied by the third number
...
)

6

356 |

18
...


2
...


4
...
Test your program on the following numbers:
10, 34, 22, 333, 678, 67876, 44444, and 123454321
...

Write a program that prompts the user to input a sequence of characters and
outputs the number of vowels
...
)
Write a program that defines the named constant PI, const double
PI = 3
...
The program should use PI
and the functions listed in Table 6-1 to accomplish the following
...
Output the value of
p
...
Prompt the user to input the value of a double variable r, which stores
the radius of a sphere
...

ii
...

The value of (4/3)pr3, which is the volume of the sphere
...


|

357

The following program is designed to find the area of a rectangle, the area of
a circle, or the volume of a cylinder
...

Rewrite the program so that it works correctly
...
(Note that the program is menu driven and allows the
user to run the program as long as the user wishes
...
1419;
double rectangle(double l, double w);
#include
int main()
{
double radius;
double height;
cout << fixed << showpoint << setprecision(2) << endl;
cout << "This program can calculate the area of a rectangle, "
<< "the area of a circle, or volume of a cylinder
...
" << endl;
cout << "2: To find the area of a circle
...
" << endl;
cout << "-1: To terminate the program
...
" << endl;
cout << "1: To find the area of rectangle
...
" << endl;
cout << "-1: To terminate the program
...


Write a function, reverseDigit, that takes an integer as a parameter and
returns the number with its digits reversed
...


Programming Exercises

7
...


|

359

Modify the roll dice program, Example 6-4, so that it allows the user to
enter the desired sum of the numbers to be rolled
...

The following formula gives the distance between two points, (x1, y1) and
(x2, y2) in the Cartesian plane:
qffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffi
ðx2 À x1 Þ2 þ ðy2 À y1 Þ2
Given the center and a point on the circle, you can use this formula to find
the radius of the circle
...
The program should then output the
circle’s radius, diameter, circumference, and area
...


b
...


d
...


Assume that p = 3
...

Rewrite the program in Programming Exercise 15 of Chapter 4 (cell phone
company) so that it uses the following functions to calculate the billing
amount
...
)
a
...


10
...

radius: This function takes as its parameters four numbers that represent the center and a point on the circle, calls the function distance
to find the radius of the circle, and returns the circle’s radius
...

(If r is the radius, the circumference is 2pr
...
(If r is the radius, the area is
pr2
...

premiumBill: This function calculates and returns the billing amount
for premium service
...
If the numbers are x1, x2,
x3, x4, and x5, then the mean is x ¼ (x1 + x2 + x3 + x4 + x5)/5 and the
standard deviation is:
sffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffi

2
2
2
2
2
ðx1 À xÞ þ ðx2 À xÞ þ ðx3 À xÞ þ ðx4 À xÞ þ ðx5 À xÞ

5

6

360 |

Chapter 6: User-Defined Functions I

Your program must contain at least the following functions: a function that
calculates and returns the mean and a function that calculates the standard
deviation
...


When you borrow money to buy a house, a car, or for some other purposes,
then you typically repay it by making periodic payments
...
Suppose that i ¼ (r / m) and r is in
decimal
...

For example, the unpaid balance after making k payments is:
"
#
1 À ð1 þ iÞÀðmtÀkÞ
;
L0 ¼ R
i

12
...
(Note that if the payments are monthly, then
m ¼ 12
...

The program then outputs the apropriate values
...
Make the program
menu driven and use a loop so that the user can repeat the program for
different values
...
Their charges are as follows
...


b
...

For others, if the consulting time is less than or equal to 20 minutes, there
are no service charges; otherwise, service charges are 70% of the regular
hourly rate for the time over 20 minutes
...
00
...
00 Â 0
...
00
...
The program should output the billing amount
...
The function
should return the billing amount
...


7

CHAPTER

U SER -D EFINED F UNCTIONS II
I N T H I S C H A P T E R , YO U W I L L :


...


Discover the difference between value and reference parameters


...


Learn about the scope of an identifier


...


Discover static variables


...


Learn function overloading


...
In this chapter, you will
explore user-defined functions in general and, in particular, those C++ functions that do
not have a data type, called void functions
...
Both have a
heading and a body
...
However, the program execution
always begins with the first statement in the function main
...
A void function does not have a data type
...
However, in a void
function, you can use the return statement without any value; it is typically used
to exit the function early
...

Because void functions do not have a data type, they are not used (called) in an
expression
...
Thus, to call a void
function, you use the function name together with the actual parameters (if any) in a
stand-alone statement
...

FUNCTION DEFINITION
The function definition of void functions with parameters has the following syntax:
void functionName(formal parameter list)
{
statements
}

in which statements are usually declaration and/or executable statements
...

FORMAL PARAMETER LIST
The formal parameter list has the following syntax:
dataType& variable, dataType& variable,
...

The symbol & after dataType has a special meaning; it is used only for certain formal
parameters and is discussed later in this chapter
...


in which expression can consist of a single constant value
...
Actual and formal parameters have a one-to-one correspondence
...
(Functions with default parameters are discussed at the
end of this chapter
...


EXAMPLE 7-1
void funexp(int a, double b, char c, int x)
{

...


...


Parameters provide a communication link between the calling function (such as main)
and the called function
...
In general, there are two types of formal parameters: value parameters
and reference parameters
...

Reference parameter: A formal parameter that receives the location (memory address) of

the corresponding actual parameter
...


7

364 |

Chapter 7: User-Defined Functions II

Example 7-2 shows a void function with value and reference parameters
...


...

}

The function expfun has four parameters: (1) one, a value parameter of type int; (2)
two, a reference parameter of type int; (3) three, a value parameter of type char; and (4)
four, a reference parameter of type double
...
Let’s write the
method printStars that has two parameters, a parameter to specify the number of
blanks before the stars in a line and a second parameter to specify the number of stars in a
line
...
If
the value of the parameter blanks is 30, for instance, then the first for loop in the

Void Functions |

365

method printStars executes 30 times and prints 30 blanks
...

Next, consider the following statements:
int numberOfLines = 15;
int numberOfBlanks = 30;
for (counter = 1; counter <= numberOfLines; counter++)
{
printStars(numberOfBlanks, counter);
numberOfBlanks--;
}

The for loop calls the function printStars
...
Every invocation of the function printStars receives
one fewer blank and one more star than the previous call
...
The
for loop then decrements the number of blanks by 1 by executing the statement,
numberOfBlanks--;
...
This is done by executing the update statement counter++
in the for statement, which increments the value of the variable counter by 1
...
Thus, the previous statements will print a triangle of stars consisting of
15 lines
...

Enter the number of star lines (1 to 20) to be printed: 15
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * * * *
* * * * * * * * * * * * * * *

In the function main, the user is first asked to specify how many lines of stars to print
(Line 1)
...
) Because the program is restricted to only 20 lines, the
while loop at Lines 3 through 6 ensures that the program prints only the triangular grid
of stars if the number of lines is between 1 and 20
...
Example 7-3 shows a program that uses a function with parameters
...
When a function is called, the value of
the actual parameter is copied into the corresponding formal parameter
...
Therefore, during program execution, the
formal parameter manipulates the data stored in its own memory space
...

EXAMPLE 7-4
The following program shows how a formal parameter of a primitive data type works
...


7

#include
using namespace std;
void funcValueParam(int num);
int main()
{
int number = 6;

//Line 1

cout << "Line 2: Before calling the function "
<< "funcValueParam, number = " << number
<< endl;
funcValueParam(number);

//Line 3

cout << "Line 4: After calling the function "
<< "funcValueParam, number = " << number
<< endl;
}

//Line 2

//Line 4

return 0;

void funcValueParam(int num)
{
cout << "Line 5: In the function funcValueParam, "
<< "before changing, num = " << num
<< endl;
//Line 5
num = 15;

//Line 6

368 |

}

Chapter 7: User-Defined Functions II

cout << "Line 7: In the function funcValueParam, "
<< "after changing, num = " << num
<< endl;
//Line 7

Sample Run:
Line
Line
Line
Line

2:
5:
7:
4:

Before calling the function funcValueParam, number = 6
In the function funcValueParam, before changing, num = 6
In the function funcValueParam, after changing, num = 15
After calling the function funcValueParam, number = 6

This program works as follows
...
The
statement in Line 1 declares and initializes the int variable number
...
The value of the variable
number is then passed to the formal parameter num
...

The statement in Line 5 outputs the value of num before changing its value
...
After this statement executes, the function funcValueParam exits and
control goes back to the function main
...
The sample run shows that the value of number (Lines 2 and 4)
remains the same even though the value of its corresponding formal parameter num was
changed within the function funcValueParam
...

After copying data, a value parameter has no connection with the actual parameter, so a
value parameter cannot pass any result back to the calling function
...
The actual parameters have no knowledge of what is happening to the formal
parameters
...
Value
parameters provide only a one-way link between actual parameters and formal parameters
...


Reference Variables as Parameters
The program in Example 7-4 illustrates how a value parameter works
...
Because a reference
parameter receives the address (memory location) of the actual parameter, reference
parameters can pass one or more values from a function and can change the value of
the actual parameter
...
Chapters 9 and 12 discuss the
third situation, when arrays and classes are introduced
...

You can declare a reference (formal) parameter as a constant by using the keyword const
...
Until then, the reference parameters that you use will be nonconstant as defined in this chapter
...
If a formal parameter is a nonconstant reference parameter, during a function call, its corresponding actual parameter must be a variable
...
This program has three functions: main, getScore, and
printGrade, as follows:
1
...
Get the course score
...
Print the course grade
...
getScore
a
...

b
...

c
...

3
...
Calculate the course grade
...
Print the course grade
...

#include
using namespace std;

7

370 |

Chapter 7: User-Defined Functions II

void getScore(int& score);
void printGrade(int score);
int main()
{
int courseScore;
cout << "Line 1: Based on the course score, \n"
<< "
this program computes the "
<< "course grade
...
" << endl;
else if (cScore >= 80)
cout << "B
...
" << endl;
else if (cScore >= 60)
cout << "D
...
" << endl;

//Line 4
//Line 5
//Line 6

//Line 7
//Line 8

Sample Run: In this sample run, the user input is shaded
...

Line 4: Enter course score: 85
Line 6: Course score is 85
Line 7: Your grade for the course is B
...
The program starts to execute at Line 1, which prints the
first line of the output (see the sample run)
...
Because

Reference Variables as Parameters

|

371

the formal parameter score of the function getScore is a reference parameter, the
address (that is, the memory location of the variable courseScore) passes to score
...


main

getScore

courseScore

FIGURE 7-1

score

Variable courseScore and the parameter score

Any changes made to score immediately change the value of courseScore
...
This statement prompts the user to enter
the course score
...
Thus, at this point, the value of the variables score
and courseScore is 85 (see Figure 7-2)
...
After Line 6 executes, control goes back to the function main (see Figure 7-3)
...
It is a function call to the function printGrade
with the actual parameter courseScore
...
Thus, the value of cScore is 85
...


main
courseScore

FIGURE 7-4

printGrade
85

85

cScore

Variable courseScore and the parameter cScore

The program then executes the statement in Line 7, which outputs the fourth line
...
else statement in Line 8 determines and outputs the grade for the course
...
else statement is part of the fourth line of the output
...
else statement executes, control goes back to the function main
...

In this program, the function main first calls the function getScore to obtain the course
score from the user
...
The course score is retrieved by the
function getScore; later, this course score is used by the function printGrade
...
Thus, the formal parameter that holds this value
must be a reference parameter
...
Recall that
in the case of a value parameter, the value of the actual parameter is copied into the memory
cell of its corresponding formal parameter
...
That is, the content of the formal
parameter is an address
...

Thus, in the case of a reference parameter, both the actual and formal parameters refer to the
same memory location
...


Value and Reference Parameters and Memory Allocation

|

373

Stream variables (for example, ifstream and ofstream) should be passed by reference to a function
...


Because parameter passing is fundamental to any programming language, Examples 7-6
and 7-7 further illustrate this concept
...

EXAMPLE 7-6
The following program shows how reference and value parameters work
...
The values of the variables are shown before and/or
after each statement executes
...
After the statement in Line 3 executes,
the variables are as shown in Figure 7-5
...
Now function
funOne has three parameters and one local variable
...
Because the formal parameter
b is a reference parameter, it receives the address (memory location) of the
corresponding actual parameter, which is num2
...
Just before the statement in Line 9 executes, the variables are as shown in
Figure 7-6
...


funOne

main
num1 10

10 a

num2 15

b

ch

A

A

v

10 one

FIGURE 7-7

Values of the variables after the statement in Line 9 executes

After the statement in Line 10, a++;, executes, the variables are as shown in
Figure 7-8
...
(Note that the variable b changed the value of num2
...

funOne

main
num1 10

11 a

num2 30

b

ch

A

B

v

10 one

FIGURE 7-10

Values of the variables after the statement in Line 12 executes

The statement in Line 13 produces the following output:
Line 13: Inside funOne: a = 11, b = 30, v = B, and one = 10

After the statement in Line 13 executes, control goes back to Line 6 and the memory
allocated for the variables of function funOne is deallocated
...


Value and Reference Parameters and Memory Allocation

|

377

main
num1 10
num2 30
ch

FIGURE 7-11

A

Values of the variables when control goes back to Line 6

Line 6 produces the following output:
Line 6: After funOne: num1 = 10, num2 = 30, and ch = A

The statement in Line 7 is a function call to the function funTwo
...
Also, x and w are reference parameters, and y is a value parameter
...
The variable y
copies the value 25 into its memory cell
...


funTwo

main
num1 10

x

num2 30

25 y

ch

FIGURE 7-12

A

w

Values of the variables before the statement in Line 14 executes

After the statement in Line 14, x++;, executes, the variables are as shown in Figure 7-13
...
)

funTwo

main
num1 10

x

num2 31

25 y

ch

FIGURE 7-13

A

w

Values of the variables after the statement in Line 14 executes

7

378 |

Chapter 7: User-Defined Functions II

After the statement in Line 15, y = y *2;, executes, the variables are as shown in Figure 7-14
...
(Note that the variable w changed the value of ch
...
The memory allocated
for the variables of function funTwo is deallocated
...


main
num1 10
num2 31
ch

FIGURE 7-16

G

Values of the variables when control goes to Line 8

Value and Reference Parameters and Memory Allocation

|

379

The statement in Line 8 produces the following output:
Line 8: After funTwo: num1 = 10, num2 = 31, and ch = G

After the statement in Line 8 executes, the program terminates
...

//Example 7-7: Reference and value parameters
...

#include
using namespace std;
void addFirst(int& first, int& second);
void doubleFirst(int one, int two);
void squareFirst(int& ref, int val);

7

int main()
{
int num = 5;
cout << "Line 1: Inside main: num = " << num
<< endl;

//Line 1

addFirst(num, num);
cout << "Line 3: Inside main after addFirst:"
<< " num = " << num << endl;

//Line 2

doubleFirst(num, num);
cout << "Line 5: Inside main after "
<< "doubleFirst: num = " << num << endl;

//Line 4

squareFirst(num, num);
cout << "Line 7: Inside main after "
<< "squareFirst: num = " << num << endl;
}

//Line 3

//Line 5
//Line 6
//Line 7

return 0;

void addFirst(int& first, int& second)
{
cout << "Line 8: Inside addFirst: first = "
<< first << ", second = " << second << endl; //Line 8
first = first + 2;

//Line 9

cout << "Line 10: Inside addFirst: first = "
<< first << ", second = " << second << endl; //Line 10

380 |

Chapter 7: User-Defined Functions II

second = second * 2;

//Line 11

cout << "Line 12: Inside addFirst: first = "
<< first << ", second = " << second << endl; //Line 12

}

void doubleFirst(int one, int two)
{
cout << "Line 13: Inside doubleFirst: one = "
<< one << ", two = " << two << endl;

//Line 13

one = one * 2;

//Line 14

cout << "Line 15: Inside doubleFirst: one = "
<< one << ", two = " << two << endl;

//Line 15

two = two + 2;

//Line 16

cout << "Line 17: Inside doubleFirst: one = "
<< one << ", two = " << two << endl;

//Line 17

}

void squareFirst(int& ref, int val)
{
cout << "Line 18: Inside squareFirst: ref = "
<< ref << ", val = " << val << endl;

//Line 18

ref = ref * ref;

//Line 19

cout << "Line 20: Inside squareFirst: ref = "
<< ref << ", val = " << val << endl;

//Line 20

val = val + 2;

//Line 21

cout << "Line 22: Inside squareFirst: ref = "
<< ref << ", val = " << val << endl;

//Line 22

}

Sample Run:
Line
Line
Line
Line
Line
Line
Line
Line
Line
Line
Line
Line
Line

1: Inside main: num = 5
8: Inside addFirst: first = 5, second = 5
10: Inside addFirst: first = 7, second = 7
12: Inside addFirst: first = 14, second = 14
3: Inside main after addFirst: num = 14
13: Inside doubleFirst: one = 14, two = 14
15: Inside doubleFirst: one = 28, two = 14
17: Inside doubleFirst: one = 28, two = 16
5: Inside main after doubleFirst: num = 14
18: Inside squareFirst: ref = 14, val = 14
20: Inside squareFirst: ref = 196, val = 14
22: Inside squareFirst: ref = 196, val = 16
7: Inside main after squareFirst: num = 196

Value and Reference Parameters and Memory Allocation

|

381

Both parameters of the function addFirst are reference parameters, and both parameters
of the function doubleFirst are value parameters
...
That is, the variables first and second
refer to the same memory location, which is num
...

addFirst
main
first
num

5
second

FIGURE 7-17

Parameters of the function addFirst

Any changes that first makes to its value immediately change the value of second and
num
...
(Note that num
was initialized to 5
...
So the statement:
doubleFirst(num, num);

in the function main (Line 4) copies the value of num into one and two because the
corresponding actual parameters for both formal parameters are the same
...

doubleFirst
main
14 one
num

14
14 two

FIGURE 7-18

Parameters of the function doubleFirst

Because both one and two are value parameters, any changes that one makes to its value do not
affect the values of two and num
...
(Note that the value of num before the function doubleFirst executes is 14
...
The variable ref receives the address of its

7

382 |

Chapter 7: User-Defined Functions II

corresponding actual parameter, which is num, and the variable val copies the value of its
corresponding actual parameter, which is also num
...
Figure 7-19 illustrates this situation
...
Any changes made by val do not
affect num
...
)
We recommend that you walk through the program in Example 7-8
...


Reference Parameters and Value-Returning
Functions
In Chapter 6, in the discussion of value-returning functions, you learned how to use
value parameters only
...
By definition, a value-returning
function returns a single value; this value is returned via the return statement
...


Scope of an Identifier
The previous sections and Chapter 6 presented several examples of programs with userdefined functions
...
A question naturally arises: Are you allowed to access any identifier anywhere in the
program? The answer is no
...
The scope
of an identifier refers to where in the program an identifier is accessible (visible)
...

This section examines the scope of an identifier
...


Local identifiers are not accessible outside of the function (block)
...


Also, C++ does not allow the nesting of functions
...


Scope of an Identifier |

383

In general, the following rules apply when an identifier is accessed:
1
...
The identifier is declared before the function definition (block),
b
...
All parameters of the function have names different than the name
of the identifier, and
d
...

2
...


Only within the block from the point at which it is declared until
the end of the block, and
b
...

3
...
That is, the scope of a function name is the
same as the scope of a global variable
...
C++ allows the programmer to declare a
variable in the initialization statement of the for statement
...
The scope of the variable count is
limited to only the body of the for loop
...

In Standard C++, the scope of the variable declared in the initialize statement may
extend from the point at which it is declared until the end of the block that immediately
surrounds the for statement
...
)

The following C++ program helps illustrate the scope rules:
#include
using namespace std;
const double RATE = 10
...


...

return 0;
}
void one(int x, char y)
{

...


...


...

}
void three(int one, double y, int z)
{
char ch;
int a;

...


...


...


...

}

Scope of an Identifier |

385

Table 7-1 summarizes the scope (visibility) of the identifiers
...
Similarly, the block marked four in function three cannot use
the int variable a, which is declared in function three, because block four has an
identifier named a
...
Chapter 2 stated that C++ does not automatically initialize variables
...
For example, if a global variable is of type int, char, or double,
it is initialized to zero
...
In C++, :: is called the scope resolution operator
...
In the preceding program, by using the scope resolution
operator, the function main can refer to the global variable z as ::z
...
Then, funExample can access
the variable t using the scope resolution operator even if funExample
has an identifier t
...
Also, in the preceding program, using the
scope resolution operator, function three can call function one
...
C++ provides a way to access a global variable declared after the definition of a function
...
In the preceding
program, the global variable w is declared after the definition of function
one
...
To declare w as an external variable inside
function one, the function one must contain the following statement:
extern int w;

In C++, extern is a reserved word
...

Thus, when function one is called, no memory for w, as declared inside
one, is allocated
...


Global Variables, Named Constants,
and Side Effects
A C++ program can contain global variables
...
If more than one function uses the same global variable and something goes
wrong, it is difficult to discover what went wrong and where
...

For example, consider the following program:
//Global variable
#include
using namespace std;
int t;
void funOne(int& a);
int main()
{
t = 15;

//Line 1

cout << "Line 2: In main: t = " << t << endl;
funOne(t);

//Line 3

cout << "Line 4: In main after funOne: "
<< " t = " << t << endl;
}

//Line 2

//Line 4

return 0;

//Line 5

void funOne(int& a)
{
cout << "Line 6: In funOne: a = " << a
<< " and t = " << t << endl;

//Line 6
//Line 7

a = a + 12;
cout << "Line 8: In funOne: a = " << a
<< " and t = " << t << endl;
t = t + 13;

}

//Line 8
//Line 9

cout << "Line 10: In funOne: a = " << a
<< " and t = " << t << endl;

//Line 10

This program has a variable t that is declared before the definition of any function
...
Also, the program consists of a void function with a reference
parameter
...
So, a, the formal parameter of funOne, receives the address of t
...
Because t can be directly
accessed anywhere in the program, in Line 9, the function funOne changes the value of t

7

388 |

Chapter 7: User-Defined Functions II

by using t itself
...

In the previous program, if the last value of t is incorrect, it would be difficult to
determine what went wrong and in which part of the program
...

In the programs given in this book, we typically placed named constants before the
function main, outside of every function definition
...
Unlike global variables, global named constants have no
side effects because their values cannot be changed during program execution
...
If you need to later modify the program and
change the value of a named constant, it will be easier to find if it is placed in the
beginning of the program
...
When the program executes,
it gives the user a list of choices to choose from
...
It converts length from feet and inches to meters
and centimeters and vice versa
...
The function showChoices informs the user how to use the program
...

//Menu-driven program
...
54;
const int INCHES_IN_FOOT = 12;
const int CENTIMETERS_IN_METER = 100;
void showChoices();
void feetAndInchesToMetersAndCent(int f, int in,
int& mt, int& ct);
void metersAndCentTofeetAndInches(int mt, int ct,
int& f, int& in);
int main()
{
int feet, inches;
int meters, centimeters;
int choice;

Global Variables, Named Constants, and Side Effects |

389

do
{
showChoices();
cin >> choice;
cout << endl;
switch (choice)
{
case 1:
cout << "Enter feet and inches: ";
cin >> feet >> inches;
cout << endl;
feetAndInchesToMetersAndCent(feet, inches,
meters, centimeters);
cout << feet << " feet(foot), "
<< inches << " inch(es) = "
<< meters << " meter(s), "
<< centimeters << " centimeter(s)
...
"
<< endl;
break;
case 99:
break;
default:
cout << "Invalid input
...
" << endl;
cout << "2: To convert from meters and centimeters to feet "
<< "and inches
...
" << endl;
}

7

390 |

Chapter 7: User-Defined Functions II

void feetAndInchesToMetersAndCent(int f, int in,
int& mt, int& ct)
{
int inches;

}

inches = f * INCHES_IN_FOOT + in;
ct = static_cast(inches * CONVERSION);
mt = ct / CENTIMETERS_IN_METER;
ct = ct % CENTIMETERS_IN_METER;

void metersAndCentTofeetAndInches(int mt, int ct,
int& f, int& in)
{
int centimeters;

}

centimeters = mt * CENTIMETERS_IN_METER + ct;
in = static_cast(centimeters / CONVERSION);
f = in / INCHES_IN_FOOT;
in = in % INCHES_IN_FOOT;

Sample Run: In this sample run, the user input is shaded
...

2: To convert from meters and centimeters to feet and inches
...

2
Enter meters and centimeters: 4 25
4 meter(s), 25 centimeter(s) = 13 feet(foot), 11 inch(es)
...

2: To convert from meters and centimeters to feet and inches
...

1
Enter feet and inches: 15 8
15 feet(foot), 8 inch(es) = 4 meter(s), 77 centimeter(s)
...

2: To convert from meters and centimeters to feet and inches
...

99

The do
...
The
preceding output is self explanatory
...
Memory for global variables remains allocated as long as the program executes
...
Memory for a variable declared within a block is allocated at block entry
and deallocated at block exit
...

A variable for which memory is allocated at block entry and deallocated at block exit is called
an automatic variable
...
Global variables are static variables, and by default,
variables declared within a block are automatic variables
...
The syntax for declaring a static variable is:
static dataType identifier;

The statement:
static int x;

declares x to be a static variable of type int
...

Most compilers initialize static variables to their default values
...
However, it is a good practice to initialize static variables
yourself, especially if the initial value is not the default value
...
The statement:
static int x = 0;

declares x to be a static variable of type int and initializes x to 0
...

//Program: Static and automatic variables
#include
using namespace std;
void test();
int main()
{
int count;

7

392 |

Chapter 7: User-Defined Functions II

for (count = 1; count <= 5; count++)
test();
}

return 0;

void test()
{
static int x = 0;
int y = 10;
x = x + 2;
y = y + 1;

}

cout << "Inside test x = " << x << " and y = "
<< y << endl;

Sample Run:
Inside
Inside
Inside
Inside
Inside

test
test
test
test
test

x
x
x
x
x

=
=
=
=
=

2 and y = 11
4 and y = 11
6 and y = 11
8 and y = 11
10 and y = 11

In the function test, x is a static variable initialized to 0, and y is an automatic
variable initialized to 10
...
Memory
for the variable y is allocated every time the function test is called and deallocated when
the function exits
...
However, because x is a static variable, memory for x remains allocated as long as
the program executes
...
The subsequent calls of the
function test use the current value of x
...
Even though you can use global variables if you want to use certain values
from one function call to another, the local scope of a static variable prevents other
functions from manipulating its value
...
A program may contain a number of
functions
...
You can write a separate program to test the function
...
For example, the program in Example 7-8
contains functions to convert the length from feet and inches to meters and centimeters

Debugging: Using Drivers and Stubs |

393

and vice versa
...

Sometimes, the results calculated by one function are needed in another function
...
For example,
consider the following program that determines the time to fill a swimming pool
...
48;
double poolCapacity(double len, double wid, double dep);
void poolFillTime(double len, double wid, double dep,
double fRate, int& fTime);
void print(int fTime);
int main()
{
double length, width, depth;
double fillRate;
int fillTime;
cout << fixed << showpoint << setprecision(2);
cout << "Enter the length, width, and the depth of the "
<< "pool (in feet): ";
cin >> length >> width >> depth;
cout << endl;
cout << "Enter the rate of the water (in gallons per minute): ";
cin >> fillRate;
cout << endl;
poolFillTime(length, width, depth, fillRate, fillTime);
print(fillTime);
}

return 0;

double poolCapacity(double len, double wid, double dep)
{
double volume;
double poolWaterCapacity;
volume = len * wid * dep;
poolWaterCapacity = volume * GALLONS_IN_A_CUBIC_FOOT;
}

return poolWaterCapacity;

7

394 |

Chapter 7: User-Defined Functions II

void poolFillTime(double len, double wid, double dep,
double fRate, int& fTime)
{
double poolWaterCapacity;

}

poolWaterCapacity = poolCapacity(len, wid, dep);
fTime = static_cast (poolWaterCapacity / fRate + 0
...
" << endl;
}

Sample Run: In this sample run, the user input is shaded
...


As you can see, the program contains the function poolCapacity to find the amount of
water needed to fill the pool, the function poolFillTime to find the time to fill the pool,
and some other functions
...
Because
the results of the function poolCapacity are needed in the function poolFillTime, the
function poolFillTime cannot be tested alone
...
In situations such as these, we use function stubs
...
For a void function, a function stub
might consist of only a function header and a set of empty braces, {}, and for a valuereturning function it might contain only a return statement with a plausible return value
...
00;
}

This allows the function poolCapacity to be called while the program is being coded
...

In the meantime, the function stub allows work to continue on other parts of the program
that call the function poolCapacity
...


Function Overloading: An Introduction

|

395

Function Overloading: An Introduction
In a C++ program, several functions can have the same name
...
Before we state the rules to overloading a function, let us define the following:
Two functions are said to have different formal parameter lists if both functions have:



A different number of formal parameters or
If the number of formal parameters is the same, then the data type of the formal
parameters, in the order you list them, must differ in at least one position
...

Now consider the following function headings:
void functionSix(int x, double y, char ch)
void functionSeven(int one, double u, char firstCh)

The functions functionSix and functionSeven both have three formal parameters,
and the data type of the corresponding parameters is the same
...

To overload a function name, any two definitions of the function must have different
formal parameter lists
...


The signature of a function consists of the function name and its formal parameter list
...
(Note that the signature of a function does not include the return type of the function
...

Therefore, all of the functions in the set have different signatures if they have different
formal parameter lists
...

Therefore, these function headings to overload the function functionABC are incorrect
...
(Notice that the return types of
these function headings are different
...

Some authors define the signature of a function as the formal parameter list, and some
consider the entire heading of the function as its signature
...
If
the function’s names are different, then, of course, the compiler would have no problem
in identifying which function is called, and it will correctly translate the code
...


Suppose you need to write a function that determines the larger of two items
...
You could write several
functions as follows:
int largerInt(int x, int y);
char largerChar(char first, char second);
double largerDouble(double u, double v);
string largerString(string first, string second);

The function largerInt determines the larger of two integers; the function largerChar
determines the larger of two characters, and so on
...
Instead of giving different names to these functions, you can use the same
name—say, larger—for each function; that is, you can overload the function larger
...
If the call is
larger('A', '9'), the second function is executed, and so on
...
Of
course, for function overloading to work, you must give the definition of each function
...


Functions with Default Parameters

|

397

This section discusses functions with default parameters
...
C++ relaxes this
condition for functions with default parameters
...

In general, the following rules apply for functions with default parameters:








If you do not specify the value of a default parameter, the default value is
used for that parameter
...

Suppose a function has more than one default parameter
...

Default values can be constants, global variables, or function calls
...

You cannot assign a constant value as a default value to a reference parameter
...
34);

The function funcExp has seven parameters
...
If no values are specified for z, u, v, and w in a call to the function funcExp,
their default values are used
...
funcExp(a, b, d);
2
...
6, 'B', 87, ch);
3
...
56, 'D');
In statement 1, the default values of z, u, v, and w are used
...
In statement 3, the
default value of z is replaced by 'D', and the default values of u, v, and w are used
...
funcExp(a, 15, 34
...
7);
2
...
76, 'D', 4567, 78
...

In statement 2, because the value of v is omitted, the value of w should be omitted, too
...
void funcOne(int x, double z = 23
...
int funcTwo(int length = 1, int width, int height = 1);
3
...
In statement 2, because the first parameter is a default
parameter, all parameters must be the default parameters
...

Example 7-10 further illustrates functions with default parameters
...
34, char z = 'B');
int main()
{
int a = 23;
double b = 48
...
68);
funcOne(a, 34
...
78, ch = M
2: Volume = 1
3: Volume = 20
4: Volume = 34
5: Volume = 120
12: x = 46, y = 12
...
68, z = B
12: x = 184, y = 34
...
78, ch = M
In programs in this book, the definition of the function main is placed before the definition
of any user-defined functions
...


PROGRAMMING EXAMPLE:

Classify Numbers

In this example, we use functions to rewrite the program that determines the number of
odds and evens from a given list of integers
...

The main algorithm remains the same:
1
...

2
...

3
...

4
...

The main parts of the program are: initialize the variables, read and classify the
numbers, and then output the results
...

A function getNumber to get the number
...
This function also increments the appropriate count
...


Let us now describe each of these functions
...
The variables that
we need to initialize are zeros, odds, and evens
...
Clearly, this function has three parameters
...
Essentially, this function is:
void initialize(int& zeroCount, int& oddCount, int& evenCount)
{
zeroCount = 0;
oddCount = 0;
evenCount = 0;
}

getNumber The function getNumber reads a number and then passes this number to the function
main
...
The formal parameter of this function must be a reference parameter
because the number read is passed outside of the function
...
See the
note at the end of this programming example
...
It also updates the
values of some of the variables, zeros, odds, and evens
...
Because this function also increments the appropriate count, the variables
(that is, zeros, odds, and evens declared in main) holding the counts must be
passed as parameters to this function
...

Because the number will only be analyzed, you need to pass only its value
...
After analyzing
the number, this function increments the values of some of the variables, zeros,
odds, and evens
...
The algorithm to analyze the number and increment
the appropriate count is the same as before
...
To print the results (that is, the

number of zeros, odds, and evens), this function must have access to the values of the
variables, zeros, odds, and evens declared in the function main
...
Because this function prints only the values of
the variables, the formal parameters are value parameters
...

MAIN
ALGORITHM

1
...

2
...

3
...
Call the function getNumber to read a number
...
Output the number
...
Call the function classifyNumber to classify the number and
increment the appropriate count
...
Call the function printResults to print the final results
...
S
...

//*************************************************************
#include
#include
using namespace std;
const int N = 20;
//Function prototypes
void initialize(int& zeroCount, int& oddCount, int& evenCount);
void getNumber(int& num);
void classifyNumber(int num, int& zeroCount, int& oddCount,
int& evenCount);
void printResults(int zeroCount, int oddCount, int evenCount);
int main()
{
//Variable declaration
int counter; //loop control variable
int number; //variable to store the
int zeros;
//variable to store the
int odds;
//variable to store the
int evens;
//variable to store the

new number
number of zeros
number of odd integers
number of even integers

initialize(zeros, odds, evens);
cout <<
<<
cout <<
<<

"Please enter " << N << " integers
...

Please enter 20 integers
...
If written as a
value-returning function, the definition of the function getNumber is:

int getNumber()
{
int num;
cin >> num;
}

return num;

In this case, the statement (function call):
getNumber(number);

in the function main should be replaced by the statement:
number = getNumber();

Of course, you also need to change the function prototype
...

How to send output to a file
...

With the help of functions and parameter passing, how to use the
same program segment on different (but similar) sets of data
...


This program is broken into two parts
...
Second, you learn how to generate bar graphs
...
The courses are offered for the first time and are taught
by different teachers
...
The data in each
file is in the following form:

Programming Example: Data Comparison

courseNo
courseNo

...


...
, scoreN –999
score1, score2,
...
The output is of the following form:
Course No
CSC

ENG

Group No
1
2

Course Average
83
...
82

1
2

82
...
20


...


...
04
Avg for group 2: 82
...

As shown above
...
Suppose the data is stored in the
file group1
...
txt for group 2
...
Processing data for each course is similar and is
a two-step process:
1
...
Sum the scores for the course
...
Count the number of students in the course
...
Divide the total score by the number of students to find the
course average
...
Output the results
...
To ensure that only the
averages of the corresponding courses are compared, we compare the course IDs for
each group
...

This discussion suggests that we should write a function, calculateAverage, to find the
course average
...
By passing the appropriate parameters, we can use the same functions,
calculateAverage and printResult, to process each course’s data for both groups
...
)

7

406 |

Chapter 7: User-Defined Functions II

The preceding discussion translates into the following algorithm:
1
...

3
...

5
...

7
...

Get the course IDs for group 1 and group 2
...

Calculate the course averages for group 1 and group 2
...

Repeat Steps 2 through 5 for each course
...


Variables The preceding discussion suggests that the program needs the following variables for
(Function data manipulation in the function main:
main)
string courseId1;
//course ID for group 1
string courseId2;
//course ID for group 2
int numberOfCourses;
double avg1;
//average for a course in group 1
double avg2;
//average for a course in group 2
double avgGroup1;
//average group 1
double avgGroup2;
//average group 2
ifstream group1;
//input stream variable for group 1
ifstream group2;
//input stream variable for group 2
ofstream outfile;

//output stream variable

Next, we discuss the functions calculateAverage and printResult
...

calculate This function calculates the average for a course
...
Furthermore, after calculating the course
average, this function must pass the course average to the function main
...

To find the course average, we must first find the sum of all scores for the course and the
number of students who took the course and then divide the sum by the number of
students
...
Of course, we must initialize
the variable to find the sum and the variable to count the number of students to zero
...
0;
int numberOfStudents = 0;
int score;

Programming Example: Data Comparison

|

407

The above discussion translates into the following algorithm for the function
calculateAverage:

1
...

2
...

3
...
Update totalScore by adding the course score
...
Increment numberOfStudents by 1
...
Get the (next) course score, score
...
courseAvg = totalScore / numberOfStudents;
We are now ready to write the definition of the function calculateAverage
...
0;
int numberOfStudents = 0;
int score;
inp >> score;
while (score != -999)
{
totalScore = totalScore + score;
numberOfStudents++;
inp >> score;
} //end while
courseAvg = totalScore / numberOfStudents;
} //end calculate Average

printResult The function printResult prints the group’s course ID, group number, and

course average
...
So we must pass four parameters to
this function: the ofstream variable associated with the output file, the group
number, the course ID, and the course average for the group
...
Because the function uses only the values of
the other variables, the remaining three parameters should be value parameters
...

1
...
Before outlining the algorithm, however, we note the following: It is quite possible that in both
input files, the data is ordered according to the course IDs, but one file might have
fewer courses than the other
...
Make sure to
check for this error before printing the final answer—that is, the averages for group 1
and group 2
...
Declare the variables (local declaration)
...
Open the input files
...
Print a message if you are unable to open a file and terminate the
program
...
Open the output file
...
To output floating-point numbers in a fixed decimal format with
the decimal point and trailing zeros, set the manipulators fixed
and showpoint
...

6
...
0
...
Initialize the course average for group 2 to 0
...

8
...

9
...

10
...

11
...

12
...
if (courseId1 != courseId2)
{
}

cout << "Data error: Course IDs do not match
...
else
{

i
...


iii
...

v
...

vii
...

Calculate the course average for group 2 (call the function calculateAverage and pass the appropriate parameters)
...

Print the results for group 2 (call the function
printResult and pass the appropriate parameters)
...

Update the average for group 2
...


}

c
...

d
...

13
...
if not_end_of_file on group 1 and end_of_file on group 2
print ‘‘Ran out of data for group 2 before group 1’’
b
...
else print the average of group 1 and group 2
...


Close the input and output files
...
S
...

//**********************************************************
#include
#include
#include
#include
using namespace std;

7

410 |

Chapter 7: User-Defined Functions II

//Function prototypes
void calculateAverage(ifstream& inp, double& courseAvg);
void printResult(ofstream& outp, string courseId,
int groupNo, double avg);
int main()
{
//Step 1
string courseId1;
string courseId2;
int numberOfCourses;
double avg1;
double avg2;
double avgGroup1;
double avgGroup2;
ifstream group1;
ifstream group2;
ofstream outfile;

//course ID for group 1
//course ID for group 2
//average for a course in group 1
//average for a course in group 2
//average group 1
//average group 2
//input stream variable for group 1
//input stream variable for group 2
//output stream variable
//Step 2
//Step 2

group1
...
txt");
group2
...
txt");

if (!group1 || !group2)
//Step 3
{
cout << "Unable to open files
...
" << endl;
return 1;
}
outfile
...
out");
outfile << fixed << showpoint;
outfile << setprecision(2);

//Step 4
//Step 5
//Step 5

avgGroup1 = 0
...
0;

//Step 6
//Step 7

numberOfCourses = 0;

//Step 8

outfile << "Course No
Group No
<< "Course Average" << endl;

"

group1 >> courseId1;
group2 >> courseId2;
while (group1 && group2)
{
if (courseId1 != courseId2)
{
cout << "Data error: Course IDs "
<< "do not match
...
" << endl;
return 1;

}
else
{
calculateAverage(group1, avg1);
calculateAverage(group2, avg2);
printResult(outfile, courseId1,
1, avg1);
printResult(outfile, courseId2,
2, avg2);
avgGroup1 = avgGroup1 + avg1;
avgGroup2 = avgGroup2 + avg2;
outfile << endl;
numberOfCourses++;
}

//Step 12b
//Step 12b
...
ii
//Step 12b
...
iv
//Step 12b
...
vi
//Step 12b
...
" << endl;
else if (!group1 && group2)
cout << "Ran out of data for group 1 "
<< "before group 2
...
close();
group2
...
close();
}

//Step 13b
//Step 13c

//Step 14
//Step 14
//Step 14

return 0;

void calculateAverage(ifstream& inp, double& courseAvg)
{
double totalScore = 0
...
71
80
...
00
78
...
69
84
...
57
84
...
22
82
...
04
Avg for group 2: 82
...
Many currently available software packages can analyze data
in several forms and then display the results in a visual form, such as bar graphs or pie
charts
...
|
*****************************************
########################################
*****************************************
#######################################


...


...
04
Avg for group 2: 82
...
If a course average is less
than 2, no symbol is printed
...

Print Bars The function printResult prints the course ID and the bar graph representing the

average for a course
...
So we must pass four parameters to
this function: the ofstream variable associated with the output file, the group
number (to print * or #), the course ID, and the course average for the department
...
If the
average is 78
...

To find the number of symbols to print, we can use integer division as follows:
numberOfSymbols = static_cast(average) / 2;

For example, static_cast(78
...

Following this discussion, the definition of the function printResult is:

7

414 |

Chapter 7: User-Defined Functions II

void printResult(ofstream& outp, string courseID,
int groupNo, double avg)
{
int noOfSymbols;
int count;
if (groupNo == 1)
outp << setw(4) << courseID << "
else
outp << "
";

";

noOfSymbols = static_cast(avg)/2;
if (groupNo == 1)
for (count = 1; count <= noOfSymbols; count++)
outp << '*';
else
for (count = 1; count <= noOfSymbols; count++)
outp << '#';
outp << endl;
}//end printResult

We also include a function printHeading to print the first two lines of the output
...
|"
<< "
...
Your program should generate a bar graph
similar to bar graph shown earlier
...
)

QUICK REVIEW
1
...

2
...
If a return
3
...

5
...

The heading of a void function starts with the word void
...

A void function may or may not have parameters
...

7
...

9
...

11
...

13
...

15
...

17
...

19
...

21
...

23
...

25
...

27
...

To call a void function, you use the function name together with the actual
parameters in a stand-alone statement
...

A value parameter receives a copy of its corresponding actual parameter
...

The corresponding actual parameter of a value parameter is an expression, a
variable, or a constant value
...

The corresponding actual parameter of a reference parameter must be a variable
...

The stream variables should be passed by reference to a function
...

The scope of an identifier refers to those parts of the program where it is accessible
...

Variables declared outside of every function definition (and block) are
called global variables
...

See the scope rules in this chapter (section, Scope of an Identifier)
...

An automatic variable is a variable for which memory is allocated on
function (or block) entry and deallocated on function (or block) exit
...

By default, global variables are static variables
...

Two functions are said to have different formal parameter lists if both
functions have:



28
...

The signature of a function consists of the function name and its formal
parameter list
...


415

7

416 |

29
...

31
...

33
...

35
...


Chapter 7: User-Defined Functions II

If a function is overloaded, then in a call to that function, the signature—
that is, the formal parameter list of the function—determines which
function to execute
...

If you do not specify the value of a default parameter, the default value is
used for that parameter
...

Suppose a function has more than one default parameter
...

Default values can be constants, global variables, or function calls
...

You cannot assign a constant value as a default value to a reference parameter
...


Mark the following statements as true or false
...

b
...

c
...

d
...

e
...

f
...

g
...

h
...

i
...

Identify the following items in the programming code shown below
...


2
...

b
...

d
...


...

hello(x, y, z);

...


...
5, 'S');

...


...


...

}
//Line 18
3
...

b
...

4
...

Explain the difference between a value and a reference parameter
...


What is the output of the following program?
#include
using namespace std;
void func1();
void func2();
int main()
{
int num;
cout << "Enter 1 or 2: ";

418 |

Chapter 7: User-Defined Functions II

cin >> num;
cout << endl;
cout << "Take ";
if (num == 1)
func1();
else if (num == 2)
func2();
else
cout << "Invalid input
...
" <}
void func2()
{
cout << "Programming II
...

b
...

d
...


6
...


8
...


What
What
What
What

is
is
is
is

the
the
the
the

output
output
output
output

if
if
if
if

the
the
the
the

input
input
input
input

is
is
is
is

1?
2?
3?
-1?

Write the definition of a void function that takes as input a decimal number
and as output 3 times the value of the decimal number
...

Write the definition of a void function that takes as input two decimal
numbers
...

Write the definition of a void function with three reference parameters of type
int, double, and string
...

Write the definition of a void function that takes as input two parameters
of type int, say sum and testScore
...
The new value of sum is reflected
in the calling environment
...


c = a + b;
temp = a;
a = b;
b = 2 * temp;

What is the output of the following program?
#include
using namespace std;
int x;
void summer(int&, int);
void fall(int, int&);
int main()
{
int intNum1 = 2;
int intNum2 = 5;
x = 6;
summer(intNum1, intNum2);
cout << intNum1 << " " << intNum2 << " " << x << endl;

7

420 |

}

Chapter 7: User-Defined Functions II

fall(intNum1, intNum2);
cout << intNum1 << " " << intNum2 << " " << x << endl;
return 0;

void summer(int& a, int b)
{
int intNum1;
intNum1 = b + 12;
a = 2 * b + 5;
b = intNum1 + 4;
}
void fall(int u, int& v)
{
int intNum2;
intNum2= x;
v = intNum2 * 4;
x = u - v;
}
11
...

#include
using namespace std;
void func(int val1, int val2);
int main()
{
int num1, num2;
___
cout << "Please enter two integers
...


Consider the following program:
#include
#include
#include

Exercises

|

421

using namespace std;
void traceMe(double x, double y);
int main()
{
double one, two;
cout << "Enter two numbers: ";
cin >> one >> two;
cout << endl;
traceMe(one, two);
traceMe(two, one);
}

return 0;

void traceMe(double x, double y)
{
double z;
if (x != 0)
z = sqrt(y) / x;
else
{
cout << "Enter a nonzero number: ";
cin >> x;
cout << endl;
z = floor(pow(y, x));
}

}
a
...

c
...


14
...


cout << fixed << showpoint << setprecision(2);
cout << x << ", " << y << ", " << z << endl;

What is the output if the input is 3 625?
What is the output if the input is 24 1024?
What is the output if the input is 0 196?

The function traceMe in Exercise 12 outputs the values of x, y, and z
...

In Exercise 12, determine the scope of each identifier
...
)
alpha = 5;
beta = 10;

7

422 |

Chapter 7: User-Defined Functions II

if (beta >= 10)
{
int alpha = 10;
beta = beta + alpha;
cout << alpha << ' ' << beta << endl;
}
cout << alpha << ' ' << beta << endl;
16
...
What is its exact output? Show the values
of the variables after each line executes, as in Example 7-6
...


cout << "Line 12: In funOne: a = " << a
<< ", x = " << x
<< ", and z = " << z << endl;

|

423

//Line 12

What is the output of the following program?
#include
using namespace std;
void tryMe(int& v);
int main()
{
int x = 8;
for (int count = 1; count < 5; count++)
tryMe(x);
}

return 0;

void tryMe(int& v)
{
static int num = 2;

}
18
...


if (v % 2 == 0)
{
num++;
v = v + 3;
}
else
{
num--;
v = v + 5;
}
cout << v << ", " << num << endl;

What is the signature of a function?
Consider the following function prototype:
void testDefaultParam(int a, int b = 7, char z = '*
');

Which of the following function calls is correct?
a
...


testDefaultParam(5, 8);

c
...

20
...
2)
{
int a;

7

424 |

}

Chapter 7: User-Defined Functions II

u = u + static_cast(2 * v + z);
a = u + v * z;
cout << "a = " << a << endl;

What is the output of the following function calls?
a
...


defaultParam(3, 4);

c
...
8);

PROGRAMMING EXERCISES
1
...

int main()
{
int x, y;
char z;
double rate, hours;
double amount;

...


...
Each of the functions described must
have the appropriate parameters to access these variables
...


b
...


d
...


Write the definition of the function initialize that initializes x and y
to 0 and z to the blank character
...

Write the definition of the value-returning function payCheck that calculates
and returns the amount to be paid to an employee based on the hours worked
and rate per hour
...
The formula for
calculating the amount to be paid is as follows: For the first 40 hours, the rate is
the given rate; for hours over 40, the rate is 1
...

Write the definition of the function printCheck that prints the hours
worked, rate per hour, and the salary
...
The function then changes the value of x by assigning
the value of the expression 2 times the (old) value of x plus the value of y
minus the value entered by the user
...

g
...

Consider the following C++ code:
f
...


#include
#include
#include
using namespace std;
void func1();
void func2(/*formal parameters*/);
int main()
{
int num1, num2;
double num3;
int choice;
cout << fixed << showpoint << setprecision(2);
do
{
func1();
cin >> choice;
cout << endl;
if (choice == 1)
{
func2(num1, num2, num3);
cout << num1 << ", " << num2 << ", " << num3 << endl;
}

}
while (choice != 99);
}

return 0;

void func1()
{
cout << "To run the program, enter 1
...
" << endl;
cout << "Enter 1 or 99: ";
}
void func2(/*formal parameters*/)
{
//Write the body of func2
...
Write the definition of func2 so that its action is as follows:
a
...


Prompt the user to input two integers and store the numbers in a and b,
respectively
...

ii
...


d
...


If a >= b, the value assigned to c is a to the power b, that is, ab
...


If a is nonzero and b is zero, the value assigned to c is the square root of
the absolute value of a
...

Otherwise, the value assigned to c is 0
...


3
...

Rearrange the statements so that the program outputs the total time an
employee spent on the job each day
...
The
program also allows the user to run the program as long as the user wishes
...

#include
#include
using namespace std;
int main()
{
string employeeName;
int arrivalHr;
int departureHr;
int departureMin;
bool departureAM;
char response;
char discard;
char isAM;
cout << "This program calculates the total time spent by an "
<< "employee on the job
...
get(discard);
while (response == 'y' || response == 'Y')
{
cout << "Enter employee's name: ";
getline(cin, employeeName);
cout << endl;
if (isAM == 'y' || isAM == 'Y')
arrivalAM = true;
else
arrivalAM = false;
cout << "Enter departure hour: ";
cin >> departureHr;
cout << endl;
cout << "Enter departure minute: ";
cin >> departureMin;
cout << endl;
cout << "Enter (y/Y) if departure is before 12:00PM: ";
cin >> isAM;
cout << endl;
if (isAM == 'y' || isAM == 'Y')
departureAM = true;
else
departureAM = false;
cout << employeeName << endl;
timeOnJob(arrivalHr, arrivalMin, arrivalAM,
departureHr, departureMin, departureAM);
cout << "Enter arrival hour: ";
cin >> arrivalHr;
cout << endl;
cout << "Enter arrival minute: ";
cin >> arrivalMin;
cout << endl;
cout << "Enter (y/Y) if arrival is before 12:00PM: ";
cin >> isAM;
cout << endl;

}
}

int arrivalMin;
bool arrivalAM;
cout << "Run program again (y/Y): ";
cin >> response;
cout << endl;
cin
...
" << endl;

else
if (arvTimeInMin <= depTimeInMin)
{
timeOnJobInMin = depTimeInMin - arvTimeInMin;
cout << "Time spent of job: "
<< timeOnJobInMin / 60 << " hour(s) and "
<< timeOnJobInMin % 60 << " minutes
...
" << endl;
if ((arvIsAM == true && depIsAM == true)
|| (arvIsAM == false && depIsAM == false))
{
cout << "Invalid input
...


5
...
The course score is passed as
a parameter to the function printGrade
...
(The course grade must be output in the function main
...

In this exercise, you are to modify the Classify Numbers programming
example in this chapter
...
The program can process only 20 numbers
...

b
...

c
...
Print only 10 numbers per line
...
Have the program find the sum and average of the numbers
...
Modify the function printResult so that it outputs the final results to
the output file (opened in the function main)
...

For research purposes and to better help students, the admissions office of
your local university wants to know how well female and male students
perform in certain courses
...
Due to confidentiality, the letter code f is
used for female students and m for male students
...
Each line has one entry
...
Write a program that computes and outputs
the average GPA for both female and male students
...
Your program should use the following functions:

|

429

a
...


Function openFiles: This function opens the input and output files,
and sets the output of the floating-point numbers to two decimal places
in a fixed decimal format with a decimal point and trailing zeros
...
Function initialize: This function initializes variables such as
countFemale, countMale, sumFemaleGPA, and sumMaleGPA
...
Function sumGrades: This function finds the sum of the female and
male students’ GPAs
...
Function averageGrade: This function finds the average GPA for
female and male students
...
Function printResults: This function outputs the relevant results
...
There can be no global variables
...

Write a program that prints the day number of the year, given the date in the
form month-day-year
...
The program
should check for a leap year
...
For example, 1992 and 2008 are divisible by 4, but not
by 100
...
For example, 1600 and 2000 are divisible by 400
...

a
...


7

430 |

8
...


10
...


12
...


14
...
Your program must contain a function with
one of its parameters as a string variable, and return the number of times each
lowercase vowel appears in it
...
(Note
that if str is a variable of type string, then str
...
The position of the first character is 0
...
length()
returns the length of the str, that is, the number of characters in str
...
Write a progam that reads a string
and outputs the number of times each lowercase vowel appears in it
...

Write a function that takes as a parameter an integer (as a long value) and
returns the number of odd, even, and zero digits
...

The cost to become a member of a fitness center is as follows: (a) Senior
citizens discount is 30%, (b) If membership is bought and paid for 12 or
more months, the discount is 15%, (c) If more than five personal training
sessions are bought and paid for, the discount on each session is 20%
...

Your program must contain a function that displays the general information
about the fitness center and its charges; a function to get all of the necessary
information to determine the membership cost; and a function to determine
the membership cost
...
(Do not use any global variables
...
Ask the user to input the
current price of an item and its price one year and two years ago
...
Your program must contain at least the following
functions: a function to get the input, a function to calculate the results, and
a function to output the results
...
Do not use any global variables
...
Your program must be menu driven, giving the user
the choice of converting the time between the two notations
...
(For
12-hour time notation, your program must display AM or PM
...
Your objective is to determine the dimensions, that is, the length and width, and the side of the square to be cut from the
corners so that the resulting box is of maximum length
...


Cardboard box

Write a program that prompts the user to enter the area of the flat cardboard
...
Calculate your answer to three decimal places
...
The function also returns the maximum volume
...
It costs $7 per foot to run power
lines over land and $9 per foot to run them under water
...
That is,
determine how long the power line should run under water and how long
it should run over land to achieve the minimum total cost of laying the
power line
...

b
...

d
...


The
The
The
The

width of the river
distance of the factory downstream on the other side of the river
cost of laying the power line under water
cost of laying the power line over land

The program then outputs the length of the power line that should run
under water and the length that should run over land so the cost of
constructing the power line is at the minimum
...

(Pipe problem, requires trigonometry) A pipe is to be carried
around the right-angled corner of two intersecting corridors
...
Your objective is to find the length of the longest
pipe, rounded to the nearest foot, that can be carried level around the
right-angled corner
...
The program then outputs the length of the longest pipe, rounded to
the nearest foot, that can be carried level around the right-angled corner
...
)

8

CHAPTER

U SER -D EFINED S IMPLE D ATA
T YPES , N AMESPACES , AND
THE string T YPE
I N T H I S C H A P T E R , YO U W I L L :


...


Become familiar with the typedef statement


...


Explore the string data type and learn how to use the various string functions to manipulate
strings

434 |

Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

In Chapter 2, you learned that C++’s simple data type is divided into three categories:
integral, floating-point, and enum
...
In this chapter, you will learn about the enum
type
...
The second
half of this chapter examines the purpose of this statement
...
You will also learn about the string type and many useful
functions that you can use to effectively manipulate strings
...


Chapter 2 defined a data type as a set of values together with a set of operations on them
...
Because the main objective of a program is to manipulate
data, the concept of a data type becomes fundamental to any programming language
...
The system thus provides you with built-in
checks against errors
...
Even though these data types are sufficient to solve just about any problem,
situations occur when these data types are not adequate to solve a particular problem
...

In this section, you will learn how to create your own simple data types, known as the
enumeration types
...

To define an enumeration type, you need the following items:




A name for the data type
A set of values for the data type
A set of operations on the values

C++ lets you define a new simple data type wherein you specify its name and values, but
not the operations
...

The values that you specify for the data type must be identifiers
...
};

in which value1, value2,
...
In C++, enum is a
reserved word
...
That is, value1 < value2 < value3 <
...
Moreover, the default value assigned to these
enumerators starts at 0
...
(You can assign different
values—other than the default values—for the enumerators when you define the
enumeration type
...
are not
variables
...


EXAMPLE 8-2
The statement:
enum standing {FRESHMAN, SOPHOMORE, JUNIOR, SENIOR};

defines standing to be an enumeration type
...


EXAMPLE 8-3
Consider the following statements:
enum grades {'A', 'B', 'C', 'D', 'F'}; //illegal enumeration type
enum places {1ST, 2ND, 3RD, 4TH}; //illegal enumeration type

8

436 |

Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

These are illegal enumeration types because none of the values is an identifier
...
The same rules apply to enumeration types declared
outside of any blocks
...

EXAMPLE 8-4
Consider the following statements:
enum mathStudent {JOHN, BILL, CINDY, LISA, RON};
enum compStudent {SUSAN, CATHY, JOHN, WILLIAM}; //illegal

Suppose that these statements are in the same program in the same block
...


Declaring Variables
Once a data type is defined, you can declare variables of that type
...
;

The statement:
enum sports {BASKETBALL, FOOTBALL, HOCKEY, BASEBALL, SOCCER,
VOLLEYBALL};

defines an enumeration type called sports
...


Assignment
Once a variable is declared, you can store values in it
...
The statement:
mySport = popularSport;

copies the value of popularSport into mySport
...
So the following statements are illegal:
mySport = popularSport + 2;
popularSport = FOOTBALL + SOCCER;
popularSport = popularSport * 2;

//illegal
//illegal
//illegal

Also, the increment and decrement operations are not allowed on enumeration types
...
You can use the cast
operator as follows:
popularSport = static_cast(popularSport + 1);

When the type name is used, the compiler assumes that the user understands what he or
she is doing
...
Consider the following
statements:
popularSport = FOOTBALL;
popularSport = static_cast(popularSport + 1);

After the second statement, the value of popularSport is HOCKEY
...


Relational Operators
Because an enumeration is an ordered set of values, the relational operators can be used
with the enumeration type
...
Then:
FOOTBALL <= SOCCER is true
HOCKEY > BASKETBALL is true
BASEBALL < FOOTBALL is false

8

438 |

Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

Suppose that:
popularSport = SOCCER;
mySport = VOLLEYBALL;

Then:
popularSport < mySport is true

ENUMERATION TYPES AND LOOPS
Recall that the enumeration type is an integral type and that, using the cast operator (that
is, type name), you can increment, decrement, and compare the values of the enumeration type
...
Suppose mySport is
a variable as declared earlier
...


...


This for loop has five iterations
...


Input /Output of Enumeration Types
Because input and output are defined only for built-in data types such as int, char,
double, and so on, the enumeration type can be neither input nor output (directly)
...
Example 8-5 illustrates this
concept
...
You can read (that is, input) the enumeration type with
the help of the char data type
...
For example, you can distinguish between ALGEBRA and BASIC
just by reading the first character; you can distinguish between ALGEBRA and ANALYSIS
by reading the first two characters
...
Thus, you need to declare two variables of type char
...
" << endl;
}

Similarly, you can output the enumeration type indirectly:
switch (registered)
{
case ALGEBRA:
cout << "Algebra";
break;
case ANALYSIS:
cout << "Analysis";
break;
case BASIC:
cout << "Basic";
break;

8

440 |

Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

case CHEMISTRY:
cout << "Chemistry";
break;
case CPP:
cout << "CPP";
break;
case HISTORY:
cout << "History";
break;
case PASCAL:
cout << "Pascal";
break;
case PHILOSOPHY:
cout << "Philosophy";
}
If you try to output the value of an enumerator directly, the computer will output the value
assigned to the enumerator
...

The following statement will output the value 0 because the (default) value assigned to
ALGEBRA is 0:

cout << registered << endl;

Similarly, the following statement will output 4:
cout << PHILOSOPHY << endl;

Functions and Enumeration Types
You can pass the enumeration type as a parameter to functions just like any other simple
data type—that is, by either value or reference
...
Using this facility, you can use
functions to input and output enumeration types
...
Assume that the enumeration type courses is defined as before:
courses readCourses()
{
courses registered;
char ch1, ch2;
cout << "Enter the first two letters of the course: "
<< endl;
cin >> ch1 >> ch2;
switch (ch1)
{
case 'a':

Enumeration Type |

}

case 'A':
if (ch2 == 'l' || ch2 == 'L')
registered = ALGEBRA;
else
registered = ANALYSIS;
break;
case 'b':
case 'B':
registered = BASIC;
break;
case 'c':
case 'C':
if (ch2 == 'h' || ch2 == 'H')
registered = CHEMISTRY;
else
registered = CPP;
break;
case 'h':
case 'H':
registered = HISTORY;
break;
case 'p':
case 'P':
if (ch2 == 'a' || ch2 == 'A')
registered = PASCAL;
else
registered = PHILOSOPHY;
break;
default:
cout << "Illegal input
...
C++ allows you to combine these two steps into one
...
For example, the statement:
enum grades {A, B, C, D, F} courseGrade;

defines an enumeration type, grades, and declares a variable courseGrade of type
grades
...


Anonymous Data Types
A data type wherein you directly specify values in the variable declaration with no type
name is called an anonymous type
...

Creating an anonymous type, however, has drawbacks
...
Second, values used in one anonymous type can
be used in another anonymous type, but variables of those types are treated differently
...
The following statement is,
therefore, illegal:
languages = foreignLanguages; //illegal

Even though these facilities are available, use them with care
...

We now describe the typedef statement in C++
...
The general syntax of the typedef statement is:
typedef existingTypeName newTypeName;

In C++, typedef is a reserved word
...

EXAMPLE 8-6
The statement:
typedef int integer;

creates an alias, integer, for the data type int
...
The statement:
typedef double decimal;

creates an alias, decimal, for the data type double
...


EXAMPLE 8-7
From Chapter 4, recall that logical (Boolean) expressions in C++ evaluate to 1 or 0,
which are, in fact, int values
...
Consider the following statements:

8

444 |

Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

typedef int Boolean;
const Boolean TRUE = 1;
const Boolean FALSE = 0;
Boolean flag;

//Line
//Line
//Line
//Line

1
2
3
4

The statement in Line 1 creates an alias, Boolean, for the data type int
...
The statement in Line 4 declares flag to be a variable of
type Boolean
...
This game has two players,
each of whom chooses one of the three objects: rock, paper, or scissors
...
The game is played according to the following rules:





If both players choose the same object, this play is a tie
...

If one player chooses rock and the other chooses paper, the player
choosing the paper wins this play because the paper covers the rock
...


Write an interactive program that allows two people to play this game
...


The players’ choices and the winner of each play
...

Two players play this game
...
Each
player enters R or r for Rock, P or p for Paper, or S or s for Scissors
...
Once both entries
are in, if the entries are valid, the program outputs the players’ choices and declares
the winner of the play
...


Programming Example: The Game of Rock, Paper, and Scissors | 445

the game
...
This discussion translates into the
following algorithm:
1
...

3
...

5
...

7
...

Ask the users if they want to play the game
...

If the plays are valid, output the plays and the winner
...

Repeat Steps 2 through 5 while the users agree to play the game
...


We will use the enumeration type to describe the objects
...



displayRules: This function displays some brief information about the game
and its rules
...

The only valid selections are R, r, P, p, S, and s
...




gameResult: This function outputs the players’ choices and the winner of
the game
...




winningObject: This function determines and returns the winning
object
...


Function This function has no parameters
...
Essentially, this function’s definition is:
void displayRules()
{
cout << " Welcome to the game of Rock, Paper, "
<< "and Scissors
...
For each "
<< "game, each" << endl;
cout << " player selects one of the objects Rock, "
<< "Paper, or Scissors
...
If both players select the same object, it "
<< "is a tie
...
Rock breaks Scissors: So player who selects "
<< "Rock wins
...
Paper covers Rock: So player who selects "
<< "Paper wins
...
Scissors cuts Paper: So player who selects "
<< "Scissors wins
...
" << endl;
}

Function This function checks whether a player’s selection is valid
...


Let’s use a switch statement to check for the valid selection
...
This function thus has
one parameter, of type char
...
In pseudocode, the algorithm of this function is:
if selection is 'R' or 'r'
return ROCK;
if selection is 'P' or 'p'
return PAPER;
if selection is 'S' or 's'
return SCISSORS;

The definition of the function retrievePlay is:
objectType retrievePlay(char selection)
{
objectType object;
switch (selection)
{
case 'R':
case 'r':
object = ROCK;
break;
case 'P':
case 'p':
object = PAPER;
break;
case 'S':
case 's':
object = SCISSORS;
}
}

return object;

Function This function decides whether a game is a tie or which player is the winner
...
Clearly, this function has

three parameters: player 1’s choice, player 2’s choice, and a parameter to return the
winner
...
if player1 and player2 have the same selection, then
this is a tie game
...
else
{
1
...
(Call function winningObject)
2
...

3
...

4
...

}

The definition of this function is:
void gameResult(objectType play1, objectType play2,
int& winner)
{
objectType winnerObject;
if (play1 == play2)
{
winner = 0;
cout << "Both players selected ";
convertEnum(play1);
cout << "
...
" << endl;
}
else
{
winnerObject = winningObject(play1, play2);
//Output each player's choice
cout << "Player 1 selected ";
convertEnum(play1);
cout << " and player 2 selected ";
convertEnum(play2);
cout << "
...
"
<< endl;

Function Because enumeration types cannot be output directly, let’s write the function
convertEnum convertEnum to output objects of the enum type objectType
...
It outputs the string that corresponds to the
objectType
...
For example, if one player chooses ROCK and another chooses
PAPER, the player who chose PAPER wins
...
The function winningObject, given two objects, decides and returns the
winning object
...
The definition of

this function is:
objectType winningObject(objectType play1, objectType play2)
{
if ((play1 == ROCK && play2 == SCISSORS)
|| (play2 == ROCK && play1 == SCISSORS))
return ROCK;
else if ((play1 == ROCK && play2 == PAPER)
|| (play2 == ROCK && play1 == PAPER))
return PAPER;
else
return SCISSORS;
}

Function After the game is over, this function outputs the final results—that is, the total
displayResults number of plays and the number of plays won by each player
...
This function has three parameters corresponding to
these three variables
...

MAIN
ALGORITHM

1
...

3
...

5
...


Declare the variables
...

Display the rules
...

Get the users’ responses to play the game
...

b
...

d
...


Prompt player 1 to make a selection
...

Prompt player 2 to make a selection
...

If both plays are legal:
{

i
...

ii
...

iii
...

}

f
...

g
...

}

7
...


Programming Example: The Game of Rock, Paper, and Scissors

|

451

PROGRAM LISTING
//*************************************************************
// Author: D
...
Malik
//
// Program: Rock, Paper, and Scissors
// This program plays the game of rock, paper, and scissors
...
i
gameResult(play1, play2, gamewinner); //Step 6e
...
iii

//Step 6f
//Step 6g

//Step 7

return 0;
}//end main
//Place the definitions of the functions displayRules,
//validSelection, retrievePlay, convertEnum, winningObject,
//gameResult, and displayResults as described previously here
...
Most recent compilers
are also compatible with ANSI/ISO Standard C++
...
) The two standards, Standard C++ and ANSI/ISO Standard
C++, are virtually the same
...


Namespaces

|

453

In subsequent chapters, unless specified otherwise, the C++ syntax applies to both
standards
...

When a header file, such as iostream, is included in a program, the global identifiers in the
header file also become the global identifiers in the program
...
The same problem can
occur if a program uses third-party libraries
...
In Chapter 2, you learned that because
compiler vendors begin their global identifier names with an underscore (_), to avoid linking
errors, you should not begin identifier names in your program with an underscore (_)
...

The general syntax of the statement namespace is:
namespace namespace_name
{
members
}

where members is usually named constants, variable declarations, functions, or another
namespaces
...

In C++, namespace is a reserved word
...
50;
int count = 0;
void printResult();
}

defines globalType to be a namespace with four members: named constants N and
RATE, the variable count, and the function printResult
...
You can usually
access a namespace member outside the namespace in one of two ways, as described
below
...

To access the member RATE of the namespace globalType, the following statement is
required:
globalType::RATE

To access the member printResult (which is a function), the following statement is
required:
globalType::printResult();

Thus, to access a member of a namespace, you use the namespace_name, followed by
the scope resolution operator, followed by the member name
...
The syntax to use the statement using is as follows:
a
...
To simplify the accessing of a specific namespace member:
using namespace_name::identifier;

For example, the using statement:
using namespace globalType;

simplifies the accessing of all members of the namespace globalType
...

In C++, using is a reserved word
...
For the
namespace globalType, for example, you usually write the code as follows:
namespace globalType
{
const int N = 10;
const double RATE = 7
...

However, if a namespace member and a global identifier in a program have the same
name, to access this namespace member in the program, the namespace_name and
the scope resolution operator must precede the namespace member
...

Examples 8-9 through 8-12 help clarify the use of the namespace mechanism
...


...

int main()
{

...


...


...


In this example, you can refer to the global identifiers of the header file iostream, such
as cin, cout, and endl, without using the prefix std:: before the identifier name
...


EXAMPLE 8-10
Consider the following C++ code:
#include
int main()
{
double x = 15
...


...


This example accesses the function pow of the header file cmath
...


...

int main()
{
using namespace std;

...


...


...


In this example, the function main can refer to the global identifiers of the header file
iostream without using the prefix std:: before the identifier name
...
Therefore, other functions (if any) should
use the prefix std:: before the name of the global identifier of the header file iostream
unless the function has a similar using statement
...


...


void expN::printResult() //Definition of the function printResult
{

...


...
To refer to the variable t in Line 2 in main, use the scope resolution
operator, which is :: (that is, refer to t as ::t), because the function
main has a variable named t (declared in Line 9)
...

2
...

3
...

4
...

5
...
To write the definition of the function
printResult, the name of the function in the function heading
can be either printResult or expN::printResult (because no
other global identifier is named printResult)
...
For this reason, to simplify the
accessing of identifiers from these header files, we have been using the following statement in the programs that we write:

using namespace std;

string Type
In Chapter 2, you were introduced to the data type string
...
Compiler vendors often supplied their own programmer-defined string
type, and the syntax and semantics of string operations often varied from vendor to
vendor
...
Before using the data type string, the
program must include the header file string, as follows:
#include

Recall that in C++, a string is a sequence of zero or more characters, and strings are
enclosed in double quotation marks
...

The position of the first character, W, in name is 0; the position of the second character,
i, is 1; and so on
...

The variable name can store (just about) any size string
...
We recommend that you revisit Chapters 3 and 4 and
review the I/O and relational operations on the string type
...
Let’s see how these operators work on the string data type
...
The statement:
str2 = str1;

copies the value of str1 into str2
...

Suppose str1 = "Hello" and str2 = "There"
...
This statement is equivalent to the statement:
str3 = str1 + ' ' + str2;

Also, the statement:
str1 = str1 + " Mickey";

updates the value of str1 by appending the string " Mickey" to its old value
...

For the operator + to work with the string data type, one of the operands of + must be a
string variable
...
Recall that the position of the first character
in a string variable is 0
...

In C++, [] is called the array subscript operator
...


8

460 |

Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

EXAMPLE 8-13
The following program shows the effect of the preceding statements
...
get(ch);
cout << endl;

//Read the newline character; Line 26
//Line 27

cout << "Line 28: The string you entered = "
<< str1 << endl;

//Line 28

cout << "Line 29: Enter a sentence: ";
getline(cin, str2);
cout << endl;

//Line 29
//Line 30
//Line 31

cout << "Line 32: The sentence is: " << str2
<< endl;
}

461

//Line 32

return 0;

Sample Run: In the following sample run, the user input is shaded
...


Additional string Operations
The data type string has a data type, string::size_type, and a named constant,
string::npos, defined as follows:
string::size_type
string::npos

An unsigned integer (data) type
The maximum value of the (data) type string::size_type,
a number such as 4294967295 on many machines

The data type string contains several other functions for string manipulation
...
In this table, we assume that strVar is a
string variable and str is a string variable, a string constant, or a character array
...
)

8

462 |

Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

TABLE 8-1

Some string functions

Expression

Effect

strVar
...


strVar[index]

Returns the element at the position specified by
index
...
append(n, ch)

Appends n copies of ch to strVar, in which ch
is a char variable or a char constant
...
append(str)

Appends str to strVar
...
clear()

Deletes all the characters in strVar
...
compare(str)

Compares strVar and str
...
)

strVar
...


strVar
...


strVar
...


strVar
...
If str is not found, the special value
string::npos is returned
...
find(str, pos)

Returns the index of the first occurrence at or
after pos where str is found in strVar
...
find_first_of
(str, pos)

Returns the index of the first occurrence of any
character of strVar in str
...


strVar
...
The search
starts at pos
...
insert(pos, n, ch);

Inserts n occurrences of the character ch at index
pos into strVar; pos and n are of type
string::size_type; ch is a character
...
insert(pos, str);

Inserts all the characters of str at index pos
into strVar
...
length()

Returns a value of type string::size_type
giving the number of characters strVar
...
replace(pos, n, str);

Starting at index pos, replaces the next n
characters of strVar with all the characters of
str
...


strVar
...
The length of the substring is at
most len characters
...


strVar
...


strVar
...
str1
is a string variable
...

E X A M P L E 8 - 1 4 (clear, empty, erase, length, AND size FUNCTIONS)
Consider the following statements:
string
string
string
string
string
string
string

firstName = "Elizabeth";
name = firstName + " Jones";
str1 = "It is sunny
...
";
str5 = firstName + " is taking " + str4;

string::size_type len;

Next, we show the effect of clear, empty, erase, length, and size functions
...
clear();
str1
...
empty();
str4
...
length() << endl;
cout << name
...
length() << endl;
cout << str5
...
length();

Effect
str3 ¼ "";
Returns false;
Returns true;
str4 ¼ "C++ program
...

//Example: clear, empty, erase, length, and size functions
#include
#include
using namespace std;
int main()
{
string
string
string
string
string
string
string

firstName = "Elizabeth";
name = firstName + " Jones";
str1 = "It is sunny
...
";
str5 = firstName + " is taking " + str4;

//Line
//Line
//Line
//Line
//Line
//Line
//Line

1
2
3
4
5
6
7

string::size_type len;

//Line 8

cout << "Line 9: str3: " << str3 << endl;
str3
...
empty(): " << str1
...
empty(): " << str2
...
erase(11, 4);
cout << "Line 16: After erase(11, 4), str4: "
<< str4 << endl;
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<

//Line 11
//Line 12
//Line 13
//Line 14
//Line 15
//Line 16

"Line 17: Length of \"" << firstName << "\" = "
static_cast (firstName
...
length())
endl;
//Line
"Line 19: Length of \"" << str1 << "\" = "
static_cast (str1
...
size())
endl;
//Line

17
18
19
20

//Line 21

len = name
...
empty(): 0
13: str2
...

16: After erase(11, 4), str4: C++ program
...
" = 12
20: Size of "Elizabeth is taking C++ programming
...
The details are left as an exercise for you
...
This is because the function length returns a value of the type
string::size_type
...
The following are valid calls to the
function find:
str1
...
find("the")
str1
...
find(str2 + "xyz")
str1
...
";
string str = "cloudy";
string::size_type position;

Next, we show the effect of the find function
...
find("is") << endl;
cout << sentence
...
find(str) << endl;
cout << sentence
...
find('i', 6) << endl;
position = sentence
...
Therefore, the position of o (lowercase o) in the
string sentence is 16
...

//Example: find function
#include
#include
using namespace std;
int main()
{
string sentence = "Outside it is cloudy and warm
...
find("is"))
<< endl;
//Line 5
cout << "Line 6: The position of 's' in sentence = "
<< static_cast (sentence
...
find(str))
endl;
//Line 7

cout << "Line 8: The position of \"the\" in sentence = "
<< static_cast (sentence
...
find('i', 6))
endl;
//Line 9

position = sentence
...
"
The position of "is" in sentence = 11
The position of 's' in sentence = 3
The position of "cloudy" in sentence = 14
The position of "the" in sentence = 4294967295
The first occurrence of 'i' in sentence
after position 6 = 8
Line 11: Position = 25

The output of this program is self-explanatory
...

Notice that this program uses the static cast operator to output the value returned by
the function find
...
Without the cast operator, some compilers might give the
following warning message:
conversion from 'size_t' to 'unsigned int', possible loss of data

EXAMPLE 8-16 (insert AND replace FUNCTIONS)
Suppose that you have the following statements:
string
string
string
string
string

firstString = "Cloudy and warm
...
";
str1 = " very ";
str2 = "Lisa";

Next, we show the effect of insert and replace functions
...
insert(10, str1);

Effect
firstString = "Cloudy and very
warm
...
insert(11, 5, '!'); secondString = "Hello there!!!!!"
thirdString
...
"

The following program evaluates the previous statements
...
";
//Line 1
secondString = "Hello there";
//Line 2
thirdString = "Henry is taking programming I
...
insert(10, str1);
cout << "Line 8: After insert; firstString = "
<< firstString << endl;
cout << "Line 9: secondString = " << secondString
<< endl;
secondString
...
replace(0, 5, str2);
cout << "Line 14: After replace, thirdString = "
<< thirdString << endl;
return 0;

//Line 6
//Line 7
//Line 8
//Line 9
//Line 10
//Line 11
//Line 12
//Line 13
//Line 14
//Line 15

}

Sample Run:
Line
Line
Line
Line
Line
Line

6: firstString = Cloudy and warm
...

9: secondString = Hello there
11: After insert; secondString = Hello there!!!!!
12: thirdString = Henry is taking programming I
...


The output of this program is self-explanatory
...


EXAMPLE 8-17 (substr FUNCTION)
Consider the following statements:
string sentence;
string str;
sentence = "It is cloudy and warm
...

Statement
cout << sentence
...
substr(6, 6) << endl;
cout << sentence
...
substr(17, 10) << endl;
cout << sentence
...
substr(0, 8);
str = sentence
...

Outputs: warm
...

//Example: substr function
#include
#include
using namespace std;
int main()
{
string sentence;
string str;

//Line 1
//Line 2

sentence = "It is cloudy and warm
...
substr(0, 5) << "\"" << endl;

//Line 4

cout << "Line 5: substr(6, 6) in \""
<< sentence << "\" = \""
<< sentence
...
substr(6, 16)
"\"" << endl;

cout << "Line 7: substr(17, 10) in \""
<< sentence << "\" = \""
<< sentence
...
substr(3, 6) << "\"" << endl;

//Line 8

8

470 |

Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

str = sentence
...
substr(2, 10);
cout << "Line 12: " << "str = \"" << str
<< "\"" << endl;

//Line 11

//Line 10

//Line 12

return 0;
}

Sample Run:
Line 4: substr(0, 5) in "It is cloudy and warm
...
" = "cloudy"
Line 6: substr(6, 16) in "It is cloudy and warm
...
"
Line 7: substr(17, 10) in "It is cloudy and warm
...
"
Line 8: substr(3, 6) in "It is cloudy and warm
...
The details are left as an exercise for you
...

Suppose you have the following statements:
string str1 = "Warm";
string str2 = "Cold";

After the following statement executes, the value of str1 is "Cold" and the value of
str2 is "Warm"
...
swap(str2);

Additional string functions are described in Appendix F (Header File string)
...
The rules for converting a
string into pig Latin form are as follows:
1
...
For example, the pig Latin form of the string "eye" is
"eye-way"
...
If the string does not begin with a vowel, first add "-" at the end of
the string
...
Then add the string
"ay" at the end
...

3
...
In cases like this, the letter
y can be considered a vowel
...
Therefore, the pig Latin form
of "by" is "y-bay"
...
Strings such as "1234" contain no vowels
...
That is, the pig Latin form
of a string that has no vowels in it is the string followed by the
string "-way"
...

Output of the program is the string in the pig Latin form
...
To convert str into pig Latin, check the first
character, str[0], of str
...

Suppose that the first character of str, str[0], is not a vowel
...
Then, remove the first character of str from str and put it at the
end of str
...

This process of checking the first character of str and moving it to the end of str if
the first character of str is not a vowel is repeated until either the first character of
str is a vowel or all the characters of str are processed, in which case str does not
contain any vowels
...
The previous
discussion translates into the following algorithm:
1
...

2
...

3
...

Before writing the main algorithm, each of these functions is described in detail
...
The definition of the function isVowel is:
bool isVowel(char ch)
{
switch (ch)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'Y':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'y':
return true;
default:
return false;
}
}

Function This function takes a string as a parameter, removes the first character of the string,
rotate and places it at the end of the string
...
The new string is returned as the value of this
function
...
length();
string rStr;
rStr = pStr
...
Suppose pStr denotes the string to be converted to its pig Latin form
...
Suppose that
pStr[0] is not a vowel
...
This
process is repeated until either the first character of pStr has become a vowel or all
the characters of pStr are checked, in which case pStr does not contain any vowels
...
If pStr[0] is a vowel, add "-way" at the end of pStr
...
Suppose pStr[0] is not a vowel
...
Move the first character of pStr to the end of pStr
...
Now pStr
may or may not contain a vowel
...

a
...

b
...

c
...

d
...

4
...

5
...

The definition of the function pigLatinString is:
string pigLatinString(string pStr)
{
string::size_type len;
bool foundVowel;
string::size_type counter;
if (isVowel(pStr [0]))
pStr = pStr + "-way";
else
{
pStr = pStr + '-';
pStr = rotate(pStr);
len = pStr
...
a
//Step 3
...
d

//Step 3
...
substr(1, len) + "-way";
else
pStr = pStr + "ay";

return pStr;

//Step 5

1
...

2
...

3
...

PROGRAM LISTING
//*************************************************************
// Author: D
...
Malik
//
// Program: Pig Latin Strings
// This program reads a string and outputs the pig Latin form
// of the string
...


Sample Runs: In these sample runs, the user input is shaded
...

2
...


An enumeration type is a set of ordered values
...

The syntax of enum is:
enum typeName {value1, value2,
...


in which value1, value2,
...

No arithmetic operations are allowed on the enumeration type
...

6
...

8
...

10
...

12
...

14
...


16
...


18
...

20
...


22
...

Enumeration type values cannot be input or output directly
...

A function can return a value of the enumeration type
...

C++’s reserved word typedef is used to create synonyms or aliases to
previously defined data types
...

The namespace mechanism is a feature of ANSI/ISO Standard C++
...

The scope of a namespace member is local to the namespace
...

In C++, namespace is a reserved word
...

The using statement simplifies the accessing of namespace members
...

The keyword namespace must appear in the using statement
...

To use an identifier declared in the standard header files without the
namespace name, after including all the necessary header files, the following statement must appear in the program:
using namespace std;

23
...

25
...

27
...

Strings in C++ are enclosed in double quotation marks
...
The other header files used in the program should be ANSI/
ISO Standard C++ style header files
...

The operator + can be used to concatenate two values of the type string
...


Exercises

28
...

In a string, the position of the first character is 0, the position of the second
character is 1, and so on
...

In C++, [] is called the array subscript operator
...

The string type contains functions such as at, append, clear, compare,
erase, find, find_first_of, find_first_not_of, insert, length,
replace, size, substr, and swap to manipulate strings
...


29
...

31
...

33
...


Mark the following statements as true or false
...


The following is a valid C++ enumeration type:
enum romanNumerals {I, V, X, L, C, D, M};

b
...

d
...


f
...


sets the value of domesticCars to GM
...

You can input the value of an enumeration type directly from a standard
input device
...

The values in the domain of an enumeration type are called enumerators
...


The following statement creates an anonymous type:
enum {A, B, C, D, F} studentGrade;

i
...


8

478 |

j
...


Chapter 8: User-Defined Simple Data Types, Namespaces, and the string Type

Suppose str = "ABCD";
...

Suppose str = "abcd"
...


the value of str is "ABCD"
...

b
...

c
...

d
...

e
...

Given:
a
...


enum currencyType {DOLLAR, POUND, FRANK, LIRA, MARK};
currencyType currency;

which of the following statements are valid?
a
...


cin >> currency;

c
...


4
...

a
...


static_cast(static_cast(WHEAT) - 1) is
WHEAT
(i) true (ii) false

c
...


for (crop = wheat; crop <= oats; ++crop)
cout << "*";
cout << endl;

outputs: *****
(i) true (ii) false

Exercises

5
...
h>

//Line 1

using namespace std;

//Line 2

int main()
{
int x = 0;
cout << "x = " << x << endl;
return 0;
}
7
...
50;
cout << "X = " << X << ", y = " << y
<< endl;
return 0;
}
8
...


|

//Line 6

//Line 3
//Line 4

What is wrong with the following program?
#include
#include

//Line 1
//Line 2

using std;

//Line 3

int main()
{
return 0;
}

//Line 4
//Line 5

//Line 7
//Line 8
//Line 9

8

480 |

9
...

a
...

c
...


What is the output if the input is Hello J?
What is the output if the input is Bingo R?
What is the output if the input is Sunny B?

Suppose that you have the following statements:
string str1, str2;
cin >> str1 >> str2;
if (str1 == str2)
cout << str1 + '!' << endl;
else if (str1 > str2)
cout << str1 + " > " + str2 << endl;
else
cout << str1 + " < " + str2 << endl;

Answer the following questions
...

b
...

11
...
length() << endl;
str1
...
substr(1, 5) << endl;

Programming Exercises

|

481

str = "ABCDEFGHIJK";
cout << str << endl;
cout << str
...


return 0;

Consider the following statement:
string str = "Now is the time for the party!";

What is the output of the following statements? (Assume that all parts are
independent of each other
...


cout << str
...


cout << str
...


string::size_type ind = str
...
substr(ind + 4, 9);
cout << s << endl;

d
...
insert(11, "best ") << endl;

e
...
erase(16, 14);
str
...


2
...


Define an enumeration type, triangleType, that has the values
scalene, isosceles, equilateral, and noTriangle
...
Write a function, triangleShape, that takes as parameters three numbers, each of which represents the length of a side of the triangle
...
(Note: In a triangle, the sum
of the lengths of any two sides is greater than the length of the third side
...
Write a program that prompts the user to input the length of the sides of
a triangle and outputs the shape of the triangle
...

The Programming Example: Pig Latin Strings converts a string into the pig
Latin form, but it processes only one word
...
If a word ends with a
punctuation mark, in the pig Latin form, put the punctuation at the end of
the string
...

Assume that the text contains the following punctuation marks: , (comma),

a
...
(period), ? (question mark), ; (semicolon), and : (colon)
...


5
...
)
Write a program that prompts the user to input a string
...
For example, if
str = "There", then after removing all the vowels, str = "Thr"
...
Your program must contain a
function to remove all the vowels and a function to determine whether a
character is a vowel
...
The tax is
calculated as follows: For single people, the standard exemption is $4,000; for
married people, the standard exemption is $7,000
...
The tax rates are as
follows: If the taxable income is:
Between $0 and $15,000, the tax rate is 15%
...

• Over $40,000, the tax is $8,460 plus 35% of the taxable income over
$40,000
...
)
• Percentage of gross income contributed to a pension fund
Your program must consist of at least the following functions:
a
...


6
...


Function getData: This function asks the user to enter the relevant data
...


To calculate the taxable income, subtract the sum of the standard exemption,
the amount contributed to a pension plan, and the personal exemption,
which is $1,500 per person
...
)
A set of integers a, b, and c is called a Pythagorean triple if a2 + b2 = c2
...
To find Pythagorean triples, use the following formula
...
If a = m2 – n2, b = 2mn, and c = m2 + n2, then a, b, and c are a
Pythagorean triple
...

(Fraction calculator) Write a program that lets the user perform arithmetic
operations on fractions
...
Your program must be menu driven, allowing the user to

Programming Exercises

|

483

select the operation (+, -, *, or /) and input the numerator and denominator
of each fraction
...


b
...


d
...


Function menu: This function informs the user about the program’s
purpose, explains how to enter data, and allows the user to select the
operation
...

(Notice that this function has a total of six parameters
...
(Notice that this function has a total of six parameters
...
(Notice that this function has a total of six parameters
...

(Notice that this function has a total of six parameters
...


9
...

Write a program that reads in a line consisting of a student’s name, Social
Security number, user ID, and password
...
(The Social Security number is in the form
000-00-0000, and the user ID and the password do not contain any
spaces
...
Use the appropriate functions described in Table 8-1
...
(Note that a student may not have a
middle name
...
Your program must read each
student’s entire name in a variable and must consist of a function that takes as
input a string, consists of a student’s name, and returns the string consisting of
the altered name
...


8

This page intentionally left blank

9

CHAPTER

A RRAYS

AND

S TRINGS

I N T H I S C H A P T E R , YO U W I L L :


...


Explore how to declare and manipulate data into arrays


...


Become familiar with the restrictions on array processing


...


Learn how to search an array


...


Examine the use of string functions to process C-strings


...


Learn about parallel arrays


...


Learn about multidimensional arrays

486 |

Chapter 9: Arrays and Strings

In previous chapters, you worked with simple data types
...
One of these categories is the structured data
type
...

Recall that a data type is called simple if variables of that type can store only one value at
a time
...
Simple data types are building blocks of structured data types
...
In Chapters 11 and 12, we will discuss other
structured data types
...
We want to
write a C++ program that reads five numbers, finds their sum, and prints the numbers in
reverse order
...
The
difference here is that we want to print the numbers in reverse order
...
To do this,
we need to store all of the numbers before we start printing them in reverse order
...

//Program to read five numbers, find their sum, and print the
//numbers in reverse order
...
However, if you need to read 100 (or more) numbers and
print them in reverse order, you would have to declare 100 variables and write many
cin and cout statements
...


Arrays

|

487

Note the following in the previous program:
1
...

2
...

3
...

Statement 1 tells you that you have to declare five variables
...
Finally, because all
variables are of the same type, you should be able to specify how many variables
must be declared—and their data type—with a simpler statement than the one we
used earlier
...


Arrays
An array is a collection of a fixed number of components all of the same data type
...

This section discusses only one-dimensional arrays
...

The general form for declaring a one-dimensional array is:
dataType arrayName[intExp];

in which intExp is any constant expression that evaluates to a positive integer
...


EXAMPLE 9-1
The statement:
int num[5];

declares an array num of five components
...
The components are num[0], num[1], num[2], num[3], and num[4]
...


9

488 |

Chapter 9: Arrays and Strings

num[0]
num[1]
num[2]
num[3]
num[4]

FIGURE 9-1

Array num

To save space, we also draw an array, as shown in Figure 9-2(a) or 9-2(b)
...
The index value specifies the position of the component in the array
...
Moreover, in C++,
the array index starts at 0
...
The components are
list[0], list[1],
...
In other words, we have declared 10 variables
(see Figure 9-3)
...


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

34

9
FIGURE 9-4

Array list after execution of the statement list[5]= 34;

Suppose i is an int variable
...
The index expression is evaluated
first, giving the position of the component in the array
...


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

10

45

35

Array list after execution of the statements list[3]= 10;, list[6]= 35;, and
list[5] = list[3] + list[6];
FIGURE 9-5

EXAMPLE 9-2
You can also declare arrays as follows:
const int ARRAY_SIZE = 10;
int list[ARRAY_SIZE];

That is, you can first declare a named constant and then use the value of the named
constant to declare an array and specify its size
...
For example, you cannot do the
following:

int arraySize;

//Line 1

cout << "Enter the size of the array: "; //Line 2
cin >> arraySize;
//Line 3
cout << endl;
//Line 4
int list[arraySize];

//Line 5; not allowed

The statement in Line 2 asks the user to enter the size of the array when the program
executes
...
When
the compiler compiles Line 1, the value of the variable arraySize is unknown
...
In Chapter 14, you will learn
how to specify the size of an array during program execution and then declare an array of
that size using pointers
...
For now, whenever you declare an array, its size must be
known
...
Moreover, if the data is numeric, some other basic operations are
finding the sum and average of the elements of the array
...
This is easily
accomplished using a loop
...
For example, the
following statements read 100 numbers from the keyboard and store the numbers
in list:
for (i = 0; i < 100; i++)
cin >> list[i];

//Line 1
//Line 2

Similarly, if processing list requires outputting the data, then the statement in Line 2
takes the form of an output statement
...

EXAMPLE 9-3
This example shows how loops are used to process arrays
...
The meaning of the other statements is clear
...


Initializing an array: The following loop initializes every component of the array sales to 0
...

for (index = 0; index < 10; index++)
sales[index] = 0
...
Reading data into an array: The following loop inputs the data
into the array sales
...

for (index = 0; index < 10; index++)
cin >> sales[index];

c
...

For simplicity, we assume that the output goes to the screen
...
Finding the sum and average of an array: Because the array
sales, as its name implies, represents certain sales data, it is natural
to find the total sale and average sale amounts
...


Largest element in the array: We now discuss the algorithm to
find the first occurrence of the largest element in an array—that is, the
first array component with the largest value
...
Of course, if you know the location (that is,
the index of the largest element in the array), you can easily determine
the value of the largest element in the array
...
We will use the index of the first occurrence of the
largest element in the array to find the largest sale
...
The general algorithm
is straightforward
...
We then compare
the element pointed to by maxIndex with every subsequent element
in the list
...
The algorithm is as follows:
maxIndex = 0;
for (index = 1; index < 10; index++)
if (sales[maxIndex] < sales[index])
maxIndex = index;
largestSale = sales[maxIndex];

Arrays

|

493

Let us demonstrate how this algorithm works with an example
...


[0]
sales

FIGURE 9-6

[1]

[2]

[3]

[4]

[5]

[6]

[7]

[8]

[9]

12
...
35

19
...
00

14
...
43

35
...
23

66
...
64

Array sales

Here, we determine the largest element in the array sales
...
In the following,
we show the values of maxIndex, index, and certain array elements during each
iteration of the for loop
...
50
12
...
35
19
...
60

25
...
00
25
...
00
39
...
43
39
...
90
98
...
23
98
...
65
35
...
50 < 8
...
50 < 19
...
60 < 25
...
00 < 14
...
00 < 39
...
43 < 35
...
43 < 98
...
23 < 66
...
23 < 35
...
Thus, largestSale = sales[maxIndex] = 98
...

You can write an algorithm to find the smallest element in the array that is similar to the
algorithm for finding the largest element in an array
...
)

Now that we know how to declare and process arrays, let us rewrite the program that we
discussed in the beginning of this chapter
...


9

494 |

Chapter 9: Arrays and Strings

EXAMPLE 9-4
//Program to read five numbers, find their sum, and
//print the numbers in reverse order
...

for (counter = 4; counter >= 0; counter--)
cout << item[counter] << " ";
cout << endl;
}

return 0;

Sample Run: In this sample run, the user input is shaded
...

The index—say, index—of an array is in bounds if index >= 0 and index <=
ARRAY_SIZE À 1
...

Unfortunately, in C++, there is no guard against out-of-bound indices
...
If the index goes out of bounds and the program tries to access
the component specified by the index, then whatever memory location is indicated by
the index that location is accessed
...
Consequently,
several strange things can happen if the index goes out of bounds during execution
...

A loop such as the following can set the index out of bounds:
for (i = 0; i <= 10; i++)
list[i] = 0;

Here, we assume that list is an array of 10 components
...
Logically, list[10] does not exist
...
For example, see the programs
Example_ArrayIndexOutOfBoundsA
...
cpp at the Web site accompanying
this book
...
For
example, the following C++ statement declares an array, sales, of five components and
initializes these components
...
25, 32
...
90, 23, 45
...
25, sales[1] = 32
...
90, sales[3] = 23
...
68
...
The size is determined by the number of initial values in the braces
...
The previous statement is, therefore,
equivalent to:
double sales[] = {12
...
50, 16
...
68};

9

496 |

Chapter 9: Arrays and Strings

Although it is not necessary to specify the size of the array if it is initialized during
declaration, it is a good practice to do so
...
This procedure is called partial initialization of an array
during declaration
...
The following examples help to explain what happens when
you declare and partially initialize an array
...

The statement:
int list[10] = {8, 5, 12};

declares list to be an array of 10 components and initializes list[0] to 8, list[1]
to 5, list[2] to 12, and all other components to 0
...
Note that, here, the size of the array in the declaration
statement does matter
...
In contrast, the statement:
int list[25] = {4, 7};

declares list to be an array of 25 components
...

When you partially initialize an array, then all of the elements that follow the last
uninitialized elements must be uninitialized
...


Some Restrictions on Array Processing
Consider the following statements:
int myList[5] = {0, 4, 8, 12, 16};
int yourList[5]; //Line 2

//Line 1

Arrays

|

497

The statement in Line 1 declares and initializes the array myList, and the statement in
Line 2 declares the array yourList
...
Suppose that you want to copy the elements of
myList into the corresponding elements of yourList
...
C++ does not allow aggregate
operations on an array
...

To copy one array into another array, you must copy it component-wise—that is, one
component at a time
...
The following
statement is illegal and, in fact, would generate a syntax error
...
Note that the following statements
are illegal in the sense that they do not generate a syntax error; however, they do not give
the desired results
...


...


We will comment on these statements in the section Base Address of an Array and Array
in Computer Memory later in this chapter
...


Because arrays are passed by reference only, you do not use the symbol & when declaring
an array as a formal parameter
...
If you specify the size of a one-dimensional array when it is declared as a
formal parameter, the size is ignored by the compiler
...


...

}

The function funcArrayAsParam has two formal parameters: (1) listOne, a onedimensional array of type int (that is, the component type is int) and (2) listTwo, a
one-dimensional array of type double
...

Sometimes, the number of elements in the array might be less than the size of the
array
...
In such situations, we want to
process only the components of the array that hold actual data
...
When the
function initialize is called, the size of the actual array is passed as the second
parameter of the function initialize
...
However, even though an array
is always passed by reference, you can still prevent the function from changing the actual
parameter
...
Consider the following function:

Arrays

|

499

void example(int x[], const int y[], int sizeX, int sizeY)
{

...


...
Any attempt to
change y results in a compile-time error
...

EXAMPLE 9-6
This example shows how to write functions for array processing and declare an array as a
formal parameter
...

//The array to be initialized and its size are passed
//as parameters
...

void initializeArray(int list[], int listSize)
{
int index;

}

for (index = 0; index < listSize; index++)
list[index] = 0;

9

//Function to read and store the data into an int array
...
The parameter listSize specifies the number
//of elements to be read
...

//The array to be printed and the number of elements
//are passed as parameters
...

void printArray(const int list[], int listSize)
{
int index;

}

for (index = 0; index < listSize; index++)
cout << list[index] << " ";

500 |

Chapter 9: Arrays and Strings

//Function to find and return the sum of the
//elements of an int array
...

int sumArray(const int list[], int listSize)
{
int index;
int sum = 0;
for (index = 0; index < listSize; index++)
sum = sum + list[index];
}

return sum;

//Function to find and return the index of the first
//largest element in an int array
...

int indexLargestElement(const int list[], int listSize)
{
int index;
int maxIndex = 0; //assume the first element is the largest
for (index = 1; index < listSize; index++)
if (list[maxIndex] < list[index])
maxIndex = index;
}

return maxIndex;

//Function to copy some or all of the elements of one array
//into another array
...
The parameter
//numOfElements specifies the number of elements of list1 to
//be copied into list2
...
The following call copies all of the
//elements of list1 into the corresponding positions in
//list2: copyArray(list1, 0, list2, 0, numOfElements);
void copyArray(int list1[], int src, int list2[],
int tar, int numOfElements)
{
for (int index = src; index < src + numOfElements; index++)
{
list2[index] = list1[tar];
tar++;
}
}

Example 9-7 will illustrate how to use some of these functions in a program
...
For example, if list is a one-dimensional array, then the base address of
list is the address of the component list[0]
...
The
components are myList[0], myList[1], myList[2], myList[3], and myList[4]
...
Moreover, the five memory spaces are contiguous
...

Suppose that the base address of the array myList is 1000
...
Typically, the memory allocated for an int variable is
four bytes
...
Typically, each cell is one byte
...
It follows that the starting address of myList[1] is 1004, the starting
address of myList[2] is 1008, and so on (see Figure 9-7)
...


...

myList [0]

1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019

myList [1]

myList [2]

myList [3]

myList [4]


...


...
There is also a memory space associated with the
identifier myList, and the base address of the array is stored in that memory space
...
That is, this statement
will not output the values of the components of myList
...
This is why the statement will
not generate a syntax error
...


...


//Line 3

the expression myList <= yourList evaluates to true if the base address of the array
myList is less than the base address of the array yourList; and evaluates to false
otherwise
...

The Web site accompanying this book contains the program
BaseAddressOfAnArray
...


You might be wondering why the base address of an array is so important
...
Using the base address of the array and the
index of an array component, the computer determines the address of a particular
component
...

Now, the base address of myList is 1000
...
To access the value of
myList[3], the computer calculates the address 1000 + 4 * 3 = 1000 + 12 = 1012
...
So, starting at 1012, the computer
accesses the next four bytes
...
For example, suppose that you have the following
function:

Arrays

|

503

void arrayAsParameter(int list[], int size)
{

...


...


...


Also, suppose that you have the following call to this function:
arrayAsParameter(myList, 5);

//Line 5

In this statement, the base address of myList is passed to the formal parameter list
...
The definition of the function contains
the statement list[2] = 28;
...
To access
list[2], the computer calculates the address as follows: 1000 + 4 * 2 = 1008
...

Note that, in fact, 1008 is the address of myList[2] (see Figure 9-7)
...
It also follows that during the execution of the function call
statement in Line 5, list[index] and myList[index] refer to the same memory
space, where 0 <= index and index < 5
...
If the array size was
large, this process would waste memory as well as the computer time needed for copying
the data
...


Functions Cannot Return a Value of the Type Array
C++ does not allow functions to return a value of the type array
...


EXAMPLE 9-7
The following program illustrates how arrays are passed as actual parameters in a function
call
...

//Arrays as parameters to functions
#include

9

504 |

Chapter 9: Arrays and Strings

using namespace std;
const int ARRAY_SIZE = 10;
void initializeArray(int x[],int sizeX);
void fillArray(int x[],int sizeX);
void printArray(const int x[],int sizeX);
int sumArray(const int x[],int sizeX);
int indexLargestElement(const int x[],int sizeX);
void copyArray(int list1[], int src, int list2[],
int tar, int numOfElements);
int main()
{
int listA[ARRAY_SIZE] = {0}; //Declare the array listA
//of 10 components and
//initialize each component
//to 0
...

cout << "Line 1: listA elements: ";

//Line 1

//Output the elements of listA using
//the function printArray
printArray(listA, ARRAY_SIZE);
cout << endl;

//Line 2
//Line 3

//Initialize listB using the function
//initializeArray
initializeArray(listB, ARRAY_SIZE);

//Line 4

cout << "Line 5: listB elements: ";

//Line 5

//Output the elements of listB
printArray(listB, ARRAY_SIZE);
cout << endl << endl;

//Line 6
//Line 7

cout << "Line 8: Enter " << ARRAY_SIZE
<< " integers: ";

//Line 8

//Input data into listA using the
//function fillArray
fillArray(listA, ARRAY_SIZE);
cout << endl;

//Line 9
//Line 10

cout << "Line 11: After filling listA, "
<< "the elements are:" << endl;

//Line 11

//Output the elements of listA
printArray(listA, ARRAY_SIZE);
cout << endl << endl;

//Line 12
//Line 13

Arrays

//Find and output the sum of the elements
//of listA
cout << "Line 14: The sum of the elements of "
<< "listA is: "
<< sumArray(listA, ARRAY_SIZE) << endl
<< endl;

|

505

//Line 14

//Find and output the position of the largest
//element in listA
cout << "Line 15: The position of the largest "
<< "element in listA is: "
<< indexLargestElement(listA, ARRAY_SIZE)
<< endl;
//Line 15
//Find and output the largest element
//in listA
cout << "Line 16: The largest element in "
<< "listA is: "
<< listA[indexLargestElement(listA, ARRAY_SIZE)]
<< endl << endl;
//Line 16
//Copy the elements of listA into listB using the
//function copyArray
copyArray(listA, 0, listB, 0, ARRAY_SIZE);
//Line 17
cout << "Line 18: After copying the elements "
<< "of listA into listB," << endl
<< "
listB elements are: ";
//Output the elements of listB
printArray(listB, ARRAY_SIZE);
cout << endl;
}

//Line 18

9
//Line 19
//Line 20

return 0;

//Place the definitions of the functions initializeArray,
//fillArray, and so on here
...


Sample Run: In this sample run, the user input is shaded
...
First, we declare the array listA of 10
components and initialize each component of listA to 0
...
The statement in Line 2 calls the function printArray and
outputs the values stored in listA
...
The statement in Line 14 calls the function sumArray and
outputs the sum of all of the elements of listA
...


Integral Data Type and Array Indices
The sections ‘‘Enumeration Type’’ and ‘‘typedef Statement’’ from Chapter 8 are
required to understand this section
...
This
feature can greatly enhance a program’s readability
...
0;

The following statement updates the sale amount of RED paint:
paintSale[RED] = paintSale[RED] + 75
...
For this reason, you should use the enumeration type for the array index or
other integral data types wherever possible
...
That is,
the value of the first identifier must be 0, and so on
...
)

Searching an Array for a Specific Item |

507

Other Ways to Declare Arrays
Suppose that a class has 20 students and you need to keep track of their scores
...
The statements in Lines 3 and 4 declare two variables, yourList and
myList
...
Of course, these statements
are equivalent to:
double yourList[50];
double myList[50];

Searching an Array for a Specific Item
Searching a list for a given item is one of the most common operations performed on a
list
...

As the name implies, you search the array sequentially, starting from the first array
element
...

Consider the list of seven elements shown in Figure 9-8
...
A sequential search works
as follows: First, you compare 27 with list[0], that is, compare 27 with 35
...
Because list[1] 6¼ 27, you compare 27 with the next element in the list, that is,
compare 27 with list[2]
...
This search is successful
...
As before, the search starts at the first element in the list, that is,
at list[0]
...
Eventually, no more data is left in the list to
compare with the search item
...

It now follows that, as soon as you find an element in the list that is equal to the search item,
you must stop the search and report success
...
) Otherwise, after the search item is unsuccessfully
compared with every element in the list, you must stop the search and report failure
...
The previous
discussion translates into the following algorithm for the sequential search:
found is set to false;
loc = 0;
while (loc < listLength and not found)
if (list[loc] is equal to searchItem)
found is set to true
else
increment loc
if (found)
return loc;
else
return -1;

The following function performs a sequential search on a list
...

int seqSearch(const int list[], int listLength, int searchItem)
{
int loc;
bool found = false;
loc = 0;
while (loc < listLength && !found)
if (list[loc] == searchItem)
found = true;
else
loc++;
if (found)
return loc;
else
return -1;
}

If the function seqSearch returns a value greater than or equal to 0, it is a successful
search; otherwise, it is an unsuccessful search
...
If searchItem is equal to the first element in the list, you
exit the loop; otherwise, loc is incremented by 1 to point to the next element in the
list
...

EXAMPLE 9-8
// This program illustrates how to use a sequential search in a
// program
...
" << endl;
for (int index = 0; index < ARRAY_SIZE; index++)
cin >> intList[index];

//Line 10
//Line 11

cout << endl;

//Line 12

cout << "Line 13: Enter the number to be "
<< "searched: ";
cin >> number;
cout << endl;

//Line 13
//Line 14
//Line 15

int pos = seqSearch(intList, ARRAY_SIZE, number);

//Line 16

if (pos!= -1)
cout <<"Line 18: " << number
<< " is found at position " << pos
<< endl;
else
cout << "Line 20: " << number
<< " is not in the list
...


//Line 18
//Line 19
//Line 20
//Line 21
//Line 22

9

510 |

Chapter 9: Arrays and Strings

Sample Run 1: In this sample run, the user input is shaded
...

2 56 34 25 73 46 89 10 5 16
Line 13: Enter the number to be searched: 25
Line 18: 25 is found at position 3

Sample Run 2:
Line 9: Enter 10 integers
...


C-Strings (Character Arrays)
Until now, we have avoided discussing character arrays for a simple reason: Character
arrays are of special interest, and you process them differently than you process other
arrays
...

Character array: An array whose components are of type char
...
The first character
in the ASCII character set is the null character, which is nonprintable
...

The statement:
ch = '\0';

stores the null character in ch, wherein ch is a char variable
...

Because the collating sequence of the null character is 0, the null character is less than any
other character in the char data set
...
However, there is a
subtle difference between character arrays and C-strings
...
In C++,
C-strings are null terminated; that is, the last character in a C-string is always the null
character
...
As you will see, the null character should not
appear anywhere in the C-string except the last position
...


C-Strings (Character Arrays)

|

511

The following are examples of C-strings:
"John L
...
"

From the definition of C-strings, it is clear that there is a difference between 'A' and
"A"
...
Because C-strings are null
terminated, "A" represents two characters: 'A' and '\0'
...
To store
'A', we need only one memory cell of type char; to store "A", we need two memory
cells of type char—one for 'A' and one for '\0'
...

Consider the following statement:
char name[16];

This statement declares an array name of 16 components of type char
...
If you store a C-string of length 10 in name, the first 11
components of name are used and the last 5 are left unused
...
During char array variable declaration, C++ allows the C-string notation to
be used in the initialization statement
...

The statement:
char name[] = "John";

//Line B

declares a C-string variable name of a length large enough—in this case, 5—and stores
"John" in it
...

Most rules that apply to other arrays also apply to character arrays
...
Johnson" in studentName
...
Johnson"; //illegal

9

512 |

Chapter 9: Arrays and Strings

C++ provides a set of functions that can be used for C-string manipulation
...
We often use three of these functions: strcpy
(string copy, to copy a C-string into a C-string variable—that is, assignment); strcmp
(string comparison, to compare C-strings); and strlen (string length, to find the length
of a C-string)
...

TABLE 9-1

strcpy, strcmp, and strlen Functions

Function

Effect
Copies the string s2 into the string variable s1

strcpy(s1, s2)

The length of s1 should be at least as large as s2
Returns a value < 0 if s1 is less than s2

strcmp(s1, s2)

Returns 0 if s1 and s2 are the same
Returns a value > 0 if s1 is greater than s2

strlen(s)

Returns the length of the string s, excluding the null

character

To use these functions, the program must include the header file cstring via the
include statement
...
Let us assume that you use the ASCII character set
...
The C-string "Air" is less than the C-string "Boat" because the first
character of "Air" is less than the first character of "Boat"
...
The C-string "Air" is less than the C-string "An" because the first
characters of both strings are the same, but the second character 'i'
of "Air" is less than the second character 'n' of "An"
...
The C-string "Bill" is less than the C-string "Billy" because the first
four characters of "Bill" and "Billy" are the same, but the fifth
character of "Bill", which is '\0' (the null character), is less than the
fifth character of "Billy", which is 'y'
...
)
4
...


C-Strings (Character Arrays)

|

513

As you can see, the function strcmp compares its first C-string argument with its second
C-string argument character by character
...
Clark");
strcmp(myname, yourname);

yourname = "Kathy Brown"
myname = "Mark G
...

C-strings are enclosed in double quotation marks
...
Therefore, to store the C-string "Hello" in
computer memory, you must use a character array of size 6
...
Thus, in a logical sense, a C-string is a sequence of zero or
more characters, but in the physical sense (that is, to store the C-string in computer
memory), a C-string has at least one character
...
However, you must remember that the null
character stored in computer memory at the end of the C-string plays a key role when we
compare C-strings, especially C-strings such as "Bill" and "Billy"
...
Aggregate
operations, such as assignment and comparison, are not allowed on arrays
...
However, the one place where C++ allows
aggregate operations on arrays is the input and output of C-strings (that is, character arrays)
...
The length of the input C-string must be less
than or equal to 30
...
If the length of the input C-string is
more than 30, then because there is no check on the array index bounds, the computer
continues storing the string in whatever memory cells follow name
...

When you input a C-string using an input device, such as the keyboard, you do not include
the double quotes around it unless the double quotes are part of the string
...


Recall that the extraction operator, >>, skips all leading whitespace characters and stops
reading data into the current variable as soon as it finds the first whitespace character or
invalid data
...
For example, if a first name and last name are separated by blanks, they
cannot be read into name
...
Recall that the function get is used to read character data
...

However, the function get can also be used to read strings
...
The first parameter is a C-string variable;
the second parameter specifies how many characters to read into the string variable
...
get(str, m + 1);

This statement stores the next m characters, or all characters until the newline character
'\n' is found, into str
...
If the input C-string
has fewer than m characters, then the reading stops at the newline character
...
get(str, 31);

If the input is:
William T
...
Johnson" is stored in str
...
My name is Mickey Blair
...
My
name is Mickey" is stored in str
...

Winter will be cold
...
Both str1 and str2 can store C-strings that are up to 25 characters in length
...
You must read and
discard the newline character at the end of the first line to store the second line into str2
...
get(str1, 26);
cin
...
get(str2, 26);

To read and store a line of input, including whitespace characters, you can also use the
stream function getline
...
The null character will be automatically appended as the last
character of textLine
...
getline(textLine, 100);

String Output
The output of C-strings is another place where aggregate operations on arrays are allowed
...
For example, the statement:
cout << name;

outputs the contents of name on the screen
...
Thus, if the length of name is
4, the above statement outputs only four characters
...


Specifying Input/Output Files at Execution Time
In Chapter 3, you learned how to read data from a file
...
By doing so, the program always received
data from the same input file
...
Also, for comparison purposes, someone might
want to process each file separately and then store the output in separate files
...
C++ allows the user to do so
...
open(fileName);

...


...
open(fileName);

//open the output file

The Programming Example: Code Detection, given later in this chapter, further illustrates how to specify the names of input and output files during program execution
...
We now want to point out that values (that
is, strings) of type string are not null terminated
...
However, the argument to the function
open must be a null-terminated string—that is, a C-string
...

The header file string contains the function c_str, which converts a value of type string
to a null-terminated character array (that is, C-string)
...
c_str()

in which strVar is a variable of type string
...
open(fileName
...
The output file
has similar conventions
...

Suppose you need to keep track of students’ course grades, together with their ID numbers, so
that their grades can be posted at the end of the semester
...
Because there may be 50
students, you need 50 variables to store the students’ IDs and 50 variables to store their grades
...
Each
array has 50 components
...

The statements:
int studentId[50];
char courseGrade[50];

declare these two arrays
...


...


A
B
C
B
D

Suppose that the input file is opened using the ifstream variable infile
...

Moreover, it is possible that there may be fewer than 50 students in the class
...
The following loop reads the data into the parallel arrays
studentId and courseGrade:
int noOfStudents = 0;
infile >> studentId[noOfStudents] >> courseGrade[noOfStudents];
while (infile && noOfStudents < 50)
{
noOfStudents++;
infile >> studentId[noOfStudents]
>> courseGrade[noOfStudents];
}

Note that, in general, when swapping values in one array, the corresponding values in
parallel arrays must also be swapped
...

In the previous section, you learned how to use one-dimensional arrays to manipulate
data
...
However,
sometimes data is provided in a table form
...
The
dealership sells six types of cars in five different colors
...


[RED]

[BROWN]

[BLACK]

[WHITE]

[GRAY]

[GM]

10

7

12

10

4

[FORD]

18

11

15

17

10

[TOYOTA]

12

10

9

5

12

[BMW]

16

6

13

8

3

[NISSAN]

10

7

12

6

4

[VOLVO]

9

4

7

12

11

inStock

FIGURE 9-9

Table inStock

You can see that the data is in a table format
...
Because the table entries are all of the same type, you can declare a one-dimensional
array of 30 components of type int
...
In other
words, you can simulate the data given in a table format in a one-dimensional array
...

You must also correctly compute the index of a particular element
...

This section first discusses how to declare two-dimensional arrays and then looks at ways
to manipulate data in a two-dimensional array
...

The syntax for declaring a two-dimensional array is:
dataType

arrayName[intExp1][intExp2];

wherein intExp1 and intExp2 are constant expressions yielding positive integer values
...

The statement:
double sales[10][5];

declares a two-dimensional array sales of 10 rows and 5 columns, in which every
component is of type double
...
9 and the columns are numbered 0
...


sales

[0]

[1]

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

FIGURE 9-10

Two-dimensional array sales

[2]

[3]

[4]

9

520 |

Chapter 9: Arrays and Strings

Accessing Array Components
To access the components of a two-dimensional array, you need a pair of indices: one for
the row position and one for the column position
...
indexExp1 specifies the row position; indexExp2 specifies the column
position
...
75;

stores 25
...


sales

[0]

[1]

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

FIGURE 9-11

sales[5][3]

Suppose that:
int i = 5;
int j = 3;

Then, the previous statement:
sales[5][3] = 25
...
75;

So the indices can also be variables
...
75

Two- and Multidimensional Arrays

|

521

Two-Dimensional Array Initialization During Declaration
Like one-dimensional arrays, two-dimensional arrays can be initialized when they are declared
...
Consider the following statement:
int board[4][3] = {{2, 3, 1},
{15, 25, 13},
{20, 4, 7},
{11, 18, 14}};

This statement declares board to be a two-dimensional array of four rows and three
columns
...
Figure 9-12 shows the array board
...
The elements of each row are enclosed within curly braces and separated
by commas
...
All rows are enclosed within curly braces
...
For number arrays, if all components of a row are not specified, the
unspecified components are initialized to 0
...


Two-Dimensional Arrays and Enumeration Types
The section ‘‘Enumeration Types’’ in Chapter 8 is required to understand this section
...
Consider the following statements:
const int NUMBER_OF_ROWS = 6;
const int NUMBER_OF_COLUMNS = 5;
enum carType {GM, FORD, TOYOTA, BMW, NISSAN, VOLVO};
enum colorType {RED, BROWN, BLACK, WHITE, GRAY};
int inStock[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];

9

522 |

Chapter 9: Arrays and Strings

These statements define the carType and colorType enumeration types and define
inStock as a two-dimensional array of six rows and five columns
...
That is, the first row corresponds to the car type GM, the second row
corresponds to the car type FORD, and so on
...

Suppose further that each entry in inStock represents the number of cars of a particular
type and color (see Figure 9-13)
...
This example illustrates that enumeration types can be used effectively
to make the program readable and easy to manage
...
Process the entire array
...
Process a particular row of the array, called row processing
...
Process a particular column of the array, called column processing
...
Finding the largest element in a row (column) or finding the sum of a row
(column) are examples of row (column) processing
...

const int NUMBER_OF_COLUMNS = 6; //This can be set to any number
...


9
matrix

[0]

[1]

[2]

[3]

[4]

[5]

[0]
[1]
[2]
[3]
[4]
[5]
[6]

FIGURE 9-15

Two-dimensional array matrix

Because the components of a two-dimensional array are of the same type, the
components of any row or column are of the same type
...
Therefore, when processing a particular row or column of a two-dimensional array, we use

524 |

Chapter 9: Arrays and Strings

algorithms similar to those that process one-dimensional arrays
...

Suppose that we want to process row number 5 of matrix (that is, the sixth row of
matrix)
...
The
second index (the column position) ranges from 0 to 5
...
The components of this column are:
matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2], matrix[4][2],
matrix[5][2], matrix[6][2]

Here, the second index (that is, the column position) is fixed at 2
...
In this case, we can use the following for loop to
process column 2 of matrix:
for (row = 0; row < NUMBER_OF_ROWS; row++)
process matrix[row][2]

Clearly, this for loop is equivalent to the following for loop:
col = 2;
for (row = 0; row < NUMBER_OF_ROWS; row++)
process matrix[row][col]

Next, we discuss specific processing algorithms
...
As
explained earlier, the following for loop does this:
row = 4;
for (col = 0; col < NUMBER_OF_COLUMNS; col++)
matrix[row][col] = 0;

If you want to initialize the entire matrix to 0, you can also put the first index, that is,
the row position, in a loop
...
The following
nested for loops print the components of matrix, one row per line:
for (row = 0; row < NUMBER_OF_ROWS; row++)
{
for (col = 0; col < NUMBER_OF_COLUMNS; col++)
cout << setw(5) << matrix[row][col] << " ";
}

cout << endl;

Input
The following for loop inputs the data into row number 4, that is, the fifth row of matrix:
row = 4;
for (col = 0; col < NUMBER_OF_COLUMNS; col++)
cin >> matrix[row][col];

As before, by putting the row number in a loop, you can input data into each component
of matrix
...

sum = 0;
row = 4;
for (col = 0; col < NUMBER_OF_COLUMNS; col++)
sum = sum + matrix[row][col];

Once again, by putting the row number in a loop, we can find the sum of each row
separately
...
Next, we
give the C++ code to perform these operations
...

for (col = 1; col < NUMBER_OF_COLUMNS; col++)
if (largest < matrix[row][col])
largest = matrix[row][col];

The following C++ code determines the largest element in each row and each column:
//Largest element in each row
for (row = 0; row < NUMBER_OF_ROWS; row++)
{
largest = matrix[row][0]; //Assume that the first element
//of the row is the largest
...

for (row = 1; row < NUMBER_OF_ROWS; row++)
if (largest < matrix[row][col])
largest = matrix[row][col];

}

cout << "The largest element in column " << col + 1
<< " = " << largest << endl;

Two- and Multidimensional Arrays

|

527

Passing Two-Dimensional Arrays as Parameters to Functions
Two-dimensional arrays can be passed as parameters to a function, and they are passed by
reference
...
If matrix is the name of a two-dimensional
array, then matrix[0][0] is the first component of matrix
...
That is, the first row is stored first, followed by the second row, followed by
the third row, and so on
...
Because C++ stores two-dimensional arrays in row
order form, to compute the address of a component correctly, the compiler must know
where one row ends and the next row begins
...

Suppose we have the following declaration:
const int NUMBER_OF_ROWS = 6;
const int NUMBER_OF_COLUMNS = 5;

Consider the following definition of the function printMatrix:
void printMatrix(int matrix[][NUMBER_OF_COLUMNS],
int noOfRows)
{
int row, col;
for (row = 0; row < noOfRows; row++)
{
for (col = 0; col < NUMBER_OF_COLUMNS; col++)
cout << setw(5) << matrix[row][col] << " ";

}

}

cout << endl;

This function takes as a parameter a two-dimensional array of an unspecified number of
rows and five columns, and outputs the content of the two-dimensional array
...

Similarly, the following function outputs the sum of the elements of each row of a twodimensional array whose elements are of type int
...

for (col = 1; col < NUMBER_OF_COLUMNS; col++)
if (largest < matrix[row][col])
largest = matrix[row][col];

}

}

cout << "The largest element of row " << (row + 1)
<< " = " << largest << endl;

Likewise, you can write a function to find the sum of the elements of each column, read
the data into a two-dimensional array, find the largest and/or smallest element in each
row or column, and so on
...

EXAMPLE 9-10
The following program illustrates how two-dimensional arrays are passed as parameters to
functions
...

#include
#include
using namespace std;
const int NUMBER_OF_ROWS = 6;
const int NUMBER_OF_COLUMNS = 5;

Two- and Multidimensional Arrays

|

529

void printMatrix(int matrix[][NUMBER_OF_COLUMNS],
int NUMBER_OF_ROWS);
void sumRows(int matrix[][NUMBER_OF_COLUMNS],
int NUMBER_OF_ROWS);
void largestInRows(int matrix[][NUMBER_OF_COLUMNS],
int NUMBER_OF_ROWS);
int main()
{
int board[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]
= {{23, 5, 6, 15, 18},
{4, 16, 24, 67, 10},
{12, 54, 23, 76, 11},
{1, 12, 34, 22, 8},
{81, 54, 32, 67, 33},
{12, 34, 76, 78, 9}};
printMatrix(board, NUMBER_OF_ROWS);
cout << endl;
sumRows(board, NUMBER_OF_ROWS);
cout << endl;
largestInRows(board, NUMBER_OF_ROWS);

//Line 1
//Line
//Line
//Line
//Line
//Line

2
3
4
5
6

return 0;

}

//Place the definitions of the functions printMatrix,
//sumRows, and largestInRows as described previously here
...
The statement in Line 2 uses the

530 |

Chapter 9: Arrays and Strings

function printMatrix to output the elements of board (see the first six lines of the
Sample Run)
...
The statement in Line 6 uses the function largestInRows to find
and print the largest element in each row
...
Because
every name is a string, a convenient way to store the list of names is to use an array
...
Also,
on some compilers, the data type string may not be available in Standard C++ (that is, nonANSI/ISO Standard C++)
...


Arrays of Strings and the string Type
Processing a list of strings using the data type string is straightforward
...
You can declare an array of 100 components of
type string as follows:
string list[100];

Basic operations, such as assignment, comparison, and input/output, can be performed on
values of the string type
...


Arrays of Strings and C-Strings (Character Arrays)
Suppose that the largest string (for example, name) in your list is 15 characters long and
your list has 100 strings
...

list[40]
list[41]

...

The following statement stores "Snow White" in list[1] (see Figure 9-17):
strcpy(list[1], "Snow White");

list
list[0]
list[1] S n o w
list[2]
list[3]

W h i

t e \0


...

list[98]
list[99]

FIGURE 9-17

Array list, showing list[1]

Suppose that you want to read and store data in list and that there is one entry per line
...
get(list[j], 16);

The following for loop outputs the string in each row:
for (j = 0; j < 100; j++)
cout << list[j] << endl;

You can also use other string functions (such as strcmp and strlen) and for loops to
manipulate list
...
If you use Standard C++ header files and the data type string
is available on your compiler, we recommend that you use the data type string to
manipulate lists of strings
...


9

532 |

Chapter 9: Arrays and Strings

If you know the size of the tables with which the program will be working, then you can
use typedef to first define a two-dimensional array data type and then declare variables
of that type
...
Now we
can declare variables of this type
...

You can also use this data type when declaring formal parameters, as shown in the
following code:
void initialize(tableType table)
{
int row;
int col;

}

for (row = 0; row < NUMBER_OF_ROWS; row++)
for (col = 0; col < NUMBER_OF_COLUMNS; col++)
table[row][col] = 0;

This function takes as an argument any variable of type tableType, which is a twodimensional array, and initializes the array to 0
...


Multidimensional Arrays
In this chapter, we defined an array as a collection of a fixed number of elements (called
components) of the same type
...
We can also define three-dimensional or larger arrays
...
Following is the general definition of
an array
...


Two- and Multidimensional Arrays

|

533

The general syntax for declaring an n-dimensional array is:
dataType arrayName[intExp1][intExp2]
...
, and intExpn are constant expressions yielding
positive integer values
...
[indexExpn]

where indexExp1,indexExp2,
...
indexExpi gives the position of the array component in the ith
dimension
...
The size of the first dimension is 10, the size of the second dimension is 5, and the size of the third
dimension is 7
...
The base address
of the array carDealers is the address of the first array component—that is, the
address of carDealers[0][0][0]
...

The statement:
carDealers[5][3][2] = 15564
...
75
...
For example, the nested for
loops:
for (i = 0; i < 10; i++)
for (j = 0; j < 5; j++)
for (k = 0; k < 7; k++)
carDealers[i][j][k] = 0
...
0
...
As parameters, multidimensional arrays are passed by reference only, and a function cannot return a value of
the array type
...


9

534 |

Chapter 9: Arrays and Strings

PROGRAMMING EXAMPLE:

Code Detection

When a message is transmitted in secret code over a transmission channel, it is
usually sent as a sequence of bits, that is, 0s and 1s
...
That is,
the message received at the destination is not the same as the message transmitted;
some of the bits may have been changed
...
One technique is to
transmit the same message twice
...
If the corresponding bits are the same, the message received is
error-free
...
For simplicity, assume that the secret code representing the message is a
sequence of digits (0 to 9) and the maximum length of the message is 250 digits
...
For example, if the
secret code is:
7 9 2 7 8 3 5 6

then the actual message is 7 digits long, and it is transmitted twice
...

PROBLEM
ANALYSIS
AND
ALGORITHM
DESIGN

Because we have to compare the corresponding digits of the secret code and its copy, we
first read the secret code and store it in an array
...
If any of the
corresponding digits are not the same, we indicate this fact by printing a message next
to the digits
...
The first number in the secret code, and in the copy of the secret code,
indicates the length of the code
...

2
...

4
...

If the input file does not exist, exit the program
...

If the length of the secret code is greater than 250, terminate the
program because the maximum length of the code in this program is 250
...
Read and store the secret code into an array
...
Read the length of the copy
...
If the length of the secret code and its copy are the same, compare
the codes
...


To simplify the function main, let us write a function, readCode, to read the secret
code and another function, compareCode, to compare the codes
...
If the length of the
secret code is greater than 250, a bool variable lenCodeOk, which is a
reference parameter, is set to false and the function terminates
...
If the length of the code is less than 250, the readCode

function reads and stores the secret code into an array
...

Furthermore, after reading the length of the secret code and the code itself, the
readCode function must pass these values to the function main
...
The
definition of the function readCode is as follows:
void readCode(ifstream& infile, int list[], int& length,
bool& lenCodeOk)
{
int count;
lenCodeOk = true;
infile >> length;

//get the length of the secret code

if (length > MAX_CODE_SIZE)
{
lenCodeOk = false;
return;
}

}

//Get the secret code
...
Therefore, it must have access

to the array containing the secret code and the length of the secret code
...
Thus, the input stream
variable corresponding to the input file must be passed as a parameter to this function
...
Because the output will be stored in a file, the output stream
variable corresponding to the output file must also be passed as a parameter to this
function
...
This discussion translates into the following algorithm for the
function compareCode:
a
...

c
...


Declare the variables
...

Read the length of the copy of the secret code
...

e
...
1
...

e
...
Output the corresponding digits from the secret code and its copy
...
3
...

f
...

else
Output an error message
...
"
<< endl;
return;
}
outfile << "Code Digit
<< endl;

}

//Step d

//Step e
//Step e
...
2

if (digit != list[count])
//Step e
...
"
endl;
"Error in transmission
...

Main
Algorithm

1
...

3
...


537

Code Digit Copy"

for (count = 0; count < length; count++)
{
infile >> digit;
outfile << setw(5) << list[count]
<< setw(17) << digit;

}

|

Declare the variables
...

Call the function readCode to read the secret code
...

else

Output an appropriate error message
...
S
...

//************************************************************
#include
#include
#include
using namespace std;
const int MAX_CODE_SIZE = 250;
void readCode(ifstream& infile, int list[],
int& length, bool& lenCodeOk);
void compareCode(ifstream& infile, ofstream& outfile,
const int list[], int length);
int main()
{
//Step 1
int codeArray[MAX_CODE_SIZE]; //array to store the secret
//code
int codeLength;
//variable to store the
//length of the secret code
bool lengthCodeOk; //variable to indicate if the length
//of the secret code is less than or
//equal to 250
ifstream incode;
ofstream outcode;

//input file stream variable
//output file stream variable

char inputFile[51]; //variable to store the name of the
//input file
char outputFile[51];
//variable to store the name of
//the output file
cout << "Enter the input file name: ";
cin >> inputFile;
cout << endl;
//Step 2
incode
...
" << endl;
return 1;
}

Programming Example: Code Detection

|

539

cout << "Enter the output file name: ";
cin >> outputFile;
cout << endl;
outcode
...
close();
outcode
...


Sample Run: In this sample run, the user input is shaded
...
txt
Enter the output file name: Ch9_SecretCodeOut
...
txt)
7927835679278356

Output File Data: (Ch9_SecretCodeOut
...


9

540 |

Chapter 9: Arrays and Strings

PROGRAMMING EXAMPLE:

Text Processing

(Line and letter count) Let us now write a program that reads a given text, outputs
the text as is, and also prints the number of lines and the number of times each letter
appears in the text
...

Because there are 26 letters, we use an array of 26 components to perform the letter
count
...

The text is stored in a file, which we will call textin
...
The output will be
stored in a file, which we will call textout
...

Input
Output
PROBLEM
ANALYSIS
AND
ALGORITHM
DESIGN

A file containing the text to be processed
...


Based on the desired output, it is clear that we must output the text as is
...
Furthermore, we
must count the number of lines in the text
...
This requirement suggests
that we cannot use the extraction operator to process the input file
...

Let us first describe the variables that are necessary to develop the program
...


Variables We need to store the line count and the letter count
...
We will use an
array of 26 components to perform the letter count
...
Because data is to be read from an input file and output is to be saved in a
file, we need an input stream variable to open the input file and an output stream
variable to open the output file
...
Clearly, the variable lineCount and the array
letterCount must be initialized to 0
...

2
...

4
...

Open the input and output files
...

While there is more data in the input file:
4
...
For each character in a line:
4
...
1
...

4
...
2
...

4
...
Increment the line count
...
Output the line count and letter counts
...
Close the files
...
Then, with the help
of these functions, we describe the algorithm for the function main
...
It,
therefore, has two parameters: one corresponding to the variable lineCount and one
corresponding to the array letterCount
...
The definition of this function is:
void initialize(int& lc, int list[])
{
int j;
lc = 0;
for (j = 0; j < 26; j++)
list[j] = 0;
} //end initialize

copyText This function reads a line and outputs the line
...
Clearly, this function has
four parameters: an input file stream variable, an output file stream variable, a char

variable, and the array to update the letter count
...
We take this step because this function calls the

9

542 |

Chapter 9: Arrays and Strings

function characterCount, which needs the array letterCount to update the
appropriate letter count
...

void copyText(ifstream& intext, ofstream& outtext, char& ch,
int list[])
{
while (ch != '\n')
//process the entire line
{
outtext << ch;
//output the character
characterCount(ch, list);
//call the function
//character count
intext
...
To increment the appropriate letter count,
it must know what the letter is
...
In pseudocode,

this function is:
a
...

b
...

c
...
At this
step, we must ensure that the character is a letter
...

Following this algorithm, the definition of this function is:
void characterCount(char ch, int list[])
{
int index;
ch = toupper(ch);

//Step a

index = static_cast(ch)
- static_cast('A');

//Step b

if (0 <= index && index < 26)
list[index]++;
} //end characterCount

//Step c

writeTotal This function outputs the line count and the letter count
...

The definition of this function is:

Programming Example: Text Processing |

543

void writeTotal(ofstream& outtext, int lc, int list[])
{
int index;
outtext << endl << endl;
outtext << "The number of lines = " << lc << endl;
for (index = 0; index < 26; index++)
outtext << static_cast(index
+ static_cast('A'))
<< " count = " << list[index] << endl;
} //end writeTotal

We now describe the algorithm for the function main
...

2
...

4
...


Declare the variables
...

If the input file does not exist, exit the program
...

Initialize the variables, such as lineCount and the array
letterCount
...
Read the first character
...
While (not end of input file):
7
...
Process the next line; call the function copyText
...
2
...
(Increment the variable lineCount
...
3
...

8
...
Call the function
writeTotal
...
Close the files
...
S
...
An uppercase letter and a
// lowercase letter are treated as being the same; that is,
// they are tallied together
...
open("textin
...
"
<< endl;
return 1;
}

//Step 3

outfile
...
out");

//Step 4

initialize(lineCount, letterCount);

//Step 5

infile
...
1
lineCount++;
//Step 7
...
get(ch);
//Step 7
...
close();
outfile
...
get(ch);

outtext << ch;
} //end copyText

//output the newline character

void characterCount(char ch, int list[])
{
int index;

9

ch = toupper(ch);

//Step a

index = static_cast(ch)
- static_cast('A');

//Step b

if (0 <= index & index < 26)
list[index]++;
} //end characterCount

//Step c

void writeTotal(ofstream& outtext, int lc, int list[])
{
int index;
outtext << endl << endl;
outtext << "The number of lines = " << lc << endl;
for (index = 0; index < 26; index++)
outtext << static_cast(index
+ static_cast('A'))
<< " count = " << list[index] << endl;
} //end writeTotal

546 |

Chapter 9: Arrays and Strings

Sample Run (textout
...
Through computers, the technological revolution is
drastically changing the way we live and communicate with one
another
...
With the help of computers you
can send letters to, and receive letters from, loved ones within
seconds
...
You can watch how stocks perform in real time, and
instantly buy and sell them
...
They also use
powerful word-processing software to complete their term papers
...

The number of lines = 15
A count = 53
B count = 7
C count = 30
D count = 19
E count = 81
F count = 11
G count = 10
H count = 29
I count = 41
J count = 4
K count = 3
L count = 31
M count = 26
N count = 50
O count = 59
P count = 21
Q count = 0
R count = 45
S count = 48
T count = 62
U count = 24
V count = 7
W count = 15
X count = 0
Y count = 20
Z count = 0

Quick Review |

547

QUICK REVIEW
1
...

3
...

5
...

7
...

9
...


11
...

13
...

15
...


17
...


19
...


A data type is simple if variables of that type can hold only one value at a time
...

An array is a structured data type with a fixed number of components
...

Elements of a one-dimensional array are arranged in the form of a list
...

In C++, an array index starts with 0
...

The value of the index must always be less than the size of the array
...

Arrays can be initialized during their declaration
...

The base address of an array is the address of the first array component
...

When declaring a one-dimensional array as a formal parameter, you usually
omit the array size
...

In a function call statement, when passing an array as an actual parameter,
you use only its name
...

Because as parameters, arrays are passed by reference only, when declaring an
array as a formal parameter, you do not use the symbol & after the data type
...

Although as parameters, arrays are passed by reference, when declaring an
array as a formal parameter, using the reserved word const before the data
type prevents the function from modifying the array
...

The sequential search algorithm searches a list for a given item, starting with
the first element in the list
...

In C++, C-strings are null terminated
...

22
...

24
...

26
...

28
...

30
...

32
...

34
...

36
...

38
...


Chapter 9: Arrays and Strings

In C++, the null character is represented as '\0'
...

C-strings are stored in character arrays
...

Input and output of C-strings is the only place where C++ allows aggregate
operations
...

Commonly used C-string manipulation functions include strcpy (string
copy), strcmp (string comparison), and strlen (string length)
...

Because C-strings are stored in arrays, individual characters in the C-string
can be accessed using the array component access notation
...

In a two-dimensional array, the elements are arranged in a table form
...

In a two-dimensional array, the rows are numbered 0 to ROW_SIZE À 1
and the columns are numbered 0 to COLUMN_SIZE À 1
...

In row processing, a two-dimensional array is processed one row at
a time
...

When declaring a two-dimensional array as a formal parameter, you can
omit the size of the first dimension but not the second
...

C++ stores, in computer memory, two-dimensional arrays in a row order form
...


Mark the following statements as true or false
...

b
...


A double type is an example of a simple data type
...

Arrays can be passed as parameters to a function either by value or by
reference
...

e
...


g
...

The size of an array is determined at compile time
...

Given the declaration:
int list[10];

the statement:
list[5] = list[3] + list[2];
h
...

j
...

If an array index goes out of bounds, the program always terminates in an
error
...

The declaration:
char name[16] = "John K
...


declares name to be an array of 15 characters because the string "John K
...

The declaration:
char str = "Sunny Day";

2
...

l
...

Consider the following declaration:
double salary[10];

In this declaration, identify the following:
The array name
...
The array size
...
The data type of each array component
...
The range of values for the index of the array
...

a
...


a
...


constint size = 100;
double list[SIZE];

c
...
9];

d
...


scores[50] double;

9

550 |

4
...
If a declaration is invaid, explain why
...


int list75;

b
...


int test[-10];

d
...
5];

6
...


Declare an array alpha of 15 components of type int
...

Output the value of the tenth component of the array alpha
...

Set the value of the fifth component of the array alpha to 35
...

Set the value of the ninth component of the array alpha to the sum of
the sixth and thirteenth components of the array alpha
...

Set the value of the fourth component of the array alpha to three
times the value of the eighth component minus 57
...

Output alpha so that five components per line are printed
...


a
...


Suppose list is an array of five components of type int
...


|

551

Suppose list is an array of six components of type int
...


Correct the following code so that it correctly initializes and outputs the
elements of the array
...


12
...
5, 3
...
8, 6
...
2, 7
...
9, 8
...
5, 9
...
However, there are errors in the code
...

for (int i = 1; i
if (scores[i]
cout << i
<< "
13
...
" << endl;

Write C++ statements to define and initialize the following arrays
...


b
...


d
...
Initilaize this array
to the following values: 5
...
3, 5
...
9, 5
...
7, 6
...
1, 5
...
0
...
Initilaize this array to the
following values: 120, 125, 137, 140, 150, 180, 210
...
Initilaize this array to the
following values: '$', '#', '%', '@', '&', '! ', '^'
...
Initilaize this array to
the following values: "fall", "winter", "spring", "summer"
...


Chapter 9: Arrays and Strings

Determine whether the following array declarations are valid
...

b
...


int c[7] = {12, 13, , 14, 16, , 8};

d
...
7, 13
...
75, 20
...

15
...


What is stored in each of the components of list
...


Consider the following function heading:
void tryMe(int x[], int size);

and the declarations:
int list[100];
int score[50];
double gpas[50];

Which of the following function calls is valid?
a
...


tryMe(list, 75);

c
...


tryMe(score, 49);

e
...


tryMe(gpa, 50);

Suppose that you have the following function definition
...


sum(list1[0], list2[0], a);

c
...


19
...


for (int i = 1; i <= 10; i++)
sum(list1[i], list2[i], list[3]);

What is the output of the following C++ code?
double salary[5] = {25000, 36500, 85000, 62500, 97000};
double raise = 0
...


A car dealer has 10 salespersons
...
The management keeps the data in a file and assigns a number, 1 to
10, to each salesperson
...

int cars[10];

21
...

(Assume that data is in the file cars
...
)
What is the output of the following program?
#include
using namespace std;
int main()
{
int count;
int alpha[5];
alpha[0] = 5;
for (count = 1; count < 5; count++)
{
alpha[count] = 5 * count + 10;
alpha[count - 1] = alpha[count] - 4;
}

9

554 |

Chapter 9: Arrays and Strings

cout << "List elements: ";
for (count = 0; count < 5; count++)
cout << alpha[count] << " ";
cout << endl;
}
22
...


return 0;

What is the output of the following C++ code?
const double PI = 3
...
5, 7
...
5, 9
...
5};
double cylinderHeights[5] = {10
...
5, 12
...
5, 8
...


25
...


|

555

When an array is passed as an actual parameter to a function, what is actually
being passed?
In C++, as an actual parameter, can an array be passed by value?
Given the declaration:
char string15[16];

mark the following statements as valid or invalid
...

a
...


strlen(string15);

c
...


cin >> string15;

e
...


if (string15 >= "Nice day")
cout << string15;

g
...


strcpy(string15, "Hello there");

string15[6] = 't';

Given the declaration:
char str1[15];
char str2[15] = "Good day";

mark the following statements as valid or invalid
...

a
...


if (str1 == str2)
cout << " Both strings are of the same length
...


if (strlen(str1) >= strlen(str2))
str1 = str2;

d
...


str1 = str2;

if (strcmp(str1, str2) < 0)
cout << "str1 is less that str2
...
Otherwise, mark
the statement as ‘‘No’’ and explain why it does not output Shelly
...


cout << name;

b
...


int j = 0;
while (name[j] != '\0')
cout << name[j++];

d
...


Chapter 9: Arrays and Strings

Given the declaration:
char str1[21];
char str2[21];

Write a C++ statement that stores "Sunny Day" in str1
...

Write a C++ statement that stores the length of str1 into the int
variable length
...

Write a C++ statement that copies the value of name into str2
...

Write C++ code that outputs str1 if str1 is less than or equal to
str2, and otherwise outputs str2
...


30
...
If a statement is invalid, explain
why
...

b
...


yourName = studentName;

e
...


int x = strcmp(yourName, studentName);

g
...


32
...


31
...

Suppose that array temp is as defined in Exercise 31
...

Output the contents of the first row and last column element of temp
...
Output the contents of the last row and first column element of temp
...
Output the contents of the last row and last column element of temp
...

b
...


const int CAR_TYPES = 5;
const int COLOR_TYPES = 6;

Exercises

|

557

double sales[CAR_TYPES][COLOR_TYPES];

How many components does the array sales have?
b
...
What is the number of columns in the array sales?
d
...
To sum the sales by COLOR_TYPES, what kind of processing is required?
Write C++ statements that do the following:
a
...


Declare an array alpha of 10 rows and 20 columns of type int
...
Initialize the array alpha to 0
...
Store 1 in the first row and 2 in the remaining rows
...
Store 5 in the first column, and make sure that the value in each
subsequent column is twice the value in the previous column
...
Print the array alpha one row per line
...

Print the array alpha one column per line
...


35
...


for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
beta[i][j] = 0;

b
...


for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
beta[i][j] = i * j;

d
...


for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
beta[i][j] = i + j;

for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
beta[i][j] = 2 * (i + j) % 4;

Suppose that you have the following declarations:
int
int
int
int
a
...


times[30][7];
speed[15][7];
trees[100][7];
students[50][7];

Write the definition of the function print that can be used to output
the contents of these arrays
...


9

558 |

Chapter 9: Arrays and Strings

PROGRAMMING EXERCISES
1
...


3
...


5
...


Write a C++ program that declares an array alpha of 50 components of
type double
...
Output the array so that 10 elements per line
are printed
...
Also, write a program to test your function
...
Also, write a program to test your function
...
It should then determine the number of students having
scores in each of the following ranges: 0–24, 25–49, 50–74, 75–99,
100–124, 125–149, 150–174, and 175–200
...
(Run your program with the following input
data: 76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189, 167, 200,
175, 150, 87, 99, 129, 149, 176, 200, 87, 35, 157, 189
...
(Use a character array to store the string
...

The students’ IDs and test answers are stored in a file
...
For example, the entry:
ABC54301 TFTFTFTT TFTFTFFTTFT

7
...
This student did not
answer question 9
...
Each correct answer is awarded two points, each wrong answer
gets one point deducted, and no answer gets zero points
...
The output should be the student’s ID, followed
by the answers, followed by the test score, followed by the test grade
...
99%, B;
70%–79
...
99%, D; and 0%–59
...

Write a program that allows the user to enter the last names of five candidates
in a local election and the number of votes received by each candidate
...

Your program should also output the winner of the election
...
91
20
...
09
12
...
33

The Winner of the Election is Duffy
...


Consider the following function main:
int main()
{
int inStock[10][4];
int alpha[20];
int beta[20];
int gamma[4] = {11, 13, 15, 17};
int delta[10] = {3, 5, 2, 6, 10, 9, 7, 11, 1, 8};

}
a
...


c
...


e
...



...


...

Write the definition of the function inputArray that prompts the user
to input 20 numbers and stores the numbers into alpha
...
Make
sure that you prevent the function from modifying the elements of alpha
...
Make sure that
you prevent the function from modifying the elements of gamma
...
Make sure that you prevent the function from modifying the
elements of alpha and beta
...
Print 15 elements per line
...
The function
should then set the elements in the remaining columns to two times the
corresponding element in the previous column, minus the corresponding element in delta
...
Write C++ statements that call each of the functions in parts a through g
...

Write a C++ program that tests the function main and the functions
discussed in parts a through g
...
)
Write a program that uses a two-dimensional array to store the highest and
lowest temperatures for each month of the year
...
Your program must consist of the following functions:
g
...


Function getData: This function reads and stores data in the twodimensional array
...
Function averageHigh: This function calculates and returns the
average high temperature for the year
...
Function averageLow: This function calculates and returns the average low temperature for the year
...
Function indexHighTemp: This function returns the index of the
highest high temperature in the array
...
Function indexLowTemp: This function returns the index of the
lowest low temperature in the array
...
)
Programming Exercise 8 in Chapter 6 asks you find the mean and standard
deviation of five numbers
...
Suppose that the mean
(average) of n numbers x1, x2,
...
Then, the standard deviation of
these numbers is:
sffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffiffi
ðx1 À xÞ2 þ ðx2 À xÞ2 þ Á Á Á þ ðxi À xÞ2 þ Á Á Á þ ðxn À xÞ2

n
a
...


11
...

So, an integer larger than this cannot be stored and processed as an integer
...
One way to store and manipulate
large integers is to store each individual digit of the number in an array
...
If the sum of the numbers has more than
20 digits, output the sum with an appropriate message
...


13
...
(Hint: Read numbers as
strings and store the digits of the number in the reverse order
...
Each day of the week, they run a certain number of miles and
write them into a notebook
...
Write a program to help them analyze their
data
...
Furthermore,
your program must contain at least the following functions: a function to
read and store the runners’ names and the numbers of miles run each day; a
function to find the total miles run by each runner and the average number
of miles run each day; and a function to output the results
...
)
Write a program to calculate students’ average test scores and their grades
...


|

Use three arrays: a one-dimensional array to store the students’ names, a
(parallel) two-dimensional array to store the test scores, and a parallel onedimensional array to store grades
...
Have your program also output the class average
...
The airplane has 13 rows, with six
seats in each row
...
Your program must prompt
the user to enter the following information:
a
...


Ticket type (first class, business class, or economy class)
Desired seat

9

562 |

Chapter 9: Arrays and Strings

Output the seating plan in the following form:
A
Row
Row
Row
Row
Row
Row
Row
Row
Row
Row
Row
Row
Row

1
2
3
4
5
6
7
8
9
10
11
12
13

B

C

D

E

F

*
*
*
X
*
*
X
*
X
*
*
*
*

*
X
*
*
X
X
*
X
*
X
*
*
*

X
*
X
X
*
*
*
*
X
*
X
X
*

*
X
X
*
X
*
*
X
X
X
*
X
*

X
*
*
X
*
*
X
X
*
X
X
*
X

X
X
X
X
*
X
X
*
X
X
*
X
*

Here, * indicates that the seat is available; X indicates that the seat is
occupied
...


10
CHAPTER

A PPLICATIONS OF A RRAYS
(S EARCHING AND S ORTING )
AND THE vector T YPE
I N T H I S C H A P T E R , YO U W I L L :


...


Learn how to implement the binary search algorithm


...
When the data values are all of the
same type, arrays are a convenient way to store and process them
...
Moreover, you can pass the
entire set of values as a parameter with a single statement
...
We then examine the vector type
...
Because all values are of the same type, a
convenient place to store a list is in an array and, particularly, in a one-dimensional array
...
Because the size of a list can increase and
decrease, the array you use to store the list should be declared as the maximum size of the list
...

Sort the list
...

Delete an item from the list
...


The following sections discuss searching and sorting algorithms
...
Recall that the sequential
search algorithm is:
int seqSearch(const int list[], int listLength, int searchItem)
{
int loc;
bool found = false;
loc = 0;
while (loc < listLength && !found)
if (list[loc] == searchItem)
found = true;
else
loc++;
if (found)
return loc;
else
return -1;
}

List Processing |

565

Suppose that you have a list with 1000 elements
...
Similarly, if the search item is the 900th item in the list, the
sequential search makes 900 key comparisons to determine whether the search item is in the
list
...

Therefore, if searchItem is always at the bottom of the list, it will take many comparisons to
find it
...
A sequential search is therefore not very efficient for large lists
...
So, for a list size
of 1000, on average, the sequential search makes about 500 key comparisons
...
If the list is sorted,
then you can significantly improve the search algorithm as discussed in the section Binary
Search of this chapter
...


Bubble Sort
There are many sorting algorithms
...

Suppose list[0]
...
We want to
rearrange, that is, sort, the elements of list in increasing order
...
If list[index] is greater than list[index + 1], then the elements
list[index] and list[index + 1] are swapped, that is, interchanged
...

In the first iteration, we consider list[0]
...
list[n - 2]; in the third iteration, we consider
list[0]
...
For example, consider list[0]
...


list
list[0]

10

list[1]

7

list[2]

19

list[3]

FIGURE 10-1

List of five elements

5

list[4]

16

1
0

566 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

Iteration 1: Sort list[0]
...
Figure 10-2 shows how the elements
of list get rearranged in the first iteration
...

Therefore, list[0] and list[1] are swapped
...
Because list[1]
< list[2], they do not get swapped
...
Then, in the fourth
diagram, we compare list[3] with list[4]
...

After the first iteration, the largest element is at the last position
...
3]
...
3]
...


7
unsorted
list

10

compare

7
10

7
compare
and
swap

7
5

5
compare

5
16

16

16

19

FIGURE 10-3

5
16

19

19

19

10

10

Elements of list during the second iteration

The elements are compared and swapped as in the first iteration
...
After the second iteration, the last two elements are in the right
place
...
2]
...
2]
...


List Processing |

7
unsorted
list

5

compare
and
swap

5
7

5
compare

7

10

10

10

16

16

16

19

FIGURE 10-4

567

19

19

Elements of list during the third iteration

After the third iteration, the last three elements are in the right
place
...
1]
...
1]
...


unsorted
list

5

compare

5
7

10

10

16

16

19

FIGURE 10-5

7

19

Elements of list during the fourth iteration

After the fourth iteration, list is sorted
...

EXAMPLE 10-1
//Bubble sort
#include
using namespace std;
void bubbleSort(int list[],

int length);

int main()
{
int list[] = {2, 56, 34, 25, 73, 46, 89, 10, 5, 16};
int i;

//Line 1
//Line 2

bubbleSort(list, 10);
cout << "After sorting, the list elements are:"
<< endl;

//Line 4

for (i = 0; i < 10; i++)
cout << list[i] << " ";

//Line 5
//Line 6

cout << endl;
}

//Line 3

//Line 7

return 0;

//Line 8

//Place the definition of the function bubbleSort given
//previously here
...
The statement in Line 3 uses the function bubbleSort to sort list
...
The for loop in Lines 5 and 6 outputs the elements of list
...
However, you can also prompt the user to input the data during program
execution
...
Therefore, if n = 1000,
to sort the list, bubble sort makes about 500,000 key comparisons and about 250,000 item

List Processing |

569

assignments
...

The performance of bubble sort can be improved if we stop the sorting process as soon as
we find that, in an iteration, no swapping of elements takes place
...
See Exercise 12 and Programming Exercise 17 at the end of this chapter
...

As the name implies, in selection sort algorithm, we rearrange the list by selecting an element
in the list and moving it to its proper position
...
The first time, we locate the smallest item in the entire list
...

Suppose you have the list shown in Figure 10-6
...


1
0

list
[0]

16

16

5

[1]

30

30

30

[2]

24

24

24

unsorted [3]
list
[4]

7

7

62

62

62

[5]

45

45

45

swap

7

[6]

5

5

16

[7]

55

55

55

(b)

(c)

(a)

FIGURE 10-7

smallest

Elements of list during the first iteration

unsorted
list

570 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

Initially, the entire list is unsorted
...
The smallest
item is at position 6, as shown in Figure 10-7(a)
...
So, we swap 16 (that is, list[0]) with 5 (that is, list[6]), as
shown in Figure 10-7(b)
...

Figure 10-8 shows the elements of list during the second iteration
...
list[7]
...
The smallest element is at position 3, as shown in Figure 10-8(a)
...

So, we swap 7 (that is, list[3]) with 30 (that is, list[1]), as shown in Figure 10-8(b)
...

Now, the unsorted list is list[2]
...
So, we repeat the preceding process of
finding the (position of the) smallest element in the unsorted portion of the list and
moving it to the beginning of the unsorted portion of the list
...

In the unsorted portion of the list:
a
...

b
...

Initially, the entire list (that is, list[0]
...
After
executing Steps a and b once, the unsorted list is list[1]
...
After
executing Steps a and b a second time, the unsorted list is list[2]
...
In this way, we can keep track of the unsorted portion of the list and repeat Steps a
and b with the help of a for loop, as shown in the following pseudocode:

List Processing |

571

for (index = 0; index < length - 1; index++)
{
a
...
list[length - 1]
...
Swap the smallest element with list[index]
...

}

The first time through the loop, we locate the smallest element in list[0]
...
The second time
through the loop, we locate the smallest element in list[1]
...

Step a is similar to the algorithm for finding the index of the largest item in the list, as
discussed in Chapter 9
...
) Here, we find the
index of the smallest item in the list
...
The following
statements accomplish this task:
temp = list[smallestIndex];
list[smallestIndex] = list[index];
list[index] = temp;

It follows that to swap the values, three item assignments are needed
...

EXAMPLE 10-3
//Selection sort
#include
using namespace std;
void selectionSort(int list[],

int length);

int main()
{
int list[] = {2, 56, 34, 25, 73, 46, 89, 10, 5, 16}; //Line 1
int i;
//Line 2
selectionSort(list, 10);
cout << "After sorting, the list elements are:"
<< endl;
for (i = 0; i < 10; i++)
cout << list[i] << " ";

//Line 4
//Line 5
//Line 6

cout << endl;
}

//Line 3

//Line 7

return 0;

//Line 8

//Place the definition of the function selectionSort given
//previously here
...
Here, we use the
selection sort algorithm to sort the list
...
Therefore, if n = 1000, then to sort the list, selection sort makes
about 500,000 key comparisons and about 3000 item assignments
...


Insertion Sort
As noted in the previous section, for a list of length 1000, both bubble sort and selection
sort make approximately 500,000 key comparisons, which is quite high
...

The insertion sort algorithm sorts the list by moving each element to its proper place
...


[0]
list

FIGURE 10-9

[1]

[2]

[3]

[4]

[5]

[6]

[7]

10

18

25

30

23

17

45

35

list

The length of the list is 8
...
That is, list[0]
...


sorted list

unsorted list

[0]
list

FIGURE 10-10

[1]

[2]

[3]

[4]

[5]

[6]

[7]

10

18

25

30

23

17

45

35

Sorted and unsorted portion of list

Next, we consider the element list[4], the first element of the unsorted list
...
It
thus follows that element list[4] should be moved to list[2] (see Figure 10-11)
...


sorted list

unsorted list

[0]
list

[1]

[2]

[3]

[4]

[5]

[6]

[7]

10

18

25

30

23

17

45

35

temp

FIGURE 10-12

copy

23

Copy list[4] into temp

Next, we copy list[3] into list[4] and then list[2] into list[3] (see Figure
10-13)
...


sorted list

unsorted list

[0]
list

[1]

[2]

[3]

[4]

[5]

[6]

[7]

10

18

25

25

30

17

45

35

temp

FIGURE 10-14

23

list after copying list[3] into list[4] and then list[2] into list[3]

List Processing |

575

We now copy temp into list[2]
...


[0]

[1]

[2]

[3]

[4]

unsorted
list
[5]
[6]

10

18

23

25

30

17

sorted list

list

temp

FIGURE 10-15

23

45

[7]
35

copy

list after copying temp into list[2]

Now list[0]
...
list[7] is unsorted
...

From this discussion, we see that during the sorting phase, the array containing the list is
divided into two sublists, sorted and unsorted
...
We use an index—say, firstOutOfOrder—to point to the first
element in the unsorted sublist
...

This discussion translates into the following pseudocode:
for (firstOutOfOrder = 1; firstOutOfOrder < listLength;
firstOutOfOrder++)
if (list[firstOutOfOrder] is less than list[firstOutOfOrder - 1])
{
copy list[firstOutOfOrder] into temp
initialize location to firstOutOfOrder
do
{
a
...
decrement location by 1 to consider the next element
in the sorted portion of the array

}
while (location > 0 && the element in the upper list at
location - 1 is greater than temp)

}
copy temp into list[location]

The following C++ function implements the previous algorithm:
void insertionSort(int list[], int listLength)

1
0

576 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

{
int firstOutOfOrder, location;
int temp;
for (firstOutOfOrder = 1; firstOutOfOrder < listLength;
firstOutOfOrder++)
if (list[firstOutOfOrder] < list[firstOutOfOrder - 1])
{
temp = list[firstOutOfOrder];
location = firstOutOfOrder;
do
{
list[location] = list[location - 1];
location--;
}
while (location > 0 && list[location - 1] > temp);
list[location] = temp;
}
} //end insertionSort

We leave it as an exercise to write a program to test the insertion sort algorithm
...
Therefore, if n = 1000, to sort
the list, insertion sort makes about 250,000 key comparisons and about 250,000 item
assignments
...
In fact, these are not the only sorting
algorithms
...
The answer is that the performance of each sorting algorithm is different
...
Also,
there are algorithms that make fewer comparisons, as well as fewer item assignments
...
Analysis of the number of key
comparisons and item assignments allows the user to decide which algorithm to use in a
particular situation
...
It typically searches about half of
the list
...
A binary search is much faster than a sequential search
...


List Processing |

577

A binary search uses the ‘‘divide and conquer’’ technique to search the list
...
If the search item is less than
the middle element of the list, we restrict the search to the upper half of the list;
otherwise, we search the lower half of the list
...


list

FIGURE 10-16

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]
89 95
4
8
19 25 34 39 45 48 66 75

List of length 12

Suppose that we want to determine whether 75 is in the list
...


search list
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]
89 95
list 4
8
19 25 34 39 45 48 66 75
mid

FIGURE 10-17

Search list, list[0]
...
Since
75 6¼ list[5] and 75 > list[5], next we restrict our search to list[6]
...


[0] [1] [2] [3] [4] [5]
list 4
8
19 25 34 39

FIGURE 10-18

[6]
45

[7]
48

search list
[8]
[9]
66 75

[10]
89

[11]
95

Search list, list[6]
...
list[11], which is a list of
length = 6
...
To determine the middle element of

1
0

578 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

the list, we add the starting index, first, and the ending index, last, of the search list
þ
and divide by 2 to calculate its index
...
Initially, first = 0 and
(since array index in C++ starts at 0 and listLength denotes the number of elements in
the list) last = listLength À 1
...
)
The following C++ function implements the binary search algorithm
...
If the search item is not in the list, -1 is
returned
...

Next, we walk through the binary search algorithm on the list shown in Figure 10-19
...
Suppose that the item
for which we are searching is 89, so searchItem = 89
...
In the following, we trace the execution of
the while loop, showing the values of first, last, and mid and the number of key

comparisons during each iteration
...
of key comparisons
2
2
1 (found is true)

The item is found at location 10, and the total number of key comparisons is 5
...
Before the while loop executes,
first = 0, last = 11, and found = false
...

Iteration
1
2
3
4

first
0
0
3
4

last
11
4
4
4

mid
5
2
3
4

list[mid]
39
19
25
34

No
...

Let’s now search for 22, so searchItem = 22
...
In the following, as before, we trace the execution
of the while loop, showing the values of first, last, and mid and the number of key
comparisons during each iteration
...
of key comparisons
39
2
19
2
25
2
the loop stops (since first > last)

mid
5
2
3

unsuccessful search

This is an unsuccessful search
...

From these tracings of the binary search algorithm, you can see that every time you go
through the loop, you cut the size of the sublist by half
...


1
0

580 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

We leave it as an exercise for you to write a program to test the function binarySearch
...


Performance of Binary Search
Suppose that L is a sorted list of size 1024, and we want to determine whether an item x is
in L
...
(For example, see Figures 10-17 and 10-18
...
Because every iteration of the while loop makes two item (key)
comparisons, that is, x is compared twice with the elements of L, the binary search will make,
at most, 22 comparisons to determine whether x is in L
...

To better understand how fast binary search is compared to sequential search, suppose that L
is of size 1048576
...
Every iteration
of the while loop makes two key (that is, item) comparisons
...

Note that 40 = 2 * 20 = 2 * log2220 = 2 * log2(1048576)
...
Moreover, suppose that n is a power of
2, that is, n = 2m, for some nonnegative integer m
...
For example, after the first iteration, the search sublist
is of size about n/2 = 2m-1
...
Also m = log2n
...
Thus, the maximum number of comparisons to determine whether an
element x is in L is 2(m + 1) = 2(log2n + 1) = 2log2n + 2
...


Chapter 9 and the previous sections of this chapter described how arrays can be used to
implement and process lists
...
This means that only a fixed number of
elements can be stored in an array
...
Similarly, removing an
element from the array also could require shifting the elements of the array, as we
typically do not leave empty positions between array positions holding some data
...


vector Type (class) | 581

In addition to arrays, C++ provides the vector type (most commonly called the class
vector) to implement a list
...
Unlike an array, the size
of a vector object can grow and shrink during program execution
...

When you declare a vector object, you must specify the type of the element the vector
object stores
...

TABLE 10-1

Various Ways to Declare and Initialize a vector Object

Statement

Effect

vector vecList;

Creates the empty vector object
vecList without any elements
...

vecList and otherVecList
are of the same type
...
vecList
is initialized using the default values
...
vecList is
initialized using n copies of the
element elem
...

EXAMPLE 10-3
a
...

vector intList;

b
...
The elements of intList are
initialized to 0
...
To do so, we must know the following basic operations:




Item insertion
Item deletion
Stepping through the elements of a vector container

The type vector provides various operations to manipulate data stored in a vector
object
...
Table 10-2 describes
some of these functions and how to use them with a vector object
...
The name of the function is shown in bold
...
at(index)

Returns the element at the position
specified by index
...


vecList
...
(Does not check
whether the object is empty
...
back()

Returns the last element
...
)

vecList
...


vecList
...


vecList
...


vecList
...


vecList
...
The value returned
is an unsigned int value
...
max_size()

Returns the maximum number of elements
that can be inserted into the object
vecList
...
(Recall that in C++, arrays start at location 0
...
) (Note that both the function at and the subscripting
operator [] return the elements at the specified position
...
)
(Exceptions are discussed in Chapter 16
...

Example 10-4 uses a for loop and the array subscripting operator, [], to access the elements
of intList
...
Does this mean that we
can store only five elements in intList? The answer is no
...
However, because when we declared intList, we specified the size
to be 5, in order to add any elements past position 4, we use the function push_back
...
Example 10-5
explains how to use this function
...
push_back(34);
intList
...


In Example 10-5, because intList is declared to be of size 0, we use the function
push_back to add elements to intList
...
For example,
suppose that intList is declared as in Example 10-5
...
resize(10);

Similarly, the following statement increases the size of intList by 10:
intList
...
size() + 10);

However, at times, the push_back function is more convenient because it does not need
to know the size of the vector; it simply adds the elements at the end
...
Therefore, to
use the class vector, you must include the header file vector, that is, include the
following statement in your program:

#include

The program in Example 10-6 illustrates how to use a vector object in a program and
how to process the elements of a vector
...

#include
#include
using namespace std;
int main()
{
vector intList;
unsigned int i;

//Line 1
//Line 2

intList
...
push_back(75);
intList
...
push_back(35);

//Line
//Line
//Line
//Line

3
4
5
6

cout << "Line 7: List Elements: ";

//Line 7

for (i = 0; i < intList
...
size(); i++)
intList[i] = intList[i] * 2;

//Line 11
//Line 12

cout << "Line 13: List Elements: ";

//Line 13

Programming Example: Election Results

for (i = 0; i < intList
...
The statement in Line 2 declares i to be an unsigned int variable
...
size(), which returns an unsigned int value, to determine the size of intList
...
The statements in Lines 8 and 9 use a
for loop and the array subscripting operator, [], to output the elements of intList
...
The statements in Lines 11 and 12 use a for loop to double the value of
each element of intList; the statements in Lines 14 and 15 output the elements of
intList
...


The data type (class) vector is a part of C++ standard template library (STL)
...


PROGRAMMING EXAMPLE:

Election Results

The presidential election for the student council of your local university will be held
soon
...
The chair is looking for someone to write a program to analyze
the data and report the winner
...

The university has four major divisions, and each division has several departments
...
Each department in each division manages its own voting
process and directly reports the results to the election committee
...


...


Region1
------23
25
110

Votes
Region2
Region3
------------89
0
71
89
158
0

Region4
------160
97
0

Total
----272
282
268

Winner: ???, Votes Received: ???
Total votes polled: ???

The names of the candidates in the output must be in alphabetical order
...
This program can be modified to accommodate any number of candidates
...
One file, candData
...
The names in the file are in no particular order
...
txt, each line consists of voting results in the following form:
candidateName regionNumber numberOfVotesForTheCandidate

That is, each line in the file voteData
...
There is one entry
per line
...


...


The first line indicates that Mia received 34 votes from region 2
...


Output

The election results in a tabular form, as described previously, and the winner
...
The program must also calculate the total number of votes received
by each candidate, as well as the total votes cast in the election
...

Because the data type of a candidate’s name (which is a string) and the data type of
the number of votes (which is an integer) are different, we need two separate
arrays—one to hold the candidates’ names and one to hold the voting data
...
Instead of using a single two-dimensional array
to hold the voting data, we will use a two-dimensional array to hold the next four
columns of the output (that is, the votes by region data) and a one-dimensional
array to hold the total votes received by each candidate
...


candidatesName

votesByRegion
[0] [1] [2] [3]

totalVotes

[0]

[0]

[0]

[1]

[1]

[1]

[2]

[2]

[2]

[3]

[3]

[3]

[4]

[4]

[4]

[5]

[5]

[5]

FIGURE 10-20

Parallel arrays: candidatesName, votesByRegion, and totalVotes

The data in the first row of these three arrays corresponds to the candidate whose
name is stored in the first row of the array candidatesName, and so on
...
Recall that in C++, an array index starts at 0
...

For easy reference, suppose that in the program, the name of the candidates’
names array is candidatesName, the name of the voting totals by region array is
votesByRegion, and the name of the total votes array is totalVotes
...
txt into the array candidatesName
...

Next, we must process the voting data
...
txt contains a
candidateName, regionNumber, and votesReceivedByTheCandidate
...
Therefore, it follows that the
array votesByRegion must be initialized to zero
...
)
After processing the voting data, the next step is to calculate the total votes received
by each candidate
...
Therefore, we must initialize the array totalVotes to zero
...

This discussion translates into the following algorithm:
1
...

3
...

5
...


Read the candidates’ names into the array candidatesName
...

Initialize the arrays votesByRegion and totalVotes
...

Calculate the total votes received by each candidate
...


Because the input data is provided in two separate files, in this program, we must
open two files
...

To implement these six steps of the algorithm, this program consists of several
functions, as described next
...
txt and fills the array
candidatesName
...
We see that this
function has three parameters: one corresponding to the input file, one corresponding
to the array candidatesName, and one to pass the number of rows of the array
candidatesName
...


candidatesName
[0]

votesByRegion
[1] [2] [3]

totalVotes

[0] Mia

[0]

[0]

[1] Mickey

[1]

[1]

[2] Donald

[2]

[2]

[3] Peter

[3]

[3]

[4] Danny

[4]

[4]

[5] Ashley

[5]

[5]

FIGURE 10-21

Function
sortCandidatesName

Arrays candidatesName, votesByRegion, and totalVotes after reading
candidates’ names

This function uses the selection sort algorithm to sort the array candidatesName
...
Essentially,
this function is:
void sortCandidatesName(string cNames[], int noOfRows)
{
int i, j;
int min;
//selection sort
for (i = 0; i < noOfRows - 1; i++)
{
min = i;
for (j = i + 1; j < noOfRows; j++)
if (cNames[j] < cNames[min])
min = j;

}

}

cNames[i]
...


1
0

590 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

candidatesName
[0]

votesByRegion
[1] [2] [3]

totalVotes

[0] Ashley

[0]

[0]

[1] Danny

[1]

[1]

[2] Donald

[2]

[2]

[3] Mia

[3]

[3]

[4] Mickey

[4]

[4]

[5] Peter

[5]

[5]

FIGURE 10-22

Arrays candidatesName, votesByRegion, and totalVotes after sorting
names

Function The function initialize initializes the arrays votesByRegion and totalVotes to
initialize zero
...
Note that both arrays have the same

number of rows
...


Programming Example: Election Results

candidatesName
[0]

votesByRegion
[1] [2] [3]

|

591

totalVotes

[0] Ashley

[0]

0

0

0

0

[0]

0

[1] Danny

[1]

0

0

0

0

[1]

0

[2] Donald

[2]

0

0

0

0

[2]

0

[3] Mia

[3]

0

0

0

0

[3]

0

[4] Mickey

[4]

0

0

0

0

[4]

0

[5] Peter

[5]

0

0

0

0

[5]

0

FIGURE 10-23

Arrays candidatesName, votesByRegion, and totalVotes after initializing

Process Processing the voting data is quite straightforward
...
txt is
Voting Data in the following form:
candidatesName regionNumber numberOfVotesForTheCandidate

The general algorithm to process the voting data is shown next
...
txt, we do the following:
Get a candidateName, regionNumber, and
numberOfVotesForTheCandidate
...
Find the row number in the array candidatesName that
corresponds to this candidate
...

c
...

d
...

a
...
Because the array candidatesName is sorted,
we can use the binary search algorithm to find the row number corresponding to a
particular candidate
...
We will write
the definition of the function binSearch shortly
...

Suppose that the three arrays are as shown in Figure 10-24
...
To find the
row, we search the array candidatesName to find the row that corresponds to this
name
...


Donald

region = 2

candidatesName
[0]
[0] Ashley

[0]

[1] Danny

[1]

[2] Donald

[2]

[3] Mia

[3]

0

[4] Mickey

[4]

50

[5] Peter

[5]

100

FIGURE 10-25

votesByRegion
[1] [2] [3]

totalVotes

0

50

0

[0]

0

10

0

56

0

[1]

0

76

13

0

0

[2]

0

45

0

0

[3]

0

0

45

0

[4]

0

0

0

20

[5]

0

0

Position of Donald and region = 2

To process this entry, we access row number 2 of the array votesByRegion
...
The following statement accomplishes this task:
votesByRegion[2][1] = votesByRegion[2][1] + 35;

Programming Example: Election Results

|

593

After processing this entry, the three arrays are as shown in Figure 10-26
...

Function This function implements the binary search algorithm on the array candidatesName
...
Its defini-

tion is:
int binSearch(string cNames[], int noOfRows, string name)
{
int first, last, mid;
bool found;
first = 0;
last = noOfRows - 1;
found = false;
while (!found && first <= last)
{
mid = (first + last) / 2;

}

if (cNames[mid] == name)
found = true;
else if (cNames[mid] > name)
last = mid - 1;
else
first = mid + 1;

1
0

594 |

}

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

if (found)
return mid;
else
return -1;

Function This function processes the voting data
...
txt
...
Thus, the
function processVotes has four parameters: one to access the input file
voteData
...
The definition of this function is:
void processVotes(ifstream& inp, string cNames[],
int vbRegion[][NO_OF_REGIONS],
int noOfRows)
{
string candName;
int region;
int noOfVotes;
int loc;
inp >> candName >> region >> noOfVotes;
while (inp)
{
loc = binSearch(cNames, noOfRows, candName);

}
Calculate
Total
Votes
(Function
addRegionsVote)

}

if (loc != -1)
vbRegion[loc][region - 1] = vbRegion[loc][region - 1]
+ noOfVotes;
inp >> candName >> region >> noOfVotes;

After processing the voting data, the next step is to calculate the total votes for each
candidate
...


Programming Example: Election Results

candidatesName
[0]

votesByRegion
[1] [2] [3]

|

595

totalVotes

[0] Ashley

[0]

23

89

0

160

[0]

0

[1] Danny

[1]

25

71

89

97

[1]

0

[2] Donald

[2]

110

158

0

0

[2]

0

[3] Mia

[3]

134

112

156

0

[3]

0

[4] Mickey

[4]

56

63

67

89

[4]

0

[5] Peter

[5]

207

56

0

46

[5]

0

FIGURE 10-27

Arrays candidatesName, votesByRegion, and totalVotes after processing
the voting data

After calculating the total votes received by each candidate, the three arrays are as
shown in Figure 10-28
...
This task is accomplished by the function addRegionsVote
...
This function must access the arrays votesByRegion and totalVotes
...
This function has
three parameters: one corresponding to the array votesByRegion, one corresponding to the array totalVotes, and one to pass the number of rows in each
array
...

Function This function outputs the first four lines of input, so it contains certain output
printHeading statements
...
Clearly, it must have access
printResults to each of the three arrays
...
(Note that each array has the same number of rows
...
Suppose that the parameter cName corresponds to
candidatesName, the parameter vbRegion corresponds to votesByRegion, and
the parameter tVotes corresponds to totalVotes
...
The algorithm for this function is:
a
...

b
...


if (largestVotes < tVotes[i])
{
largestVotes = tVotes[i];
winLoc = i;
}

Programming Example: Election Results

|

597

ii
...
Output the data from the corresponding rows of each array
...
Output the final lines of output
...

Suppose that the variables in the function main are:
string candidatesName[NO_OF_CANDIDATES]; //array to store the
//candidate's name
int votesByRegion[NO_OF_CANDIDATES][NO_OF_REGIONS]; //array to
//hold the voting data by region
int totalVotes[NO_OF_CANDIDATES]; //array to hold the total votes
//received by each candidate
ifstream infile;

//input file variable

1
0

598 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

Furthermore, suppose that the candidates’ names are in the file candData
...
txt
...

2
...

4
...

6
...

8
...

10
...

12
...


Declare the variables
...
txt
...

Read the data from the file candData
...

Sort the array candidatesName
...
txt and clear the input stream
...
txt
...

Initialize the arrays votesByRegion and totalVotes
...

Calculate the number of total votes received by each candidate and
store the results in the array totalVotes
...

Print the results
...
S
...
It outputs each candidate's name and the
// votes they received
...

//*************************************************************
#include
#include
#include
#include






using namespace std;
const int NO_OF_CANDIDATES = 6;
const int NO_OF_REGIONS = 4;
void printHeading();

Programming Example: Election Results

|

599

void initialize(int vbRegion[][NO_OF_REGIONS], int tVotes[],
int noOfRows);
void getCandidatesName(ifstream& inp, string cNames[],
int noOfRows);
void sortCandidatesName(string cNames[], int noOfRows);
int binSearch(string cNames[], int noOfRows, string name);
void processVotes(ifstream& inp, string cNames[],
int vbRegion[][NO_OF_REGIONS],
int noOfRows);
void addRegionsVote(int vbRegion[][NO_OF_REGIONS],
int tVotes[], int noOfRows);
void printResults(string cNames[],
int vbRegion[][NO_OF_REGIONS],
int tVotes[], int noOfRows);
int main()
{
//Declare variables; Step 1
string candidatesName[NO_OF_CANDIDATES];
int votesByRegion[NO_OF_CANDIDATES][NO_OF_REGIONS];
int totalVotes[NO_OF_CANDIDATES];
ifstream infile;
infile
...
txt");
if (!infile)
{
cout << "Input file (candData
...
" << endl;
return 1;
}
getCandidatesName(infile, candidatesName,
NO_OF_CANDIDATES);
sortCandidatesName(candidatesName,
NO_OF_CANDIDATES);

//Step 2
//Step 3

//Step 4
//Step 5

infile
...
clear();

//Step 6
//Step 6

infile
...
txt");
if (!infile)
{
cout << "Input file (voteData
...
" << endl;
return 1;
}

//Step 7
//Step 8

1
0

600 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

initialize(votesByRegion, totalVotes,
NO_OF_CANDIDATES);
processVotes(infile, candidatesName,
votesByRegion, NO_OF_CANDIDATES);
addRegionsVote(votesByRegion, totalVotes,
NO_OF_CANDIDATES);
printHeading();
printResults(candidatesName,votesByRegion,
totalVotes, NO_OF_CANDIDATES);
}

//Step 9
//Step 10
//Step 11
//Step 12
//Step 13

return 0;

//Place the definitions of the functions initialize,
//getCandidatesName, sortCandidatesName, binSearch,
//processVotes, addRegionsVote, printHeading, and
//printResults here
...
)
--------------Election Results-------------Candidate
Name
--------Ashley
Danny
Donald
Mia
Mickey
Peter

Region1
------23
25
110
134
56
207

Votes
Region2
Region3
------------89
0
71
89
158
0
112
156
63
67
56
0

Winner: Mia, Votes Received: 402
Total votes polled: 1808

Input Files:
candData
...
txt
Mia 2 34
Mickey 1 56
Donald 2 56
Mia 1 78
Danny 4 29
Ashley 4 78
Mickey 2 63
Donald 1 23
Peter 2 56
Danny 1 25
Peter 4 23
Danny 4 12
Ashley 4 82
Mickey 3 67
Donald 2 67
Mia 3 67
Ashley 1 23
Mia 1 56
Donald 2 35
Peter 1 27
Danny 2 34
Peter 4 23
Mickey 4 89
Peter 1 23
Danny 3 89
Mia 3 89
Peter 1 67
Danny 2 37
Ashley 2 89
Mia 2 78
Donald 1 87
Peter 1 90
Danny 4 56

The complete listing of this program is available at the Web site accompanying this book
...

2
...

4
...

The length of a list is the number of elements in the list
...

The sequential search algorithm searches a list for a given item, starting with
the first element in the list
...

6
...


8
...

10
...

12
...

14
...

16
...


18
...

20
...

On average, the sequential search searches half of the list
...

To sort a list, say list, of n elements, the bubble sort algorithm works
as follows: In a series of n À 1 iterations, the successive elements,
list[index] and list[index + 1], of list are compared
...

À
For a list of length n, bubble sort given in this chapter makes exactly nðn2 1Þ
À
key comparisons and, on average, about nðn4 1Þ item assignments
...

À
For a list of length n, selection sort makes exactly nðn2 1Þ key comparisons
and 3(nÀ1) item assignments
...

2
For a list of length n, on average, insertion sort makes n þ 3n À 4 key
4
À
comparisons and about nðn4 1Þ item assignments
...

Binary search requires that the list elements are in order—that is, the list
must be sorted
...

In addition to arrays, C++ provides the vector type (most commonly
called the class vector) to implement a list
...
Therefore, you do not need to be concerned
with the number of data elements
...

The elements in a vector can be processed just as they are in an array
...

The following functions can be used to perform various operations on a
vector object: at, front, back, clear, push_back, pop_back, empty,
size, resize, and max_size
...


Exercises

|

603

EXERCISES
1
...

A sequential search of a list assumes that the list elements are sorted in
ascending order
...
A binary search of a list assumes that the list is sorted
...
A binary search is faster on ordered lists and slower on unordered lists
...
A binary search is faster on large lists, but a sequential search is faster on
small lists
...
When you declare a vector object and specify its size as 10, then only
10 elements can be stored in the object
...


2
...
)
a
...


90

a
...

Consider the following list:

b
...


57

c
...


120

5 12 17 35 46 65 78 85 93 110 115

Using a sequential search on ordered lists, which you designed in (a), how
many comparisons are required to determine whether the following items
are in the list or not? (Recall that comparisons mean item comparisons, not
index comparisons
...

4
...


60

iii
...


120

Consider the following list:
2 10 17 45 49 55 68 85 92 98 110

Using the binary search, how many comparisons are required to determine
whether the following items are in the list or not? Show the values of
first, last, and middle and the number of comparisons after each
iteration of the loop
...

5
...


49

c
...


99

Sort the following list using the bubble sort algorithm as discussed in this
chapter
...

26, 45, 17, 65, 33, 55, 12, 18

1
0

604 |

6
...
Show the list after each iteration of the outer for loop
...


Consider the following list:
5, 18, 21, 10, 55, 20

8
...
To move 10 to its proper position using the
insertion sort as described in this chapter, exactly how many key comparisons
are executed?
Consider the following list:
7, 28, 31, 40, 5, 20

9
...
To move 5 to its proper position using the
insertion sort as described in this chapter, exactly how many key comparisons are executed?
Consider the following list:
28, 18, 21, 10, 25, 30, 12, 71, 32, 58, 15

10
...
Show the resulting list after six passes of the sorting phase—that is,
after six iterations of the for loop
...
Assume the
following list of keys:
18, 8, 11, 9, 15, 20, 32, 61, 22, 48, 75, 83, 35, 3

11
...


13
...


Exactly how many key comparisons are executed to sort this list using insertion
sort?
Suppose that L is a list of 10,000 elements
...

a
...
Write a function that
implements bubble sort algorithm using this fact
...
Using the algorithm that you designed in part (a), find the number of
iterations that are needed to sort the list: 65, 14, 52, 43, 75, 25, 80, 90, 95
...
What is the maximum
number of comparisons made by binary search to determine whether an
item is in L?
Suppose that the elements of a list are in descending order, and they need to
be put in ascending order
...
The
function rearranges the element of the array in ascending order
...


Exercises

15
...


605

To use a vector object in a program, which header file must be included in
the program?
What do the following statements do?
a
...

17
...
at(i) << " ";
cout << endl;

18
...
push_back("Nisha");
classList
...
push_back("Bobby");
classList
...
size(); i++)
cout << classList[i] << " ";
cout << endl;

19
...


b
...
(Do not specify the size of secretList
...
(Use
the expression secretList
...
)
What is the output of the following C++ code?

c
...


vector intList(10);
for (int i = 0; i < 10; i++)
intList[i] = 2 * i + 5;
cout << intList
...
back() << endl;

1
0

606 |

21
...
push_back(46);
myList
...
push_back(35);

Write a C++ statement that outputs the first and the last elements of
myList
...
)
b
...

c
...

What is the difference between the size and capacity of a vector?
a
...


PROGRAMMING EXERCISES
1
...


3
...


5
...
Use either the
function bubbleSort or selectionSort to sort the list before the search
...
Use either the function
bubbleSort or selectionSort to sort the list before the search
...
The
function should find and delete the first occurrence of removeItem in the
array
...
(Note that after deleting the element, the number of elements in
the array is reduced by 1
...

Write a function, removeAt, that takes three parameters: an array of
integers, the number of elements in the array, and an integer (say,
index)
...
If index is out of range or the array is empty, output an appropriate
message
...
) Assume that the array is unsorted
...
The
function should find and delete all of the occurrences of removeItem in the
array
...
(Note that after deleting the element, the number of elements in the
array is reduced
...


Programming Exercises

6
...


8
...


10
...


12
...

14
...


16
...


18
...


Redo Exercises 3, 4, and 5 for a sorted array
...
The function should insert insertItem in the array at
the position specified by index
...
(Note that index must be between 0 and the number
of elements in the array; that is, 0 <= index < the number of elements in
the array
...

Write a version of the selection sort algorithm that can be used to sort a list
of strings
...
(Use the selection sort that you designed in Exercise 8 to sort
the list
...
Also, write a program to test your algorithm
...
Also, write a program to test your algorithm
...
Also, write a program to test your algorithm
...

Write a version of the insertion sort algorithm that can be used to sort a
string vector object
...

Write a version of the binary search algorithm that can be used to search
a string vector object
...

(Use the selection sort algorithm you developed in Programming Exercise 12
to sort the vector
...
The program then sorts list1 using bubble sort,
list2 using selection sort, and list3 using insertion sort and outputs
the number of comparisons and item assignments made by each sorting
algorithm
...

Write a program to test the function you designed in Exercise 14
...
You may assume that the data set has, at most, 100
numbers and that -999 marks the end of the input data
...
For example, for the data:
55 80 78 92 95 55 78 53 92 65 78 95 85 92 85 95 95

|

607

1
0

608 |

Chapter 10: Applications of Arrays (Searching and Sorting) and the vector Type

the output is:
Test Score
53
55
65
78
80
85
92
95
20
...


In Programming Exercise 13 (Chapter 9), you are asked to write a program
to calculate students’ average test scores and their grades
...

Your state is in a process of creating a weekly lottery
...
If a player
guesses all of the numbers correctly, the player wins a certain amount
...


b
...


d
...


23
...

Sorts the array containing the lottery numbers
...
The player can select the numbers
in any order, and the array containing the numbers need not be sorted
...
If
the player guessed the lottery numbers correctly, it outputs the message
‘‘You win!’’; otherwise it outputs the message ‘‘You lose!’’ and outputs
the lottery numbers
...
Before each play, generate a new set of lottery
numbers
...

Write a program to keep track of a hardware store inventory
...
For each item in the store, the following information is kept:
item ID, item name, number of pieces ordered, number of pieces currently
in the store, number of pieces sold, manufacturer’s price for the item, and
the store’s selling price
...


...


pOrdered pInStore pSold manufPrice sellingPrice
150
150
40
45
...
00
50
50
20
450
...
00

Total Inventory: $#########
...
The
total number of items is the sum of the number of pieces of all of the items in the store
...
After inputting
the data, sort it according to the items’ names
...

Initially, the number of pieces (of an item) in the store is the same as the number of pieces
ordered, and the number of pieces of an item sold is zero
...
The program must contain at least the
following functions: one to input data into the vectors, one to display the menu, one to
sell an item, and one to print the report for the manager
...


Learn about records (structs)


...


Explore ways to manipulate data using a struct


...


Discover how arrays are used in a struct


...
You also
learned how to process data stored in an array and how to perform list operations, such as
searching and sorting
...


In this chapter, you will learn how to group related values that are of different types
...
An array is a homogeneous data
structure; a struct is typically a heterogeneous data structure
...
A struct in this
chapter, therefore, is a C-like struct
...


Records (structs)
Suppose that you want to write a program to process student data
...
Thus, various components are associated with a student
...
For example, the student’s name is a
string, and the GPA is a floating-point number
...
C++ provides a structured data type called struct to group items of
different types
...
For example, a single variable can pass all the components as
parameters to a function
...
The components may be of different types
...
The general syntax
of a struct in C++ is:
struct structName
{
dataType1 identifier1;
dataType2 identifier2;

...


...
The members of a struct, even though they
are enclosed in braces (that is, they form a block), are not considered to form a
compound statement
...
A semicolon at the end of the struct definition is, therefore, a
part of the syntax
...
The members firstName,
lastName, address1, address2, and deptID are of type string, and the member
salary is of type double
...
That is, it defines
only a data type; no memory is allocated
...
Let us first define a
struct type, studentType, and then declare variables of that type
...
The memory allocated is large enough to store firstName, lastName,
courseGrade, testScore, programmingScore, and GPA (see Figure 11-1)
...
For example,
consider the following statements:

struct studentType
{
string firstName;
string lastName;
char courseGrade;
int testScore;
int programmingScore;
double GPA;
} tempStudent;
These statements define the struct studentType and also declare tempStudent
to be a variable of type studentType
...
Therefore, if you
define a struct and also simultaneously declare a struct variable (as in the preceding
statements), then that struct variable becomes a global variable and thus can be
accessed anywhere in the program
...


Accessing struct Members
In arrays, you access a component by using the array name together with the relative
position (index) of the component
...
To access a structure member (component), you use the struct variable name
together with the member name; these names are separated by a dot (period)
...
memberName

Records (structs) |

615

The structVariableName
...
For example,
newStudent
...
firstName is a
string variable, and so on
...
You can, for example, use them in assignment statements or input/output (where permitted) statements
...
) is an operator called the member access operator
...
0
...
GPA = 0
...
firstName = "John";
newStudent
...

After the preceding three assignment statements execute, newStudent is as shown in
Figure 11-2
...
0

struct newStudent

The statement:
cin >> newStudent
...
firstName

The statement:
cin >> newStudent
...
programmingScore;

1
1

616 |

Chapter 11: Records (structs)

reads two integer values from the keyboard and stores them in newStudent
...
programmingScore, respectively
...
The statement:
score = (newStudent
...
programmingScore) / 2;

assigns the average of newStudent
...
programmingScore
to score
...
courseGrade:
if (score >= 90)
newStudent
...
courseGrade
else if (score >= 70)
newStudent
...
courseGrade
else
newStudent
...
Suppose that newStudent is as shown in Figure 11-3
...
9

struct newStudent

The statement:
student = newStudent;

Records (structs) |

617

copies the contents of newStudent into student
...


student
firstName

Lisa

lastName

Robinson

courseGrade

A

testScore
programmingScore

98

GPA

FIGURE 11-4

95

3
...
firstName = newStudent
...
lastName = newStudent
...
courseGrade = newStudent
...
testScore = newStudent
...
programmingScore = newStudent
...
GPA = newStudent
...
As with an array, no
aggregate relational operations are performed on a struct
...
Furthermore, suppose that
you want to see whether student and newStudent refer to the same student
...
To compare the values of student and newStudent, you must
compare them member-wise, as follows:
if (student
...
firstName &&
student
...
lastName)

...


...
Therefore, the following would be illegal:
if (student == newStudent)

...


...
Data in a
struct variable must be read one member at a time
...

We have seen how to read data into a struct variable
...
The statement:
cout <<
<<
<<
<<
<<

newStudent
...
lastName
" " << newStudent
...
testScore
" " << newStudent
...
GPA << endl;

outputs the contents of the struct variable newStudent
...
However:


A struct variable can be passed as a parameter either by value or by
reference, and
• A function can return a value of type struct
...
It also determines the student’s course grade and stores it
in the member courseGrade
...
firstName >> student
...
testScore >> student
...
GPA;
score = (newStudent
...
programmingScore) / 2;
if (score >= 90)
student
...
courseGrade
else if (score >= 70)
student
...
courseGrade
else
student
...
The function readIn stores the appropriate information in
the variable newStudent
...
For
example, the following function outputs the contents of a struct variable of type
studentType on the screen:
void printStudent(studentType student)
{
cout << student
...
lastName
<< " " << student
...
testScore
<< " " << student
...
GPA << endl;
}

Arrays versus structs
The previous discussion showed us that a struct and an array have similarities as well as
differences
...

TABLE 11-1

Arrays vs
...
Thus, a list has two things associated with it:
the values (that is, elements) and the length
...

const int ARRAY_SIZE = 1000;
struct listType
{
int listElem[ARRAY_SIZE];
int listLength;
};

//array containing the list
//length of the list

The following statement declares intList to be a struct variable of type listType
(see Figure 11-5):
listType intList;

intList
listElem

listElem[0]
listElem[1]
listElem[2]

...


...
Moreover, intList
...
listLength accesses the member listLength
...
listLength = 0;
intList
...
listLength++;
intList
...
listLength++;

//Line
//Line
//Line
//Line
//Line

1
2
3
4
5

The statement in Line 1 sets the value of the member listLength to 0
...
The statement in Line
3 increments the value of listLength by 1
...
After these statements execute, intList is as shown in Figure 11-6
...


...


listElem[999]
listLength

FIGURE 11-6

2

intList after the statements in Lines 1 through 5 execute

Next, we write the sequential search algorithm to determine whether a given item is in
the list
...

int seqSearch(const listType& list, int searchItem)
{
int loc;
bool found = false;
for (loc = 0; loc < list
...
listElem[loc] == searchItem)
{
found = true;
break;
}

}

if (found)
return loc;
else
return -1;

In this function, because listLength is a member of list, we access this by
list
...
Similarly, we can access an element of list via
list
...

Notice that the formal parameter list of the function seqSearch is declared as
a constant reference parameter
...

Recall that when a variable is passed by value, the formal parameter copies the value of
the actual parameter
...


1
1

622 |

Chapter 11: Records (structs)

Suppose that a struct has several data members requiring a large amount of memory to
store the data, and you need to pass a variable of that struct type by value
...
The
compiler must then allocate memory for the formal parameter in order to copy the value
of the actual parameter
...

On the other hand, if a variable is passed by reference, the formal parameter receives only
the address of the actual parameter
...
If a variable is passed by reference, then when the formal
parameter changes, the actual parameter also changes
...
In C++, you
can pass a variable by reference and still prevent the function from changing its value
...

Likewise, we can also rewrite the sorting, binary search, and other list-processing functions
...
We need to print their monthly
paychecks and keep track of how much money has been paid to each employee in the
year-to-date
...

Because we have 50 employees and the data type of each employee is the same, we can
use an array of 50 components to process the employees’ data
...
Every element of employees is a struct
...


Records (structs) |

employees
[0]
[1]
[2]

...


...
For our discussion, we
assume that each employee’s data is stored in a file, say, employee
...
The following
C++ code loads the data into the employees’ array
...

ifstream infile; //input stream variable
//assume that the file employee
...
firstName
>> employees[counter]
...
personID
>> employees[counter]
...
yearlySalary;
employees[counter]
...
yearlySalary / 12;
employees[counter]
...
0;
employees[counter]
...
0;
}

Suppose that for a given month, the monthly bonuses are already stored in each employee’s
record, and we need to calculate the monthly paycheck and update the yearToDatePaid
amount
...
firstName << " "
<< employees[counter]
...
monthlySalary +
employees[counter]
...
yearToDatePaid =
employees[counter]
...
You also saw examples wherein a member of a struct is an array, and the
array type is a struct
...

Let us consider the following employee record:
struct employeeType
{
string firstname;
string middlename;
string lastname;
string empID;
string address1;
string address2;
string city;
string state;
string zip;
int hiremonth;
int hireday;
int hireyear;
int quitmonth;
int quitday;
int quityear;
string phone;
string cellphone;
string fax;
string pager;
string email;
string deptID;
double salary;
};

As you can see, a lot of information is packed into one struct
...
Some members of this struct will be accessed more frequently than others,
and some members are more closely related than others
...
For example, the hire date and the quit date are of
the date type int
...

Furthermore, we have defined a struct dateType
...

Some of this struct can be reused to build another struct
...
Every customer has a first name, last name, and

1
1

626 |

Chapter 11: Records (structs)

middle name, as well as an address and a way to be contacted
...

Next, let us declare a variable of type employeeType and discuss how to access its members
...


newEmployee
first
middle
last

name

empID
address

address 1
address 2
city
state
zip

hireDate

month
day
year

quitDate

month
day
year

contact

phone
cellphone
fax
pager
email

deptID
salary

FIGURE 11-8

struct variable newEmployee

Records (structs) |

627

The statement:
newEmployee
...
00;

sets the salary of newEmployee to 45678
...
The statements:
newEmployee
...
first = "Mary";
newEmployee
...
middle = "Beth";
newEmployee
...
last = "Simmons";

set the first, middle, and last name of newEmployee to "Mary", "Beth", and
"Simmons", respectively
...
We
access this member via newEmployee
...
Note also that newEmployee
...
We apply the member access criteria to access the
member first of the struct newEmployee
...
So, newEmployee
...
first
is the member where we store the first name
...
name
...
name
...
The statement:
newEmployee
...
salary * 1
...

The following statement declares employees to be an array of 100 components,
wherein each component is of type employeeType:
employeeType employees[100];

The for loop:
for (int j = 0; j < 100; j++)
cin >> employees[j]
...
first >> employees[j]
...
middle
>> employees[j]
...
last;

reads and stores the names of 100 employees in the array employees
...
For example, employees[50] is the
51st component of the array employees (recall that an array index starts with 0)
...


1
1

628 |

Chapter 11: Records (structs)

PROGRAMMING EXAMPLE:

Sales Data Analysis

A company has six salespeople
...
At the end of each month, the total sales for each salesperson,
together with that salesperson’s ID and the month, is recorded in a file
...
00
343
...
00
893
...
00
893
...
00
892
...
00
892
...
00
0
...
00

4906
...
00
9023
...
00
8834
...
00
392
...
00
0
...
00
0
...
00
3420
...
00
10258
...
00
10619
...
00
4705
...
00

4965
...
00
Max Sale by Quarter: Quarter = 3, Amount = $18743
...

The salespeople’s IDs are stored in one file; the sales data is stored in another file
...


...


month

saleAmount

Furthermore, the sales data is in no particular order; it is not ordered by ID
...


...


1
1
3
2

893
343
903
893

Programming Example: Sales Data Analysis

|

629

Let us write a program that produces the output in the specified format
...

A file containing the annual sales report in the above format
...
Because the components are of different types, we can group them with the
help of a struct, defined as follows:
struct salesPersonRec
{
string ID;
//salesperson's ID
double saleByQuarter[4];
//array to store the total
//sales for each quarter
double totalSale;
//salesperson's yearly sales amount
};

Because there are six salespeople, we use an array of six components, wherein each
component is of type salesPersonRec, defined as follows:
salesPersonRec salesPersonList[NO_OF_SALES_PERSON];

wherein the value of NO_OF_SALES_PERSON is 6
...
Note that this data will be used to
determine the quarter in which the maximum sales were made
...
Therefore,
totalSaleByQuarter[0] stores data for quarter 1, totalSaleByQuarter[1]
stores data for quarter 2, and so on
...

The array salesPersonList is as shown in Figure 11-9
...
After this step, the array salesPersonList is as shown in Figure 11-10
...
0

0
...
0

0
...
0

salesPersonList[1]

32214

0
...
0

0
...
0

0
...
0

0
...
0

0
...
0

salesPersonList[3]

57373

0
...
0

0
...
0

0
...
0

0
...
0

0
...
0

salesPersonList[5]

54654

0
...
0

0
...
0

0
...
Processing the sales data is quite straightforward
...
Read the salesperson’s ID, month, and sale amount for the month
...
Search the array salesPersonList to locate the component
corresponding to this salesperson
...
Determine the quarter corresponding to the month
...
Update the sales for the quarter by adding the sale amount for the month
...
Calculate the total sales by salesperson
...
Calculate the total sales by quarter
...
Print the report
...
Initialize the array salesPersonList
...
Process the sales data
...
Calculate the total sales by quarter
...
Calculate the total sales by salesperson
...
Print the report
...
Calculate and print the maximum sales by salesperson
...
Calculate and print the maximum sales by quarter
...

Function This function reads the salesperson’s ID from the input file and stores the salesperson’s ID
initialize in the array salesPersonList
...
The definition of this function is:
void initialize(ifstream& indata, salesPersonRec list[],
int listSize)
{
int index;
int quarter;
for (index = 0; index < listSize; index++)
{
indata >> list[index]
...
saleByQuarter[quarter] = 0
...
totalSale = 0
...
The algorithm for this function is:

1
...

2
...
(Because the salespeople’s IDs
are not sorted, we will use a sequential search to search the array
...
Determine the quarter corresponding to the month
...
Update the sales for the quarter by adding the sales amount for the
month
...

Suppose that the array salesPersonList is as shown in Figure 11-11
...
80

0
...
0

654
...
0

salesPersonList[1]

32214

0
...
90

0
...
0

0
...
0

0
...
0

564
...
0

salesPersonList[3]

57373

354
...
0

0
...
0

0
...
0

0
...
90

0
...
0

salesPersonList[5]

54654

783
...
0

0
...
80

0
...
Therefore, you add 350 to 354
...
80
...


Programming Example: Sales Data Analysis

|

633

ID = 57373
month = 2
salesPersonList

saleByQuarter

ID

totalSale

salesPersonList[0]

12345

150
...
0

0
...
92

0
...
0

439
...
0

0
...
0

salesPersonList[2]

23422

0
...
0

0
...
76

0
...
80

0
...
0

0
...
0

salesPersonList[4]

35864

0
...
0

763
...
0

0
...
45

0
...
0

563
...
0

FIGURE 11-12

Array salesPersonList after processing entry 57373 2 350

The definition of the function getData is:
void getData(ifstream& infile, salesPersonRec list[],
int listSize)
{
int index;
int quarter;
string sID;
int month;
double amount;
infile >> sID;

//get salesperson’s ID

while (infile)
{
infile >> month >> amount;

//get the sale month and
//the sale amount

for (index = 0; index < listSize; index++)
if (sID == list[index]
...
saleByQuarter[quarter] += amount;
else
cout << "Invalid salesperson's ID
...
To find the total sales for
saleByQuarter each quarter, we add the sales amount of each salesperson for that quarter
...
This function also needs to know the number of rows in

each array
...
The definition of this function is:
void saleByQuarter(salesPersonRec list[], int listSize,
double totalByQuarter[])
{
int quarter;
int index;
for (quarter = 0; quarter < 4; quarter++)
totalByQuarter[quarter] = 0
...
saleByQuarter[quarter];
} //end saleByQuarter
Function
totalSaleByPerson

This function finds each salesperson’s yearly sales amount
...
Clearly, this
function must have access to the array salesPersonList
...
Thus, this function has two parameters
...
totalSale +=
list[index]
...
The algorithm in
printReport pseudocode is:

1
...

2
...

3
...

Note that the next two functions will produce the final two lines of output
...
Also, because the output will be stored in a file, this
function must have access to the ofstream variable associated with the output file
...
The definition of this function is:
void printReport(ofstream& outfile, salesPersonRec list[],
int listSize, double saleByQuarter[])
{
int index;
int quarter;
outfile <<
<<
outfile <<
outfile <<
<<
outfile <<
<<

"––––––––––– Annual Sales Report –––––––––"
"––––" << endl;
endl;
" ID
QT1
QT2
QT3
"
"QT4
Total" << endl;
"_____________________________________________"
"_________________" << endl;

for (index = 0; index < listSize; index++)
{
outfile << list[index]
...
saleByQuarter[quarter];
}

outfile << setw(10) << list[index]
...
To identify this salesperson, we look at the sales total for each salesperson
and find the largest sales amount
...
Also, because the output will be stored in a file, this function
must have access to the ofstream variable associated with the output file
...

The algorithm to find the largest sales amount is similar to the algorithm to find the
largest element in an array (discussed in Chapter 9)
...
totalSale ...
ID
<< ", Amount = $" << list[maxIndex]
...
To identify
this quarter, we look at the total sales for each quarter and find the largest sales amount
...
Also, because the
output will be stored in a file, this function must have access to the ofstream variable
associated with the output file
...

The algorithm to find the largest sales amount is the same as the algorithm to find the
largest element in an array (discussed in Chapter 9)
...

We are now ready to write the algorithm for the function main
...
Declare the variables
...
Prompt the user to enter the name of the file containing the
salesperson’s ID data
...
Read the name of the input file
...
Open the input file
...
If the input file does not exist, exit the program
...
Initialize the array salesPersonList
...

7
...

8
...

9
...

10
...

11
...

12
...

13
...

14
...

15
...
Also, to output floating-point numbers to two
decimal places, set the precision to two decimal places
...

17
...

19
...

21
...


Process the sales data
...

Calculate the total sales by quarter
...

Calculate the total sales for each salesperson
...

Print the report in a tabular format
...

Find and print the salesperson who produces the maximum sales
for the year
...

Find and print the quarter that produces the maximum sales for the
year
...

Close the files
...
S
...
For each
// salesperson, it outputs the ID, the total sales by each
// quarter, and the total sales for the year
...
The quarter generating the
// maximum sale and the sales amount is also output
...
open(inputFile
...
"
<< endl;
return 1;
}

//Step 5

1
1

initialize(infile, salesPersonList,
NO_OF_SALES_PERSON);

//Step 6

infile
...
clear();

//Step 7
//Step 7

cout << "Enter the sales data file name: ";
cin >> inputFile;
cout << endl;

//Step 8
//Step 9

infile
...
c_str());

//Step 10

640 |

Chapter 11: Records (structs)

if (!infile)
{
cout << "Cannot open the input file
...
open(outputFile
...
close();
outfile
...


Sample Run: In this sample run, the user input is shaded
...
txt
Enter the sales data file name: Ch11_SalesData
...
txt

Programming Example: Sales Data Analysis

|

641

Input File: Salespeople’s IDs
12345
32214
23422
57373
35864
54654

Input File: Salespeople’s Data
12345
32214
23422
57373
35864
54654
12345
32214
23422
23422
57373
35864
54654
12345
35864
54654
12345
32214
23422
23422
57373
35864

1 893
1 343
3 903
2 893
5 329
9 392
2 999
4 892
4 895
2 492
6 892
10 1223
11 3420
12 322
5 892
3 893
8 494
8 9023
6 223
4 783
8 8834
3 2882

Sample Run:
–––––––––––– Annual Sales Report ––––––––––––
ID

QT1

12345
32214
23422
57373
35864
54654
Total

1892
...
00
1395
...
00
2882
...
00
8298
...
00
892
...
00
892
...
00
0
...
00

QT3

QT4

Total

494
...
00
0
...
00
0
...
00
18743
...
00
0
...
00
0
...
00
3420
...
00

2708
...
00
3296
...
00
5326
...
00

Max Sale by SalesPerson: ID = 57373, Amount = $10619
...
00

1
1

642 |

Chapter 11: Records (structs)

QUICK REVIEW
1
...

3
...

Components of a struct can be of different types
...


...

dataTypen identifiern;
};

4
...

6
...

8
...


10
...

12
...

14
...

In C++, struct is a definition; no memory is allocated
...

Components of a struct are called members of the struct
...

In C++, the dot (
...

Members of a struct are accessed by using the dot (
...
For
example, if employeeType is a struct, employee is a variable of type
employeeType, and name is a member of employee, then the expression
employee
...
That is, employee
...

The only built-in operations on a struct are the assignment and member
access operations
...

As a parameter to a function, a struct can be passed either by value or by
reference
...

A struct can be a member of another struct
...


Mark the following statements as true or false
...

b
...

d
...

A function cannot return a value of type struct
...

The only allowable operations on a struct are assignment and member selection
...

In C++, some aggregate operations are allowed on a struct
...

Because a struct has a finite number of components, relational operations are allowed on a struct
...

Assume the definition of Exercise 2
...
38, interest rate—2
...

Define a struct, movieType, to store the following data about a movie:
movie name (string), movie director (string), producer (string), the
year movie was released (int), and number of copies in stock
...
Declare a variable of type movieType
to store the following data: movie name—Summer Vacation, director—
Tom Blair, producer—Rajiv Merchant, year the movie released—2005,
the number of copies in stock—34
...

f
...


3
...


5
...


struct nameType
{
string first;
string last;
};

struct dateType
{
int month;
int day;
int year;
};
personalInfoType person;
personalInfoType classList[100];
nameType student;

struct personalInfoType
{
nameType name;
int pID;
dateType dob;
};

Mark the following statements as valid or invalid
...

a
...
name
...


cout << person
...


classList[1] = person;

d
...
pID = 000011100;

e
...


student = person
...


cin >> student;

h
...
pID = 00000000;

i
...
dob
...


student = name;

1
1

644 |

7
...
If a statement is invalid, explain
why
...

b
...
name;

c
...


if (employees[45]
...
performanceRating = 1;

e
...


newEmployee
...
salary = 0;

Assume the declarations of Exercises 6 and 7
...


Store the following information in newEmployee:
name: Mickey Doe
pID: 111111111
performanceRating: 2
dept: ACCT
salary: 34567
...

c
...

d
...
87 to its previous value
...

b
...


struct partsType
{
string partName;
int partNum;
double price;
int quantitiesInStock;
};

Declare an array, inventory, of 100 components of type partsType
...


|

645

Assume the definition of Exercise 9
...
0, and
quantitiesInStock to 0
...
Write a C++ code that uses a loop to output the data stored in
inventory
...

Assume the definition and declaration of Exercise 9
...
Also write a C++ code that uses your function to input data
in inventory
...


11
...


struct timeType
{
int hr;
double min;
int sec;
};
a
...


c
...


e
...

Write C++ statements to store the following data in destination:
cityName—Chicago, distance—550 miles, travelTime—9 hours
and 30 minutes
...

Write the definition of a value-returning function that inputs data into
a variable of type tourType
...


PROGRAMMING EXERCISES
1
...


Assume the definition of Exercise 4, which defines the struct movieType
...

Write a program that reads students’ names followed by their test scores
...
It should also find and print the highest test score
and the name of the students having the highest test score
...
Suppose that the class has 20 students
...

Your program must contain at least the following functions:
A function to read the students’ data into the array
...
A function to assign the relevant grade to each student
...
A function to find the highest test score
...
A function to print the names of the students having the highest test
score
...
Moreover, other than declaring the variables and
opening the input and output files, the function main should only be a
collection of function calls
...


3
...


Define a struct, menuItemType, with two components: menuItem of
type string and menuPrice of type double
...
The program should do the following:
a
...

c
...

Allow the customer to select more than one item from the menu
...

Assume that the restaurant offers the following breakfast items (the price
of each item is shown to the right of the item):
Plain Egg
Bacon and Egg
Muffin
French Toast
Fruit Basket
Cereal
Coffee
Tea

$1
...
45
$0
...
99
$2
...
69
$0
...
75

Use an array, menuList, of the struct menuItemType, as defined in
Programming Exercise 2
...

• Function showMenu: This function shows the different items
offered by the restaurant and tells the user how to select the items
...

(Note that the billing amount should include a 5% tax
...
45
Muffin
$0
...
50
Tax
$0
...
14

5
...
The name of each item in the
output must be left justified
...

Redo Exercise 4 so that the customer can select multiple items of a
particular type
...
45
2 Muffin
$1
...
50
Tax
$0
...
18

6
...
This program reads a text and outputs the
letters, together with their counts, as explained below in the function
printResult
...
Use a structure to store the information
...
You must pass
the file streams as parameters (by reference, of course)
...
The
program must ask the user for the names of the input and output files
...
This
information must go into an array of structures
...

Function printResult: Prints the number of capital letters and small
letters, as well as the percentage of capital letters for every letter A-Z and
the percentage of small letters for every letter a-z
...
This information must come from an array
of structures, and this array must be passed as a parameter
...


Chapter 11: Records (structs)

Write a program that declares a struct to store the data of a baseball
player (player’s name, number of home runs, and number of hits)
...
Your
program must contain a function to input data and a function to output
data
...
(You may assume that input data is
stored in a file
...
Your program should be menu driven, giving the user
various choices
...


Learn about classes


...


Explore how classes are implemented


...


Learn about the abstract data type (ADT)


...


Learn about information hiding


...


Learn about the static members of a class

650 |

Chapter 12: Classes and Data Abstraction

In Chapter 11, you learned how to group data items that are of different types by using a
struct
...
However, the members of a C++ struct can be data items as well as functions
...
This chapter first introduces classes and explains how to use them
and then discusses the similarities and differences between a struct and a class
...
In fact, a struct and a class have similar
capabilities, as discussed in the section ‘‘A struct versus a class’’ in this chapter
...
In OOD, the first step is to identify the components, called objects
...
In C++, the mechanism
that allows you to combine data and the operations on that data in a single unit is called a
class
...

This and subsequent chapters develop and implement programs using OOD
...

A class is a collection of a fixed number of components
...

The general syntax for defining a class is:
class classIdentifier
{
classMembersList
};

in which classMembersList consists of variable declarations and/or functions
...



If a member of a class is a variable, you declare it just like any other
variable
...

• If a member of a class is a function, you typically use the function
prototype to declare that member
...
That is, when you write
the definition of a member function, you can directly access any member
variable of the class without passing it as a parameter
...


Classes

|

651

In C++, class is a reserved word, and it defines only a data type; no memory is
allocated
...
Moreover, note the semicolon (;) after
the right brace
...
A missing semicolon, therefore, will
result in a syntax error
...
This chapter mainly discusses the first two types, private and public
...

Following are some facts about public and private members of a class:



By default, all members of a class are private
...
(Example 12-1 illustrates this concept
...
(Example 12-1
illustrates this concept
...

Suppose that we want to define a class to implement the time of day in a program
...
Furthermore, to
represent time in computer memory, we use three int variables: one to represent the
hours, one to represent the minutes, and one to represent the seconds
...

2
...

4
...

6
...


Set the time
...

Print the time
...

Increment the time by one minute
...

Compare the two times for equality
...

From this discussion, it is clear that the class clockType has 10 members: three
member variables and seven member functions
...

Deciding which member to make public and which to make private depends on the
nature of the member
...
For example, the user should be able to set the
time and print the time
...

Similarly, the members to increment the time and compare the time for equality should
be declared public
...
Furthermore, note
that if the user has direct access to the member variables, member functions such as
setTime are not needed
...

The following statements define the class clockType:
class clockType
{
public:
void setTime(int, int, int);
void getTime(int&, int&, int&) const;
void printTime() const;
void incrementSeconds();
void incrementMinutes();
void incrementHours();
bool equalTime(const clockType&) const;
private:
int hr;
int min;
int sec;
};

In this definition:


The class clockType has seven member functions: setTime,
getTime, printTime, incrementSeconds, incrementMinutes,
incrementHours, and equalTime
...

• The three member variables—hr, min, and sec—are private to the
class and cannot be accessed outside of the class
...
)
• The seven member functions—setTime, getTime, printTime,
incrementSeconds, incrementMinutes, incrementHours, and
equalTime—can directly access the member variables (hr, min, and
sec)
...

• In the function equalTime, the formal parameter is a constant
reference parameter
...

You could have declared the formal parameter as a value parameter,
but that would require the formal parameter to copy the value of the
actual parameter, which could result in poor performance
...
)
• The word const at the end of the member functions getTime,
printTime, and equalTime specifies that these functions cannot
modify the member variables of a variable of type clockType
...
If you want, you
can declare the private members first and then declare the public ones
...


In the definition of the class clockType, all member variables are private
and all member functions are public
...
For example, if a member function is used only to implement other
member functions of the class and the user does not need to access this
function, you make it private
...


Note that we have not yet written the definitions of the member functions of the class
...

The function setTime sets the three member variables—hr, min, and sec—to a given
value
...
The function
printTime prints the time, that is, the values of hr, min, and sec
...

Note that the function equalTime has only one parameter, although you need two
things to make a comparison
...


1
2

654 |

Chapter 12: Classes and Data Abstraction

Unified Modeling Language Class Diagrams
A class and its members can be described graphically using a notation known as the
Unified Modeling Language (UML) notation
...


clockType
-hr: int
-min: int
-sec: int
+setTime(int, int, int): void
+getTime(int&, int&, int&) const: void
+printTime() const: void
+incrementSeconds(): int
+incrementMinutes(): int
+incrementHours(): int
+equalTime(const clockType&) const: bool

FIGURE 12-1

UML class diagram of the class clockType

The top box contains the name of the class
...
The last box contains the member function name, parameter list, and the
return type of the function
...
The
symbol # before the member name indicates that the member is a protected member
...
In C++ terminology, a class
variable is called a class object or class instance
...

The syntax for declaring a class object is the same as that for declaring any other variable
...
Each
object has separate memory allocated for hr, min, and sec
...
The C++
compiler generates only one physical copy of a member function of a class, and each class
object executes the same copy of the member function
...
As an example, Figure 12-2
shows the objects myClock and yourClock with values in their member variables
...
The general
syntax for an object to access a member of a class is:
classObjectName
...



If the object is declared in the definition of a member function of the
class, then the object can access both the public and private members
...
)
• If the object is declared elsewhere (for example, in a user’s program),
then the object can access only the public members of the class
...
(period), is an operator called the member access operator
...


1
2

EXAMPLE 12-1
Suppose we have the following declaration (say, in a user’s program):
clockType myClock;
clockType yourClock;

Consider the following statements:
myClock
...
printTime();
yourClock
...
equalTime(yourClock))

...


...

In the first statement, myClock
...
The values 5, 2, and 30 are passed as parameters to the
function setTime, and the function uses these values to set the values of the three
member variables hr, min, and sec of myClock to 5, 2, and 30, respectively
...
In the third
statement, the values of the variables x, y, and z are used to set the values of the
three member variables of yourClock
...
Because in this statement equalTime is a member of the object
myClock, it has direct access to the three member variables of myClock
...
This explains
why the function equalTime has only one parameter
...

Thus, the following statements are illegal because hr and min are declared as private
members of the class clockType and, therefore, cannot be accessed by the objects
myClock and yourClock:
myClock
...
min = yourClock
...
You cannot use arithmetic
operators to perform arithmetic operations on class objects (unless they are overloaded;
see Chapter 15)
...
Also, you cannot use relational operators to compare two
class objects for equality (unless they are overloaded; see Chapter 15)
...
) and
assignment (=)
...
(For example, if
myClock is a clockType object, in the statement myClock
...
)
We now show how an assignment statement works with the help of an example
...

Furthermore, suppose that the values of myClock and yourClock are as shown in
Figure 12-3(a)
...
That is,




the value of yourClock
...
hr,
the value of yourClock
...
min, and
the value of yourClock
...
sec
...
Therefore, an assignment statement
performs a member-wise copy
...


Class Scope
A class object can be either automatic (that is, created each time the control reaches
its declaration and destroyed when the control exits the surrounding block) or static
(that is, created once, when the control reaches its declaration, and destroyed when the
program terminates)
...
A class object
has the same scope as other variables
...
That is, a member of a class is local to the class
...


1
2

658 |

Chapter 12: Classes and Data Abstraction

Functions and Classes
The following rules describe the relationship between functions and classes:


Class objects can be passed as parameters to functions and returned as
function values
...

• If a class object is passed by value, the contents of the member variables of
the actual parameter are copied into the corresponding member variables
of the formal parameter
...
That is, memory space to copy the value of the actual parameter is
allocated for the formal parameter
...

Suppose that a class has several member variables requiring a large amount of memory to store
data, and you need to pass a variable by value
...
That is, the compiler must allocate memory for the
formal parameter, so as to copy the value of the member variables of the actual parameter
...

On the other hand, if a variable is passed by reference, the formal parameter receives only the
address of the actual parameter
...
If a variable is passed by reference, then when the formal parameter changes, the
actual parameter also changes
...
In C++, you can pass a variable by reference
and still prevent the function from changing its value by using the keyword const in the
formal parameter declaration
...


...

}

The function testTime contains a reference parameter, otherClock
...
Thus, in a call to the function
testTime, the formal parameter otherClock receives the address of the actual parameter, but otherClock cannot modify the contents of the actual parameter
...

Recall that if a formal parameter is a value parameter, within the function definition,
you can change the value of the formal parameter
...
However, if a formal parameter is a constant
reference parameter, you cannot use an assignment statement to change its value
within the function, nor can you use any other function to change its value
...
For example, the following would be illegal in the definition of the
function testTime:
otherClock
...
For these functions to work properly, we must write the
related algorithms
...
Unfortunately, the
class definition would then be very long and difficult to comprehend
...
We
will discuss this issue later in this chapter, in the section ‘‘Information Hiding
...

That is, we will write the definitions of the functions setTime, getTime, printTime,
incrementSeconds, equalTime, and so on
...
In order to reference these identifiers, we use the scope resolution operator, ::
(double colon)
...
For
example, the definition of the function setTime is as follows:
void clockType::setTime(int hours, int minutes, int seconds)
{
if (0 <= hours && hours < 24)
hr = hours;
else
hr = 0;
if (0 <= minutes && minutes < 60)
min = minutes;
else
min = 0;

1
2

660 |

}

Chapter 12: Classes and Data Abstraction

if (0 <= seconds && seconds < 60)
sec = seconds;
else
sec = 0;

Note that the definition of the function setTime checks for the valid values of hours,
minutes, and seconds
...
Let us now explain how the member function setTime
works when accessed by an object of type clockType
...

Therefore:



A call to this function is a stand-alone statement
...


Furthermore, recall that because setTime is a member of the class clockType, it can
directly access the member variables hr, min, and sec, as shown in the definition of
setTime
...
The
object myClock has three member variables, as shown in Figure 12-4(a)
...
setTime(3, 48, 52);

myClock
...
setTime(3, 48, 52);

Consider the following statement:
myClock
...
setTime(3, 48, 52);, setTime is accessed by the object
myClock
...
Thus, the values 3,
48, and 52, which are passed as parameters in the preceding statement, are assigned to the
three member variables of myClock by the function setTime (see the body of the
function setTime)
...


Classes

|

661

Next, let us give the definitions of the other member functions of the class clockType
...

The function equalTime has the following definition:
bool clockType::equalTime(const clockType& otherClock) const
{
return (hr == otherClock
...
min
&& sec == otherClock
...

Suppose that myClock and yourClock are objects of type clockType, as declared
previously
...


myClock

hr

14

yourClock

hr

14

min

min

25

sec

FIGURE 12-5

8
25

sec

54

Objects myClock and yourClock

Consider the following statement:
if (myClock
...


...


In the expression:
myClock
...
Because otherClock
is a reference parameter, the address of the actual parameter yourClock is passed to the
formal parameter otherClock, as shown in Figure 12-6
...
In other words, when the body of the function equalTime executes,
the value of otherClock
...
min is 25, and the value
of otherClock
...
The function equalTime is a member of myClock
...
Therefore, the
member hr of myClock is compared with otherClock
...
min, and the member sec of myClock is
compared with otherClock
...

Once again, from the definition of the function equalTime, it is clear why it has only
one parameter
...
Notice that within
the definition of this function, the object otherClock accesses the member variables hr,
min, and sec
...
So is there any violation?
The answer is no
...
Moreover, otherClock is an object of type
clockType
...

The same is true for any member function of a class
...

Once a class is properly defined and implemented, it can be used in a program
...

When you declare objects of the class clockType, every object has its own copy of
the member variables hr, min, and sec
...


1
2

664 |

Chapter 12: Classes and Data Abstraction

Accessor and Mutator Functions
Let us look at the member functions of the class clockType
...
In other
words, it alters or modifies the values of the member variables
...
On the other hand, functions such as getTime, printTime, and
equalTime only access the values of the member variables
...
We can, therefore, categorize the member functions of the class
clockType into two categories: member functions that modify the member variables
and member functions that only access, and do not modify, the member variables
...
That is, every class has member functions that only
access and do not modify the member variables, called accessor functions, and member
functions that modify the member variables, called mutator functions
...

Mutator function: A member function of a class that modifies the value(s) of the member

variable(s)
...
Moreover, a constant member function of a class cannot modify the
member variables of that class
...

A member function of a class is called a constant function if its heading contains the reserved
word const at the end
...
A constant member function
of a class cannot modify the member variables of that class, so these are accessor functions
...

Therefore, you should be careful when you make a member function constant
...
Note that we
have combined the definition of the class, the definition of the member functions, and the
main function to create a complete program
...

EXAMPLE 12-2
//The program listing of the program that defines
//and uses the class clockType

Classes

|

665

#include
using namespace std;
class clockType
{
public:
void setTime(int, int, int);
void getTime(int&, int&, int&) const;
void printTime() const;
void incrementSeconds();
void incrementMinutes();
void incrementHours();
bool equalTime(const clockType&) const;
private:
int hr;
int min;
int sec;
};
int main()
{
clockType myClock;
clockType yourClock;
int hours;
int minutes;
int seconds;
//Set the time of myClock
myClock
...
printTime(); //print the time of myClock
cout << endl;

//Line 2
Line 3
//Line 4

cout << "Line 5: yourClock: ";
//Line 5
yourClock
...
setTime(5, 45, 16);

//Line 8

cout << "Line 9: After setting, yourClock: ";
//Line 9
yourClock
...
equalTime(yourClock))
cout << "Line 13: Both times are equal
...
"
<< endl;
//Line 15
cout << "Line 16: Enter the hours, minutes, and "
<< "seconds: ";
cin >> hours >> minutes >> seconds;
cout << endl;

//Line 16
//Line 17
//Line 18

//Set the time of myClock using the value of the
//variables hours, minutes, and seconds
myClock
...
printTime();
//print the time of myClock
Line 21
cout << endl;
//Line 22
//Increment the time of myClock by one second
myClock
...
printTime();
//print the time of myClock
Line 25
cout << endl;
//Line 26
//Retrieve the hours, minutes, and seconds of the
//object myClock
myClock
...


Sample Run: In this sample run, the user input is shaded
...

16: Enter the hours, minutes, and seconds: 5 23 59

Line 20: New myClock: 05:23:59
Line 24: After incrementing myClock by one second, myClock: 05:24:00
Line 28: hours = 5, minutes = 24, seconds = 0

The value of yourClock, as printed in the second line of the output (Line 5), is
machine dependent you might get different values
...
The only thing you need to remember is that, by default, all
members of a class are private
...
If you decide to declare the private
members after the public members (as is done in the case of clockType), you must
use the member access specifier private to begin the declaration of the private
members
...

EXAMPLE 12-3
This declaration is the same as before
...

It is a common practice to list all of the public members first and then the private
members
...


Constructors
In the program in Example 12-2, when we printed the value of yourClock without
calling the function setTime, the output was some strange numbers (see the output of
Line 5 in the sample run)
...
Because the private members of a class cannot be accessed outside of the
class (in our case, the member variables), if the user forgets to initialize these variables by
calling the function setTime, the program will produce erroneous results
...

There are two types of constructors: with parameters and without parameters
...

Constructors have the following properties:








The name of a constructor is the same as the name of the class
...
That is, it is
neither a value-returning function nor a void function
...
However, all constructors of
a class have the same name
...
That is, either they have a different
number of formal parameters or, if the number of formal parameters is
the same, then the data type of the formal parameters, in the order you
list, must differ in at least one position
...

Because they have no types, they cannot be called like other functions
...


Let us extend the definition of the class clockType by including two constructors:
class clockType
{
public:
void setTime(int, int, int);
void getTime(int&, int&, int&) const;
void printTime() const;
void incrementSeconds();

1
2

670 |

Chapter 12: Classes and Data Abstraction

void incrementMinutes();
void incrementHours();
bool equalTime(const clockType&) const;
clockType(int, int, int); //constructor with parameters
clockType(); //default constructor
private:
int hr;
int min;
int sec;
};

This definition of the class clockType includes two constructors: one with three
parameters and one without any parameters
...
Also, the constructor with parameters
sets the member variables to whatever values are assigned to the formal parameters
...

Because a class might have more than one constructor, including the default constructor,
next we discuss how to invoke a specific constructor
...
The syntax to invoke the default
constructor is:
className classObjectName;

For example, the statement:
clockType yourClock;

declares yourClock to be an object of type clockType
...

If you declare an object and want the default constructor to be executed, the empty
parentheses after the object name are not required in the object declaration statement
...
For example, the following statement to declare the object yourClock is illegal:

clockType yourClock();

//illegal object declaration

Invoking a Constructor with Parameters
Suppose a class contains constructors with parameters
...
);

in which argument1, argument2, and so on are either a variable or an expression
...

• If the type of the arguments does not match the formal parameters of any
constructor (in the order given), C++ uses type conversion and looks for
the best match
...
Any ambiguity will result
in a compile-time error
...
Here, we are passing three
values of type int, which matches the type of the formal parameters of the constructor with
a parameter
...

Example 12-6 further illustrates how constructors are executed
...
Suppose that the definitions of
the constructors are as follows:
inventory::inventory() //default constructor
{
name = "";
itemNum = -1;
price = 0
...
0;
unitsInStock = 0;
}
inventory::inventory(string n, int iNum, double cost)
{
name = n;
itemNum = iNum;
price = cost;
unitsInStock = 0;
}

Classes

|

673

inventory::inventory(string n, int iNum, double cost, int inStock)
{
name = n;
itemNum = iNum;
price = cost;
unitsInStock = inStock;
}

Consider the following declarations:
inventory
inventory
inventory
inventory

item1;
item2("Dryer");
item3("Washer", 2345, 278
...
49, 200);

For item1, the default constructor in Line 1 executes because no value is passed to this
variable
...
For
item3, the constructor in Line 3 executes because three parameters are passed to item3,
and they match with the constructor in Line 3
...


item1

item2
name

name

Dryer

itemNum

-1

itemNum

-1

price

0
...
0

unitsInStock

0

item3

0

item4
name

itemNum
price
unitsInStock

FIGURE 12-7

unitsInStock

Washer
2345
278
...
49

unitsInStock

200

Effect of constructors on objects

If the values passed to a class object do not match the parameters of any constructor and
if no type conversion is possible, a compile-time error will be generated
...
In such cases, the rules for declaring
formal parameters are the same as those for declaring default formal parameters in a
function
...
(Chapter 7 discusses
functions with default parameters
...
(Recall that in the function prototype, the name of a formal parameter is optional
...

If you replace the constructors of the class clockType with the constructor in Line 1
(the constructor with the default parameters), then you can declare clockType objects
with zero, one, two, or three arguments, as follows:
clockType
clockType
clockType
clockType

clock1;
clock2(5);
clock3(12, 30);
clock4(7, 34, 18);

//Line
//Line
//Line
//Line

2
3
4
5

The member variables of clock1 are initialized to 0
...

The member variable hr of clock3 is initialized to 12, the member variable min of
clock3 is initialized to 30, and the member variable sec of clock3 is initialized to 0
...

Using these conventions, we can say that a constructor that has no parameters, or has all
default parameters, is called the default constructor
...
Typically, the default constructor is used to initialize the member
variables to some default values, and this constructor has no parameters
...

We have seen that if a class has no constructor(s), then the object created is uninitialized
because C++ does not automatically initialize variables when they are declared
...
However, this default constructor does not do anything
...

The important things to remember about classes and constructors are the following:


If a class has no constructor(s), C++ automatically provides the default
constructor
...


Classes



|

675

On the other hand, suppose a class, say, dummyClass, includes constructor(s) with parameter(s) and does not include the default constructor
...
Therefore, when an object of the class dummyClass is
declared, we must include the appropriate arguments in its declaration
...
Consider the definition of the following class:
class dummyClass
{
public:
void print() const;
dummyClass(int dX, int dY);
private:
int x;
int y;
};

The class dummyClass does not have the default constructor
...
Given this definition of the class dummyClass, the following object
declaration is legal:
dummyClass myObject(10, 25);

//object declaration is legal

However, because the class dummyClass does not contain the default constructor, the
following declaration is incorrect and would generate a syntax error:
dummyClass dummyObject;

//incorrect object declaration

Therefore, to avoid such pitfalls, if a class has constructor(s), the class should also include
the default constructor
...
The default constructor is typically used to initialize each (array) class object
...
(We will further clarify
this at the end of this section
...
You can declare two arrays—arrivalTimeEmp
and departureTimeEmp—of 100 components each, wherein each component is an object
of type clockType
...
, arrivalTimeEmp[99], as shown in Figure 12-8
...
For example, the following statement sets the arrival time, that is, hr,
min, and sec, of the 50th employee to 8, 5, and 10, respectively (see Figure 12-9)
...
setTime(8, 5, 10);

//Line 2

arrivalTimeEmp
arrivalTimeEmp[0]
arrivalTimeEmp[1]

hr
arrivalTimeEmp[49]

8

min

5

sec

arrivalTimeEmp[49]

10

arrivalTimeEmp[98]
arrivalTimeEmp[99]

FIGURE 12-9

Array arrivalTimeEmp after setting the time of employee 49

To output the arrival time of each employee, you can use a loop, such as the following:
for (int j = 0; j < 100; j++)
{
cout << "Employee " << (j + 1)
<< " arrival time: ";
arrivalTimeEmp[j]
...


Classes

|

677

To keep track of the departure time of each employee, you can use the array
departureTimeEmp
...

Before leaving our discussion of arrays of class objects, we would like to point out the
following: The beginning of this section stated that if you declare an array of class objects
and the class has constructor(s), then the class should have the default constructor
...
If the array size is
large, then it is impractical to specify a different constructor with parameters for each
object
...

For example, the following statement declares clocks to be an array of two components
...
The member variables of the second component are initialized to 6, 52, and
39, respectively
...

Consider the following statement, which creates the object myClock and initializes its
member variables to 10, 45, and 38, respectively
...
In fact, the statement:

clockType myClock(10, 45, 38);
is equivalent to the statement:

clockType myClock = clockType(10, 45, 38);
However, the first statement is more efficient
...

The main point that we are stressing here, and that we discussed in the preceding section,
is the following: To avoid any pitfalls, if a class has constructor(s), it should also have the
default constructor
...
Moreover, like constructors, a destructor
does not have a type
...

However, a class can have only one destructor, and the destructor has no parameters
...
For
example, the name of the destructor for the class clockType is:
~clockType();

1
2

678 |

Chapter 12: Classes and Data Abstraction

The destructor automatically executes when the class object goes out of scope
...


Data Abstraction, Classes, and Abstract
Data Types
For the car that we drive, most of us want to know how to start the car and drive it
...
By
separating the design details of a car’s engine from its use, the manufacturer helps the
driver focus on how to drive the car
...
For
the most part, we are concerned only with how to use certain items, rather than with
how they work
...
In other words, abstraction focuses on what the engine does and
not on how it works
...
Driving the car is a logical property;
the construction of the engine constitutes the implementation details
...

Abstraction can also be applied to data
...
The data type clockType has three member variables and the following

basic operations:
1
...

3
...

5
...

7
...

Return the time
...

Increment the time by one second
...

Increment the time by one hour
...


The actual implementation of the operations, that is, the definitions of the member
functions of the class clockType, was postponed
...
The definition of clockType and its basic operations are the logical
properties; the storing of clockType objects in the computer and the algorithms to
perform these operations are the implementation details of clockType
...


Data Abstraction, Classes, and Abstract Data Types |

679

Like any other data type, an ADT has three things associated with it: the name of the
ADT, called the type name; the set of values belonging to the ADT, called the domain;
and the set of operations on the data
...

operations
Set the time
...

Print the time
...

Increment the time by one minute
...

Compare the two times to see whether they are equal
...
Because all values in a list are of the
same type, a convenient way to represent and process a list is to use an array
...

Check to see whether the list is full
...

Delete an item from the list
...

Sort the list
...

Print the list
...
To implement an
ADT, you must represent the data and write algorithms to perform the operations
...
Furthermore, our
definition of a class consisted only of the specifications of the operations; functions to
implement the operations were written separately
...
In fact, in C++, classes were specifically designed
to handle ADTs
...
Typically in a list,
not only do we store the elements, but we also keep track of the number of elements in
the list
...
The following
class, listType, defines the list as an ADT
...


listType
-list: int
-length: int
+isEmptyList() const: bool
+isFullList() const: bool
+search(int) const: int
+insert(int): void
+remove(int): void
+destroyList(): void
+printList(): const: void
+listType()

FIGURE 12-10

UML class diagram of the class listType

A struct Versus a class
Chapter 11 defined a struct as a fixed collection of components, wherein the components can be of different types
...
However, a C++ struct is very similar to a C++ class
...
The only difference between a struct and a class is that, by default, all
members of a struct are public, and all members of a class are private
...


In C, the definition of a struct is similar to the definition of a struct in C++, as given
in Chapter 11
...
However, the definition of a struct in C++ was expanded to
include member functions and constructors and destructors
...

Both C++ classes and structs have the same capabilities
...
In other words, if all of the member variables of a
class are public and the class has no member functions, you typically use a struct to
group these members
...


Information Hiding
The previous section defined the class clockType to implement the time in a
program
...
In fact, we
combined the class clockType with the function definitions to implement the
operations and the function main so as to complete the program
...

Is it a good practice to include the specification and implementation details of a class in
the program? Definitely not
...
Suppose the
definition of the class and the definitions of the member functions are directly included in
the user’s program
...
Therefore, the user can modify the operations in
any way the user pleases
...
Thus, in this sense, the private member variables of an object
are no longer private to the object
...
Thus, we must hide the implementation details
...
Hiding the implementation details frees the user from having to fit this extra piece of code in the program
...
Furthermore, once an object has been written, debugged, and
tested properly, it becomes (and remains) error-free
...
For illustration
purposes, we will use the class clockType
...

So, the user must have access to the specification details
...
Also, because the specification details can be too long,
we must free the user from having to include them directly in the program
...
We must, therefore, put the specification details in a
separate file
...

The implementation file contains the definitions of the functions to implement the
operations of an object
...
Because a C++ program can have only one function,
main, the implementation file does not contain the function main
...
Because the implementation file does not contain
the function main, we cannot produce the executable code from this file
...
The user then links
the object code produced by the implementation file with the object code of the program
that uses the class to create the final executable code
...
Suppose that the specification details of the class clockType are in a file called
clockType
...
h
...
cpp
...
cpp contains only the definitions of the functions, not
the definition of the class
...
h in the file clockTypeImp
...
The following include statement is required by any program that uses
the class clockType, as well as by the implementation file that defines the
operations for the class clockType:
#include "clockType
...
h is enclosed in double quotation marks, not angular
brackets
...
h is called the user-defined header file
...

The implementation contains the definitions of the functions, and these definitions are
hidden from the user because the user is typically provided only the object code
...
Therefore, in the specification file with the function prototypes, we
include comments that briefly describe the function and specify any preconditions and/
or postconditions
...

Postcondition: A statement specifying what is true after the function call is completed
...
h, the specification file for the class clockType
class clockType
{
public:
void setTime(int hours, int minutes, int seconds);
//Function to set the time
...

//Postcondition: hr = hours; min = minutes;
//
sec = seconds;
//
The function checks whether the
//
values of hours, minutes, and seconds
//
are valid
...

void getTime(int& hours, int& minutes, int& seconds) const;
//Function to return the time
...

//Postcondition: The time is printed in the form
//
hh:mm:ss
...

//Postcondition: The time is incremented by one second
...

void incrementMinutes();
//Function to increment the time by one minute
...

//
If the before-increment time is
//
23:59:53, the time is reset to 00:00:53
...

//Postcondition: The time is incremented by one hour
...


bool equalTime(const clockType& otherClock) const;
//Function to compare the two times
...

clockType(int hours, int minutes, int seconds);
//Constructor with parameters
...

//Postcondition: hr = hours; min = minutes;
//
sec = seconds;
//
The constructor checks whether the
//
values of hours, minutes, and seconds
//
are valid
...

clockType();
//Default constructor
//The time is set to 00:00:00
...
cpp, the implementation file
#include
#include


"clockType
...


...

//Place the definitions of the member functions of the class
//clockType here
...


...


Next, we describe the user file containing the program that uses the class clockType
...
h"

Executable Code

|

685

using namespace std;

...


...


...

To save space, we have not provided the complete details of the implementation file and
the file that contains the user program
...


Executable Code
The previous section discussed how to hide the implementation details of a class
...
This section discusses how a client’s program obtains access to the
implementation details of an object
...

As explained previously, to use the class clockType, the program must include the
header file clockType
...
For example, the following
program segment includes the header file clockType
...
cpp
#include "clockType
...


...

int main()
{

...


...
cpp must include only the header file, not the implementation file
...
cpp, the following steps are
required:
1
...
cpp and create the
object code file clockTypeImp
...
The object code file contains
the machine language code, but the code is not in an executable form
...
The command:
cc -c clockTypeImp
...
obj
...
To create the executable code for the source code file test
...
cpp, create the object code file
test
...
obj and clockTypeImp
...
exe
...
exe:
cc test
...
obj
1
...
For example, to create the
object code file for the source code file, called exercise
...
cpp
2
...
For example, to link
A
...
obj with the source code file test
...
cpp A
...
obj
3
...


4
...


5
...
Access to
the header file is needed to see what the objects do and how to use
them
...
The
user does not need access to the source code file containing the
implementation details
...
NET, C++
Builder, and CodeWarrior put the editor, compiler, and linker all into one package
...

These systems also manage multiple-file programs in the form of a project
...
These systems usually have a
command, called build, rebuild, or make
...
)
When the build, rebuild, or make command is applied to a project, the system
automatically compiles and links all of the files required to create the executable code
...

EXAMPLE 12-8
In Example 6-4, the function rollDice rolls a pair of dice until the sum of the numbers
rolled is a given number and returns the number of times the dice are rolled to get the
desired sum
...

Consider the definition of the following class die
...

//This function uses a random number generator to randomly
//generate a number between 1 and 6, and stores the number
//in the instance variable num and returns the number
...

//Returns the value of the instance variable num
...

die::die()
{
num = 1;
srand(time(0));
}
int die::roll()
{
num = rand() % 6 + 1;
}

return num;

int die::getNum() const
{
return num;
}

1
2

688 |

Chapter 12: Classes and Data Abstraction

The following program shows how to use the class die in a program
...
h"
using namespace std;
int main()
{
die die1;
die die2;

//Line 1
//Line 2
//Line 3

cout << "Line 4: die1: " << die1
...
getNum() << endl;

//Line 5

cout << "Line 6: After rolling die1: "
<< die1
...
roll() << endl;
"Line 8: The sum of the numbers rolled"
" by the dice is: "
die1
...
getNum() << endl;

cout << "Line 9: After again rolling, the sum of "
<< "the numbers rolled is: "
<< die1
...
roll() << endl;
return 0;
}//end main

//Line 7
//Line 8

//Line 9
//Line 10
//Line 11

Sample Run:
Line
Line
Line
Line
Line
Line

4:
5:
6:
7:
8:
9:

die1: 1
die2: 1
After rolling die1: 3
After rolling die2: 4
The sum of the numbers rolled by the dice is: 7
After again rolling, the sum of the numbers rolled is: 5

The preceding program works as follows
...
The
statements in Lines 4 and 5 output the number of both the dice
...
Similarly, the statement in Line 7 rolls die2 and
outputs the number rolled
...
The statement in Line 9 again rolls both the dice and outputs the sum
of the numbers rolled
...
The class
personType that is designed in Example 12-9 is very useful; we will use this class in
subsequent chapters
...
The
typical operations on a person’s name are to set the name and print the name
...

#include
using namespace std;
class personType
{
public:
void print() const;
//Function to output the first name and last name
//in the form firstName lastName
...

//Postcondition: firstName = first; lastName = last;
string getFirstName() const;
//Function to return the first name
...

string getLastName() const;
//Function to return the last name
...

personType(string first = "", string last = "");
//Constructor
//Sets firstName and lastName according to the parameters
...

//Postcondition: firstName = first; lastName = last;
private:
string firstName; //variable to store the first name
string lastName; //variable to store the last name
};

Figure 12-11 shows the UML class diagram of the class personType
...

void personType::print() const
{
cout << firstName << " " << lastName;
}
void personType::setName(string first, string last)
{
firstName = first;
lastName = last;
}
string personType::getFirstName() const
{
return firstName;
}
string personType::getLastName() const
{
return lastName;
}
//constructor
personType::personType(string first, string last)
{
firstName = first;
lastName = last;
}

Static Members of a Class |

691

Static Members of a Class
This section may be skipped without any loss of continuation
...
Recall that if
a local variable of a function is static, it exists between function calls
...
Let us note the
following about the static members of a class:


If a function of a class is static, in the class definition it is declared using
the keyword static in its heading
...

• A public static member, function, or variable of a class can be
accessed using the class name and the scope resolution operator
...

EXAMPLE 12-10
Consider the following definition of the class illustrate:
class illustrate
{
public:
static int count;

//public static variable

void print() const;
//Function to output x, y, and count
...

//Postcondition: x = a;
static void incrementY();
//static function
//Function to increment y by 1
...
(These statements are all placed in the
implementation file
...
)
int illustrate::count = 0;
int illustrate::y = 0;
void illustrate::print() const
{
cout << "x = " << x << ", y = " << y
<< ", count = " << count << endl;
}
void illustrate::setX(int a)
{
x = a;
}
void illustrate::incrementY()
{
y++;
}
illustrate::illustrate(int a)
{
x = a;
}

Because the function incrementY is static and public, the following statement is
legal:
illustrate::incrementY();

Similarly, because the member variable count is static and public, the following
statement is legal:
illustrate::count++;

Next, we elaborate on static member variables a bit more
...
When
you create objects of type myClass, only non-static member variables of the class
myClass become the member variables of each object
...
All myClass objects refer to
the same memory space
...
You can access the public static member variables
outside of the class, as explained earlier in this section
...

Suppose that you have the class illustrate, as given in Example 12-10
...

Consider the following statements:
illustrate illusObject1(3);
illustrate illusObject2(5);

//Line 1
//Line 2

The statements in Line 1 and Line 2 declare illusObject1 and illusObject2 to be
illustrate type objects (see Figure 12-12)
...


1
2

y 1
count 1
illusObject1

illusObject2
x

FIGURE 12-13

3

x

5

illusObject1 and illusObject2 after the statements illustrate::
incrementY(); and illustrate::count++; execute

694 |

Chapter 12: Classes and Data Abstraction

The output of the statement:
illusObject1
...
print();

is:
x = 5, y = 1, count = 1

Now consider the statement:
illustrate::count++;

After this statement executes, the objects and static members are as shown in
Figure 12-14
...
print();
illusObject2
...


Static Members of a Class |

695

EXAMPLE 12-11
#include
#include "illustrate
...
print();
illusObject2
...
incrementY();
illusObject1
...
print();
illusObject2
...
incrementY();
illusObject2
...
print();
illusObject2
...
The static member variables y and count
are initialized to 0
...
The statement in

1
2

696 |

Chapter 12: Classes and Data Abstraction

Line 2 declares illusObject2 to be an object of the class
initializes its member variable x to 5
...
Now, count is a public static member of the class
illustrate
...
The statements in Lines 5 and 6 output the data
stored in the objects illusObject1 and illusObject2
...
Similarly, the value of count for both objects is the same
...
The statement in Line 8 uses the object
illusObject1 and the function incrementY to increment y
...
Lines 10 and 11 output the
data stored in the objects illusObject1 and illusObject2
...
Similarly, the value of count for both objects is the same
...

The statement in Line 13 uses the object illusObject2 and the function incrementY
to increment y
...
Lines 15 and 16 output the data stored in the objects
illusObject1 and illusObject2
...
Similarly, the value of count for both objects is the same
...


Here are some additional comments on static members of a class
...
It can be called using the name of the class and the scope resolution operator, as
illustrated
...
In other words, in the definition of a static member function, you
cannot use a non-static member variable or a non-static function unless there is
an object declared locally that accesses the non-static member variable or the nonstatic member function
...
This class
contains both static and non-static member variables
...
Earlier in
this chapter, we defined the terminology instance variables of a class using the class
clockType
...
A class can have static as well as non-static member variables
...


Programming Example: Candy Machine |

PROGRAMMING EXAMPLE:

697

Candy Machine

A common place to buy candy is from a machine
...
The machine sells candies,
chips, gum, and cookies
...

The program should do the following:
1
...

3
...

5
...

Let the customer make the selection
...

Accept money from the customer
...

The item selection and the cost of the item
...


A candy machine has two main components: a built-in cash register and several
dispensers to hold and release the products
...
The register has some cash on hand, it

accepts the amount from the customer, and if the amount deposited is more than the cost
of the item, then—if possible—it returns the change
...
The cash register
should also be able to show to the candy machine’s owner the amount of money in the
register at any given time
...

//Postcondition: The value of cashOnHand is returned
...

//Postcondition: cashOnHand = cashOnHand + amountIn;
cashRegister(int cashIn = 500);
//Constructor
//Sets the cash in the register to a specific amount
...


//variable to store the cash
//in the register

Figure 12-15 shows the UML class diagram of the class cashRegister
...
The definitions of these functions are very simple and easy to

follow
...
It
returns the value of the private member variable cashOnHand
...

It updates the cash in the register by adding the amount deposited by the customer to the
previous amount in the cash register
...
Therefore, if the user does not specify any value when the object is
declared, the default value is used to initialize the member variable cashOnHand
...
The definition of the constructor is as follows:
cashRegister::cashRegister(int cashIn)
{
if (cashIn >= 0)
cashOnHand = cashIn;
else
cashOnHand = 500;
}

Note that the definition of the constructor checks for valid values of the parameter
cashIn
...

Dispenser The dispenser releases the selected item if it is not empty
...
The following class defines the
properties of a dispenser
...

//Postcondition: The value of numberOfItems is returned
...

//Postcondition: The value of cost is returned
...

//Postcondition: numberOfItems--;
dispenserType(int setNoOfItems = 50, int setCost = 50);
//Constructor
//Sets the cost and number of items in the dispenser
//to the values specified by the user
...

private:
int numberOfItems;
};

int cost;

//variable to store the number of
//items in the dispenser
//variable to store the cost of an item

1
2

700 |

Chapter 12: Classes and Data Abstraction

Figure 12-16 shows the UML class diagram of the class dispenserType
...
For example, the statement:
dispenserType chips(100, 65);

declares chips to be an object of type dispenserType, sets the number of
chip bags in the dispenser to 100, and sets the cost of each chip bag to 65 cents
(see Figure 12-17)
...

The function getNoOfItems returns the number of items of a particular product
...
The definition of this function is:
int dispenserType::getNoOfItems() const
{
return numberOfItems;
}

Programming Example: Candy Machine |

701

The function getCost returns the cost of a product
...
The definition of this function is:
int dispenserType::getCost() const
{
return cost;
}

When a product is sold, the number of items in that dispenser is reduced by 1
...
That is,
it decrements the value of the private member variable numberOfItems by 1
...
If these
values are less than 0, the default values are assigned to the member variables
...
Show the different products sold by the candy machine
...
Show how to select a particular product
...
Show how to terminate the program
...
Once the user has made the appropriate
selection, the candy machine must act accordingly
...
If the amount deposited is at least the
cost of the item, the candy machine should sell the item and display an appropriate
message
...
Show the selection to the customer
...
Get the selection
...
If the selection is valid and the dispenser corresponding to the
selection is not empty, sell the product
...

showSelection This function displays the information necessary to help the user select and buy a
product
...
Therefore, it

must have access to the dispenser holding the product
...
If the
dispenser is empty, the function informs the customer that this product is sold out
...

If the user does not deposit enough money to buy the product, sellProduct tells the user
how much additional money must be deposited
...
(Programming
Exercise 9, at the end of this chapter, asks you to revise the definition of the method
sellProduct so that it keeps asking the user to enter the additional amount as long as
the user has not entered enough money to buy the product
...

Selling the product means to decrement the number of items in the dispenser
by 1 and to update the money in the cash register by adding the cost of
the product
...
)
From this discussion, it is clear that the function sellProduct must have access to
the dispenser holding the product (to decrement the number of items in the dispenser
by 1 and to show the cost of the item) as well as the cash register (to update the cash)
...
Furthermore, both parameters must be
referenced
...
If the dispenser is not empty,
a
...

b
...

c
...


Show and prompt the customer to enter the additional
amount
...
Calculate the total amount entered by the customer
...
If the amount entered by the customer is at least the cost of the
product,
i
...


Update the amount in the cash register
...

iii
...

e
...

2
...

This definition of the function sellProduct is:
void sellProduct(dispenserType& product,
cashRegister& pCounter)
{
int amount; //variable to hold the amount entered
int amount2; //variable to hold the extra amount needed
if (product
...
getCost()
<< " cents" << endl;
cin >> amount;

1
2

704 |

Chapter 12: Classes and Data Abstraction

if (amount < product
...
getCost()- amount
<< " cents" << endl;
cin >> amount2;
amount = amount + amount2;
}
if (amount >= product
...
acceptAmount(amount);
product
...
" << endl;
}
else
cout << "The amount is not enough
...
" << endl;
cout << "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
<< endl << endl;

}
else

cout << "Sorry, this item is sold out
...

main The algorithm for the function main is as follows:

1
...

2
...
For example, the statement:
dispenserType candy(100, 50);

3
...

5
...


creates a dispenser object, candy, to hold the candies
...

Declare additional variables as necessary
...

Get the selection
...
Sell the product; call the function sellProduct
...
Show the selection; call the function showSelection
...
Get the selection
...
" << endl;
}//end switch
showSelection();
cin >> choice;
}//end while
return 0;
}//end main

COMPLETE PROGRAM LISTING

In the previous sections, we designed the classes to implement cash registers and
dispensers to implement a candy machine
...


1
2

706 |

Chapter 12: Classes and Data Abstraction

//************************************************************
// Author: D
...
Malik
//
// class cashRegister
// This class specifies the members to implement a cash
// register
...

//Postcondition: The value of cashOnHand is returned
...

//Postcondition: cashOnHand = cashOnHand + amountIn;
cashRegister(int cashIn = 500);
//Constructor
//Sets the cash in the register to a specific amount
...

private:
int cashOnHand;
};

//variable to store the cash
//in the register

//************************************************************
// Author: D
...
Malik
//
// class dispenserType
// This class specifies the members to implement a dispenser
...

//Postcondition: The value of numberOfItems is returned
...

//Postcondition: The value of cost is returned
...

//Postcondition: numberOfItems--;

Programming Example: Candy Machine |

707

dispenserType(int setNoOfItems = 50, int setCost = 50);
//Constructor
//Sets the cost and number of items in the dispenser
//to the values specified by the user
...

private:
int numberOfItems;
};

int cost;

//variable to store the number of
//items in the dispenser
//variable to store the cost of an item

//**********************************************************
// Author: D
...
Malik
//
// Implementation file candyMachineImp
...

//**********************************************************
#include
#include "candyMachine
...
S
...

// ****************************************************
#include
#include "candyMachine
...
" << endl;
}//end switch
showSelection();
cin >> choice;
}//end while
return 0;
}//end main
void showSelection()
{
cout << "*** Welcome to Shelly's Candy Shop ***" << endl;
cout << "To select an item, enter " << endl;
cout << "1 for Candy" << endl;
cout << "2 for Chips" << endl;
cout << "3 for Gum" << endl;
cout << "4 for Cookies" << endl;
cout << "9 to exit" << endl;
}//end showSelection
void sellProduct(dispenserType& product,
cashRegister& pCounter)
{
int amount; //variable to hold the amount entered
int amount2; //variable to hold the extra amount needed
if (product
...
getCost()
<< " cents" << endl;
cin >> amount;
if (amount < product
...
getCost()- amount
<< " cents" << endl;
cin >> amount2;
amount = amount + amount2;
}

1
2

710 |

Chapter 12: Classes and Data Abstraction

if (amount >= product
...
acceptAmount(amount);
product
...
" << endl;
}
else
cout << "The amount is not enough
...
" << endl;
cout << "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
<< endl << endl;

}
else

cout << "Sorry, this item is sold out
...

*** Welcome to Shelly's Candy Shop ***
To select an item, enter
1 for Candy
2 for Chips
3 for Gum
4 for Cookies
9 to exit
1
Please deposit 50 cents
50
Collect your item at the bottom and enjoy
...
h
...
Similarly, you
can also create separate implementation files for these classes
...


Quick Review |

711

QUICK REVIEW
1
...

3
...

5
...

7
...

9
...

11
...

13
...

15
...

17
...

19
...

21
...


A class is a collection of a fixed number of components
...

Members of a class are accessed by name
...

Members of a class are classified into one of three categories: private,
protected, and public
...

The public members of a class are accessible outside of the class
...

The public members are declared using the member access specifier
public and the colon, :
...

A member of a class can be a function or a variable
...

If any member of a class is a variable, it is declared like any other variable
...

In the Unified Modeling Language (UML) diagram of a class, the top box
contains the name of the class
...
The last box contains the member function
name, parameter list, and the return type of the function
...
A (minus) sign preceding a member indicates that this is a private member
...

In C++, a class is a definition
...

In C++, class variables are called class objects or class instances or, simply,
objects
...
), followed by the member name
...

As parameters to functions, classes can be passed either by value or by reference
...

Any program (or software) that uses a class is called a client of the class
...

24
...


26
...

28
...

30
...

32
...

34
...


36
...

38
...

40
...

42
...

44
...

A member function of a class that modifies the value(s) of the member
variable(s) is called a mutator function
...
Moreover, a constant
member function of a class cannot modify the member variables of the class
...

Constructors guarantee that the member variables are initialized when an
object is declared
...

A class can have more than one constructor
...

Constructors automatically execute when a class object enters its scope
...

A class can have only one destructor, and the destructor has no parameters
...

Constructors and destructors are functions without any type; that is, they
are neither value-returning nor void
...

A data type that separates the logical properties from the implementation
details is called an abstract data type (ADT)
...

To implement an ADT, you must represent the data and write related
algorithms to implement the operations
...

A postcondition is a statement specifying what is true after the function call
is completed
...

For each static variable of a class, C++ allocates only one memory
space
...

static member variables of a class exist even when no object of the
class type exists
...


Exercises

|

713

EXERCISES
1
...

The member variables of a class must be of the same type
...
The member functions of a class must be public
...
A class can have more than one constructor
...
A class can have more than one destructor
...
Both constructors and destructors can have parameters
...

a
...


a
...


class BB
{
int one;
int two;
public:
bool equal() const;
print();
BB(int, int);
}

c
...


class AA
{
public:
void print()const;
int sum();
AA();
int AA(int, int);
private:
int x;
int y;
};

class CC
{
public;
void set(int, int);
void print()const;
CC();
CC(int, int);
bool CC(int, int);
private:
int u;
int v;
};

Consider the following declarations:
class xClass
{
public:
void func();
void print() const ;

1
2

714 |

Chapter 12: Classes and Data Abstraction

xClass ();
xClass (int, double);
private:
int u;
double w;
};

and assume that the following statement is in a user program:
xClass x;

How many members does class xClass have?
b
...
How many constructors does class xClass have?
d
...
3
...
Write the definition of the member function print that prints the
contents of u and w
...

Write the definition of the default constructor of the class xClass so
that the private member variables are initialized to 0
...
Write a C++ statement that prints the values of the member variables of
the object x
...
Write a C++ statement that declares an object t of type xClass and
initializes the member variables of t to 20 and 35
...

Consider the definition of the following class:
a
...


class CC
{
public :
CC();
CC(int);
CC(int, int);
CC(double, int);

...


...


//Line
//Line
//Line
//Line

1
2
3
4

Give the line number containing the constructor that is executed in
each of the following declarations
...


CC one;

ii
...


CC three(3
...

c
...

d
...

Consider the definition of the following class:
b
...


class testClass
{
public:
int sum();
//Returns the sum of the private member variables
void print() const;
//Prints the values of the private member variables
testClass();
//Default constructor
//Initializes the private member variables to 0
testClass(int a, int b);
//Constructors with parameters
//initializes the private member variables to the values
//specified by the parameters
//Postcondition: x = a; y = b;
private:
int x;
int y;
};

Write the definitions of the member functions as described in the
definition of the class testClass
...
Write a test program to test the various operations of the class testClass
...


6
...
printTime();
cout << endl;
clock2
...
setTime(6, 59, 39);
clock1
...
incrementMinutes();
clock1
...
setTime(0, 13, 0);
if (clock1
...
"
<< endl;
else
cout << "The two times are different
...


Assume the definition of the class personType as given in this chapter
...

b
...

c
...

Explain why you would need both public and private members in a class
...
?
Which of the following characters appears before a destructor’s name?
a
...

9
...


a
...

12
...


!

c
...


$

What is a destructor and what is its purpose?
Write the definition of a class that has the following properties:
a
...


c
...

The class secretType has four member variables: name of type
string, age and weight of type int, and height of type double
...
(Make
each accessor function constant
...


appropriate titles
setName—function to set the name
setAge—function to set the age
setWeight—function to set the weight
setHeight—function to set the height
getName—value-returning function to return the name
getAge—value-returning function to return the age
getWeight—value-returning function to return the weight
getHeight—value-returning function to return the height
constructor—with default parameters: The default value of name is the
empty string " ", and the default values of age, weight, and height are 0
...


Exercises

13
...

//Postcondition: x = a;
void printX() const;
//Function to output x
...

static void incrementCount();
//Function to increment count
...


b
...

d
...


f
...


Write a C++ statement that initializes the member variable count to
0
...

Write a C++ statement that outputs the value of count
...

Write a C++ statement that declares myObject1 to be a myClass
object and initializes its member variable x to 5
...

Which of the following statements are valid? (Assume that myObject1
and myObject2 are as declared in Parts e and f
...
printCount();
myObject1
...
printCount();
myClass
...


//Line
//Line
//Line
//Line
//Line

1
2
3
4
5

Assume that myObject1 and myObject2 are as declared in Parts e and f
...
printX();
cout << endl;
myObject1
...
printCount();
cout << endl;
myObject2
...
printX();
cout << endl;
myObject1
...
incrementCount();
myObject1
...
printCount();
cout << endl;
myObject2
...


In Example 12-8, we designed the class die
...
Write C++ statements to roll each die of the array rolls, find and output the heighest
number rolled and the number of times this number was rolled, and find
and output the number that is rolled the maximum number of times
together with its count
...


PROGRAMMING EXERCISES
1
...
Your program should consist of a class, say, romanType
...

b
...


Store the number as a Roman numeral
...

Print the number as a Roman numeral or decimal number as requested
by the user
...


1000

1

Test your program using the following Roman numerals: MCXIV,
CCCLIX, MDCLXVI
...


|

719

Design and implement a class dayType that implements the day of the
week in a program
...
The program should be able to perform the following operations
on an object of type dayType:
Set the day
...
Print the day
...
Return the day
...
Return the next day
...
Return the previous day
...
Calculate and return the day by adding certain days to the current day
...
Similarly, if today is Tuesday and we add 13 days,
the day to be returned is Monday
...
Add the appropriate constructors
...
Also, write a
program to test various operations on this class
...
Add functions to this class so that a program that uses this class can set
only the hours, minutes, or seconds and retrieve only the hours, minutes, or
seconds
...

Example 12-9 defined a class personType to store the name of a person
...
Redefine the class personType so that, in addition to
what the existing class does, you can:
a
...


4
...


a
...

c
...

e
...


a
...

Set the last name only
...

Check whether a given first name is the same as the first name of this person
...

Write the definitions of the member functions to implement the operations
for this class
...

Some of the characteristics of a book are the title, author(s), publisher,
ISBN, price, and year of publication
...

i
...
To keep track of
the number of authors, add another member variable
...
For example, the usual operations that
can be performed on the title are to show the title, set the title, and
check whether a title is the same as the actual title of the book
...
Add similar operations for the publisher, ISBN, book price, and authors
...

b
...

c
...
Declare an array
of 100 components of type bookType
...

In this exercise, you will design a class memberType
...


7
...

b
...
Similarly, update, modify, and show the number of books bought
and the amount spent
...
Add the appropriate constructors
...
Write the definitions of the member functions of memberType
...
Write a program to test various operations of your class memberType
...
The bookstore has two types of customers:
those who are members of the bookstore and those who buy books from the
bookstore only occasionally
...

For each member, the bookstore keeps track of the number of books
purchased and the total amount spent
...

Write a program that can process up to 1000 book titles and 500 members
...

The method sellProduct of the Candy Machine programming example
gives the user only two chances to enter enough money to buy the product
...


8
...


Programming Exercises

10
...


12
...
Also, write a program to test your method
...
Your class should have the instance
variables to store the length (in feet), width (in feet), depth (in feet), the
rate (in gallons per minute) at which the water is filling the pool, and the
rate (in gallons per minute) at which the water is draining from the pool
...
Also add
member functions to do the following: determine the amount of water
needed to fill an empty or partially filled pool; determine the time needed
to completely or partially fill or empty the pool; add or drain water for a
specific amount of time
...
Your program must contain the class ticTacToe to implement a
ticTacToe object
...
If needed, include additional member
variables
...
Add additional operations as needed
...
If b 6¼ 0, then –a/b is the
slope of the line
...
The slope of a vertical line is undefined
...
Two lines are
perpendicular if either one of the lines is horizontal and the other is vertical
or the product of their slopes is –1
...
To store a line, you need to store the values of a (coefficient of x), b
(coefficient of y), and c
...

a
...


c
...

e
...

Determine if two lines are equal
...
)
Determine if two lines are parallel
...

If two lines are not parallel, then find the point of intersection
...
Also write
a program to test your class
...


Chapter 12: Classes and Data Abstraction

Typically, everyone saves money periodically for retirement, buying a
house, or for some other purposes
...
In this
exercise, for simplicity, we assume that the money is put into an account that
pays a fixed interest rate, and money is deposited into the account at the end
of the specified period
...
Then i total accumulated at the end of t years is given by
the
h
R

ð1þr=mÞmt À1
r=m


...
8% interest per year compounded
monthly for 25 years
...
048/12)300 – 1]/(0
...
42
...

sðr=mÞ
The periodic payment is given by the formula ð1þr=mÞ mt À1
...

Your class should have instance variables to store the periodic deposit, the
value of m, the interest rate, and the number of years the money will be
saved
...


13
CHAPTER

I NHERITANCE AND
COMPOSITION
I N T H I S C H A P T E R , YO U W I L L :


...


Learn about derived and base classes


...


Examine how the constructors of base and derived classes work


...


Explore three types of inheritance: public, protected, and private


...


Become familiar with the three basic principles of object-oriented design

724 |

Chapter 13: Inheritance and Composition

Chapter 12 introduced classes, abstract data types (ADT), and ways to implement ADT in
C++
...
An object,
therefore, becomes a self-contained entity
...

In addition to implementing ADT, classes have other features
...
This important feature encourages code reuse
...
Two common ways to
relate classes in a meaningful way are:



Inheritance (‘‘is-a’’ relationship)
Composition (aggregation) (‘‘has-a’’ relationship)

Inheritance
Suppose that you want to design a class, partTimeEmployee, to implement and
process the characteristics of a part-time employee
...
In
Example 12-9 (in Chapter 12), we designed a class to implement a person’s name
...
Therefore, rather than design the class
partTimeEmployee from scratch, we want to be able to extend the definition of
the class personType (from Example 12-9) by adding additional members (data
and/or functions)
...

In fact, we want to create the class partTimeEmployee without making any
physical changes to the class personType by adding only the members that are
necessary
...
In fact, these member variables will be inherited from the
class personType
...
)
In Chapter 12, we extensively studied and designed the class clockType to implement
the time of day in a program
...
Certain applications, in addition to the hours, minutes, and
seconds, might also require us to store the time zone
...
That is, we want to derive the class extClockType by
adding a member variable—say, timeZone—and the necessary member functions to
manipulate the time (see Programming Exercise 1 at the end of this chapter)
...
Inheritance is
an ‘‘is-a’’ relationship; for instance, ‘‘every employee is a person
...
The new classes that we create
from the existing classes are called the derived classes; the existing classes are called the

Inheritance

|

725

base classes
...
So rather than
create completely new classes from scratch, we can take advantage of inheritance and
reduce software complexity
...
Inheritance
can be either single inheritance or multiple inheritance
...
This chapter concentrates on single
inheritance
...
Consider the tree diagram shown in Figure 13-1
...
The classes circle and rectangle are
derived from shape, and the class square is derived from rectangle
...
Every square is a rectangle
...
When no
memberAccessSpecifier is specified, it is assumed to be a private inheritance
...
)

1
3

726 |

Chapter 13: Inheritance and Composition

EXAMPLE 13-1
Suppose that we have defined a class called shape
...

class circle: public shape
{

...


...


...

};

This is a private inheritance
...
So any object of type circle
cannot directly access these members
...


...

};

That is, if we do not use either the memberAccessSpecifier public or private,
the public members of a base class are inherited as private members
...

1
...
In
other words, when you write the definitions of the member functions of
the derived class, you cannot directly access the private members of
the base class
...
The public members of a base class can be inherited either as public
members or as private members by the derived class
...

3
...


Inheritance

|

727

4
...
That is, in the derived class, you can have a member function with
the same name, number, and types of parameters as a function in the
base class
...

5
...
Similarly, the member functions of the base class
(unless redefined) are also member functions of the derived class
...
)
The next sections describe two important issues related to inheritance
...
While
discussing this issue, we will also address how to access the private (data) members of
the base class in the derived class
...
The constructor of a derived class cannot directly access the private
member variables of the base class
...


Redefining (Overriding) Member Functions of the Base Class
Suppose that a class derivedClass is derived from the class baseClass
...
It then follows that the member variables of the class derivedClass
are its own member variables, together with the member variables of baseClass
...
Now derivedClass contains member variables
in addition to the member variables inherited from baseClass
...
You can give any name to this function
...
This is called redefining (or overriding) the member function of the
base class
...

To redefine a public member function of a base class in the derived class, the
corresponding function in the derived class must have the same name, number, and
types of parameters
...
If the
corresponding functions in the base class and the derived class have the same name but
different sets of parameters, then this is function overloading in the derived class,
which is also allowed
...

//Postcondition: length = l; width = w;
double getLength() const;
//Function to return the length of the rectangle
...

double getWidth() const;
//Function to return the width of the rectangle
...

double area() const;
//Function to return the area of the rectangle
...

double perimeter() const;
//Function to return the perimeter of the rectangle
...

void print() const;
//Function to output the length and width of
//the rectangle
...


Inheritance

|

729

rectangleType
–length: double
–width: double
+setDimension(double, double): void
+getLength() const: double
+getWidth() const: double
+area() const: double
+perimeter() const: double
+print() const: void
+rectangleType()
+rectangleType(double, double)

FIGURE 13-2

UML class diagram of the class rectangleType

The class rectangleType has 10 members
...

//Postcondition: length = l; width = w; height = h;
double getHeight() const;
//Function to return the height of the box
...

double area() const;
//Function to return the surface area of the box
...

double volume() const;
//Function to return the volume of the box
...

void print() const;
//Function to output the length, width, and height of a box
...


boxType
–height: double
+setDimension(double, double, double): void
+getHeight() const: double
+area() const: double
+volume() const: double
+print() const: void
+boxType()
+boxType(double, double, double)

FIGURE 13-3

rectangleType

boxType

UML class diagram of the class boxType and the inheritance hierarchy

From the definition of the class boxType, it is clear that the class boxType
is derived from the class rectangleType, and it is a public inheritance
...
The class boxType also overrides (redefines) the functions print
and area
...

• If the derived class does not override a public member function of the
base class, you may specify a call to that public member function by
using the name of the function and the appropriate parameter list
...
)

1
3

732 |

Chapter 13: Inheritance and Composition

If a derived class overloads a public member function of the base class, then while
writing the definition of a member function of the derived class, to specify a call to
that (overloaded) member function of the base class, you might need (depending on
the compiler) to use the name of the base class, followed by the scope resolution
operator, ::, followed by the function name with the appropriate parameter list
...
(See the definition of the function setDimension
[of the class boxType], given later in this section
...

The class boxType has three member variables: length, width, and height
...
To write the definition of the function print of the class boxType, keep in
mind the following:


The member variables length and width are private members of
the class rectangleType, so they cannot be directly accessed in the
class boxType
...

• The member variables length and width of the class rectangleType
are accessible in the class boxType through the public member
functions of the class rectangleType
...
After printing the values of length and
width, we output the values of height
...

The definition of the member function print of the class boxType is:
void boxType::print() const
{
rectangleType::print();
cout << "; Height = " << height;
}

Let us write the definitions of the remaining member functions of the class boxType
...

The definition of the function getHeight is:
double boxType::getHeight() const
{
return height;
}

The member function area of the class boxType determines the surface area of a box
...
Therefore, we
use the member functions getLength and getWidth of the class rectangleType to
retrieve the length and width, respectively
...

double boxType::area() const
{
return 2 * (getLength() * getWidth()
+ getLength() * height
+ getWidth() * height);
}

The member function volume of the class boxType determines the volume of a box
...
Let us write the definition of
the member function volume by using the second alternative
...
Because the class boxType overrides the member function area, to specify a call
to the member function area of the class rectangleType, we use the name of the
base class and the scope resolution operator, as shown in the following definition:
double boxType::volume() const
{
return rectangleType::area() * height;
}

1
3

734 |

Chapter 13: Inheritance and Composition

In the next section, we discuss how to specify a call to the constructor of the base class
when writing the definition of a constructor of the derived class
...
A constructor typically serves to initialize the
member variables
...
The same is true for the member functions
of a derived class
...

As a consequence, the constructors of a derived class can (directly) initialize only the
(public data) members inherited from the base class of the derived class
...
Because constructors cannot be called like other
functions, the execution of a derived class’s constructor must trigger the execution
of one of the base class’s constructors
...
Furthermore, a
call to the base class’s constructor is specified in the heading of the definition of a
derived class constructor
...
Moreover, we illustrated how to override a member function
of the class rectangleType
...

The class rectangleType has two constructors and two member variables
...
The
member variables length and width are inherited from the class rectangleType
...

Recall that, if a class contains the default constructor and no values are specified when
the object is declared, the default constructor executes and initializes the object
...

boxType::boxType()
{
height = 0
...
To trigger
the execution of a constructor (with parameters) of the base class, you specify the name of
a constructor of the base class with the parameters in the heading of the definition of the
constructor of the derived class
...

When this constructor of boxType executes, it triggers the execution of the constructor
with two parameters of type double of the class rectangleType
...
0, 3
...
0, 5
...
0);

//Line 1
//Line 2

The statement in Line 1 creates the rectangleType object myRectangle
...
The statement in
Line 2 creates the boxType object myBox
...


myBox
myRectangle

length
width

length

3
...
0

width

5
...
0

height

FIGURE 13-4

4
...
print();
cout << endl;
myBox
...
In the statement in Line 5, the function print associated with the class
boxType is executed
...
Thus, the
output of the statement in Line 3 is:
Length = 5
...
0

1
3

736 |

Chapter 13: Inheritance and Composition

The output of the statement in Line 5 is:
Length = 6
...
0; Height = 4
...
Note that the constructors of a base class are not inherited in a derived
class
...
When a derived class constructor executes, first a constructor of the base class
executes to initialize the data members inherited from the base class, and then the constructor
of the derived class executes to initialize the data members declared by the derived class
...

The program in Example 13-2 shows how the objects of a base class and a derived class
behave
...
h"
"boxType
...
print();
cout << endl;
cout << "Line 9: Area of myRectangle1: "
<< myRectangle1
...
print();
cout << endl;
cout << "Line 13: Area of myRectangle2: "
<< myRectangle2
...
print();
cout << endl;
cout << "Line 17: Surface Area of myBox1: "
<< myBox1
...
volume() << endl;
cout << "Line 19: myBox2: ";
myBox2
...
area() << endl;
cout << "Line 23: Volume of myBox2: "
<< myBox2
...
00; Width = 0
...
00
10: myRectangle2: Length = 8
...
00
13: Area of myRectangle2: 48
...
00; Width = 0
...
00
17: Surface Area of myBox1: 0
...
00
19: myBox2: Length = 10
...
00; Height = 3
...
00
23: Volume of myBox2: 210
...
The statement in Line 2
creates the rectangleType object myRectangle2 and initializes its member variables
length and width to 8
...
0, respectively
...
The statement in Line 4 creates the boxType object myBox2 and initializes
its member variables length, width, and height to 10
...
0, and 3
...

The statement in Line 5 sets the output of the decimal number to two decimal places in a
fixed decimal format with the decimal point and trailing zeros
...

Because the member variables of myRectangle1 are initialized to 0 by the default
constructor, the area of the rectangle is 0 square units
...

The statements in Lines 10 through 13 output the length, width, and area of
myRectangle2
...
0 and 6
...
0 square units
...


1
3

738 |

Chapter 13: Inheritance and Composition

The statements in Lines 14 through 18 output the length, width, height, surface area, and
volume of myBox1
...
0 square units, and the volume is 0
...
See Lines 17 and 18 in the sample run
...
Because the member variables length, width, and height of
myBox2 are initialized to 10
...
0, and 3
...
0 square units, and the volume is 210
...
See Lines 22 and 23 in the sample run
...


(Constructors with default parameters and the inheritance hierarchy) Recall that a class can
have a constructor with default parameters
...
For example, suppose that the definition of the
class rectangleType is as shown below
...
)

class rectangleType
{
public:
void setDimension(double l, double w);
double getLength() const;
double getWidth() const;
double area() const;
double perimeter()const;
void print() const;
rectangleType(double l = 0, double w = 0);
//Constructor with default parameters
private:
double length;
double width;
};
Suppose the definition of the constructor is:

rectangleType::rectangleType(double l, double w)
{
setDimension(l, w);
}

Inheritance

|

739

Now suppose that the definition of the class boxType is:

class boxType: public rectangleType
{
public:
void setDimension(double l, double w, double h);
double getHeight()const;
double area() const;
double volume() const;
void print() const;
boxType(double l = 0, double w = 0, double h = 0);
//Constructor with default parameters
private:
double height;
};
You can write the definition of the constructor of the class boxType as follows:

boxType::boxType(double l, double w, double h)
: rectangleType(l, w)
{
if (h >= 0)
height = h;
else
height = 0;
}
Notice that this definition also takes care of the default constructor of the class
boxType
...

Further suppose that the class derivedClass is derived from baseClass, and
derivedClass has no member variables
...
A constructor cannot be called
like other functions, and the member variables of baseClass cannot be directly accessed
by the member functions of derivedClass
...

A constructor (with parameters) of derivedClass merely issues a call to a constructor
(with parameters) of baseClass
...


1
3

740 |

Chapter 13: Inheritance and Composition

EXAMPLE 13-3
Suppose that you want to define a class to group the attributes of an employee
...
Part-time employees are paid based on
the number of hours worked and an hourly rate
...
You can then print the employee’s name together with his or her wages
...

You can also redefine the print function to print the appropriate information
...

//Postcondition: Outputs
//
firstName lastName wages are $$$$
...

//Postcondition: Pay is calculated and returned
void setNameRateHours(string first, string last,
double rate, double hours);
//Function to set the first name, last name, payRate,
//and hoursWorked according to the parameters
...
If no value is specified,
//the default values are assumed
...


Inheritance

|

741

partTimeEmployee
–payRate: double
–hoursWorked: double
+print() const: void
+calculatePay() const: double
+setNameRateHours(string, string,
double, double ): void
+partTimeEmployee(string = "", string = "",
double = 0), double = 0)

FIGURE 13-5

personType

partTimeEmployee

UML class diagram of the class partTimeEmployee and inheritance hierarchy

The definitions of the member functions of the class partTimeEmployee are as follows:
void partTimeEmployee::print() const
{
personType::print(); //print the name of the employee
cout << "'s wages are: $" << calculatePay() << endl;
}
double partTimeEmployee::calculatePay() const
{
return (payRate * hoursWorked);
}
void partTimeEmployee::setNameRateHours(string first,
string last, double rate, double hours)
{
personType::setName(first, last);
payRate = rate;
hoursWorked = hours;
}
//Constructor
partTimeEmployee::partTimeEmployee(string first, string last,
double rate, double hours)
: personType(first, last)
{
if (rate >= 0)
payRate = rate;
else
payRate = 0;
if (hours >= 0)
hoursWorked = hours;
else
hoursWorked = 0;
}

1
3

742 |

Chapter 13: Inheritance and Composition

Destructors in a Derived Class
Recall from Chapter 12 that a class can have a destructor
...
(A memory space that is allocated during execution time is called a
dynamic memory space
...
) Suppose that a base class and its derived class have destructors
...
When the destructor
of the derived class executes, it automatically invokes the destructor of the base class
...
Furthermore, when the destructor of the
derived class exectues first, it executes its own code and then calls the destructor of the
base class
...
When an object of
class three goes out of scope, first the destructor of class three executes, then the
destructor of class two executes, and finally, the destructor of class one executes
...

HEADER FILE OF A DERIVED CLASS
The previous section explained how to derive new classes from previously defined
classes
...
The base classes are
already defined, and header files contain their definitions
...


Suppose that the definition of the class personType is placed in the header file
personType
...
To create the definition of the class partTimeEmployee, the
header file—say, partTimeEmployee
...
h"

before the definition of the class partTimeEmployee
...
h is as shown below
...
h"
class partTimeEmployee: public personType
{
public:
void print() const;
//Function to output the first name, last name, and
//the wages
...
$$

Inheritance

|

743

double calculatePay() const;
//Function to calculate and return the wages
...

//Postcondition: firstName = first; lastName = last;
//
payRate = rate; hoursWorked = hours
partTimeEmployee(string first = "", string last = "",
double rate = 0, double hours = 0);
//Constructor with parameters
//Sets the first name, last name, payRate, and hoursWorked
//according to the parameters
...

//Postcondition: firstName = first; lastName = last;
//
payRate = rate; hoursWorked = hours
private:
double payRate;
//variable to store the pay rate
double hoursWorked; //variable to store the hours worked
};

The definitions of the member functions can be placed in a separate file
...


Multiple Inclusions of a Header File
The previous section discussed how to create the header file of a derived class
...
Recall that
before a program is compiled, the preprocessor first processes the program
...
h
const int ONE = 1;
const int TWO = 2;

Suppose that the header file testA
...
h in order to use the
identifiers ONE and TWO
...
h looks like:
//Header file testA
...
h"

...


...
cpp
#include "test
...
h"

...


...
cpp is compiled, it is first processed by the preprocessor
...
h and then the header file testA
...

When the header file testA
...
h", the header file test
...
The
second inclusion of the header file test
...
This problem occurs because the first inclusion of
the header file test
...
To avoid multiple
inclusion of a file in a program, we use certain preprocessor commands in the header file
...
h using these preprocessor commands and then explain
the meaning of these commands
...
h
#ifndef H_test
#define H_test
const int ONE = 1;
const int TWO = 2;
#endif

a
...
#define H_test means ‘‘define H_test’’
c
...

The effect of these commands is as follows: If the identifier H_test is not defined,
we must define the identifier H_test and let the remaining statements between
#define and #endif pass through the compiler
...
h
is included the second time in the program, the statement #ifndef fails and all
of the statements until #endif are skipped
...


C++ Stream Classes
Chapter 3 described in detail how to perform input/output (I/O) using standard I/O
devices and file I/O
...
You
also used the object cout and the insertion operator << to send output to the standard
output device
...
Moreover, for file
I/O, the programs included the header file fstream, and they used objects of type
ifstream for file input and objects of type ofstream for file output
...

In C++, stream classes are implemented using the inheritance mechanism, as shown in
Figure 13-6
...

From this figure, it follows that the class ios is the base class for all stream classes
...
The class
ifstream is derived from the class istream, and the class ofstream is derived
from the class ostream
...
(The classes
iostream and fstream are not discussed in this book
...
To identify the I/O status, the class ios contains an integer
status word
...

The classes istream and ostream are responsible for providing the operations for
the data transfer between memory and devices
...
The class ostream
defines the insertion operator, <<, which is used by the object cout
...
Similarly, the class ofstream is derived from the class ostream to
provide the file output operations
...
The header file fstream contains the
definitions of the classes ifstream and ofstream
...
Only member functions of that class can access the
private members
...
However, it is sometimes necessary (say, for
efficiency and/or to simplify the code) for a derived class to directly access a private
member of a base class
...
Recall that the members of a class are classified into three
categories: public, private, and protected
...
Thus,
the accessibility of a protected member of a class is in between public and
private
...

To summarize, if a member of a base class needs to be accessed by a derived class, that
member is declared under the memberAccessSpecifier protected
...
Then, B cannot directly access the private
members of A
...
What about the
public and protected members of A? This section gives the rules that generally apply
when accessing the members of a base class
...


...

};

In this statement, memberAccessSpecifier is either public, protected, or private
...
If memberAccessSpecifier is public—that is, the inheritance is
public—then:
The public members of A are public members of B
...

b
...

They can be directly accessed by the member functions (and
friend functions) of B
...
The private members of A are hidden in B
...
They can be accessed by the member functions
(and friend functions) of B through the public or protected
members of A
...


Inheritance

|

747

2
...
They can
be accessed by the member functions (and friend functions) of B
...
The protected members of A are protected members of B
...

c
...
They cannot be
directly accessed in B
...

3
...


The public members of A are private members of B
...

b
...
They can
be accessed by the member functions (and friend functions) of B
...
The private members of A are hidden in B
...
They can be accessed by the member
functions (and friend functions) of B through the public or
protected members of A
...


Chapter 15 describes the friend functions
...

EXAMPLE 13-4

(Accessing protected Members in the Derived Class)
Consider the following definition of the class bClass:
class bClass
{
public:
void setData(double);
void setData(char, double);
void print() const;

1
3

748 |

Chapter 13: Inheritance and Composition

bClass(char ch = '*', double u = 0
...
It also contains an
overloaded member function setData
...
The class also
has a constructor with default parameters
...
0, int x = 0);
private:
int dA;
};

Inheritance

|

749

The class dClass contains a private member variable dA of type int
...

Let us now write the definition of the function setData
...
However, because bX is a private member variable of the class
bClass, the function setData cannot directly access it
...
The definition of the
function setData of the class dClass can be written as follows:
void dClass::setData(char ch, double v, int a)
{
bClass::setData(v);

}

bCh = ch; //initialize bCh using the assignment statement
dA = a;

Note that the definition of the function setData calls the function bClass::setData,
with one parameter to set the member variable bX, and then directly sets the value of bCh
...

We now write the definition of the function print of the class dClass
...
It prints the values of both member variables, bCh and
bX
...
Even though bCh is a protected member variable and
it can be directly accessed in the class dClass, we must print its value using the
function print of the class bClass, because this function outputs the values of both
bCh and dX
...
The definition of the function print is:
void dClass::print() const
{
bClass::print();
}

cout << "Derived class dA = " << dA << endl;

The definition of the constructor is:
dClass::dClass(char ch, double u, int x)
: bClass(ch, u)
{
dA = x;
}

The following program illustrates how the objects of bClass and dClass work
...
h, and
the definition of the class dClass is in the header file protectMembInDerivedCl
...


1
3

750 |

Chapter 13: Inheritance and Composition

//Accessing protected members of a base class in the derived
//class
...
h"
#include "protectMembInDerivedCl
...
print();
cout << endl;

cout << "*** Derived class object ***" << endl; //Line 5
dObject
...
5, 7);
dObject
...
5
Derived class dA = 7

When you write the definitions of the member functions of the class dClass, the
protected member variable bCh can be accessed directly
...
That is, the following statement is illegal (it is, in fact, a syntax
error):
dObject
...
In composition (aggregation), one or more members of a class are objects of another class type
...
’’
Example 12-9 in Chapter 12 defined a class called personType
...
Suppose we want to keep track of additional
information for a person, such as a personal ID (e
...
, a Social Security number)

Composition (Aggregation) |

751

and a date of birth
...
We can declare additional members to store the personal ID and date
of birth for the class personalInfo
...

Then, we construct the class personalInfo from the classes personType and
dateType
...

To define the class dateType, we need three member variables—to store the
month, day number, and year
...
The following statements define the
class dateType:
class dateType
{
public:
void setDate(int month, int day, int year);
//Function to set the date
...

//Postcondition: dMonth = month; dDay = day;
//
dYear = year
int getDay() const;
//Function to return the day
...

int getMonth() const;
//Function to return the month
...

int getYear() const;
//Function to return the year
...

void printDate() const;
//Function to output the date in the form mm-dd-yyyy
...

//Postcondition: dMonth = month; dDay = day; dYear = year;
//
If no values are specified, the default
//
values are used to initialize the member
//
variables
...


dateType
–dMonth: int
–dDay: int
–dYear: int

+setDate(int, int, int): void
+getDay() const: int
+getMonth() const: int
+getYear() const: int
+printDate() const: void
+dateType(int = 1, int = 1, int = 1900)

FIGURE 13-7

UML class diagram of the class dateType

The definitions of the member functions of the class dateType are as follows:
void dateType::setDate(int month, int day, int year)
{
dMonth = month;
dDay = day;
dYear = year;
}

The definition of the function setDate, before storing the date into the member
variables, does not check whether the date is valid
...
In Programming Exercise 2 at the end of this
chapter, you are asked to rewrite the definition of the function setDate so that the date
is validated before storing it in the member variables
...

Next, we give the definition of the class personalInfo
...

//The member variables are set according to the
//parameters
...

personalInfo(string first = "", string last = "",
int month = 1, int day = 1, int year = 1900,
int ID = 0);
//Constructor
//The member variables are set according to the
//parameters
...


1
3

754 |

Chapter 13: Inheritance and Composition

private:
personType name;
dateType bDay;
int personID;
};

Figure 13-8 shows the UML class diagram of the class personalInfo and composition (aggregation)
...

Recall that a class constructor is automatically executed when a class object enters its
scope
...
As a result, one of their constructors is
executed
...
Recall that constructors do not have a type and so cannot be
called like other functions
...

Furthermore, member objects of a class are constructed (that is, initialized) in the order
they are declared (not in the order they are listed in the constructor’s member initialization list) and before the containing class objects are constructed
...

The following statements illustrate how to pass arguments to the constructors of the
member objects name and bDay:

Object-Oriented Design (OOD) and Object-Oriented Programming (OOP) |

755

personalInfo::personalInfo(string first, string last, int month,
int day, int year, int ID)
: name(first, last), bDay(month, day, year)
{

...


...
setName(first,last);
bDay
...
print();
cout << "'s date of birth is ";
bDay
...
In
the case of composition, use the member object name to invoke its own constructor
...
Problems were broken down into
modules, and each module solved a particular part of the problem
...
The functions and the
data were kept separate, and the functions acted on the data in a passive way
...
In structured programming, functions are

1
3

756 |

Chapter 13: Inheritance and Composition

dependent on the data, and functions are designed specifically to solve a particular
problem
...
For some of these reasons, structured programming is not
very efficient for large software development
...
We learned how classes are defined
and used
...
With the help of classes, we combined the data—
and the operations on that data—in a single unit
...
Also, with the help of classes, we were able to separate the
data and the algorithms to manipulate that data
...
This chapter explains how to
create new classes from existing classes through inheritance (and also using composition)
...
These are some
of the features of object-oriented design (OOD)
...

• Inheritance—The ability to create new objects (classes) from existing
objects (classes)
...

In OOD, an object is a fundamental entity; in structured programming, a function is a
fundamental entity
...
In OOD, a program is a collection of interacting objects; in structured programming, a program is a collection of interacting functions
...

Once a class becomes error-free, it can be reused in many programs because it is a selfcontained entity
...

To create objects, we must know how to represent the data and write functions to
manipulate that data
...
The first nine chapters are essential for any type of programming, whether
structured or object-oriented
...
We have already examined the first
two features of OOP, encapsulation and inheritance, in this chapter and Chapter 12
...
A polymorphic function
or operator has many forms
...
An example of function
overloading occurs when the function is called, and the operator is evaluated according to
the arguments used
...
Suppose a
class has constructors
...
However, all constructors have the same name
...
In parametric polymorphism, the (data)
type is left unspecified and then later instantiated
...
Also, C++ provides virtual functions as a means to
implement polymorphism in an inheritance hierarchy, which allows the run-time selection of appropriate member functions
...
)
There are several OOP languages in existence today, including Ada, Modula-2, Object Pascal,
Turbo Pascal, Eiffel, C++, Java, and Smalltalk
...
The OOP terminology is influenced by the vocabulary of Smalltalk, the
OOP language largely developed at a Xerox research center during the 1970s
...

OOP is a natural and intuitive way to view the programming process
...
For example, when we think about a car,
we also think about the operations on the car, such as starting the car and driving the car
...
OOP allows ADT to be created and used
...

Objects are created when class variables are declared
...
Every object has an internal state and an external state
...
Only the
object can manipulate its internal state
...
To reduce the complexity of the function
main, we wrote functions to manipulate the data
...
The objects
were designed and implemented independently of the main program
...
In this section, we describe a common and
simple technique to identify classes and objects
...
We
choose our classes from the list of nouns, and we choose our operations from the list of verbs
...
We can state this problem as follows:
Write a program to input the dimensions of a cylinder and calculate and print the
surface area and volume
...
From the list of nouns—
program, dimensions, cylinder, surface area, and volume—we can easily visualize

1
3

758 |

Chapter 13: Inheritance and Composition

cylinder to be a class—say, cylinderType—from which we can create many cylinder
objects of various dimensions
...

After we identify a class, the next step is to determine three pieces of information:




Operations that an object of that class type can perform
Operations that can be performed on an object of that class type
Information that an object of that class type must maintain

From the list of verbs identified in the problem description, we choose a list of possible
operations that an object of that class can perform, or has performed, on itself
...

For the class cylinderType, the dimensions represent the data
...

You can input data to the object either by a constructor or by a mutator function
...
From this, you
can deduce the operations: cylinderVolume and cylinderSurfaceArea
...
In Programming Exercise 5 at the end of this chapter, you are asked to design a
class to implement the characteristics of a cylinder
...
There are several other OOD techniques in the literature
...


PROGRAMMING EXAMPLE:

Grade Report

This programming example further illustrates the concepts of inheritance and composition
...
The registrar’s office
wants to prepare the grade reports as soon as the students’ grades are recorded
...

1
...

2
...
For
these students, the grade report contains a message indicating that
the grades have been held for nonpayment of the tuition
...

The registrar’s office and the business office want your help in writing a program that
can analyze the students’ data and print the appropriate grade reports
...


...

studentName studentID isTuitionPaid
courseName courseNumber creditHours
courseName courseNumber creditHours

...


...
The students’ data is given thereafter
...


...


The first line indicates that the input file contains three students’ data, and the tuition
rate is $345 per credit hour
...

The course number for the mathematics class she is taking is MTH345, the course has
four credit hours, her mid-semester grade is A, and so on
...
54

It is clear from this output that the courses must be ordered according to the course
number
...

Input
Output
PROBLEM
ANALYSIS
AND
ALGORITHM
DESIGN

A file containing the data in the form given previously
...
txt
...


We must first identify the main components of the program
...
Thus, the two main components are the
student and the course
...


Course The main characteristics of a course are the course name, course number, and

number of credit hours
...

2
...

4
...

Print the course information
...

Show the course number
...

//The course information is set according to the
//parameters
...

//This function sends the course information to the
//output device specified by the parameter outF
...

//If the actual parameter is an ofstream variable, say,
//outFile, then the output goes to the file specified by
//outFile
...

//Postcondition: The value of courseCredits is returned
...

//Postcondition: The value of courseNo is returned
...

//Postcondition: The value of courseName is returned
...

//Postcondition: courseName = cName; courseNo = cNo;
//
courseCredits = credits;
private:
string courseName;
string courseNo;
int courseCredits;
};

//variable to store the course name
//variable to store the course number
//variable to store the credit hours

Figure 13-9 shows the UML class diagram of the class courseType
...
These definitions are quite straightforward and easy to follow
...
Its definition is:

1
3

762 |

Chapter 13: Inheritance and Composition

void courseType::setCourseInfo(string cName, string cNo,
int credits)
{
courseName = cName;
courseNo = cNo;
courseCredits = credits;
} //end setCourseInfo

The function print prints the course information
...
Also, we print the course name and course number left-justified rather
than right-justified (the default)
...
Before
printing the credit hours, the manipulator is set to be right-justified
...

2
...

4
...


Set the left manipulator
...

Print the course name
...

Print the credit hours
...
If no values are specified when a
courseType object is declared, the constructor uses the default to initialize the
object
...

Otherwise, the values specified in the object declaration are used to initialize the
object
...

Notice that in the definition of the class courseType, the member functions,
such as print and getCredits, are accessor functions
...
As noted in Chapter 12, we typically define the accessor
functions with the keyword const at the end of their headings
...
(See Programming Exercise 13 at the end of this
chapter
...

Because every student has to pay tuition, we also include a member to indicate
whether the student has paid the tuition
...
We have already designed
a class personType to process a person’s first name and last name
...
Thus, we see that we can
derive the class studentType to keep track of a student’s information from the
class personType, and one member of this class is of type courseType
...

The basic operations to be performed on an object of type studentType are as
follows:
1
...

2
...

3
...


1
3

764 |

Chapter 13: Inheritance and Composition

4
...

5
...

6
...

The following class defines studentType as an ADT
...

class studentType: public personType
{
public:
void setInfo(string fname, string lName, int ID,
int nOfCourses, bool isTPaid,
courseType courses[], char courseGrades[]);
//Function to set the student's information
...

void print(ostream& outF, double tuitionRate);
//Function to print the student's grade report
...
If the
//actual parameter corresponding to outF is the object
//cout, then the output is shown on the standard output
//device
...

studentType();
//Default constructor
//The member variables are initialized
...

//Postcondition: The number of credit hours is
//
calculated and returned
...

//Postcondition: The gpa is calculated and returned
...

//Postcondition: The billing amount is calculated
//and returned
...

//Postcondition: The array coursesEnrolled is sorted
...
Therefore, when
//
the array coursesEnrolled is sorted, the
//
corresponding entries in the array
//
coursesGrade are adjusted
...


studentType
-sId: int
-numberOfCourses: int
-isTuitionPaid: bool
-coursesEnrolled[6]: courseType
-coursesGrade[6]: char
personType
+setInfo(string, string, int, int, bool,
courseType [], char []): void
+print(ostream&, double): void
+getHoursEnrolled(): int
+getGpa(): double
+billingAmount(double): double
-sortCourses(): void
+studentType()

studentType

courseType

UML class diagram of the class studentType together with inheritance and
composition (aggregation) relation

FIGURE 13-10

Before writing the definitions of the member functions of the class studentType,
we make the following note
...
This class also has other
accessor functions
...
We leave it as an
exercise for you to redefine this class so that the accessor functions are declared as
constant functions
...
)

Note that the member function sortCourses to sort the array coursesEnrolled
is a private member of the class studentType
...

Next, we discuss the definitions of the functions to implement the operations of the
class studentType
...
This function then calls the function sortCourses to sort
the array coursesEnrolled by course number
...
Therefore, we call the member
function setName of the class personType and pass the appropriate variables to
set the first and last names
...
Note that because the private member variable coursesEnrolled is
of type courseType and is an array, the default constructor of the class
courseType executes automatically, and the entire array is initialized
...
The parameter outF specifies the
output device
...
Otherwise, three stars are printed in place of each grade, the GPA is not
shown, a message indicates that the grades are being held for nonpayment of the
tuition, and the amount due is shown
...

2
...

4
...

student’s ID
...

heading:

Course No Course Name

Credits

Grade

5
...

For each course, print:
a
...
if isTuitionPaid is true
Output the grade
else

Output three stars
...
Print the total credit hours
...
To output the GPA and billing amount in a fixed decimal format
with the decimal point and trailing zeros, set the necessary flag
...

8
...


1
3

768 |

Chapter 13: Inheritance and Composition

The definition of the function print is as follows:
void studentType::print(ostream& outF, double tuitionRate)
{
int i;
outF << "Student Name: " << getFirstName()
<< " " << getLastName() << endl;

//Step 1

outF << "Student ID: " << sId << endl;

//Step 2

outF << "Number of courses enrolled: "
<< numberOfCourses << endl;
outF << endl;

//Step 3

outF << left;
outF << "Course No" << setw(15) << "
<< setw(8) << "Credits"
<< setw(6) << "Grade" << endl;

Course Name"

outF << right;
for (i = 0; i < numberOfCourses; i++)
{
coursesEnrolled[i]
...
***" << endl;
outF << "Amount Due: $" << billingAmount(tuitionRate)
<< endl;
}
outF << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
<< "-*-*-*-*-" << endl << endl;
} //end print

Programming Example: Grade Report |

769

Let us take a look at the formal parameter of the function print
...
We can use this function to
send the output to the standard output device, the screen, or to a file
...
If the actual parameter is, say, outfile, an object of the
class ofstream, then the output is sent to the device indicated by outfile
...
Therefore, the class ostream is the base
class
...

In general, C++ allows a formal reference parameter of the base class type to refer to an
object of the derived class
...


The function getHoursEnrolled calculates and returns the total credit hours that
a student is taking
...
The total credit hours are calculated by adding the credit hours of
each course in which the student is enrolled
...
The definition of this function is:
int studentType::getHoursEnrolled()
{
int totalCredits = 0;
int i;
for (i = 0; i < numberOfCourses; i++)
totalCredits += coursesEnrolled[i]
...
The
definition of this function is:
double studentType::billingAmount(double tuitionRate)
{
return tuitionRate * getHoursEnrolled();
} //end billingAmount

1
3

770 |

Chapter 13: Inheritance and Composition

We now discuss the function getGpa
...
To find
the GPA, we find the equivalent points for each grade, add the points, and then divide
the sum by the total credit hours the student is taking
...
0;
for (i = 0; i < numberOfCourses; i++)
{
switch (coursesGrade[i])
{
case 'A':
sum += coursesEnrolled[i]
...
getCredits() *
break;
case 'C':
sum += coursesEnrolled[i]
...
getCredits() *
break;
case 'F':
break;
default:
cout << "Invalid Course Grade
...

To sort the array, we use a selection sort algorithm
...

void studentType::sortCourses()
{
int i, j;
int minIndex;
courseType temp;
//variable to swap the data
char tempGrade;
//variable to swap the grades
string course1;
string course2;

Programming Example: Grade Report |

771

for (i = 0; i < numberOfCourses - 1; i++)
{
minIndex = i;
for (j = i + 1; j < numberOfCourses; j++)
{
//get the course numbers
course1 =
coursesEnrolled[minIndex]
...
getCourseNumber();
if (course1 > course2)
minIndex = j;
}//end for
temp = coursesEnrolled[minIndex];
coursesEnrolled[minIndex] = coursesEnrolled[i];
coursesEnrolled[i] = temp;
tempGrade = coursesGrade[minIndex];
coursesGrade[minIndex] = coursesGrade[i];
coursesGrade[i] = tempGrade;
} //end for
} //end sortCourses
MAIN
PROGRAM

Now that we have designed the classes courseType and studentType, we will
use these classes to complete the program
...
Note that this
program can easily be enhanced to process any number of students
...
In fact, all that is left
for the main program is to declare the objects to hold the students’ data, load the data
into these objects, and then print the grade reports
...
Essentially, the main algorithm for the program is:
1
...

3
...

5
...

7
...

Open the input file
...

Open the output file
...

Load the students’ data
...


1
3

772 |

VARIABLES

Chapter 13: Inheritance and Composition

This program processes a maximum of 10 students
...
We also need
to store the number of students registered and the tuition rate
...
Thus, we need the following variables:
studentType studentList[MAX_NO_OF_STUDENTS]; //array to store
//the students' data
int noOfStudents;
double tuitionRate;

//variable to store the number of students
//variable to store the tuition rate

ifstream infile;
ofstream outfile;

//input stream variable
//output stream variable

Function This function has three parameters: a parameter to access the input file, a parameter to
getStudentData

access the array studentList, and a parameter to know the number of students
registered
...
Get the first name, last name, student ID, and isPaid
...
if isPaid is ‘Y’
set isTuitionPaid to true
else

set isTuitionPaid to false
3
...

4
...

Load the course information into a courseType object
...
Load the data into a studentType object
...
The definition of
the function getStudentData is:
void getStudentData(ifstream& infile,
studentType studentList[],
int numberOfStudents)
{
//local variables
string fName;
//variable to store the first name
string lName;
//variable to store the last name
int ID;
//variable to store the student ID
int noOfCourses; //variable to store the number of courses
char isPaid;
//variable to store Y/N, that is,
//is tuition paid
bool isTuitionPaid; //variable to store true/false

Programming Example: Grade Report |

string cName;
string cNo;
int credits;
int count;
int i;

773

//variable to store the course name
//variable to store the course number
//variable to store the course credit hours
//loop control variable
//loop control variable

courseType courses[6]; //array of objects to store the
//course information
char cGrades[6];
//array to hold the course grades
for (count = 0; count < numberOfStudents; count++)
{
infile >> fName >> lName >> ID >> isPaid; //Step 1
if (isPaid == 'Y')
isTuitionPaid = true;
else
isTuitionPaid = false;

//Step 2

infile >> noOfCourses;

//Step 3

for (i = 0; i < noOfCourses; i++)
//Step
{
infile >> cName >> cNo >> credits
>> cGrades[i];
//Step
courses[i]
...
setInfo(fName, lName, ID,
noOfCourses,
isTuitionPaid,
courses, cGrades); //Step
}//end for
} //end getStudentData

4
4
...
b

5

Function This function prints the grade reports
...
The definition of the function
Reports printGradeReports is:
void printGradeReports(ofstream& outfile,
studentType studentList[],
int numberOfStudents,
double tuitionRate)
{
int count;
for (count = 0; count < numberOfStudents; count++)
studentList[count]
...
S
...

//************************************************************
#ifndef H_courseType
#define H_courseType
#include
#include
using namespace std;
//The definition of the class courseType goes here
...


...

#endif
//**********************************************************
// Author: D
...
Malik
//
// Implementation file courseTypeImp
...

//**********************************************************
#include
#include
#include
#include
#include





"courseType
...


...


...
S
...

//**********************************************************
#ifndef H_personType
#define H_personType
#include
using namespace std;
//The definition of the class personType goes here
...


...

#endif
//**********************************************************
// Author: D
...
Malik
//
// Implementation file personTypeImp
...

//**********************************************************
#include
#include
#include "personType
...


...


...
S
...

//************************************************************

1
3

776 |

Chapter 13: Inheritance and Composition

#ifndef H_studentType
#define H_studentType
#include
#include
#include
#include



"personType
...
h"

using namespace std;
//The definition of the class studentType goes here
...


...

#endif
//**********************************************************
// Author: D
...
Malik
//
// Implementation file studentTypeImp
...

//**********************************************************
#include
#include
#include
#include
#include
#include
#include





"personType
...
h"
"studentType
...


...


...
S
...
If student has not paid the tuition, the
// grades are not shown, and an appropriate message is
// output
...

//************************************************************

Programming Example: Grade Report |

#include
#include
#include
#include

777




"studentType
...
open("stData
...
"
<< "Program terminates
...
open("sDataOut
...


1
3

778 |

Chapter 13: Inheritance and Composition

Sample Run:
Student Name: Lisa Miller
Student ID: 890238
Number of courses enrolled: 4
Course No
CSC478
HIS356
MTH345
PHY357

Course Name
ComputerSci
History
Mathematics
Physics

Credits Grade
3
B
3
A
4
A
3
B

Total number of credit hours: 13
Mid-Semester GPA: 3
...
***
Amount Due: $5865
...
16
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

Quick Review

|

779

Input File:
3 345
Lisa Miller 890238 Y 4
Mathematics MTH345 4 A
Physics PHY357 3 B
ComputerSci CSC478 3 B
History HIS356 3 A
Bill Wilton 798324 N 5
English ENG378 3 B
Philosophy PHL534 3 A
Chemistry CHM256 4 C
Biology BIO234 4 A
Mathematics MTH346 3 C
Dandy Goat 746333 Y 6
History HIS101 3 A
English ENG328 3 B
Mathematics MTH137 3 A
Chemistry CHM348 4 B
ComputerSci CSC201 3 B
Business BUS128 3 C

QUICK REVIEW
1
...

3
...

5
...

7
...

9
...

Inheritance is an ‘‘is-a’’ relation
...

In a single inheritance, the derived class is derived from only one existing
class called the base class
...

The private members of a base class are private to the base class
...

The public members of a base class can be inherited either as public or
private by the derived class
...

A call to a base class’s constructor (with parameters) is specified in the
heading of the definition of the derived class’s constructor
...


11
...

13
...

15
...


Chapter 13: Inheritance and Composition

If in the heading of the definition of a derived class’s constructor, no call to
a constructor (with parameters) of a base class is specified, then during the
derived class’s object declaration and initialization, the default constructor
(if any) of the base class executes
...

Review the inheritance rules given in this chapter
...

In composition (aggregation), a call to the constructor of the member
objects is specified in the heading of the definition of the class’s constructor
...

An easy way to identify classes, objects, and operations is to describe the
problem in English and then identify all of the nouns and verbs
...


EXERCISES
1
...

The constructor of a derived class can specify a call to the constructor of
the base class in the heading of the function definition
...
The constructor of a derived class can specify a call to the constructor of
the base class using the name of the class
...
Suppose that x and y are classes, one of the member variables of x is an
object of type y, and both classes have constructors
...

Draw a class hierarchy in which several classes are derived from a single base
class
...
Give examples of
members—data and functions—that can be added to the class
employeeType
...


2
...


4
...

};

In this declaration, which class is the base class, and which class is the derived class?

Exercises

5
...


7
...

Suppose that class three is derived from class two, class two is
derived from class one, and each class has instance variables
...
Determine the order in which the constructors of these
classes will execute
...


class bClass public aClass
{
public:
void print();
void set(int, int, int);
private:
int z;
}

1
3

782 |

b
...


Chapter 13: Inheritance and Composition

class cClass: public aClass
{
public:
void print();
int sum();
cClass();
cClass(int)
}

Consider the following statements:
class yClass
{
public:
void one();
void two(int, int);
yClass();
private:
int a;
int b;
};

class xClass: public yClass
{
public:
void one();
xClass();
private:
int z;
};

Suppose the following statements are in a user program (client code):
yClass y;
xClass x;
a
...


The private members of yClass are public members of xClass
...
If a statement is
invalid, explain why
...


ii
...
a = 15;
x
...


void xClass::one()
{
a = 10;
b = 15;
z = 30;
cout << a + b + z << endl;
}

iv
...


void yClass::one()
{
cout << a + b << endl;
}

cout << y
...
b << " " << x
...

a
...


Exercises

|

783

Write the definition of the default constructor of xClass so that the
private member variables of xClass are initialized to 0
...

Write the definition of the member function two of yClass so that
the private member variable a is initialized to the value of the first
parameter of two, and the private member variable b is initialized to
the value of the second parameter of two
...

Explain the difference between the protected and public members of a
class
...


10
...


12
...


Determine which members of class first are private, protected,
and public in class second
...
Suppose that class third is
derived from class first using the statement:
class third: protected first

14
...

Assume the declaration of Exercise 12
...


Determine which members of class first are private, protected,
and public in class fourth
...
Suppose that class fifth is
derived from class first using the statement:
class fifth: first

1
3

784 |

16
...

What is wrong with the following code?
class classA
{
protected:
void setX(int a);
//Postcondition: x = a;
private:
int x;
};

...


...


aObject
...

b
...

Write the definition of the function print of the class two
...


|

785

What is the output of the following C++ program?
#include
#include
using namespace std;
class baseClass
{
public:
void print() const;
baseClass(string s = " ", int a = 0);
//Postcondition: str = s; x = a;
protected:
int x;
private:
string str;
};
class derivedClass: public baseClass
{
public:
void print() const;
derivedClass(string s = "", int a = 0, int b = 0);
//Postcondition: str = s; x = a; y = b;
private:
int y;
};
int main()
{
baseClass baseObject("This is the base class", 2);
derivedClass derivedObject("DDDDDD", 3, 7);
baseObject
...
print();
return 0;
}
void baseClass::print() const
{
cout << x << " " << str << endl;
}

1
3

786 |

Chapter 13: Inheritance and Composition

baseClass::baseClass(string s, int a)
{
str = s;
x = a;
}
void derivedClass::print() const
{
cout << "Derived class: " << y << endl;
baseClass::print();
}
derivedClass::derivedClass(string s, int a, int b)
:baseClass("Hello Base", a + b)
{
y = b;
}
19
...
print();
derivedObject
...
getX() << endl;
cout << "####" << derivedObject
...


2
...
Certain applications, in addition to hours, minutes, and
seconds, might require you to store the time zone
...
Add the necessary member functions and constructors
to make the class functional
...
Finally, write a test program to test your
class
...


4
...


6
...
Rewrite the definitions of the function setDate and the constructor so that the values for the month, day, and year are checked before
storing the date into the member variables
...
Moreover, write a
test program to test your class
...

Design a class, pointType, that can store and process a point in the x-y
plane
...
Also, write a program to test
various operations on the point
...
Given the radius, we can determine
the circle’s area and circumference
...
The center of the circle is a point in the x-y plane
...
Because the center is a point in the x-y plane and you designed the
class to capture the properties of a point in Programming Exercise 3, you
must derive the class circleType from the class pointType
...
Also, write a
program to test various operations on a circle
...
Design a
class, cylinderType, that can capture the properties of a cylinder and
perform the usual operations on the cylinder
...
Some of the
operations that can be performed on a cylinder are as follows: calculate and
print the volume, calculate and print the surface area, set the height, set the
radius of the base, and set the center of the base
...

Using classes, design an online address book to keep track of the names,
addresses, phone numbers, and dates of birth of family members, close
friends, and certain business associates
...

a
...


Define a class, addressType, that can store a street address, city,
state, and ZIP code
...
Also, use constructors to automatically initialize the member
variables
...

Add a member variable to this class to classify the person as a family

Programming Exercises

c
...
Also, add a member variable to store
the phone number
...
Use constructors to automatically initialize the
member variables
...
An object of the type addressBookType should be able to
process a maximum of 500 entries
...

ii
...

iii
...

iv
...

v
...

vi
...

vii
...

In Programming Exercise 2, the class dateType was designed and implemented to keep track of a date, but it has very limited operations
...


7
...

b
...

d
...

f
...

h
...


j
...


Set the month
...

Set the year
...

Return the day
...

Test whether the year is a leap year
...
For example, if the date is
3-12-2013, the number of days to be returned is 31 because there are
31 days in March
...
For example, if the date is
3-18-2013, the number of days passed in the year is 77
...

Return the number of days remaining in the year
...

Calculate the new date by adding a fixed number of days to the date
...


1
3

790 |

8
...


10
...

The class dateType defined in Programming Exercise 7 prints the date in
numerical form
...
Derive the class extDateType so
that the date can be printed in either form
...
Add a member function to output the
month in the string format, followed by the year—for example, in the
form March 2013
...

Using the classes extDateType (Programming Exercise 9) and dayType
(Chapter 12, Programming Exercise 2), design the class calendarType so
that, given the month and the year, we can print the calendar for that month
...
Thus, you must store the first day of
the month, which is of the form dayType, and the month and the year of the
calendar
...
Thus, the class calendarType
has two member variables: an object of the type dayType and an object of the
type extDateType
...
Note that the day for January 1 of the
year 1500 is a Monday
...

For the class calendarType, include the following operations:
a
...

c
...

e
...

g
...


Chapter 13: Inheritance and Composition

a
...
Call this operation firstDayOfMonth
...

Set the year
...

Return the year
...

Add the appropriate constructors to initialize the member variables
...


Programming Exercises

b
...
For example, the calendar for September 2013 is:
Sun
1
8
15
22
29

12
...

Design the class doctorType, inherited from the class
personType, defined in Chapter 12, with an additional data member
to store a doctor’s speciality
...

b
...
Add appropriate constructors and
member functions to initialize and access and manipulate the data
members
...
Design the class patientType, inherited from the class
personType, defined in Chapter 12, with additional data members
to store a patient’s ID, age, date of birth, attending physician’s name,
the date when the patient was admitted in the hospital, and the date
when the patient was discharged from the hospital
...
)
Add appropriate constructors and member functions to initialize,
access, and manipulate the data members
...

In the Programming Example Grade Report, in the definitions of the
classes courseType and studentType, the accessor functions are not
made constants; that is, they are not defined with the reserved word const
at the end of their headings
...
Accordingly, modify the definitions of the
accessor functions and rerun the program
...
Define the class bankAccount to store a bank customer’s account
number and balance
...
Your class should, at least, provide the
following operations: set the account number, retrieve the account
number, retrieve the balance, deposit and withdraw money, and print
account information
...

a
...


14
...


c
...


Chapter 13: Inheritance and Composition

Every bank offers a checking account
...
This class inherits members to store the account number
and the balance from the base class
...
Add member variables to store this additional information
...
Add appropriate constructors
...
Derive the class
savingsAccount from the class bankAccount (designed in part
(a))
...
A customer with a savings account
typically receives interest, makes deposits, and withdraws money
...
Add appropriate constructors
...


14
CHAPTER

P OINTERS , C LASSES , V IRTUAL
F UNCTIONS , AND A BSTRACT
C LASSES
I N T H I S C H A P T E R , YO U W I L L :


...


Explore how to declare and manipulate pointer variables


...


Discover dynamic variables


...


Learn about pointer arithmetic


...


Become aware of the shallow and deep copies of data


...


Learn about virtual functions


...


Become aware of abstract classes

794 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

In Chapter 2, you learned that C++’s data types are classified into three categories:
simple, structured, and pointers
...
This chapter discusses the third data type called the pointer data type
...
Later, you will use these concepts when you study dynamic arrays and
linked lists
...


Pointer Data Type and Pointer Variables
Chapter 2 defined a data type as a set of values together with a set of operations
...
In addition to these two properties,
until now, all of the data types you have encountered have one more thing associated with
them: the name of the data type
...
The set of
values belonging to this data type includes integers that range between –2147483648 and
2147483647, and the operations allowed on these values are the arithmetic operators
described in Chapter 2
...
The name of the data type
allows you to declare a variable
...

The values belonging to pointer data types are the memory addresses of your computer
...
Because the domain—that is, the set of values of a pointer data type—is the
addresses (memory locations), a pointer variable is a variable whose content is an address,
that is, a memory location
...


Declaring Pointer Variables
As remarked previously, there is no name associated with pointer data types
...
So the obvious question is: If no name is
associated with a pointer data type, how do you declare pointer variables?
The value of a pointer variable is an address
...
The data is typically stored in this memory space
...

In C++, you declare a pointer variable by using the asterisk symbol (*) between the data
type and the variable name
...
The content of p (when
properly assigned) points to a memory location of type int, and the content of ch
points to a memory location of type char
...

Before discussing how pointers work, let us make the following observations
...

Now, consider the following statement:
int* p, q;

In this statement, only p is the pointer variable, not q
...
To avoid
confusion, we prefer to attach the character * to the variable name
...

Now that you know how to declare pointers, next we will discuss how to make a pointer
point to a memory space and how to manipulate the data stored in these memory
locations
...
For example, if p is a pointer of type int, p can
store the address of any memory space of type int
...
The
next two sections describe these operators
...
For example, given the statements:
int x;
int *p;

1
4

796 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

the statement:
p = &x;

assigns the address of x to p
...


Dereferencing Operator (*)
Every chapter until now has used the asterisk character, *, as the binary multiplication
operator
...
When used as a unary operator, *, commonly
referred to as the dereferencing operator or indirection operator, refers to the object to
which its operand (that is, the pointer) points
...
Also,
the statement:
*p = 55;

stores 55 in the memory location pointed to by p—that is, in x
...

Let us assume that memory location 1200 is allocated for p, and memory location 1800 is
allocated for num
...
)


...

1200
p

FIGURE 14-1

Variables p and num


...

1
...
p = #
3
...

After
Statement
1

Values of the Variables

...


Explanation
78

1200
p

1800
num


...


78

1200
p

1800
num


...


24

1200
p

2

1800
num


...


3


...


The statement p = # stores
the address of num, which is 1800,
into p
...
Because the value of p is
1800, statement 3 stores 24 into
memory location 1800
...


Let us summarize the preceding discussion
...
A declaration such as int *p; allocates memory for p only, not for *p
...

2
...

3
...

4
...

5
...

6
...

Note that after the statement p = # executes, the value
of *p is 78; after the statement *p = 24; executes, the value of
*p is 24
...



...

1400
p

FIGURE 14-2


...

After the statement x = 50; executes, the values of &p, p, *p, &x, and x are as follows:
&p

1400

p

? (unknown)

*p

Does not exist
(undefined)

&x

1750

x 50

After the statement p = &x; executes, the values of &p, p, *p, &x, and x are as follows:
&p

1400

p

1750

*p

50

&x

1750

x 50

After the statement *p = 38; executes, the values of &p, p, *p, &x, and x are as follows
...
)
&p

1400

p

1750

*p

38

&x

1750

x 38

Dereferencing Operator (*) |

799

Let us note the following:
1
...

2
...

3
...
Therefore, the assignment
statement:
p = &x;

is legal
...

The program in Example 14-3 further illustrates how a pointer variable works
...
The statement in Line 1 outputs the value of x,
and the statement in Line 2 stores the address of x into p
...
Because p contains the address of p, the values of *p and x are the
same, as shown by the output of Line 3
...
The statements in Lines 6 through 10 output the address of p, the value of p, the
value of *p, the address of x, and the value of x
...
(Note
that the address of p, the value of p, and the address of x, as shown by the outputs of Lines
6, 7, and 9, respectively, are machine dependent
...
Furthermore, the pointer values, that is,
addresses, are printed in hexadecimal by default
...
You can also declare pointers to other data types, such
as classes
...
(Recall that both classes and structs have the same capabilities
...
Therefore, the following discussion applies
to both
...
The following statement stores
the address of student in studentPtr:
studentPtr = &student;

The following statement stores 3
...
gpa = 3
...
gpa is a mixture of pointer dereferencing and the class
component selection
...
, has a higher precedence than the
dereferencing operator
...
In the expression (*studentPtr)
...
Because studentPtr is a
pointer variable of type studentType, *studentPtr refers to a memory space of type
studentType, which is a struct
...
gpa refers to the
component gpa of that struct
...
gpa
...

Because
...
gpa evaluates
first
...
gpa would result in a syntax error, as studentPtr is
not a struct variable, so it has no such component as gpa
...
gpa, the parentheses are important
...
Therefore, to simplify the accessing of class or
struct components via a pointer, C++ provides another operator called the member
access operator arrow, ->
...

The syntax for accessing a class (struct) member using the operator -> is:
pointerVariableName->classMemberName

Thus, the statement:
(*studentPtr)
...
9;

is equivalent to the statement:
studentPtr->gpa = 3
...
Because typos are unavoidable and missing parentheses can result in either an abnormal program termination or
erroneous results, when accessing class (struct) components via pointers, this book
uses the arrow notation
...

EXAMPLE 14-4
Consider the following class:
class classExample
{
public:
void setX(int a);
//Function to set the value of x
//Postcondition: x = a;
void print() const;
//Function to output the value of x
private:
int x;
};

The definition of the member function is as follows:
void classExample::setX(int a)
{
x = a;
}
void classExample::print() const
{
cout << "x = " << x << endl;
}

Consider the following function main:
int main()
{
classExample *cExpPtr;
classExample cExpObject;

//Line 1
//Line 2

cExpPtr = &cExpObject;
cExpPtr->setX(5);
cExpPtr->print();
}

//Line 3
//Line 4
//Line 5

return 0;

Sample Run:
x = 5

In the function main, the statement in Line 1 declares cExpPtr to be a pointer of type
classExample, and the statement in Line 2 declares cExpObject to be an object of
type classExample
...


Dynamic Variables |

803

cExpObject
cExpPtr

FIGURE 14-3

x

cExpObject and cExpPtr after the statement cExpPtr = &cExpObject;

executes

In the statement in Line 4, the pointer cExpPtr accesses the member function setX to
set the value of the member variable x (see Figure 14-4)
...


Initializing Pointer Variables
Because C++ does not automatically initialize variables, pointer variables must be
initialized if you do not want them to point to anything
...
Thus, the statement p = 0; stores the
null pointer in p, that is, p points to nothing
...
The following two statements are equivalent:
p = NULL;
p = 0;

The number 0 is the only number that can be directly assigned to a pointer variable
...
However, you learned how to use pointers to manipulate
data only into memory spaces that were created using other variables
...
So what is the benefit to using

1
4

804 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

pointers? You can access these memory spaces by working with the variables that were
used to create them
...
In
particular, you will learn how to allocate and deallocate memory during program execution using pointers
...
With
the help of pointers, C++ creates dynamic variables
...
When a program
requires a new variable, the operator new is used
...

In C++, new and delete are reserved words
...
The syntax to use the operator new is:
new dataType;
new dataType[intExp];

//to allocate a single variable
//to allocate an array of variables

in which intExp is any expression evaluating to a positive integer
...
Moreover, the allocated
memory is uninitialized
...
However, no new memory is allocated
...
The allocated memory is accessed via
pointer dereferencing—namely, *p
...


Dynamic Variables |

805

Because a dynamic variable is unnamed, it cannot be accessed directly
...
The following statements illustrate this
concept:
int *p;
char *name;
string *str;

//p is a pointer of type int
//name is a pointer of type char
//str is a pointer of type string

p = new int;

//allocates memory of type int
//and stores the address of the
//allocated memory in p
//stores 28 in the allocated memory

*p = 28;

name = new char[5];

strcpy(name, "John");

//allocates memory for an array of
//five components of type char and
//stores the base address of the array
//in name
//stores John in name

str = new string; //allocates memory of type string
//and stores the address of the
//allocated memory in str
*str = "Sunny Day";
//stores the string "Sunny Day" in
//the memory pointed to by str

Recall that the operator new allocates memory space of a specific type and
returns the address of the allocated memory space
...

Exceptions are covered in detail in Chapter 16
...


Operator delete
Suppose you have the following declaration:
int *p;

This statement declares p to be a pointer variable of type int
...


1
4

806 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

1500

1500

p 1500

p 1500

(b) p and *p after the
execution of *p = 54;

(a) p after the execution of
p = new int;
1500

1500

54

54

1800
p 1800

(c) p after the execution of
p = new int;

FIGURE 14-5

54

1800
main

p 1800

73

(d) p and *p after the
execution of *p = 73;

p after the memory space it points to following the execution of various statements

(The number 1500 on top of the box indicates the address of the memory space
...
Suppose that the address of allocated memory space is 1500
...
The statement in
Line 2 stores 54 into the memory space that p points to, which is 1500 (see Figure 14-5(b))
...
Suppose the address of
this allocated memory space is 1800
...
The statement in Line 4 stores 73 into the memory space that p points
to, which is 1800
...

Now the obvious question is what happened to the memory space 1500 that p was
pointing to after execution of the statement in Line 1
...
The previous memory space
at location 1500 is now inaccessible
...
In other words, it cannot be reallocated
...

That is, there is an unused memory space that cannot be allocated
...
There would be a good amount of memory leak
...

The question at hand is how to avoid memory leak
...
The C++

Operations on Pointer Variables |

807

operator delete is used to destroy dynamic variables
...

Suppose p and name are pointer variables, as declared previously
...

Depending on a particular system, after these statements execute, these pointer variables
may still contain the addresses of the deallocated memory spaces
...
Therefore, if later you access the memory spaces via these
pointers without properly initializing them, depending on a particular system, either the
program will access a wrong memory space, which may result in corrupting data, or the
program will terminate with an error message
...
Also note that for the operator delete to
work properly, the pointer must point to a valid memory space
...
The value of one pointer variable can be assigned
to another pointer variable of the same type
...
Integer values can be added and subtracted from a pointer
variable
...

For example, suppose that we have the following statements:
int *p, *q;

The statement:
p = q;

1
4

808 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

copies the value of q into p
...
Any changes made to *p automatically change the value of *q, and
vice versa
...
Similarly, the expression:
p != q

evaluates to true if p and q point to different memory locations
...
First, let us use the following statements to explain the increment and decrement operations on pointer variables:
int *p;
double *q;
char *chPtr;
studentType *stdPtr;

//studentType is as defined before

Recall that the size of the memory allocated for an int variable is 4 bytes, a double
variable is 8 bytes, and a char variable is 1 byte
...

The statement:
p++;

or

p = p + 1;

increments the value of p by 4 bytes because p is a pointer of type int
...
The
statement:
stdPtr++;

increments the value of stdPtr by 40 bytes
...
Similarly, the decrement operator decrements the value
of a pointer variable by the size of the memory to which it is pointing
...


Dynamic Arrays

|

809

Thus, when an integer is added to a pointer variable, the value of the pointer variable is
incremented by the integer times the size of the memory that the pointer is pointing to
...

Pointer arithmetic can be very dangerous
...
If a pointer
variable tries to access either the memory spaces of other variables or an illegal memory
space, some systems might terminate the program with an appropriate error message
...


Dynamic Arrays
In Chapter 9, you learned how to declare and process arrays
...
One of the
limitations of a static array is that every time you execute the program, the size of the
array is fixed, so it might not be possible to use the same array to process different data sets
of the same type
...
However, if the array is very big and the data set
is small, such a declaration would result in memory waste
...
This approach is especially
helpful if you cannot even guess the array size
...

An array created during the execution of a program is called a dynamic array
...

The statement:
int *p;

declares p to be a pointer variable of type int
...
In other words, the operator new creates an array of
10 components of type int, it returns the base address of the array, and the assignment
operator stores the base address of the array into p
...
Thus, by using the increment and decrement
operations, you can access the components of the array
...
C++ allows
us to use array notation to access these memory locations
...
That is, p[0]
refers to the first array component, p[1] refers to the second array component, and so on
...
After the preceding statements
execute, p still points to the first array component
...

When the array notation is used to process the array pointed to by p, p stays fixed at
the first memory location
...

The statement:

int list[5];
declares list to be an array of five components
...
Suppose the address of the first array component is
1000
...


list 1000
list[0] 1000
list[1] 1004
list[2] 1008
list[3] 1012
list[4] 1016

FIGURE 14-6

list and array list

Because the value of list, which is 1000, is a memory address, list is a pointer
variable
...
That is, the value of list is constant
...
In fact, any attempt to use the
increment or decrement operations on list results in a compile-time error
...
However,
the data into the array list can be manipulated as before
...
Similarly, the statement
list[3] = 78; stores 78 into the fourth component of list (see Figure 14-7)
...
We are
allowed to perform increment and decrement operations on p
...


EXAMPLE 14-5
The following program segment illustrates how to obtain a user’s response to get the array
size and create a dynamic array during program execution
...
The statement in Line 3 prompts the
user to enter the size of the array, and the statement in Line 4 inputs the array size into the
variable arraySize
...
From this point on,
you can treat intList just like any other array
...


Functions and Pointers
A pointer variable can be passed as a parameter to a function either by value or by
reference
...
To make a formal parameter be a
reference parameter, you use & when you declare the formal parameter in the function
heading
...
The obvious question is: In
what order should & and * appear between the data type name and the identifier to
declare a pointer as a reference parameter? In C++, to make a pointer a reference
parameter in a function heading, * appears before the & between the data type name
and the identifier
...

void pointerParameters(int* &p, double *q)
{

...


...
The parameter p is a
reference parameter; the parameter q is a value parameter
...
However, the
function pointerParameters can change the value of both p and *p
...
For example, the return type of
the function:
int* testExp(
...


...

}

is a pointer type int
...

You can also create dynamic multidimensional arrays
...
Dynamic multidimensional arrays are created
similarly
...
One way is as follows
...
Because board[0], board[1], board[2], and board[3] are pointers, you
can now use these pointers to create the rows of board
...
Then, the following for loop creates the rows of board
...
The assignment statement then stores the returned
address into board[row]
...

In the previous for loop, if you replace the number 6 with the number 10, then the loop
will create a two-dimensional array of four rows and 10 columns
...
However, the way
board is declared, the number of rows is fixed
...

Next, consider the following statement:
int **board;

This statement declares board to be a pointer to a pointer
...
Now board can store the address of a pointer or an array of pointers
of type int, and *board can store the address of an int memory space or an array of int
values
...
To accomplish
this, first we create an array of 10 pointers of type int and assign the address of that array
to board
...
The following for loop accomplishes this
...

Note that the number of rows and the number of columns of board can be specified
during program execution
...

EXAMPLE 14-6
// Dynamic two-dimensional arrays
#include
#include
using namespace std;
void fill(int **p, int rowSize, int columnSize);
void print(int **p, int rowSize, int columnSize);
int main()
{
int **board;

//Line 1

int rows;
int columns;

//Line 2
//Line 3

cout << "Line 4: Enter the number of rows "
<<"and columns: ";
//Line 4
cin >> rows >> columns;
//Line 5
cout << endl;
//Line 6
//Create the rows of board
board = new int* [rows];
//Create the columns of board
for (int row = 0; row < rows; row++)
board[row] = new int[columns];

//Line 8
//Line 9

//Insert elements into board
fill(board, rows, columns);

//Line 10

cout << "Line 11: Board:" << endl;

//Line 11

//Output the elements of board
print(board, rows, columns);
}

//Line 7

//Line 12

return 0;

Dynamic Arrays

|

815

void fill(int **p, int rowSize, int columnSize)
{
for (int row = 0; row < rowSize; row++)
{
cout << "Enter " << columnSize << " number(s) for row "
<< "number " << row << ": ";
for (int col = 0; col < columnSize; col++)
cin >> p[row][col];
cout << endl;
}
}
void print(int **p, int rowSize, int columnSize)
{
for (int row = 0; row < rowSize; row++)
{
for (int col = 0; col < columnSize; col++)
cout << setw(5) << p[row][col];
cout << endl;
}
}

Sample Run: In this sample run, the user input is shaded
...
The function fill
prompts the user to enter the elements of a two-dimensional array of type int
...

For the most part, the preceding output is self-explanatory
...
The statement in Line 1 declares board to be a pointer to a pointer
of type int
...

The statement in Line 4 prompts the user to input the number of rows and number of
columns
...
The statement in Line 7 creates the rows of
board, and the for loop in Lines 8 and 9 creates the columns of board
...


1
4

816 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

Shallow versus Deep Copy and Pointers
In an earlier section, we discussed pointer arithmetic and explained that if we are not careful,
one pointer might access the data of another (completely unrelated) pointer
...
Here, we discuss another peculiarity of pointers
...

Consider the following statements:
int *first;
int *second;
first = new int[10];

The first two statements declare first and second pointer variables of type int
...
(Note that first together with the arrow indicates
that first points to the allocated memory
...
To be
specific, suppose that this array is as shown in Figure 14-9
...
After this statement executes,
both first and second point to the same array, as shown in Figure 14-10
...
This action
results in Figure 14-11
...
Therefore, if the program later tries to access the memory pointed to by first,
either the program will access the wrong memory or it will terminate in an error
...
More formally, in a shallow copy, two or more
pointers of the same type point to the same memory; that is, they point to the same data
...
The second statement copies the array pointed to by first
into the array pointed to by second (see Figure 14-12)
...
If second deletes its memory,
there is no effect on first
...
More formally, in a
deep copy, two or more pointers have their own data
...


Classes and Pointers: Some Peculiarities
In the previous section, we discussed how to use the arrow notation to access class
members via the pointer if a pointer variable is of a class type
...
To
facilitate the discussion, we will use the following class:
class ptrMemberVarType
{
public:

...


...
Suppose that during program
execution, the pointer p creates a dynamic array
...
However, p created a dynamic
array, and dynamic memory must be deallocated using the operator delete
...
How do we ensure that when p is destroyed, the dynamic memory created by p
is also destroyed? Suppose that objectOne is as shown in Figure 14-14
...


FIGURE 14-14

Object objectOne and its data

Recall that if a class has a destructor, the destructor automatically executes whenever a
class object goes out of scope (see Chapter 12)
...
For example, the definition of the destructor for the
class ptrMemberVarType is:
ptrMemberVarType::~ptrMemberVarType()
{
delete [] p;
}

Of course, you must include the destructor as a member of the class in its definition
...
Moreover, the remainder of this section assumes that the definition of the
destructor is as given previously—that is, the destructor deallocates the memory space
pointed to by p
...


...

private:
int x;
int lenP;
int *p;
};
For the destructor to work properly, the pointer p must have a valid value
...
For this reason, you should exercise extra caution while working
with pointers
...
Suppose that objectOne and objectTwo are as shown in
Figure 14-15
...


FIGURE 14-15

Objects objectOne and objectTwo

Recall that one of the built-in operations on classes is the assignment operator
...
That is, the value of
objectOne
...
x, and the value of objectOne
...
p
...
That is, both objectTwo
...
p
would point to the same memory space, as shown in Figure 14-16
...


FIGURE 14-16

Objects objectOne and objectTwo after the statement objectTwo = objectOne;
executes

Now, if objectTwo
...
p
would become invalid
...
It suggests that there must be

Classes and Pointers: Some Peculiarities

|

821

a way to avoid this pitfall
...
This process is called overloading the assignment operator
...
Once the assignment operator is
properly overloaded, both objectOne and objectTwo have their own data, as shown in
Figure 14-17
...


FIGURE 14-17

5 36 24 15
...
For example, consider the following statement:
ptrMemberVarType objectThree(objectOne);

The object objectThree is being declared and is also being initialized by using the value
of objectOne
...
This initialization is called the
default member-wise initialization
...
Just as in the case
of the assignment operator, because the class ptrMemberVarType has pointer member
variables, this default initialization would lead to a shallow copying of the data, as shown
in Figure 14-18
...
)

objectOne

objectThree
x 8

x 8
lenP 50

lenP 50

p

p

5 36 24 15
...
The solution to both these problems is the same
...
Remember that the class ptrMemberVarType has the destructor, which
deallocates the memory space pointed to by p
...


objectOne
x 8
lenP 50
p

5 36 24 15
...
Now consider
the following statement:
destroyList(objectOne);

In this statement, objectOne is passed as a parameter to the function destroyList
...
Just
as in the previous case, paramObject
...
p would point to the same
memory space, as shown in Figure 14-20
...


FIGURE 14-20

Pointer member variables of objects objectOne and paramObject pointing to the
same array

Classes and Pointers: Some Peculiarities

|

823

Because objectOne is passed by value, the member variables of paramObject should
have their own copy of the data
...
p should have its own
memory space
...

• If, as a parameter, an object is passed by value and the default member-wise
copying of data is allowed, it would lead to a shallow copying of the data
...
This is usually done by putting a statement that includes the
copy constructor in the definition of the class and then writing the definition of the copy
constructor
...
Therefore, for the
class ptrMemberVarType, we can overcome this shallow copying problem by including the
copy constructor in the class ptrMemberVarType
...

The copy constructor automatically executes in three situations (the first two are
described previously)
...
p and objectThree
...
Similarly, objectOne
...
p will have their own
copies of the data, as shown in Figure 14-21
...


FIGURE 14-21

5 36 24 15
...
p
...

The general syntax to include the copy constructor in the definition of a class is:
className(const className& otherObject);

Notice that the formal parameter of the copy constructor is a constant reference parameter
...

EXAMPLE 14-7
Consider the following class:
class ptrMemberVarType
{
public:
void print() const;
//Function to output the data stored in the array p
...

//If index is out of bounds, the program is terminated
...

ptrMemberVarType(int size = 10);
//Constructor
//Creates an array of the size specified by the
//parameter size; the default array size is 10
...

ptrMemberVarType(const ptrMemberVarType& otherObject);
//Copy constructor
private:
int maxSize; //variable to store the maximum size of p
int length; //variable to store the number elements in p
int *p;
//pointer to an int array
};

Suppose that the definitions of the members of the class ptrMemberVarType are as
follows:

Classes and Pointers: Some Peculiarities

|

825

void ptrMemberVarType::print() const
{
for (int i = 0; i < length; i++)
cout << p[i] << " ";
}
void ptrMemberVarType::insertAt(int index, int num)
{
//if index is out of bounds, terminate the program
assert(index >= 0 && index < maxSize);

}

if (index < length)
p[index] = num;
else
{
p[length] = num;
length++;
}

ptrMemberVarType::ptrMemberVarType(int size)
{
if (size <= 0)
{
cout << "The array size must be positive
...
" << endl;
maxSize = 10;
}
else
maxSize = size;
length = 0;
p = new int[maxSize];
}
ptrMemberVarType::~ptrMemberVarType()
{
delete [] p;
}
//copy constructor
ptrMemberVarType::ptrMemberVarType
(const ptrMemberVarType& otherObject)
{
maxSize = otherObject
...
length;

1
4

826 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

p = new int[maxSize];

}

for (int i = 0; i < length; i++)
p[i] = otherObject
...
(We assume that the definition of the class
ptrMemberVarType is in the header file ptrMemberVarType
...
)
#include
#include "ptrMemberVarType
...
" << endl;

//Line 4

for (index = 0; index < 5; index++)
{
cin >> num;
listOne
...
print();
cout << endl;

//Line 8
//Line 9
//Line 10

//Declare listTwo and initialize it using listOne
ptrMemberVarType listTwo(listOne);
//Line 11
cout << "Line 12: listTwo: ";
listTwo
...
insertAt(5, 34);
listTwo
...
print();
cout << endl;

//Line 17
//Line 18
//Line 19

cout << "Line 20: After modifying listTwo, "
<< "listOne: ";
listOne
...
print();
cout << endl;
}

//Line 26
//Line 27

return 0;

//Line 28

void testCopyConst(ptrMemberVarType temp)
{
cout << "Line 29: *** Inside the function "
<< "testCopyConst ***" << endl;

//Line 29

cout << "Line 30: Object temp data: ";
temp
...
insertAt(3, -100);
cout << "Line 34: After changing temp: ";
temp
...

Line
14 8
Line
Line
Line
Line
Line
Line
Line
Line
Line
Line

4: Enter 5 integers
...
The member variable p of listOne is an array of size 10, which is

1
4

828 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

the default array size
...
p
...
(See the output of the line marked Line 8 in the sample run
...
The statement in Line 13 outputs the
numbers stored in listTwo
...
)
The statements in Lines 15 and 16 modify listTwo, and the statement in Line 18 outputs
the modified data of listTwo
...
) The statement in Line 21 outputs the data stored in listOne
...
It follows that
the copy constructor used to initialize listTwo using listOne (at Line 11) provides
listTwo its own copy of the data
...
Notice that the function testCopyConst modifies the
object temp; however, the object listOne remains unchanged
...
Also notice that when the function
testCopyConst terminates, the destructor of the class ptrMemberVarType deallocates
the memory space occupied by temp
...
p
...
Include the destructor in the class
...
Overload the assignment operator for the class
...
Include the copy constructor
...
Until then, whenever we
discuss classes with pointer member variables, out of the three items in the previous list,
we will implement only the destructor and the copy constructor
...

Earlier chapters also said that the types of the actual and formal parameters must match
...

First, let us discuss the case in which the formal parameter is either a reference parameter
or a pointer
...
The class dogType is derived from the
class petType and has three members of its own
...
Suppose that the definitions of the member functions of both classes
are as follows:
void petType::print()
{
cout << "Name: " << name;
}
petType::petType(string n)
{
name = n;
}
void dogType::print()
{
petType::print();
cout << ", Breed: " << breed << endl;
}

Consider the following function in a user program (client code):
void callPrint(petType& p)
{
p
...
You can
call the function callPrint by using an object of either type petType or type dogType
as a parameter
...
Consider the following function main:
int main()
{
petType pet("Lucky");
dogType dog("Tommy", "German Shepherd");
pet
...
print();

//Line 1
//Line 2
//Line 3
//Line 4
//Line 5

1
4

830 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

cout << "*** Calling the function callPrint ***"
<< endl;
//Line 6
callPrint(pet);
//Line 7
cout << endl;
//Line 8
callPrint(dog);
//Line 9
return 0;
}

Sample Run:
Name = Lucky
Name = Tommy, Breed = German Shepherd
*** Calling the function callPrint ***
Name = Lucky
Name = Tommy

The statements in Lines 1 through 6 are quite straightforward
...
The statement in Line 7 calls the function callPrint and
passes the object pet as the parameter; it generates the fourth line of the output
...
The output generated by the statements in Lines 7 and 9 shows only the value of name, even though each time a different
class object was passed as a parameter
...
What actually
occurred is that for both statements (Lines 7 and 9), the member function print of the
class petType was executed
...

Because the formal parameter p of the function callPrint is of type petType, for the
statement p
...
More specifically, in compile-time binding, the necessary code to call a
specific function is generated by the compiler
...
)
For the statement in Line 9, the actual parameter is of type dogType
...
So, during program execution, how does
C++ correct this problem of making the call to the appropriate function? C++
corrects this problem by providing the mechanism of virtual functions
...
This kind
of binding is called run-time binding or late binding
...
Instead,
it generates enough information to enable the run-time system to generate the
specific code for the appropriate function call
...

In C++, virtual functions are declared using the reserved word virtual
...


Inheritance, Pointers, and Virtual Functions |

class petType
{
public:
virtual void print();
petType(string n = "");

831

//virtual function

private:
string name;
};
class dogType: public petType
{
public:
void print();
dogType(string n = "", string b = "");
private:
string breed;
};

Note that we need to declare a virtual function only in the base class
...
If we execute the
previous program with these modifications, the output is as follows
...

The previous discussion also applies when a formal parameter is a pointer to a class, and a
pointer of the derived class is passed as an actual parameter
...
(We assume that the definition of the class
petType is in the header file petType
...
h
...
h"
#include "dogType
...

However, if p is a value parameter, then this mechanism of passing a derived class object as
an actual parameter to p does not work, even if p uses a virtual function
...
Therefore, if a formal parameter is of a class type, the member
variables of the actual object are copied into the corresponding member variables of the
formal parameter
...
Consider the
following function definition:
void callPrint(petType p)
{
p
...
The member variable name
is inherited from the base class
...
However, because p is an object of type
petType, it has only one member variable
...
Also, the statement:
p
...

The output of the following program further illustrates this concept
...
h, and the
definition of the class dogType is in the header file dogType
...
)
//Chapter 14: Virtual Functions and Value Parameters
#include
#include "petType
...
h"
using namespace std;
void callPrint(petType p);
int main()
{
petType pet("Lucky");
dogType dog("Tommy", "German Shepherd");

//Line 1
//Line 2
//Line 3
//Line 4
//Line 5

pet
...
print();

cout << "*** Calling the function callPrint ***"
<< endl;
//Line 6
callPrint(pet);
//Line 7
cout << endl;
//Line 8
callPrint(dog);
//Line 9
cout << endl;
//Line 10
return 0;
}
void callPrint(petType p)
{

//p is a value parameter

p
...
In Line 9, because the formal parameter p is a value parameter, the member
variables of dog are copied into the corresponding member variables of p
...
Consequently, only the member variable name of dog is copied into the member variable
name of p
...
print(); in the function callPrint executes the function print of the class petType, not of the class dogType
...

An object of the base class type cannot be passed to a formal parameter of the derived
class type
...

Suppose that the definition of the class petType is as before, and the definition of the
class dogType is modified slightly as follows:
class dogType: public petType
{
public:
void print();
void setBreed(string b = "");
dogType(string n = "", string b = "");
private:
string breed;
};

Consider the following statements:
petType pet("Lucky");
dogType dog("Tommy", "German Shepherd");
pet = dog;

C++ allows this type of assignment, that is, the values of a derived class object can be
copied into a base class object
...
) Now, because the object pet has only one data member (name)
and the object dog has two data members (name and breed), only the value of
the data member name of dog is copied into the data member name of pet
...
The following statement will result in a
compile-time error
...
setBreed("Siberian Husky");

C++ offers a way to treat a dogType object as a petType object without losing the
additional properties of the class dogType by using pointers
...
The destructor executes automatically when the class object goes out of
scope
...
If a derived class object is passed to a formal parameter of the
base class type, the destructor of the base class executes regardless of whether the derived class
object is passed by reference or by value
...

To correct this problem, the destructor of the base class must be virtual
...

When a derived class object is passed to a formal parameter of the base class type, then
when the object goes out of scope, the destructor of the derived class executes
...

Therefore, when the derived class object is destroyed, the base class part (that is, the
members inherited from the base class) of the derived class object is also destroyed
...


Abstract Classes and Pure Virtual Functions
The preceding sections discussed virtual functions
...

Chapter 13 discussed the second principal of OOD—inheritance
...
The derived classes, in
addition to inheriting the existing members of the base class, can add their own members
and also redefine or override public and protected member functions of the base class
...
There are many scenarios for which a class is desired to be served as a base class for
a number of derived classes; however, the base class may contain certain functions that
may not have meaningful definitions in the base class
...
As noted in that chapter, from the
class shape, you can derive other classes, such as rectangle, circle, ellipse,

1
4

836 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

and so on
...
We can include these in the
class shape
...

virtual void move(double x, double y);
//Function to move the shape at the position
//(x, y)
...


...


Because the definitions of the functions draw and move are specific to a particular shape,
each derived class can provide an appropriate definition of these functions
...

This definition of the class shape requires you to write the definitions of the functions
draw and move
...
Therefore,
these function bodies have no code
...
This solution would work, but it has another drawback
...
Because there is no shape to work with, we would like to prevent the user from
creating objects of the class shape
...

Because we do not want to include the definitions of the functions draw and move of the
class shape, we must convert these functions to pure virtual functions
...
Once you make these functions pure
virtual functions in the class shape, you no longer need to provide the definitions of
these functions for the class shape
...
Thus, the abstract definition of the class shape is similar to the
following:

Abstract Classes and Pure Virtual Functions |

837

class shape
{
public:
virtual void draw() = 0;
//Function to draw the shape
...

virtual void move(double x, double y) = 0;
//Function to move the shape at the position
//(x, y)
...


...


...

Now suppose that we derive the class rectangle from the class shape
...

Note that in addition to the pure virtual functions, an abstract class can contain instance
variables, constructors, and functions that are not pure virtual
...

The following example further illustrates how abstract classes work
...
We also noted that there are two types of
employees full-time and part-time
...
In addition, a full-time employee may receive a bonus
...
In this example, we first define the class employeeType,
derived from the class personType, to store an employee’s name and ID
...
We also include pure virtual functions
print and calculatePay to print an employee’s data, which includes the employee’s
ID, name, and wages
...


1
4

838 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

The definition of the class employeeType is:
#include "personType
...

virtual double calculatePay() const = 0;
//Function to calculate and return the wages
...

//Postcondition: personId = id;
long getId() const;
//Function to retrieve the id
...
If
//no value is specified, the default values are
//assumed
...
h"
class fullTimeEmployee: public employeeType
{
public:
void set(string first, string last, long id,
double salary, double bonus);
//Function to set the first name, last name,
//id, and salary according to the parameters
...

//Postcondition: empSalary = salary;
double getSalary();
//Function to retrieve the salary
...

//Postcondition: empBonus = bonus;
double getBonus();
//Function to retrieve the bonus
...

//Postcondition: Outputs
//
Id:
//
Name: firstName lastName
//
Wages: $$$$
...

//Postcondition: Pay is calculated and returned
fullTimeEmployee(string first = "", string last = "",
long id = 0, double salary = 0,
double bonus = 0);
//Constructor with default parameters
...
If
//no value is specified, the default values are
//assumed
...
h"
class partTimeEmployee: public employeeType
{
public:
void set(string first, string last, long id, double rate,
double hours);
//Function to set the first name, last name, id,
//payRate, and hoursWorked according to the
//parameters
...

//Postcondition: Pay is calculated and returned
...

//Postcondition: payRate = rate;
double getPayRate();
//Function to retrieve the salary
...

//Postcondition: hoursWorked = hours
double getHoursWorked();
//Function to retrieve the bonus
...

//Postcondition: Outputs
//
Id:
//
Name: firstName lastName
//
Wages: $$$$
...
If
//no value is specified, the default values are
//assumed
...
h"
#include "fullTimeEmployee
...
50, 57);
newEmp
...
print();
}

return 0;

Sample Run:
Id: 75
Name: John Smith
Wages: $61700
Id: 275
Name: Bill Nielson
Wages: $883
...
We leave the details as an exercise
...
The address of operator is also used to create aliases to an object
...
That is, both x and y refer to the same memory location
...
The statement:
y = 25;

sets the value of y and, hence, the value of x to 25
...

The address of operator can also be used to return the address of a private member
variable of a class
...
The following example helps illustrate this idea
...
h
#ifndef H_testAdd
#define H_testAdd
class testAddress
{
public:
void setX(int);
void printX() const;
int& addressOfX();
//this function returns the address
//of the x
private:
int x;
};
#endif

The definitions of the functions to implement the member functions are as follows:
//Implementation file testAdd
...
h"

Address of Operator and Classes

|

845

using namespace std;
void testAddress::setX(int inX)
{
x = inX;
}
void testAddress::printX() const
{
cout << x;
}
int& testAddress::addressOfX()
{
return x;
}

Because the return type of the function addressOfX, which is int&, is an address of an
int memory location, the effect of the statement:
return x;

is that the address of x is returned
...
Later, we will show how to fix the problem
...

#include
#include "testAdd
...
addressOfX();
a
...
printX();
cout << endl;
y = 25;
cout << "After y = 25, x in class testAddress = ";
a
...
addressOfX();

executes, y becomes an alias of the private member variable x of the object a
...

Chapter 12 said that private member variables are not accessible outside of the class
...
One way
to resolve this problem is to never provide the user of the class with the addresses of the
private member variables
...
How can we prevent the
program from directly manipulating the private member variables? To fix this problem,
we use the word const before the return type of the function
...
Let us rewrite
the class testAddress using this feature
...


QUICK REVIEW
1
...


Pointer variables contain the addresses of other variables as their values
...


Quick Review |

3
...
For example, the statements:
int *p;
char *ch;

4
...


declare p and ch to be pointer variables
...
Usually, p is called a pointer variable of type int, and ch is called a
pointer variable of type char
...

The address of operator returns the address of its operand
...

7
...

When used as a unary operator, * is called the dereferencing operator
...
For example, if p is a
pointer variable of type int, the statement:
*p = 25;

8
...

10
...


12
...

14
...


sets the value of the memory location indicated by the value of p to 25
...

Pointer variables are initialized using either 0 (the integer zero), NULL, or
the address of a variable of the same type
...

The only arithmetic operations allowed on pointer variables are increment
(++), decrement (--), addition of an integer to a pointer variable, subtraction of an integer from a pointer variable, and subtraction of a pointer from
another pointer
...
When an integer is
added to a pointer, the value added to the value of the pointer variable is
the integer times the size of the object to which the pointer is pointing
...

Pointer variables can be compared using relational operators
...
)
The value of one pointer variable can be assigned to another pointer
variable of the same type
...


1
4

848 |

16
...

18
...

20
...

The operator delete is used to deallocate the memory occupied by a
dynamic variable
...

The operator new has two forms: one to create a single dynamic variable
and another to create an array of dynamic variables
...


22
...

The operator delete has two forms: one to deallocate the memory
occupied by a single dynamic variable and another to deallocate the
memory occupied by an array of dynamic variables
...

24
...

The array name is a constant pointer
...

To create a dynamic array, the form of the new operator that creates an
array of dynamic variables is used
...


26
...


creates an array of 10 components of type int
...
We call p a dynamic array
...

For example, suppose p is a dynamic array of 10 components
...
In particular, p[i] refers to the (i + 1)th component of the array
...

If p is a dynamic array, then the statement:
delete [] p;

28
...

30
...

C++ allows a program to create dynamic multidimensional arrays
...

In a shallow copy, two or more pointers of the same type point to the same
memory space; that is, they point to the same data
...

32
...

34
...

36
...

38
...


40
...


|

849

In a deep copy, two or more pointers of the same type have their own
copies of the data
...

If a class has pointer member variables, the built-in assignment operators
provide a shallow copy of the data
...

C++ allows a user to pass an object of a derived class to a formal parameter
of the base class type
...

In C++, virtual functions are declared using the reserved word virtual
...

Because an abstract class is not a complete class—as it (or its implementation
file) does not contain the definitions of certain functions—you cannot
create objects of that class
...

However, the abstract class must provide the definitions of constructors
and functions that are not pure virtual
...


EXERCISES
1
...

a
...

c
...


e
...

In C++, pointer variables are declared using the word pointer
...

The statement delete p; deallocates the dynamic variable that is
pointed to by p
...


1
4

850 |

f
...


dynamically allocates an array of 50 components of type int, and p contains
the base address of the array
...

The address of operator returns the address and value of its operand
...

If p is a pointer variable, then the statement p = p * 2; is valid in C++
...
If a statement is invalid, explain why
...

b
...


*p = *q;

e
...


4
...


3
...

Consider the following statement:
int* p, q;

5
...


What is the output of the following C++ code?
int x;
int y;
int *p = &x;
int *q = &y;
x = 35;
y = 46;
p = q;
*p = 78;

Exercises

|

851

cout << x << " " << y << endl;
cout << *p << " " << *q << endl;
7
...

b
...


num++;

d
...


p++;

(*num)++;

What is the output of the following code?
int *p;
int *q;
p = new int;
q = p;
*p = 46;
*q = 39;
cout << *p << " " << *q << endl;

9
...


What is the output of the following C++ code?
int *p;
int *q;
p = new int;
q = new int;
*p = 27;
*q = 35;
cout << *p << " " << *q << endl;
q = p;
*q = 73;
cout << *p << " " << *q << endl;
p = new int;
*p = 36;
*q = 42;
cout << *p << " " << *q << endl;

1
4

852 |

11
...


What is wrong with the following code?
int *p;
int *q;
p = new int;
*p = 43;

//Line 3
//Line 4

q = p;
*q = 52;

//Line 5
//Line 6

delete q;

//Line 7

cout << *p << " " << *q << endl;
13
...

15
...


|

853

What is the output of the following code?
int *secret;
int j;
secret = new int[10];
secret[0] = 10;
for (j = 1; j < 10; j++)
secret[j] = secret[j - 1] + 5;
for (j = 0; j < 10; j++)
cout << secret[j] << " ";
cout << endl;

17
...

b
...

c
...

Consider the following C++ code:
a
...


int *p;
p = new int[10];
for (int j = 0; j < 10; j++)
p[i] = 2 * j - 2;

19
...


Write the C++ statement that deallocates the memory space occupied by
the array to which p points
...

What is wrong with the following code?
int *p;
int *q;

//Line 1
//Line 2

p = new int[5];
*p = 2;

//Line 3
//Line 4

for (int i = 1; i < 5; i++)
p[i] = p[i - 1] + i;

//Line 5
//Line 6

q = p;

//Line 7

delete [] p;

//Line 8

for (int j = 0; j < 5; j++)
cout << q[j] << " ";

//Line 9
//Line 10

cout << endl;

//Line 11

1
4

854 |

21
...


23
...

25
...


Write a statement that declares sales to be a pointer to a pointer of type
double
...
Write a C++ code that dynamically creates a two-dimensional array of
five rows and seven columns and sales contains the base address of
that array
...
Write a C++ code that inputs data from the standard input device into
the array sales
...
Write a C++ code that deallocates the memory space occupied by the
two-dimensional array to which sales points
...

Name three things that you should do for classes with pointer member variables
...


class classA
{
public:
virtual void print() const;
void doubleNum();
classA(int a = 0);
private:
int x;
};

Exercises

|

855

void classA::print() const
{
cout << "ClassA x: " << x << endl;
}
void classA::doubleNum()
{
x = 2 * x;
}
classA::classA(int a)
{
x = a;
}
class classB: public classA
{
public:
void print() const;
void doubleNum();
classB(int a = 0, int b = 0);
private:
int y;
};
void classB::print() const
{
classA::print();
cout << "ClassB y: " << y << endl;
}
void classB::doubleNum()
{
classA::doubleNum();
}

y = 2 * y;

classB::classB(int a, int b)
: classA(a)
{
y = b;
}

What is the output of the following function main?
int main()
{
classA *ptrA;
classA objectA(2);
classB objectB(3, 5);

1
4

856 |

Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes

ptrA = &objectA;
ptrA->doubleNum();
ptrA->print();
cout << endl;
ptrA = &objectB;
ptrA->doubleNum();
ptrA->print();
cout << endl;
}
27
...

29
...


What is the difference between compile-time binding and run-time binding?
Is it legal to have an abstract class with all member functions pure virtual?
Consider the following definition of the class studentType:
public studentType: public personType
{
public:
void print();
void calculateGPA();
void setID(long id);
void setCourses(const string c[], int noOfC);
void setGrades(const char cG[], int noOfC);
void
void
void
void

getID();
getCourses(string c[], int noOfC);
getGrades(char cG[], int noOfC);
studentType(string fName = "", string lastName = "",
long id, string c[] = NULL,
char cG[] = NULL, int noOfC = 0);

private:
long studentId;
string courses[6];
char coursesGrade[6]
int noOfCourses;
}

Programming Exercises

31
...

Suppose that the definitions of the classes employeeType,
fullTimeEmployee, and partTimeEmployee are as given in Example
14-8 of this chapter
...


employeeType tempEmp;

b
...


partTimeEmployee pEmp("Molly", "Burton", 101, 0
...

2
...


4
...


Redo Programming Exercise 5 of Chapter 9 using dynamic arrays
...

Redo Programming Exercise 7 of Chapter 9 using dynamic arrays
...

Programming Exercise 11 in Chapter 9 explains how to add large integers using
arrays
...
This chapter explains how to work with dynamic integers
...
Add operations to add, subtract,
multiply, and compare integers stored in two objects
...

Banks offer various types of accounts, such as savings, checking, certificate
of deposits, and money market, to attract customers as well as meet with
their specific needs
...
Each of these accounts has various options
...
Similarly, you may have a checking account that limits
the number of checks you may write
...

In this programming exercise, you use abstract classes and pure virtual
functions to design classes to manipulate various types of accounts
...

Savings accounts: Suppose that the bank offers two types of savings
accounts: one that has no minimum balance and a lower interest rate and
another that requires a minimum balance and has a higher interest rate
...

Certificate of deposit (CD): In an account of this type, money is left for
some time, and these accounts draw higher interest rates than savings or
checking accounts
...
Then
we say that the CD will mature in six months
...

Figure 14-22 shows the inheritance hierarchy of these bank accounts
...

That is, we cannot instantiate objects of these classes
...

bankAccount: Every bank account has an account number, the name of
the owner, and a balance
...
Some operations common to all types of accounts are retrieve

account owner’s name, account number, and account balance; make deposits;
withdraw money; and create monthly statement
...
Some of these functions will be pure virtual
...
Therefore, it
inherits all the properties of a bank account
...


Programming Exercises

|

859

serviceChargeChecking: A service charge checking account is a checking
account
...
For
simplicity, assume that this type of account does not pay any interest, allows the
account holder to write a limited number of checks each month, and does not
require any minimum balance
...

noServiceChargeChecking: A checking account with no monthly service
charge is a checking account
...
Furthermore, this type of account pays interest, allows the
account holder to write checks, and requires a minimum balance
...
Therefore, it inherits all the properties
of a no service charge checking account
...

savingsAccount: A savings account is a bank account
...
Furthermore, a savings account also pays
interest
...


Therefore, it inherits all the properties of a savings account
...

certificateOfDeposit: A certificate of deposit account is a bank account
...
In addition, it has
instance variables to store the number of CD maturity months, interest rate, and
the current CD month
...


1
4

This page intentionally left blank

15
CHAPTER

O VERLOADING
T EMPLATES

AND

I N T H I S C H A P T E R , YO U W I L L :


...


Become aware of the restrictions on operator overloading


...


Learn about friend functions


...


Discover how to overload various operators


...


Explore how to construct function templates and class templates

862 |

Chapter 15: Overloading and Templates

In Chapter 12, you learned how classes in C++ are used to combine data and
operations on that data in a single entity
...
It is the first principle of object-oriented design
(OOD)
...
Chapter 13 discussed how new classes can be derived from
existing classes through the mechanism of inheritance
...

This chapter covers operator overloading and templates
...
We will also simplify
function overloading (introduced in Chapter 7) through the use of templates, called
function templates
...
It also showed how you
can use the class clockType to represent the time of day in a program
...

Consider the following statements:
clockType myClock(8, 23, 34);
clockType yourClock(4, 5, 30);

The first statement declares myClock to be an object of type clockType and initializes
the member variables hr, min, and sec of myClock to 8, 23, and 34, respectively
...

Now consider the following statements:
myClock
...
incrementSeconds();
if (myClock
...


...


The first statement prints the value of myClock in the form hr:min:sec
...
The third statement checks
whether the value of myClock is the same as the value of yourClock
...
However, if we can use the insertion operator << to
output the value of myClock, the increment operator ++ to increment the value of
myClock by one second, and relational operators for comparison, we can enhance the

Operator Overloading

|

863

flexibility of the class clockType considerably
...


...


Recall that the only built-in operations on classes are the assignment operator and the
member selection operator
...
However, C++ allows the programmer to extend the definitions of
most of the operators so that operators—such as relational operators, arithmetic
operators, the insertion operator for data output, and the extraction operator for data
input—can be applied to classes
...


Operator Overloading
Recall how the arithmetic operator / works
...
Similarly, the stream
insertion operator, <<, and the stream extraction operator, >>, are overloaded
...
The
operator << is used as both a stream insertion operator and a left shift operator
...
(Note that the operators << and >> have also been
overloaded for various data types, such as int, double, and string
...
The results of + and - are different
for integer arithmetic, floating-point arithmetic, and pointer arithmetic
...
It does not allow the user to create new
operators
...

In order to overload operators, you must write functions (that is, the header and body)
...
For example, the name of the function to
overload the operator >= is:
operator>=

Operator function: The function that overloads an operator
...
Therefore, the operator function is a value-returning
function
...

Recall that the only built-in operations on classes are assignment (=) and member
selection
...

Operator overloading provides the same concise expressions for user-defined data types as
it does for built-in data types
...
Include the statement to declare the function to overload the operator
(that is, the operator function) prototype in the definition of the class
...
Write the definition of the operator function
...
These rules are described in the section, ‘‘Operator Functions as Member
Functions and Nonmember Functions’’ later in this chapter
...
You cannot change the precedence of an operator
...
The associativity cannot be changed
...
)
3
...

4
...

5
...
Only existing operators can be overloaded
...
The operators that cannot be overloaded are:

...
*

::

?:

sizeof

7
...

8
...


Operator Overloading

|

865

Pointer this
A member function of a class can (directly) access the member variables of that class for
a given object
...
How do you refer to
the object as a whole (that is, as a single unit) in the definition of the member
function, especially when the object is not passed as a parameter? Every object of a
class maintains a (hidden) pointer to itself, and the name of this pointer is this
...
The pointer this (in a member function) is available
for you to use
...
For example, suppose that test is a class
and has a member function called one
...


...

return *this;
}

If x and y are objects of type test, then the statement:
y = x
...
That is, the member variables of x are copied
into the corresponding member variables of y
...

The following example illustrates how the pointer this works
...
Using the
pointer this returns the value of the entire object
...

thisPointerClass::thisPointerClass(int a, int b, int c)
{
x = a;
y = b;
z = c;
}

Consider the following function main:
//Chapter 15: this pointer illustration
#include
#include "thisPointerIllus
...
print();

//Line 3
//Line 4

object2 = object1
...
print();

//Line 6
//Line 7

cout << "Object 2: ";
object2
...
The statement in Line 5 evaluates the
expression object1
...
The value of object1 is then returned by the pointer this, as shown in
the definition of the function updateXYZ
...

The following example also shows how the pointer this works
...
Here, we extend the definition of the class personType to individually set a
person’s first name and last name and then return the entire object
...

//the form firstName lastName
void setName(string first, string last);
//Function to set firstName and lastName according
//to the parameters
...

//Postcondition: firstName = first
//
After setting the first name, a reference
//
to the object, that is, the address of the
//
object, is returned
...

//Postcondition: lastName = last
//
After setting the last name, a reference
//
to the object, that is, the address of the
//
object, is returned
...

//Postcondition: The value of firstName is returned
...

//Postcondition: The value of lastName is returned
...

//Postcondition: firstName = first; lastName = last
private:
string firstName; //variable to store the first name
string lastName; //variable to store the last name
};

Notice that in this definition of the class personType, we replace the default constructor and the constructor with parameters by one constructor with default parameters
...
The definitions of the
functions setFirstName and setLastName are as follows:
personType& personType::setLastName(string last)
{
lastName = last;
}

return *this;

personType& personType::setFirstName(string first)
{
firstName = first;
}

return *this;

Operator Overloading

|

869

The following program shows how to use the class personType
...
h)
//Test Program: class personType
#include
#include
#include "personType
...
print();
cout << endl;

//Line 4
//Line 5
//Line 6

student2
...
setLastName("Malik"); //Line 7
cout << "Line 8 -- Student 2: ";
student2
...
setFirstName("Chelsea");

//Line 11

cout << "Line 12 -- Student 3: ";
student3
...
setLastName("Tomek");

//Line 15

cout << "Line 16 -- Student 3: ";
student3
...
The objects student2 and student3 are initialized to empty
strings
...
The statement in Line 7 works as
follows
...
setFirstName("Shelly")
...
setFirstName("Shelly")

is executed because the associativity of the dot operator is from left to right
...
Thus, the next expression executed is:
student2
...
The statement in Line 9 outputs the
value of student2
...
The statement in Line 13 outputs the
value of student3
...
The output shows only the first name,
not the last name, because we have not yet set the last name of student3
...
Next, the statement in Line 15 sets the last name of student3, and the
statement in Line 17 outputs the value of student3
...
To make a function be a friend to a
class, the reserved word friend precedes the function prototype (in the class definition)
...

Consider the following statements:
class classIllusFriend
{
friend void two(/*parameters*/);

...


...
That is, it is a nonmember function of the class
classIllusFriend
...
(Example
15-3 illustrates this concept
...
However, they are typically placed before any member function declaration
...
Also, recall that the word friend does not appear in the heading of the
friend function’s definition
...


...

}

Of course, we will place the definition of the friend function in the implementation file
...

The following example shows how a friend function accesses the private members of
a class
...

Suppose that the definitions of the member functions of the class classIllusFriend
are as follows:
void classIllusFriend::print()
{
cout << "In class classIllusFriend: x = " << x << endl;
}
void classIllusFriend::setx(int a)
{
x = a;
}

1
5

872 |

Chapter 15: Overloading and Templates

Consider the following definition of the function two:
void two(classIllusFriend cIFObject)
{
classIllusFriend localTwoObject;

//Line 1
//Line 2

localTwoObject
...
print();

//Line 4

cout <<
<<
<<
<<

//Line 5

"Line 5: In Friend Function two "
"accessing private member variable "
"x = " << localTwoObject
...
x = 88;
cIFObject
...
x << endl;

//Line 8

The function two contains a formal parameter cIFObject and a local variable
localTwoObject, both of type classIllusFriend
...
If two is not declared as a friend function of the class classIllusFriend,
then this statement would result in a syntax error because an object cannot directly
access its private members
...
Once
again, this statement would result in a syntax error if two is not declared a friend
function of the class classIllusFriend
...

Similarly, the statement in Line 8 outputs the value of x of cIFObject by directly
accessing it
...

Now consider the definition of the following function main:
int main()
{
classIllusFriend aObject;

//Line 9

aObject
...
x: ";
aObject
...
x: In class classIllusFriend: x = 32
*~*~*~*~*~* Testing Friend Function two *~*~*~*~*~*
In class classIllusFriend: x = 45
Line 5: In Friend Function two accessing private member variable x = 45
In class classIllusFriend: x = 88
Line 8: In Friend Function two accessing private member variable x = 88

For the most part, the output is self-explanatory
...
Notice that the function two generates the last four lines of the output
...


Operator Functions as Member Functions
and Nonmember Functions
The beginning of this chapter stated that certain rules must be followed when you include
an operator function in the definition of a class
...

Most operator functions can be either member functions or nonmember functions—that
is, friend functions of a class
...
The function that overloads any of the operators (), [], ->, or = for a
class must be declared as a member of the class
...
Suppose that an operator op is overloaded for a class—say, opOverClass
...
)
If the far left operand of op is an object of a different type (that is,
not of type opOverClass), the function that overloads the operator
op for opOverClass must be a nonmember—that is, a friend of
the class opOverClass
...
If the operator function that overloads the operator op for the
class opOverClass is a member of the class opOverClass,
then when applying op on objects of type opOverClass, the far
left operand of op must be of type opOverClass
...


1
5

874 |

Chapter 15: Overloading and Templates

You must follow these rules when including an operator function in a class definition
...

Except for certain operators noted previously, operators can be overloaded either as
member functions or as nonmember functions
...

To facilitate our discussion of operator overloading, we will use the class rectangleType,
given next
...
For easy reference, we reproduce the definition of this class and the definitions of the
member functions
...

//Postcondition: length = l; width = w;
double getLength() const;
//Function to return the length of the rectangle
...

double getWidth() const;
//Function to return the width of the rectangle
...

double area() const;
//Function to return the area of the rectangle
...

double perimeter() const;
//Function to return the perimeter of the rectangle
...

void print() const;
//Function to output the length and width of
//the rectangle
...
We will add operator functions to the class rectangleType as
we overload the operators
...

C++ consists of both binary and unary operators
...
The next few sections discuss how to overload various binary and unary operators
...
This operator can be
overloaded as either a member function of the class or as a friend function
...

OVERLOADING THE BINARY OPERATORS AS MEMBER FUNCTIONS
Suppose that # is overloaded as a member function of the class rectangleType
...
operator#(yourRectangle)

This expression clearly shows that the function operator# has only one parameter,
which is yourRectangle
...
Thus, the first parameter
of operator# is the object that is invoking the function operator#, and the second
parameter is passed as a parameter to this function
...


Function Prototype (to be included in the definition of the class):
returnType operator#(const className&) const;

in which # stands for the binary operator, arithmetic or relational, to be overloaded;
returnType is the type of value returned by the function; and className is the name
of the class for which the operator is being overloaded
...


EXAMPLE 15-4
Let us overload +, *, ==, and != for the class rectangleType
...

class rectangleType
{
public:
void setDimension(double l, double w);
double getLength() const;
double getWidth() const;
double area() const;
double perimeter() const;
void print() const;
rectangleType operator+(const rectangleType&) const;
//Overload the operator +
rectangleType operator*(const rectangleType&) const;
//Overload the operator *

1
5

878 |

Chapter 15: Overloading and Templates

bool operator==(const rectangleType&) const;
//Overload the operator ==
bool operator!=(const rectangleType&) const;
//Overload the operator !=
rectangleType();
rectangleType(double l, double w);
private:
double length;
double width;
};

The definition of the function operator+ is as follows:
rectangleType rectangleType::operator+
(const rectangleType& rectangle) const
{
rectangleType tempRect;
tempRect
...
length;
tempRect
...
width;
}

return tempRect;

Notice that operator + adds the corresponding lengths and widths of the two rectangles
...
length = length * rectangle
...
width = width * rectangle
...

Two rectangles are equal if their lengths and widths are equal
...
length &&
width == rectangle
...
Therefore, the definition of the function to overload the operator != is:

Operator Overloading

|

879

bool rectangleType::operator!=
(const rectangleType& rectangle) const
{
return (length != rectangle
...
width);
}

(Note that after writing the definition of the function to overload the operator ==, you
can use it to write the definition of the function to overload the operator !=
...
)
Consider the following program
...
h
...

#include
#include "rectangleType
...
print();
cout << endl;

//Line 5
//Line 6
//Line 7

cout << "Line 8: rectangle2: ";
rectangle2
...
print();
cout << endl;

//Line 12
//Line 13
//Line 14

rectangle4 = rectangle1 * rectangle2;

//Line 15

cout << "Line 16: rectangle4: ";
rectangle4
...
" << endl;
else
cout << "Line 22: rectangle1 and "
<< "rectangle2 are not equal
...
"
<< endl;
else
cout << "Line 25: rectangle1 and "
<< "rectangle3 are equal
...

24: rectangle1 and rectangle3 are not equal
...
However, let us look at the
statements in Lines 11, 15, 19, and 23
...
(That is, after the execution of this statement, the length of rectangle3
is the sum of the lengths of rectangle1 and rectangle2, and the width of
rectangle3 is the sum of the widths of rectangle1 and rectangle2
...
) Similarly, the statement in
Line 15 uses the operator * to multiply the lengths and widths of rectangle1 and
rectangle2 and stores the result in rectangle4
...
) The statement in Line 19 uses the relational
operator == to determine whether the dimensions of rectangle1 and rectangle2 are
the same
...


OVERLOADING THE BINARY OPERATORS (ARITHMETIC OR RELATIONAL) AS
NONMEMBER FUNCTIONS
Suppose that # represents the binary operator (arithmetic or relational) that is to be
overloaded as a nonmember function of the class rectangleType
...
This expression also clearly
shows that the function operator# is neither a member of the object myRectangle

Operator Overloading

|

881

nor a member of the object yourRectangle
...

To include the operator function operator# as a nonmember function of the class in
the definition of the class, the reserved word friend must appear before the function
heading
...

GENERAL SYNTAX TO OVERLOAD THE BINARY (ARITHMETIC OR RELATIONAL)
OPERATORS AS NONMEMBER FUNCTIONS
This section describes the general form of the functions to overload the binary operators
as nonmember functions of a class
...

Function Definition:
returnType operator#(const className& firstObject,
const className& secondObject)
{
//algorithm to perform the operation
}

return value;

EXAMPLE 15-5
This example illustrates how to overload the operators + and == as nonmember functions
of the class rectangleType
...
length = firstRect
...
length;
tempRect
...
width + secondRect
...
Recall that the private
members of a class are local to the class and, therefore, cannot be accessed outside of the
class
...
length must be
illegal because length is a private member of firstRect
...
Also, note that in the function heading, the name of the class—that
is, rectangleType—and the scope resolution operator are not included before the name
of the function operator+, because the function operator+ is not a member of the class
...
length == secondRect
...
width == secondRect
...


Overloading the Stream Insertion (<<) and Extraction (>>)
Operators
The operator function that overloads the insertion operator, <<, or the extraction operator,
>>, for a class must be a nonmember function of that class for the following reason
...
Because the far left operand of << is not an object of

Operator Overloading

|

883

type rectangleType, the operator function that overloads the insertion operator for
rectangleType must be a nonmember function of the class rectangleType
...


OVERLOADING THE STREAM INSERTION OPERATOR (<<)
The general syntax to overload the stream insertion operator, <<, for a class is described next
...

//osObject <<
...

return osObject;

}

In this function definition:



Both parameters are reference parameters
...

• The second parameter is usually a const reference to a particular class,
because (recall from Chapter 12) the most effective way to pass an object
as a parameter to a class is by reference
...
The
word const appears before the class name because we want to print only
the member variables of the object
...

• The function return type is a reference to an ostream object
...


Suppose that the operator << is overloaded for the class rectangleType
...
The first parameter, cout, is of type ostream; the second
parameter, myRectangle, is of type rectangleType
...

To execute the previous statement, you must first execute the expression:
cout << myRectangle

that is, the expression:
operator<<(cout, myRectangle)

After executing this expression, which outputs the value of myRectangle, whatever is
returned by the function operator << will become the left-side parameter of the
operator << (that is, the first parameter of the function operator<<) in order to output
the value of object yourRectangle (see the statement in Line A)
...

Therefore, the return type of the function operator<< must be a reference to an object
of the ostream type
...


Function Prototype (to be included in the definition of the class):
friend istream& operator>>(istream&, className&);

Function Definition:
istream& operator>>(istream& isObject, className& cObject)
{
//local declaration, if any
//Read the data into cObject
...


}

//Return the stream object
...

The first parameter—that is, isObject—is a reference to an istream
object
...
The data
read will be stored in the object
...

For the same reasons as explained previously (when we overloaded the insertion operator
<<), the return type of the function operator>> must be a reference to an istream

object
...

EXAMPLE 15-6
The definition of the class rectangleType and the definitions of the operator
functions are:
#include
using namespace std;
class rectangleType
{
//Overload the stream insertion and extraction operators
friend ostream& operator<< (ostream&, const rectangleType &);
friend istream& operator>> (istream&, rectangleType &);
public:
void setDimension(double l, double w);
double getLength() const;
double getWidth() const;
double area() const;
double perimeter() const;
void print() const;
rectangleType operator+(const rectangleType&) const;
//Overload the operator +
rectangleType operator*(const rectangleType&) const;
//Overload the operator *
bool operator==(const rectangleType&) const;
//Overload the operator ==
bool operator!=(const rectangleType&) const;
//Overload the operator !=

1
5

886 |

Chapter 15: Overloading and Templates

rectangleType();
rectangleType(double l, double w);
private:
double length;
double width;
};

Notice that we have removed the member function print because we are overloading
the stream insertion operator <<
...

ostream& operator<< (ostream& osObject,
const rectangleType& rectangle)
{
osObject << "Length = " << rectangle
...
width;
}

return osObject;

istream& operator>> (istream& isObject,
rectangleType& rectangle)
{
isObject >> rectangle
...
width;
}

return isObject;

Consider the following program
...
h
...

#include
#include "rectangleType
...

Line 3: myRectangle: Length = 23; Width = 45
Line 4: Enter the length and width of a rectangle: 32 15
Line 7: yourRectangle: Length = 32; Width = 15
Line 8: myRectangle + yourRectangle: Length = 55; Width = 60
Line 9: myRectangle * yourRectangle: Length = 736; Width = 675

The statements in Lines 1 and 2 declare and initialize myRectangle and yourRectangle
to be objects of type rectangleType
...
The statement in Line 5 inputs the
data into yourRectangle using cin and the extraction operator
...
The cout
statement in Line 8 adds the lengths and widths of myRectangle and yourRectangle
and outputs the result
...
The output shows
that both the stream insertion and stream extraction operators were overloaded successfully
...
The assignment
operator causes a member-wise copy of the member variables of the class
...
length = yourRectangle
...
width = yourRectangle
...

Therefore, to avoid the shallow copy of data for classes with pointer member variables,
we must explicitly overload the assignment operator
...


1
5

888 |

Chapter 15: Overloading and Templates

GENERAL SYNTAX TO OVERLOAD THE ASSIGNMENT OPERATOR = FOR A CLASS
The general syntax to overload the assignment operator = for a class is described next
...

return *this;

}

In the definition of the function operator=:




There is only one formal parameter
...

The function return type is a constant reference to a particular class
...

Suppose that the assignment operator = is overloaded for the class rectangleType
...
operator=(yourRectangle);

That is, the object yourRectangle becomes the actual parameter to the function:
operator=

Now consider the statement:
myRectangle = yourRectangle = tempRect;

Because the associativity of the operator = is from right to left, this statement is equivalent
to the statement:
myRectangle
...
operator=(tempRect)); //Line A

Operator Overloading

|

889

Clearly, we must first execute the expression:

1
5

yourRectangle
...
operator=(tempRect)

will become the parameter to the function operator= in order to assign a value to the
object myRectangle (see the statement in Line A)
...
operator=(tempRect)

must return a reference to the object, rather than its value
...
For this
reason, the return type of the function to overload the assignment operator = for a class
must be a reference to the class type
...
One reason why we must prevent such assignments is
because they waste computer time
...

As noted above, the body of the function operator= does prevent assignments, such as
the one given in Line B
...

Consider the if statement in the body of the operator function operator=:
if (this != &rightObject) //avoid self-assignment
{
//algorithm to copy rightObject into this object
}

The statement:
myRectangle = myRectangle;

is compiled into the statement:
myRectangle
...

Furthermore, because myRectangle is also a parameter of the function operator=,

890 |

Chapter 15: Overloading and Templates

the formal parameter rightObject also refers to the object myRectangle
...
Thus, the expression will evaluate to false and, therefore, the body of the if statement will be skipped
...
Let us consider the following class:

class arrayClass
{
public:
const arrayClass& operator= (const& arrayClass);

...


...
Suppose that the definition of the function to overload
the assignment operator for the class arrayClass is written without the if
statement, as follows:

const arrayClass & arrayClass::operator=
(const arrayClass& otherList)
{
delete [] list;
//Line 1
maxSize = otherList
...
length;
//Line 3
list = new int[maxSize];
for (int i = 0; i < length; i++)
list[i] = otherList
...
When this statement executes in the body of the function
operator=:
1
...
list, maxSize means myList
...
length
...
otherList

is the same as myList
...
list, so the array
holding the numbers no longer exists
...
The problem is in
Line 6
...
list[i] is equivalent to
the statement myList
...
list[i]
...
list[i] has no valid data (it was destroyed in Line 1), the statement in
Line 6 produces garbage
...

The correct definition of operator= for the class arrayClass is:

const arrayClass& arrayClass::operator=
(const arrayClass& otherList)
{
if (this != & otherList)
//Line
{
delete [] list;
//Line
maxSize = otherList
...
length;
//Line

1
2
3
4

list = new int[maxSize];

}
}

//Line 5

for (int i = 0; i < length; i++)
list[i] = otherList
...

EXAMPLE 15-7
Consider the following class:
class cAssignmentOprOverload
{
public:
const cAssignmentOprOverload&
operator=(const cAssignmentOprOverload& otherList);
//Overload assignment operator

1
5

892 |

Chapter 15: Overloading and Templates

void print() const;
//Function to print the list
void insertEnd(int item);
//Function to insert an item at the end of the list
//Postcondition: if the list is not full,
//
length++; list[length] = item;
//
if the list is full,
//
output an appropriate message
void destroyList();
//Function to destroy the list
//Postcondition: length = 0; maxSize = 0; list = NULL;
cAssignmentOprOverload(int size = 0);
//Constructor
//Postcondition: length = 0; maxSize = size;
//
list is an arry of size maxSize
private:
int maxSize;
int length;
int *list;
};

The definitions of the member functions of the class cAssignmentOprOverload are:
void cAssignmentOprOverload::print() const
{
if (length == 0)
cout << "The list is empty
...
maxSize;
//Line 3
length = otherList
...
list[i];

//Line 6
//Line 7

return *this;

//Line 8

The function to overload the assignment operator works as follows
...
The statement in Line 2 destroys
list
...
The statement in Line 5 creates the array to store the
numbers
...
The statement in
Line 8 returns the address of this object, because the return type of the function
operator= is a reference type
...
h"
using namespace std;
int main()
{
cAssignmentOprOverload intList1(10);
cAssignmentOprOverload intList2;
cAssignmentOprOverload intList3;

//Line 9
//Line 10
//Line 11

1
5

894 |

Chapter 15: Overloading and Templates

int i;
int number;
cout << "Line 14: Enter 5 integers: ";

//Line 14

for (i = 0; i < 5; i++)
{
cin >> number;
intList1
...
print();

//Line 18
//Line 19
//Line 20

intList3 = intList2 = intList1;

//Line 21

cout << "Line 22: intList2: ";
intList2
...
destroyList();

//Line 24

cout << endl;
cout << "Line 26: intList2: ";
intList2
...
print();

//Line 28
//Line 29

cout << "Line 30: After destroying intList2, "
<< "intList3: ";
intList3
...

Line 14: Enter 5 integers: 8 5 3 7 2
Line 19: intList1: 8 5 3 7 2
Line 22: intList2: 8 5 3 7 2
Line 26: intList2: The list is empty
...
The statements in Lines 15 through
17 input the data into intList1, and the statement in Line 20 outputs intList1
...
The statement in Line 23 outputs intList2 (see Line 22 in the sample run,
which contains the output of Lines 22 and 23)
...
The statement in Line 27 outputs intList2, which is empty
...
) After destroying
intList2, the program outputs the contents of intList1 and intList3 (see Lines 28
and 30 in the sample run)
...


Overloading Unary Operators
The process of overloading unary operators is similar to the process of overloading binary
operators
...
In the case of unary operators, the operator has only one parameter
...
If the operator function is a member of the class, it has no parameters
...
If the operator function is a nonmember—that is, a friend function of
the class—it has one parameter
...

OVERLOADING THE INCREMENT (++) AND DECREMENT (--) OPERATORS
The increment operator has two forms: pre-increment (++u) and post-increment (u++), in
which u is a variable, say, of type int
...
In the case of
post-increment, the value of u is used in the expression before it is incremented by 1
...
Overloading the pre-increment operator is quite
straightforward
...


For example, suppose that we overload the pre-increment operator for the class
rectangleType to increment the length and width of a rectangle by 1
...

The operator function operator++ then has no parameters
...
Moreover, the pointer
this associated with myRectangle returns the incremented value of myRectangle,
which is ignored
...

GENERAL SYNTAX TO OVERLOAD THE PRE-INCREMENT OPERATOR ++ AS A MEMBER FUNCTION
The general syntax to overload the pre-increment operator ++ as a member function is
described next
...

Because the operator function operator++ is a nonmember function of the class
rectangleType, it has one parameter, which is an object of type rectangleType
...
)
rectangleType operator++(rectangleType& rectangle)
{
//increment the length and width of the rectangle
(rectangle
...
width)++;
return rectangle; //return the incremented
//value of the object
}

Operator Overloading

|

897

GENERAL SYNTAX TO OVERLOAD THE PRE-INCREMENT OPERATOR ++ AS A NONMEMBER FUNCTION
The general syntax to overload the pre-increment operator ++ as a nonmember function
is described next
...
As in the case of the preincrement operator, we first describe the overloading of this operator as a member of a class
...
In both cases,
pre- and post-increment, the name of the operator function is the same—operator++
...
Thus, the function
prototype for the post-increment operator of the class rectangleType is:
rectangleType operator++(int);

The statement:
myRectangle++;

is compiled by the compiler in the statement:
myRectangle
...
The parameter 0 is used
merely to distinguish between the pre- and post-increment operator functions
...
So the steps required to implement this function are:
1
...

2
...

3
...

The function definition of the post-increment operator for the class rectangleType is:
rectangleType rectangleType::operator++(int u)

1
5

898 |

Chapter 15: Overloading and Templates

{
rectangleType temp = *this;

//use this pointer to copy
//the value of the object

//increment the length and width
length++;
width++;
return temp;

}

//return the old value of the object

GENERAL SYNTAX TO OVERLOAD THE POST-INCREMENT OPERATOR ++ AS A MEMBER FUNCTION
The general syntax to overload the post-increment operator ++ as a member function is
described next
...
In this situation, the operator function operator++ has two parameters
...
length)++;
(rectangle
...


Operator Overloading

|

899

Function Prototype (to be included in the definition of the class):
friend className operator++(className&, int);

Function Definition:
className operator++(className& incObj, int u)
{
className temp = incObj; //copy incObj into temp
//increment incObj
}

return temp;

//return the old value of the object

The decrement operators can be overloaded in a similar way, the details of which are left
as an exercise for you
...
Because certain operators can be overloaded as either member or nonmember functions, we give two equivalent definitions of
the class rectangleType
...
In the second
definition, the increment, decrement, arithmetic, and relational operators are overloaded
as nonmember functions
...

#include
using namespace std;
class rectangleType
{
//Overload the stream insertion and extraction operators
friend ostream& operator<<(ostream&, const rectangleType &);
friend istream& operator>>(istream&, rectangleType &);
public:
void setDimension(double l, double w);
double getLength() const;
double getWidth() const;
double area() const;
double perimeter() const;
//Overload the arithmetic operators
rectangleType operator+(const rectangleType &) const;
rectangleType operator-(const rectangleType &) const;

1
5

900 |

Chapter 15: Overloading and Templates

rectangleType operator*(const rectangleType&) const;
rectangleType operator/(const rectangleType&) const;
//Overload the increment and decrement operators
rectangleType operator++();
//pre-increment
rectangleType operator++(int);
//post-increment
rectangleType operator--();
//pre-decrement
rectangleType operator--(int);
//post-decrement
//Overload the relational operators
bool operator==(const rectangleType&) const;
bool operator!=(const rectangleType&) const;
bool operator<=(const rectangleType&) const;
bool operator<(const rectangleType&) const;
bool operator>=(const rectangleType&) const;
bool operator>(const rectangleType&) const;
//Constructors
rectangleType();
rectangleType(double l, double w);
private:
double length;
double width;
};

Following is the definition of the class rectangleType, in which the increment,
decrement, arithmetic, and relational operators are overloaded as nonmembers
...

#include
using namespace std;
class rectangleType
{
//Overload the stream insertion and extraction operators
friend ostream& operator<<(ostream&, const rectangleType&);
friend istream& operator>>(istream&, rectangleType&);
//Overload the arithmetic operators
friend rectangleType operator+(const rectangleType&,
const rectangleType&);
friend rectangleType operator-(const rectangleType&,
const rectangleType&);
friend rectangleType operator*(const rectangleType&,
const rectangleType&);
friend rectangleType operator/(const rectangleType&,
const rectangleType&);

Operator Overloading

|

901

//Overload the increment and decrement operators
friend rectangleType operator++(rectangleType&);
//pre-increment
friend rectangleType operator++(rectangleType&, int);
//post-increment
friend rectangleType operator--(rectangleType&);
//pre-decrement
friend rectangleType operator--(rectangleType&, int);
//post-decrement
//Overload the relational operators
friend bool operator==(const rectangleType&,
const rectangleType&);
friend bool operator!=(const rectangleType&,
const rectangleType&);
friend bool operator<=(const rectangleType&,
const rectangleType&);
friend bool operator<(const rectangleType&,
const rectangleType&);
friend bool operator>=(const rectangleType&,
const rectangleType&);
friend bool operator>(const rectangleType&,
const rectangleType&);
public:
void setDimension(double l, double w);
double getLength() const;
double getWidth() const;
double area() const;
double perimeter() const;
//Constructors
rectangleType();
rectangleType(double l, double w);
private:
double length;
double width;
};

The definitions of the functions to overload the operators for the class rectangleType
are left as an exercise for you
...
)

Operator Overloading: Member versus Nonmember
The preceding sections discussed and illustrated how to overload operators
...
What about the operators that can be
overloaded as either member functions or nonmember functions? For example, the
binary arithmetic operator + can be overloaded as a member function or a nonmember
function
...
On the other hand, if you overload + as a nonmember function, then you must
pass both objects as parameters
...
So it is a matter of preference whether you overload + as a
member or as a nonmember function
...


Classes and Pointer Member Variables (Revisited)
Chapter 14 described the peculiarities of classes with pointer member variables
...

Recall that the only built-in operations on classes are assignment and member selection
...
That is, the member
variables of an object are copied into the corresponding member variables of another
object of the same type
...
Other problems that may arise with classes with
pointer member variables relate to deallocating dynamic memory when an object goes
out of scope and passing a class object as a parameter by value
...
Explicitly overload the assignment operator
2
...
Include the destructor

Operator Overloading: One Final Word
Next, we look at three examples that illustrate operator overloading
...
Whenever we use the operator op on
objects of type rectangleType, the body of the function that overloads the operator op
for the class rectangleType executes
...


PROGRAMMING EXAMPLE:

clockType

Chapter 12 defined a class clockType to implement the time of day in a program
...
This example redefines the class
clockType
...
The program that uses the class clockType
requires the user to input the time in the form hr:min:sec
...
h
#ifndef H_newClock
#define H_newClock
#include
using namespace std;
class clockType
{
friend ostream& operator<<(ostream&, const clockType&);
friend istream& operator>>(istream&, clockType&);
public:
void setTime(int hours, int minutes, int seconds);
//Function to set the member variables hr, min, and sec
...

//Postcondition: hours = hr; minutes = min; seconds = sec;
clockType operator++();
//Overload the pre-increment operator
...

bool operator==(const clockType& otherClock) const;
//Overload the equality operator
...

bool operator!=(const clockType& otherClock) const;
//Overload the not equal operator
...

bool operator<=(const clockType& otherClock) const;
//Overload the less than or equal to operator
...

bool operator<(const clockType& otherClock) const;
//Overload the less than operator
...


903

1
5

904 |

Chapter 15: Overloading and Templates

bool operator>=(const clockType& otherClock) const;
//Overload the greater than or equal to operator
...

bool operator>(const clockType& otherClock) const;
//Overload the greater than operator
...

clockType(int hours = 0, int minutes = 0, int seconds = 0);
//Constructor to initialize the object with the values
//specified by the user
...

//Postcondition: hr = hours; min = minutes;
//
sec = seconds;
private:
int hr; //variable to store the hours
int min; //variable to store the minutes
int sec; //variable to store the seconds
};
#endif

Figure 15-1 shows a UML class diagram of the class clockType
...
Notice that the class clockType overloads only the preincrement operator
...
This step is left as an exercise for you
...
)
First, we write the definition of the function operator++
...
Increment the seconds by 1
...
If seconds > 59,
b
...
Set the seconds to 0
...
2
...

b
...
If minutes > 59
b
...
1
...

b
...
2
...

b
...
3
...
3
...
1
...

c
...

The definition of the function operator++ is:
//Overload the pre-increment operator
...
1
//Step b
...
3
//Step b
...
1
//Step b
...
2
//Step b
...
3
//Step b
...
3
...
The two times are the
same if they have the same hours, minutes, and seconds
...

bool clockType::operator==(const clockType& otherClock) const
{
return (hr == otherClock
...
min
&& sec == otherClock
...
The first time is less than
or equal to the second time if:
1
...
The hours of the first time and the second time are the same, but the
minutes of the first time are less than the minutes of the second time, or
3
...

The definition of the function operator<= is:
//Overload the less than or equal to operator
...
hr) ||
(hr == otherClock
...
min) ||
(hr == otherClock
...
min &&
sec <= otherClock
...

bool clockType::operator!=(const clockType& otherClock) const
{
return (hr != otherClock
...
min
|| sec != otherClock
...

bool clockType::operator<(const clockType& otherClock) const
{
return ((hr < otherClock
...
hr && min < otherClock
...
hr && min == otherClock
...
sec));
}
//Overload the greater than or equal to operator
...
hr) ||
(hr == otherClock
...
min) ||
(hr == otherClock
...
min &&
sec >= otherClock
...

bool clockType::operator>(const clockType& otherClock) const
{
return ((hr > otherClock
...
hr && min > otherClock
...
hr && min == otherClock
...
sec));
}

(Note that after writing the definition of the function to overload the operator ==, you
can use the operator == to write the definition of the function to overload the operator
!=
...
We leave the details as an exercise
...
They are included here for the sake of completeness
...
The definitions are as follows:
void clockType::setTime(int hours, int minutes, int seconds)
{
if (0 <= hours && hours < 24)
hr = hours;
else
hr = 0;
if (0 <= minutes && minutes < 60)
min = minutes;
else
min = 0;

}

if (0 <= seconds && seconds < 60)
sec = seconds;
else
sec = 0;

void clockType::getTime(int& hours, int& minutes,
int& seconds) const
{
hours = hr;
minutes = min;
seconds = sec;
}

1
5

908 |

Chapter 15: Overloading and Templates

//Constructor
clockType::clockType(int hours, int minutes, int seconds)
{
setTime(hours, minutes, seconds);
}

We now discuss the definition of the function operator<<
...
Here, after printing
the time in the previous format, we must return the ostream object
...

ostream& operator<<(ostream& osObject, const clockType& timeOut)
{
if (timeOut
...
hr << ':';
if (timeOut
...
min << ':';
if (timeOut
...
sec;
}

return osObject;

//return the ostream object

Let us now discuss the definition of the function operator>>
...
Clearly, the algorithm to input the time is:
a
...

c
...

e
...


Get the input, which is a number, and store it in the member
variable hr
...

Get the next input, which is a colon, and discard it
...
Also check if the input is valid
...

Get the next input, which is a number, and store it in the
member variable sec
...

Return the istream object
...
hr;

//Step a

if (timeIn
...
hr >= 24)
timeIn
...
Step b

is >> timeIn
...
min < 0 || timeIn
...
min = 0;

//Step c

is
...
Step d

is >> timeIn
...
sec < 0 || timeIn
...
sec = 0;

//Step e

return is;

//Step f

}

The following test program uses the class clockType:
//**********************************************************
// Author: D
...
Malik
//
// This program shows how to use the class clockType
...
h"
using namespace std;
int main()
{
clockType myClock(5, 6, 23);
clockType yourClock;
cout << "Line 3: myClock = " << myClock
<< endl;

909

1
5

Clearly, we need a local variable of type char to read the colon
...
get(ch);

|

//Line 1
//Line 2
//Line 3

910 |

Chapter 15: Overloading and Templates

cout << "Line 4: yourClock = " << yourClock
<< endl;

//Line 4

cout << "Line 5: Enter the time in the form "
<< "hr:min:sec ";
cin >> myClock;
cout << endl;

//Line 5
//Line 6
//Line 7

cout << "Line 8: The new time of myClock = "
<< myClock << endl;

//Line 8

++myClock;

//Line 9

cout << "Line 10: After incrementing the time, "
<< "myClock = " << myClock << endl;
//Line 10
yourClock
...
" << endl;
//Line
//Line
"Line 16: The times of myClock and "
"yourClock are not equal
...
" << endl;
"Line 20: The time of myClock is "
"greater than the time of "
"yourClock
...

Line 3: myClock = 05:06:23
Line 4: yourClock = 00:00:00
Line 5: Enter the time in the form hr:min:sec 4:50:59
Line 8: The new time of myClock = 04:50:59
Line 10: After incrementing the time, myClock = 04:51:00
Line 12: After setting the time, yourClock = 13:35:38
Line 16: The times of myClock and yourClock are not equal
...


Programming Example: Complex Numbers

PROGRAMMING EXAMPLE:

|

911

Complex Numbers

A number of the form a + ib, in which i2 = -1 and a and b are real numbers, is called a
complex number
...

Complex numbers can also be represented as ordered pairs (a, b)
...
In this
example, we will construct a data type, complexType, that can be used to process
complex numbers
...
We will also overload the operators + and * to
perform addition and multiplication of complex numbers
...

//Specification file complexType
...

//Postcondition: realPart = real; imaginaryPart = imag;
void getComplex(double& real, double& imag) const;
//Function to retrieve the complex number
...

//Postcondition: realPart = real; imaginaryPart = imag;
complexType operator+
(const complexType& otherComplex) const;
//Overload the operator +
complexType operator*
(const complexType& otherComplex) const;
//Overload the operator *
bool operator== (const complexType& otherComplex) const;
//Overload the operator ==
private:
double realPart;
//variable to store the real part
double imaginaryPart; //variable to store the
//imaginary part
};
#endif

Figure 15-2 shows a UML class diagram of the class complexType
...

The definitions of most of these functions are straightforward
...


Programming Example: Complex Numbers

|

913

1
5

To output a complex number in the form:
(a, b)

in which a is the real part and b is the imaginary part, clearly the algorithm is:
a
...

c
...

e
...

real part
...

imaginary part
...


Therefore, the definition of the function operator<< is:
ostream& operator<<(ostream& osObject,
const complexType& complex)
{
osObject
osObject
osObject
osObject
osObject
}

<<
<<
<<
<<
<<

"(";
complex
...
imaginaryPart;
")";

return osObject;

//Step
//Step
//Step
//Step
//Step

a
b
c
d
e

//return the ostream object

Next, we discuss the definition of the function to overload the stream extraction
operator, >>
...

Clearly, the algorithm to read this complex number is:
a
...

c
...

e
...

store the real part
...

store the imaginary part
...


Following these steps, the definition of the function operator>> is:
istream& operator>>(istream& isObject, complexType& complex)
{
char ch;
isObject >> ch;
isObject >> complex
...
imaginaryPart;
isObject >> ch;
}

return isObject;

//Step c
//Step d
//Step e

//return the istream object

The definitions of the other functions are as follows:
bool complexType::operator==
(const complexType& otherComplex) const
{
return (realPart == otherComplex
...
imaginaryPart);
}
//Constructor
complexType::complexType(double real, double imag)
{
realPart = real;
imaginaryPart = imag;
}
//Function to set the complex number after the object
//has been declared
...
realPart = realPart + otherComplex
...
imaginaryPart = imaginaryPart
+ otherComplex
...
realPart = (realPart * otherComplex
...
imaginaryPart);
temp
...
imaginaryPart)
+ (imaginaryPart * otherComplex
...
S
...

//**********************************************************
#include
#include "complexType
...

Line
Line
Line
Line
Line
Line
Line

4: Num1 = (23, 34)
5: Num2 = (0, 0)
6: Enter the complex number in the form (a, b) (3, 4)
9: New value of num2 = (3, 4)
11: Num3 = (26, 38)
12: (23, 34) + (3, 4) = (26, 38)
13: (23, 34) * (3, 4) = (-67, 194)

You can extend this data type to perform subtraction and division on complex numbers
...
That is, when we declare a variable of type newString, we will
be able to use the assignment operator to copy one string into another and relational
operators to compare the two strings
...
Recall that we have used the operator [] to access the components of an
array
...


Overloading the Array Index (Subscript)
Operator ([])
Recall that the function to overload the operator [] for a class must be a member of the
class
...

The syntax to declare the operator function operator[] as a member of a class for
nonconstant arrays is:
Type& operator[](int index);

The syntax to declare the operator function operator[] as a member of a class for
constant arrays is:
const Type& operator[](int index) const;

in which Type is the data type of the array elements
...
The definition of
classTest to overload the operator [] is:
class classTest
{
public:

Overloading the Array Index (Subscript) Operator ([])

|

917

Type& operator[](int index);
//Overload the operator for nonconstant arrays
const Type& operator[](int index) const;
//Overload the operator for constant arrays

...


...

The definitions of the functions to overload the operator [] for classTest are:
//Overload the operator [] for nonconstant arrays
Type& classTest::operator[](int index)
{
assert(0 <= index && index < arraySize);
return list[index];
//return a pointer of the
//array component
}
//Overload the operator [] for constant arrays
const Type& classTest::operator[](int index) const
{
assert(0 <= index && index < arraySize);
return list[index]; //return a pointer of the
//array component
}
The preceding function definitions use the assert statement
...
)

Consider the following statements:
classTest list1;
classTest list2;
const classTest list3;

In the case of the statement:
list1[2] = list2[3];

the body of the operator function operator[] for nonconstant arrays is executed
...
Next, the body of the operator function operator[]
for nonconstant arrays is executed to complete the execution of the assignment statement
...
Recall that:
1
...

3
...


A C-string is a sequence of one or more characters
...

C-strings are null terminated
...


The only aggregate operations allowed on C-strings are input and output
...

Initially, C++ did not provide any built-in data types to handle C-strings
...

Our objective in this example is to define our own class for C-string manipulation
and, at the same time, to further illustrate operator overloading
...
Let us call this class
newString
...
h
#ifndef H_myString
#define H_myString
#include
using namespace std;
class newString
{
//Overload the stream insertion and extraction operators
...

Next, we give the definitions of the functions to implement the newString operations
...
(For an explanation of the function assert, see Chapter 4 or the
header file cassert in the Appendix)
...
cpp
#include
#include
#include
#include
#include "myString
...
strLength;
strPtr = new char[strLength + 1];
strcpy(strPtr, rightStr
...
strLength;
strPtr = new char[strLength + 1];
strcpy(strPtr, rightStr
...

bool newString::operator==(const newString& rightStr) const
{
return (strcmp(strPtr, rightStr
...
strPtr) < 0);
}
bool newString::operator<=(const newString& rightStr) const
{
return (strcmp(strPtr, rightStr
...
strPtr) > 0);
}
bool newString::operator>=(const newString& rightStr) const
{
return (strcmp(strPtr, rightStr
...
strPtr) != 0);
}
//Overload the stream insertion operator <<
ostream& operator << (ostream& osObject, const newString& str)
{
osObject << str
...
Because temp is declared to be an
array of size 81, the largest string that can be stored into temp is of length 80
...


1
5

922 |

Chapter 15: Overloading and Templates

Most of these functions are quite straightforward
...

The conversion constructor is a single-parameter function that converts its argument to an object of the constructor’s class
...

Note that the assignment operator is explicitly overloaded only for objects of the
newString type
...
Consider the declaration:
newString str;

and the statement:
str = "Hello there";

The compiler translates this statement into:
str
...
First, the compiler automatically invokes the conversion constructor
to create an object of the newString type to temporarily store the
string "Hello there"
...
Second, the compiler invokes the overloaded assignment operator to
assign the temporary newString object to the object str
...

Next, we write a C++ program that tests some of the operations of the class
newString
...
S
...

//**********************************************************
#include
#include "myString
...

Line 1: Sunny
Warm ***###
...
" << endl;

|

924 |

Line
Line
Line
Line
Line
Line
Line

Chapter 15: Overloading and Templates

6: Enter a string with a length of at least 7: 123456789
9: The new value of str1 = 123456789
11: str3 = Birth Day, str4 = Birth Day
13: The new value of str3 = 123456789
16: After replacing the second character of str3 = 1t3456789
18: After replacing the third character of str3 = 1tW456789
20: After replacing the sixth character of str3 = 1tW45g789

The preceding program works as follows
...
Notice that the value of str3 is to be printed between
*** and ###
...
The statements in Lines 2 through 5 compare str1 and
str2 and output the result
...
Note
that in the statement (see Line 10):
str4 = str3 = "Birth Day";

Because the associativity of the assignment operator is from right to left, first the
statement str3 = "Birth Day"; executes, and then the statement str4 = str3;
executes
...
The
statements in Lines 15, 17, and 19 use the array subscripting operator [] to individually manipulate the characters of str3
...


Function Overloading
The previous section discussed operator overloading
...
The types of parameters used with an operator determine the action
to take
...
Chapter 7 introduced function overloading
...

Recall that a class can have more than one constructor, but all constructors of a class have
the same name, which is the name of the class
...
Further recall that overloading a function refers to having several functions
with the same name but different parameter lists
...

For function overloading to work, we must give the definition of each function
...


Templates |

925

Templates
Templates are a very powerful feature of C++
...
The syntax we use for templates is:
template
declaration;

in which Type is the name of a data type, built-in or user-defined, and declaration is
either a function declaration or a class declaration
...

The word class in the heading refers to any user-defined type or built-in type
...
(Note that in the first line, template
, the keyword class can be replaced with the keyword typename
...


Function Templates
In Chapter 7, when we introduced function overloading, the function larger was
overloaded to find the larger of two integers, characters, floating-point numbers, or
strings
...

However, the body of each function is similar
...

The syntax of the function template is:
template
function definition;

in which Type is referred to as a formal parameter of the template
...

The statements:
template
Type larger(Type x, Type y)
{
if (x >= y)
return x;
else
return y;
}

define a function template larger, which returns the larger of two items
...
The statement:

1
5

926 |

Chapter 15: Overloading and Templates

cout << larger(5, 6) << endl;

is a call to the function template larger
...

Note that the function template larger will work only for those data types for which
the operator >= has been defined
...

The following example illustrates the use of function templates
...

// Template larger
#include
#include "myString
...
6 and 3
...
6, 3
...
6 and 3
...
6
Hello and Happy = Hello

Class Templates
Like function templates, class templates are used to write a single code segment for a set of
related classes
...
If the list element type changes from int to, say, char, double, or
string, we need to write separate classes for each element type
...

Using class templates, we can create a generic class listType, and the compiler can
generate the appropriate source code for a specific implementation
...

The following statements define listType to be a class template:
template
class listType
{
public:
bool isEmpty() const;
//Function to determine whether the list is empty
...

bool isFull() const;
//Function to determine whether the list is full
...

bool search(const elemType& searchItem) const;
//Function to search the list for searchItem
...


928 |

Chapter 15: Overloading and Templates

void insert(const elemType& newElement);
//Function to insert newElement in the list
...

//Postcondition: The list is the old list plus
//
newElement
...

//Postcondition: If removeElement is found in the list,
//
it is deleted from the list, and the
//
list is the old list minus removeElement
...
"
void destroyList();
//Function to destroy the list
...

listType();
//Default constructor
//Sets the length of the list to 0
...
To derive a specific list from this list and to add or rewrite
the operations, we declare the array containing the list elements and the length of the list
as protected
...
Suppose that you want to create a list to process integer
data
...
The protected member list is an array
of 100 components, with each component being of type int
...
The protected member list is
an array of 100 components, with each component being of type newString
...
A template instantiation
can be created with either a built-in or user-defined type
...
Thus, when
giving the definitions of the function members of a class template, we must follow the
definition of the function template
...


...

}

In the heading of the member function’s definition, the name of the class is specified with
the parameter elemType
...
When the
compiler generates the code for intList, it replaces the word elemType with int in
the definition of the class listType
...

HEADER FILE AND IMPLEMENTATION FILE OF A CLASS TEMPLATE
Until now, we have placed the definition of the class (in the header file) and the definitions
of the member functions (in the implementation file) in separate files
...
However, this
mechanism of separating the class definition and the definitions of the member functions
does not work with class templates
...
Because
the actual parameter to a class is specified in the user code and because the compiler cannot
instantiate a function template without the actual parameter to the template, we can no
longer compile the implementation file independently of the user code
...
We could put the class definition and the
definitions of the function templates directly in the client code, or we could put the class
definition and the definitions of the function templates together in the same header file
...
In either case, the function definitions and the client code are compiled
together
...

The following example demonstrates the use of class templates
...
Some of the
operations included are as follows: check whether the list is empty, check whether the list
is full, sort the list, and print the list
...
The default array size is 50
...
Because the class newString that we
defined earlier allows us to use relational operators for comparison and the assignment
operator for assignment, we will use the class newString to declare strings
...

//Postcondition: Returns true if the list is empty,
//
otherwise it returns false
...

//Postcondition: Returns true if the list is full,
//
otherwise it returns false
...

//Postcondition: The value of length is returned
...

//Postcondition: The value of maxSize is returned
...

//Postcondition: The list elements are in ascending order
...

void insertAt(const elemType& item, int position);
//Function to insert item in the list at the location

Templates |

//specified by position
...

listType(int listSize = 50);
//Constructor
//Creates an array of the size specified by the
//parameter listSize; the default array size is 50
...

//Postcondition: The array list is deleted
...

#include
#include "myString
...
h"
using namespace std;
int main()
{
listType intList(100);
listType stringList;
int index;
int number;
cout << "List 5: Processing the integer list"
<< endl;
cout << "List 6: Enter 5 integers: ";

//Line
//Line
//Line
//Line

1
2
3
4

//Line 5
//Line 6

for (index = 0; index < 5; index++)
{
cin >> number;
intList
...
print();
cout << endl;

//Line
//Line
//Line
//Line

//Sort intList
intList
...
print();
cout << endl;

//Line 15
//Line 16
//Line 17

newString str;

//Line 18

cout << "Line 19: Processing the string list"
<< endl;

//Line 19

cout << "Line 20: Enter 5 strings: ";

//Line 20

for (index = 0; index < 5; index++)
{
cin >> str;
stringList
...
print();
cout << endl;

//Line
//Line
//Line
//Line

24
25
26
27

//Sort stringList
stringList
...
print();
//Line 30
cout << endl;
//Line 31
int intListSize;

//Line 32

cout << "Line 33: Enter the size of the integer "
<< "list: ";
//Line 33
cin >> intListSize;
//Line 34
cout << endl;
//Line 35
listType intList2(intListSize);
cout <<
<<
cout <<
<<

"Line 37: Processing the integer list"
endl;
"Line 38: Enter " << intListSize
" integers: ";

//Line 36
//Line 37
//Line 38

for (index = 0; index < intListSize; index++)
{
cin >> number;
intList2
...
print();
cout << endl;

//Line 43
//Line 44
//Line 45

//Sort intList2
intList2
...
print();
cout << endl;

//Line 47
//Line 48
//Line 49

cout <<
<<
cout <<
<<
}

"Line 50: Length of intList2: "
intList2
...
getMaxSize() << endl;

return 0;

//Line 40
//Line 41

//Line 50
//Line 51

Quick Review |

Sample Run: In this sample run, the user input is shaded
...

2
...

4
...

In C++, >> is used as a stream extraction operator and as a right shift
operator
...
Both are examples of operator overloading
...

The syntax of the heading of the operator function is:
returnType operator operatorSymbol(parameters)

5
...

7
...


In C++, operator is a reserved word
...

Except for the assignment operator and the member selection operator, to
use an operator on class objects, that operator must be overloaded
...

For classes with pointer member variables, the assignment operator must be
explicitly overloaded
...

10
...

12
...

14
...

16
...

18
...


20
...


22
...


24
...


Chapter 15: Overloading and Templates

Operator overloading provides the same concise notation for user-defined
data types as is available for built-in data types
...

It is not possible to create new operators
...

Most C++ operators can be overloaded
...
*, ::, ?:, and sizeof
...

The operator functions that overload the operators (), [], ->, or = for a
class must be members of that class
...

The heading of the prototype of a friend function is preceded by the word
friend
...

If an operator function is a member of a class, the far left operand of the
operator must be a class object (or a reference to a class object) of that
operator’s class
...

The operator functions that overload the stream insertion operator, <<, and
the stream extraction operator, >>, for a class must be friend functions of
that class
...
Similarly, to
overload the pre-decrement (--) operator for a class if the operator function is a member of that class, it must have no parameters
...
The user does not specify any value for the parameter
...
The post-decrement operator has similar
conventions
...

A conversion constructor converts its argument to an object of the constructor’s class
...


Exercises

26
...

28
...

30
...


Classes with pointer member variables must overload the assignment operator and include both the copy constructor and the destructor
...

In C++, template is a reserved word
...

Using templates, you can write a single code segment for a set of related
classes—called the class template
...

33
...

35
...
The word class in the heading refers to any user-defined data type
or built-in data type
...

In a class template, the parameter Type specifies how a generic class
template is to be customized to form a specific template class
...

Suppose cType is a class template, and func is a member function of
cType
...


in which funcType is the type of the function, such as void
...
The
statement:
cType x;

declares x to be an object of type cType, and the type passed to the class
cType is int
...


Mark the following statements as true or false
...

b
...

d
...

In C++, operators cannot be redefined for built-in types
...

C++ allows users to create their own operators
...

f
...

g
...

h
...

i
...

j
...

k
...

What is a friend function?
What is the difference between a friend function of a class and a member
function of a class?
Consider the definition of the class dateType given in Chapter 13
...


2
...


4
...

b
...

Suppose that the operator << is to be overloaded for a user-defined class
mystery
...
How many parameters does the function operator+ have?
When should a class overload the assignment operator and define the copy
constructor?
Consider the following declaration:
a
...


6
...


8
...


...

};
a
...


c
...

Write a statement that shows the declaration in the class strange to
overload the operator =
...


Exercises

9
...

e
...

Assume the declaration of Exercise 8
...


Write a statement that shows the declaration in the class strange to
overload the binary operator + as a friend function
...

Write a statement that shows the declaration in the class strange to
overload the operator == as a friend function
...

Write a statement that shows the declaration in the class strange to
overload the post-increment operator ++ as a friend function
...


a
...


...

bool operator<=(mystery);

...


...


...

}
11
...


...

bool operator<=(mystery, mystery);

...


...


//Line 1

//Line 2

Find the error(s) in the following code:
class mystery
{

...


...


14
...

16
...


18
...


20
...


22
...


24
...


Chapter 15: Overloading and Templates

friend operator+(mystery);
//overload binary +

...


...
The conjugate of a + ib is a – ib, and the
pffiffiffiffiffiffiffiffiffiffiffiffiffiffi
absolute value of a + ib is a2 þ b2
...
Also,
write the definitions of these operator functions
...

Find the error(s) in the following code:
template
class strange
{

...


...


Consider the following declaration:
template
class strange
{

...


...

b
...

c
...
Write the definition of the function
operator== for the class strange, which is overloaded as a
member function
...


27
...

b
...


cout << surprise(5, 7) << endl;
string str1 = "Sunny";
string str2 = " Day";
cout << surprise(str1, str2) << endl;

Consider the definition of the following function template:
template
Type funcExp(Type list[], int size)
{
int j;
Type x = list[0];
Type y = list[size - 1];
for (j = 1;
{
if (x <
x =
if (y >
y =
}
}

j < (size - 1)/2; j++)
list[j])
list[j];
list[size – 1 – j])
list[size – 1 – j];

return x + y;

|

941

1
5

942 |

Chapter 15: Overloading and Templates

Further suppose that you have the following declarations:
int list[10] = {5, 3, 2, 10, 4, 19, 45, 13, 61, 11};
string strList[] = {"One", "Hello", "Four", "Three",
"How", "Six"};

What is the output of the following statements?
a
...

29
...


cout << funExp(list, 10);
cout << funExp(strList, 6) << endl;

Write the definition of the function template that swaps the contents of two
variables
...
Overload the operator + for the class newString to perform string
concatenation
...


should assign "Hello there" to s3, in which s1, s2, and s3 are
newString objects
...
Suppose that s1 is "Hello " and s2 is
"there"
...


PROGRAMMING EXERCISES
1
...


b
...


a
...


3
...


b
...

Write a test program that tests various operations on the class
rectangleType
...

Write a test program that tests various operations on the class
rectangleType
...

Write the definition of the function to overload the post-increment
operator for the class clockType as defined in part a
...


a
...


c
...


a
...


c
...


a
...


c
...


a
...
Rewrite the definition of the class
clockType so that these operators are overloaded as nonmember functions
...

Write the definitions of the member functions of the class clockType
as designed in part a
...

Extend the definition of the class complexType so that it performs
the subtraction and division operations
...

If (a, b) and (c, d ) are complex numbers:
(a, b) - (c, d ) = (a - c, b - d )
...

Write the definitions of the functions to overload the operators - and / as
defined in part a
...
Format your answer with two decimal places
...

Write the definitions of the member functions of the class complexType
as designed in part a
...
Format your answer with
two decimal places
...

ii
...

Write the definition of the function to implement the operations defined
in part a
...

Rewrite the definition of the class newString as defined and
extended in Programming Exercise 7 so that the relational operators
are overloaded as nonmember functions
...

Write a test program that tests various operations on the class
newString
...


b
...

8
...


b
...


|

943

1
5

944 |

9
...
In this exercise, by ‘‘fractions’’ we mean rational fractions
...
Arithmetic operations on fractions are defined
by the following rules:
a=b þ c=d ¼ ðad þ bcÞ=bd
a=b À c=d ¼ ðad À bcÞ=bd
a=b  c=d ¼ ac=bd
ða=bÞ=ðc=dÞ ¼ ad=bc; in which c=d 6¼ 0:
Fractions are compared as follows: a / b op c / d if ad op bc, in which op is
any of the relational operations
...

Design a class—say, fractionType—that performs the arithmetic and
relational operations on fractions
...
Also, overload the stream insertion and stream extraction
operators for easy input and output
...

Among other things, test the following: Suppose x, y, and z are objects
of type fractionType
...
The statement:
cout << x + y << endl;

should output the value of x + y in fraction form
...


should store the sum of x and y in z in fraction form
...

Recall that in C++, there is no check on an array index out of bounds
...
Also, in C++, the array index starts at 0
...
Every object of type myArray is an
array of type int
...
Consider the following statements:
myArray list(5);
myArray myList(2, 13);
myArray yourList(-5, 9);

11
...


//Line 1
//Line 2
//Line 3

The statement in Line 1 declares list to be an array of 5 components, the
component type is int, and the components are: list[0], list[1],
...
, myList[12]; the statement in Line 3 declares yourList
to be an array of 14 components, the component type is int, and the
components are: yourList[-5], yourList[-4],
...
, yourList[8]
...

Programming Exercise 10 processes only int arrays
...

Design a class to perform various matrix operations
...
Therefore, every element of a
matrix has a row position and a column position
...
Clearly, a convenient place to store a matrix is
in a two-dimensional array
...
Suppose A = [aij] and B = [bij] are two matrices of
the size m  n, in which aij denotes the element of A in the ith row and the
jth column, and so on
...
If A is of the size
m  n and B is of the size n  t, then A *B = [cik] is of the size m  t and
the element cik is given by the formula:
cik ¼ ai1 b1k þ ai2 b2k þ Á Á Á þ ain bnk

13
...

Overload the operators +, -, and * to perform the addition, subtraction, and
multiplication operations, respectively, and overload the operator << to output a
matrix
...

a
...
In that
exercise, we also implemented a function, romanToDecimal, to con-

|

945

1
5

946 |

Chapter 15: Overloading and Templates

vert a Roman number into its equivalent decimal number
...
Use the class newString, as
designed in Programming Exercise 7, to manipulate strings
...
The stream insertion operator outputs the
Roman number in the Roman format
...
Write the definition of the member
function decimalToRoman
...


c
...


For simplicity, we assume that only the letter I can appear in front of
another letter and that it appears only in front of the letters V and X
...
Also, 40 will be represented as XXXX, 190 will be represented as CLXXXX, and so on
...
Also, overload the pre- and post-increment and decrement operators as member functions of the class extRomanType
...
For subtraction, if the
first number is smaller than the second number, output a message saying
that, ‘‘Because the first number is smaller than the second,
the numbers cannot be subtracted’’
...
Use similar conventions
for the increment and decrement operators
...

Test your class extRomanType on the following program
...
)
int main()
{
extRomanType num1("XXXIV");
extRomanType num2("XV");
extRomanType num3;
cout << "Num1 = " << num1 << endl;
cout << "Num2 = " << num2 << endl;
cout << "Num1 + Num2 = " << num1 + num2 << endl;

Programming Exercises

cout << "Num1 * Num2 = " << num1 * num2 << endl;
cout << "Enter two numbers in Roman format: ";
cin >> num1 >> num2;
cout << endl;
cout << "Num1 = " << num1 << endl;
cout << "Num2 = " << num2 << endl;
num3 = num2 * num1;
cout << "Num3 = " << num3 << endl;
cout << "--num3: " << --num3 << endl;
cout << "++num3: " << ++num3 << endl;
}
14
...


16
...
For illustration purposes, that example included only the
sorting operation
...
Write the definitions of the member functions to implement the class template listType
...

Consider the class dateType given in Chapter 13
...
(Assume that the date is input and output in the form MM-DD-YYYY
...

Programming Exercise 12, Chapter 12, describes how to design the class
lineType to implement a line
...

b
...

d
...


f
...


Overloads the stream insertion operator, <<, for easy output
...
(The line
ax + by ¼ c is input as (a, b, c)
...

Overloads the unary operator +, as a member function, so that it returns
true if a line is vertical; false otherwise
...

Overloads the operator ==, as a member function, so that it returns
true if two lines are equal; false otherwise
...


|

947

1
5

948 |

h
...


Chapter 15: Overloading and Templates

Overloads the operator &&, as a member function, so that it returns
true if two lines are perpendicular; false otherwise
...

Consider the classes class cashRegister and dispenserType given in
the programming example in Chapter 12
...


b
...

The class dispenserType, in the programming example in
Chapter 12, is designed to implement a dispenser to hold and release
products
...

Write a program to test the classes designed in parts a and b
...


(Stock Market) Write a program to help a local stock trading company
automate its systems
...
At the
end of each trading day, the company would like to generate and post the
listing of its stocks so that investors can see how their holdings performed
that day
...

The desired output is to produce two listings, one sorted by stock symbol
and another sorted by percent gain from highest to lowest
...
50 115
...
50 111
...
50 6723823
CBA 67
...
50 78
...
50 65
...


...


The first line indicates that the stock symbol is MSMT, today’s opening price was
112
...
75, today’s high price was 116
...
75, yesterday’s closing price was 113
...

The listing sorted by stock symbols must be of the following form:

Programming Exercises

********* First Investor's Heaven **********
*********
Financial Report
**********
Stock
Today
Previous Percent
Symbol Open
Close
High
Low
Close
Gain
------ ------------------------ ------ABC 123
...
95 132
...
00 120
...
67%
AOLK
80
...
00
82
...
00
83
...
64%
CSCO 100
...
00 105
...
00 101
...
99%
IBD
68
...
00
72
...
00
75
...
33%
MSET 120
...
00 145
...
00 115
...
74%
Closing Assets: $9628300
...
In the first step (part a), design and
implement a stock object
...

a
...
Call the class
that captures the various characteristics of a stock object stockType
...
Moreover, we need to output the opening price,
closing price, high price, low price, previous price, and the percent
gain/loss for the day
...

Therefore, the stock object should store all this information
...

ii
...

iv
...


Set the stock information
...

Show the different prices
...

Show the number of shares
...
1
...
2
...
3
...

Overload the relational operators to compare two stock
objects by their symbols
...

Because the data is stored in a file, overload the stream
extraction operator, >>, for easy input
...
Further suppose that myStock is
a stock object
...

(Note that this statement reads and stores the data in the relevant
components of myStock
...


Chapter 15: Overloading and Templates

Now that you have designed and implemented the class stockType
to implement a stock object in a program, it is time to create a list of
stock objects
...

The class stockListType must be derived from the class
listType, which you designed and implemented in the previous
exercise
...
Therefore, the class
stockListType is no longer a template
...

The following statement derives the class stockListType from
the class listType
...
Therefore, these members can be directly accessed in the
class stockListType
...
However, you are not to physically sort the list by the component percent gain/
loss
...


c
...
Call this array
sortIndicesGainLoss
...
The elements of the array sortIndicesGainLoss will
tell which component of the stock list to print next
...


16
CHAPTER

E XCEPTION H ANDLING
I N T H I S C H A P T E R , YO U W I L L :


...


Learn how to handle exceptions within a program


...


Become familiar with C++ exception classes


...


Discover how to throw and rethrow an exception


...
For example, division by zero is an exception
...

Until now, we have dealt with certain exceptions by using either an if statement or
the assert function
...
Similarly,
in the Programming Example newString (Chapter 15), we used the assert function to
determine whether the array index is within bounds
...
For
instance, while determining a substring in a string (Chapter 8), we never checked
whether the starting position of the substring was within range
...
However, in all of these cases, if exceptions
occurred during program execution, either we included code to terminate the program
or the program terminated with an appropriate error message
...

There are situations when an exception occurs, but you don’t want the program to
simply ignore the exception and terminate
...
It should inform the stockholder and request an appropriate action
...
A program that monitors a satellite in space cannot be
terminated if there is a temporary power failure in some section of the satellite
...
One
common way to provide exception-handling code is to add exception-handling code at
the point where an error can occur
...
The disadvantage of this approach
is that the program can become cluttered with exception-handling code, which can make
understanding and maintaining the program difficult
...


Handling Exceptions within a Program
In Chapter 3, we noted that if you try to input invalid data into a variable, the input
stream enters the fail state, so an exception occurs
...
Chapter 3 also showed how to clear and restore
the input stream
...
Even though the
function assert can check whether an expression meets the required condition(s), if
the conditions are not met, it terminates the program
...


Handling Exceptions within a Program |

953

This section discusses how to handle exceptions
...
We also review some of the
ways to handle exceptions
...

EXAMPLE 16-1
// Division by zero
...
exe has encountered a problem and needs to close
...


In Sample Run 1, the value of divisor is nonzero, so no exception occurs
...


1
6

954 |

Chapter 16: Exception Handling

In Sample Run 2, the value entered for divisor is 0
...
However, the program does not check whether divisor is 0
before dividing dividend by divisor
...

Notice that the error message is platform independent, that is, IDE dependent
...

Next, consider Example 16-2
...

EXAMPLE 16-2
// Checking division by zero
...
"
<< endl;
}

//Line 2
//Line 3
//Line 4

//Line 8

return 0;

Sample Run 1:
Line 2: Enter the dividend: 12
Line 5: Enter the divisor: 5
Line 10: Quotient = 2

//Line 9
//Line 10
//Line 11
//Line 12
//Line 13

Handling Exceptions within a Program |

955

Sample Run 2:
Line 2: Enter the dividend: 24
Line 5: Enter the divisor: 0
Line 12: Cannot divide by zero
...
The program
calculates and outputs the quotient and terminates normally
...
In Line 8, the program checks
whether divisor is 0
...

The program in Example 16-3 uses the function assert to determine whether the divisor is
zero
...

EXAMPLE 16-3
// Division by zero and the assert function
...
cpp,
line 20

In Sample Run 1, the value of divisor is nonzero, so no exception occurs
...

In Sample Run 2, the value entered for divisor is 0
...
Because divisor is 0, the expression in the
assert statement evaluates to false, and the function assert terminates the program
with the error message shown in the third line of the output
...
This section describes how to include the necessary code to handle
exceptions within a program
...
The try block
also contains statements that should not be executed if an exception occurs
...
A catch block specifies the type of
exception it can catch and contains an exception handler
...


...

catch (dataTypen identifier)
{
//exception-handling code
}

...


...
)
{
//exception-handling code
}

Handling Exceptions within a Program |

957

Suppose there is a statement that can generate an exception, for example, division by 0
...

For example, before performing the division, we check whether the divisor is nonzero
...
This is typically done using the throw statement, which
we will explain shortly
...

Let us now note the following about try/catch blocks
...

• If an exception is thrown in a try block, the remaining statements in that
try block are ignored
...
If the type of thrown exception matches the parameter type
in one of the catch blocks, the code of that catch block executes, and
the remaining catch blocks after this catch block are ignored
...

Consider the following catch block:
catch (int x)
{
//exception-handling code
}

In this catch block:
• The identifier x acts as a parameter
...

• The data type int specifies that this catch block can catch an exception
of type int
...

Essentially, the catch block parameter becomes a placeholder for the value thrown
...
In other
words, if the thrown value is caught by this catch block, then the thrown value is stored
in the catch block parameter
...

Suppose in a catch block heading only the data type is specified, that is, there is no
catch block parameter
...

THROWING AN EXCEPTION
In order for an exception to occur in a try block and be caught by a catch block, the
exception must be thrown in the try block
...
The object being thrown
can be either a specific object or an anonymous object
...

In C++, throw is a reserved word
...

EXAMPLE 16-4
Suppose we have the following declaration:
int num = 5;
string str = "Something is wrong!!!";
throw expression

Effect

throw
throw
throw
throw

The constant value 4 is thrown
...

The object str is thrown
...


4;
x;
str;
string("Exception found!");

ORDER OF catch BLOCKS
A catch block can catch either all exceptions of a specific type or all types of exceptions
...
As noted
previously, the catch block that has an ellipses (three dots) is designed to catch any type
of exception
...


Suppose that an exception occurs in a try block and is caught by a catch block
...
Therefore, you
should be careful about the order in which you list catch blocks following a try block
...
)
{
//statements
}
catch (int x)
{
//statements
}

//Line 1

//Line 2

//Line 3

Handling Exceptions within a Program |

959

Suppose that an exception is thrown in the try block
...
For this
sequence of try/catch blocks, some compilers might, in fact, give a syntax error (check
your compiler’s documentation)
...

USING try/catch BLOCKS IN A PROGRAM
Next, we provide examples that illustrate how a try/catch block might appear in a program
...
If, during program execution, division by zero occurs with integer
values and is not addressed by the program, the program might terminate with an error message
or might simply hang
...

EXAMPLE 16-5
This example illustrates how to catch and handle division by zero exceptions
...

// Handling division by zero exception
...
" << endl;

return 0;

//Line 14
//Line 15

Sample Run 1: In this sample run, the user input is shaded
...

Line 3: Enter the dividend: 34
Line 6: Enter the divisor: 0
Line 14: Division by 0
...
The statement in Line 1 declares the int variables dividend,
divisor, and quotient
...
The statement in Line 3 prompts the
user to enter the value for the dividend; the statement in Line 4 stores this number in the
variable dividend
...
The statement in
Line 9 checks whether the value of divisor is 0
...
The statement in Line 11 calculates the quotient
and stores it in quotient
...

The catch block starts in Line 13 and catches an exception of type int
...

In Sample Run 2, the entered value of divisor is 0
...
The statement in Line
14 outputs the appropriate message
...

EXAMPLE 16-6
// Handling division by zero exception
...

Line 3: Enter the dividend: 14
Line 6: Enter the divisor: 5
Line 12: Quotient = 2

Sample Run 2: In this sample run, the user input is shaded
...

The program in Example 16-7 illustrates how to handle division by zero, division by a
negative integer, and input failure exceptions
...
This program is similar to the programs in Examples 16-5 and 16-6
...

#include
#include
using namespace std;
int main()
{
int dividend, divisor = 1, quotient;
string inpStr
= "The input stream is in the fail state
...
");
else if (!cin)
throw inpStr;

//Line
//Line
//Line
//Line
//Line
//Line

quotient = dividend / divisor;

//Line 16

cout << "Line 17: Quotient = " << quotient
<< endl;

//Line 17

}
catch (int x)
{
cout << "Line 19: Division by " << x
<< endl;
}
catch (string s)
{
cout << "Line 21: " << s << endl;
}
}

return 0;

10
11
12
13
14
15

//Line 18
//Line 19
//Line 20
//Line 21
//Line 22

Handling Exceptions within a Program |

963

Sample Run 1: In this sample run, the user input is shaded
...

Line 4: Enter the dividend: 34
Line 7: Enter the divisor: -6
Line 21: Negative divisor
...

Line 4: Enter the dividend: 34
Line 7: Enter the divisor: g
Line 21: The input stream is in the fail state
...

Notice that the string object inpStr is also initialized
...
The statement in Line 10 checks whether divisor is 0; the statement in Line
12 checks whether divisor is negative; and the statement in Line 14 checks whether the
standard input stream is in the fail state
...
"; and the statement in
Line 15 throws the object inpStr
...
If the exception is thrown by the statement in Line
11, it is caught and processed by the catch block in Line 18
...

In Sample Run 1, the program does not encounter any problems
...
In Sample Run 3, the standard input stream enters the fail state
...
The class
exception is the base of the classes designed to handle exceptions
...
The function what returns a string containing an

1
6

964 |

Chapter 16: Exception Handling

appropriate message
...

Two classes are immediately derived from the class exception: logic_error and
runtime_error
...

To deal with logical errors in a program, such as a string subscript out of range or an invalid
argument to a function call, several classes are derived from the class logic_error
...
The class out_of_range deals with the string subscript out of range
error
...
For example, recall that every string object has a
maximum length (see Chapter 8)
...
If the operator new cannot
allocate memory space, this operator throws a bad_alloc exception
...
For example, to deal with arithmetic overflow and underflow
exceptions, the classes overflow_error and underflow_error are derived from the
class runtime_error
...

The program in Example 16-8 shows how to handle the exceptions out_of_range and
length_error
...
Because the exceptions are
thrown by these functions, we do not include any throw statement in the try block
...

#include
#include
using namespace std;
int main()
{
string sentence;
string str1, str2, str3;
try
{

//Line 1
//Line 2
//Line 3

sentence = "Testing string exceptions!";
cout << "Line 5: sentence = " << sentence
<< endl;

//Line 4
//Line 5

Handling Exceptions within a Program |

965

cout << "Line 6: sentence
...
length())
<< endl;
//Line 6
str1 = sentence
...
substr(28, 10);
cout << "Line 10: str2 = " << str2
<< endl;

//Line 9

str3 = "Exception handling
...
what()
<< endl;
}
catch (length_error le)
{
cout << "Line 16: In the length_error "
<< "catch block: " << le
...
length() = 26
8: str1 = string exceptions!
14: In the out_of_range catch block: invalid string position

In this program, the statement in Line 7 uses the function substr to determine a
substring in the string object sentence
...
Because
the starting position of the substring is 8, which is less than 26, no exception is thrown
...
Therefore, the function substr throws an
out_of_range exception, which is caught and processed by the catch block in Line 13
...

The program in Example 16-9 illustrates how to handle the exception bad_alloc
thrown by the operator new
...

#include
using namespace std;
int main()
{
int *list[100];

//Line 1

try
{

//Line 2
for (int i = 0; i
{
list[i] = new
cout << "Line
<< "] of
<< endl;
}

< 100; i++)

//Line 3

int[50000000];
4: Created list[" << i
50000000 components
...
what() << "
...

Created list[1] of 50000000 components
...

Created list[3] of 50000000 components
...

Created list[5] of 50000000 components
...

Created list[7] of 50000000 components
...


The preceding program works as follows
...
The body of the for loop in Line 3 is designed to execute 100
times
...
As shown in the sample run, the
operator new is able to create eight arrays of 50000000 components each
...
This exception is caught and processed by the catch block in Line 6
...
what() returns the string bad allocation
...
what() is SDK dependent
...
) After the statement in Line 7 executes, control exits the try/catch block,
and the statement in Line 8 terminates the program
...

As you have seen, C++ provides numerous exception classes to deal with these situations
...
Therefore,
C++ enables programmers to create their own exception classes to handle both the
exceptions not covered by C++’s exception classes and their own exceptions
...

C++ uses the same mechanism to process the exceptions that you define as it uses for built-in
exceptions
...

In C++, any class can be considered an exception class
...
It need not be inherited from the class exception
...

The exception class that you define can be very simple in the sense that it does not contain
any members
...

class dummyExceptionClass
{
};

The program in Example 16-10 uses a user-defined class (with no members) to throw an
exception
...

#include
using namespace std;
class divByZero
{};
int main()
{
int dividend, divisor, quotient;

//Line 1

1
6

968 |

Chapter 16: Exception Handling

try
{

//Line 2
cout << "Line 3: Enter the dividend: ";
cin >> dividend;
cout << endl;

//Line 3
//Line 4
//Line 5

cout << "Line 6: Enter the divisor: ";
cin >> divisor;
cout << endl;

//Line 6
//Line 7
//Line 8

if (divisor == 0)
throw divByZero();

//Line 9
//Line 10

quotient = dividend / divisor;
cout << "Line 12: Quotient = " << quotient
<< endl;

//Line 11

}
catch (divByZero)
{
cout << "Line 14: Division by zero!"
<< endl;
}
}

return 0;

//Line 12
//Line 13
//Line 14
//Line 15

Sample Run 1: In this sample run, the user input is shaded
...

Line 3: Enter the dividend: 56
Line 6: Enter the divisor: 0
Line 14: Division by zero!

The preceding program works as follows
...

The class divByZero has no members, so we cannot really do anything with
the thrown object
...
The statement in Line 14 outputs the appropriate error
message
...
Notice that in this
statement, divByZero is the name of the class, the expression divByZero() creates an
anonymous object of this class, and the throw statement throws the object
...

Next, we illustrate how to create exception classes with members
...
Consider the following definition of the class divisionByZero
...

#include
#include
using namespace std;
class divisionByZero
{
public:
divisionByZero()
{
message = "Division by zero";
}

//Line
//Line
//Line
//Line

1
2
3
4

//Line 5
//Line 6

divisionByZero(string str)
{
message = str;
}

//Line
//Line
//Line
//Line

7
8
9
10

string what()
{
return message;
}

//Line
//Line
//Line
//Line

11
12
13
14

private:
string message;
};

//Line 15
//Line 16
//Line 17

The definition of the class divisionByZero contains two constructors: the default
constructor and the constructor with parameters
...
The constructor with parameters allows users
to create their own error messages
...

In the definition of the class divisionByZero, the constructors can also be
written as:

divisionByZero() : message("Division by zero"){}
divisionByZero(string str) : message(str){}

The program in Example 16-11 uses the preceding class to throw an exception
...

#include
#include "divisionByZero
...
what() << endl;
}
}

return 0;

Sample Run 1: In this sample run, the user input is shaded
...

Line 3: Enter the dividend: 56
Line 6: Enter the divisor: 0
Line 14: In the divisionByZero catch block: Division by zero

In this program, the statement in Line 10 throws an object (exception) of the class
divisionByZero if the user enters 0 for the divisor
...
The parameter divByZeroObj in the
catch block catches the value of the thrown object and then uses the function what to
return the string stored in the object
...

The program in Example 16-12 is similar to the program in Example 16-11
...

EXAMPLE 16-12
// Using user-defined exception class divisionByZero with a
// specific error message
...
h"
using namespace std;
int main()
{
int dividend, divisor, quotient;
try
{

//Line 1
//Line 2

cout << "Line 3: Enter the dividend: ";
cin >> dividend;
cout << endl;

//Line 3
//Line 4
//Line 5

cout << "Line 6: Enter the divisor: ";
cin >> divisor;
cout << endl;

//Line 6
//Line 7
//Line 8

//Line 9
if (divisor == 0)
throw divisionByZero("Found division by zero"); //Line 10

}

quotient = dividend / divisor;
cout << "Line 12: Quotient = " << quotient
<< endl;

//Line 11
//Line 12

1
6

972 |

Chapter 16: Exception Handling

catch(divisionByZero divByZeroObj)
{
cout << "Line 14: In the divisionByZero "
<< "catch block: "
<< divByZeroObj
...

Line 3: Enter the dividend: 34
Line 6: Enter the divisor: 5
Line 12: Quotient = 6

Sample Run 2: In this sample run, the user input is shaded
...
The details are left
as an exercise for you
...
Therefore, the exception is thrown, caught, and processed in the function
main
...
Therefore, the exception is thrown, caught, and processed in the
function doDivision
...

#include
#include "divisionByZero
...
what() << endl;
}

//Line 13
//Line 14

//Line 15

Sample Run 1: In this sample run, the user input is shaded
...

Line 4: Enter the dividend: 56
Line 7: Enter the divisor: 0
Line 15: In the function doDivision: Division by zero

Rethrowing and Throwing an Exception
When an exception occurs in a try block, control immediately passes to one of the
catch blocks
...
The catch block in Examples
16-4 through 16-13 handles the exception
...
This allows the programmer to provide the
exception-handling code all in one place
...
The general syntax to
rethrow an exception caught by a catch block is:
throw;

(in this case, the same exception is rethrown) or:
throw expression;

in which expression is a constant value, variable, or object
...

A function specifies the exceptions it throws (to be handled somewhere) in its heading
using the throw clause
...

void exmpThrowExcep(int x) throw (int, string, divisionByZero)
{

...


...


...

}

The program in Example 16-14 further explains how a function specifies the exception it
throws
...
The function throws the same exception object
...
h"
using namespace std;
void doDivision() throw (divisionByZero);

Creating Your Own Exception Classes

int main()
{
try
{
doDivision();
}
catch (divisionByZero divByZeroObj)
{
cout << "Line 4: In main: "
<< divByZeroObj
...

Line 8: Enter the dividend: 34
Line 11: Enter the divisor: 5
Line 17: Quotient = 6

Sample Run 2: In this sample run, the user input is shaded
...

In Sample Run 1, no exception is thrown
...
The function main calls the function
doDivision in the try block
...
The exception is caught by the
catch block in Line 18
...
In other
words, the catch block catches and rethrows the same exception
...
This exception is
caught and processed by the catch block in Line 3
...
The function throws a different exception object
...
h"
using namespace std;
void doDivision() throw (divisionByZero);
int main()
{
try
{
doDivision();
}
catch (divisionByZero divByZeroObj)
{
cout << "Line 4: In main: "
<< divByZeroObj
...

Line 8: Enter the dividend: 34
Line 11: Enter the divisor: 5
Line 17: Quotient = 6

Sample Run 2: In this sample run, the user input is shaded
...
The only difference is
that here, the catch block in Line 18 rethrows a different exception value, that is, object
...
This
mechanism is quite useful because it allows a program to handle all of the exceptions in
one location, rather than spread the exception-handling code throughout the program
...
The following sections discuss each of these situations
...
Suppose
you have written a program that inputs data from a file
...
In
this case, the program can output an appropriate error message and terminate
...

Suppose that you have a program that takes as input an integer
...
This is a situation in which
you can include the necessary code to keep prompting the user to input a number until
the entry is valid
...

EXAMPLE 16-16
// Handle exceptions by fixing the errors
...

#include
#include
using namespace std;
int main()
{
int number;
bool done = false;

//Line 1
//Line 2

string str =
"The input stream is in the fail state
...
" << endl;
cin
...
ignore(100, '\n');
}

}
while (!done);
}

979

//Line 10

if (!cin)
throw str;

|

return 0;

//Line
//Line
//Line
//Line

14
15
16
17

//Line 18
//Line
//Line
//Line
//Line

19
20
21
22

//Line 23
//Line 24

Sample Run: In this sample run, the user input is shaded
...

Line 19: Restoring the input stream
...

Line 19: Restoring the input stream
...

Line 19: Restoring the input stream
...
If the input is invalid, the standard
input stream enters the fail state
...
Control passes to the catch block, and the
exception is caught and processed
...

The do
...


1
6

980 |

Chapter 16: Exception Handling

Log the Error and Continue
The program that terminates when an exception occurs usually assumes that this
termination is reasonably safe
...
These programs should report the exception, but the program must continue
to run
...
Because
numerous ticketing transactions occur each day, a program is run at the end of each day
to validate that day’s transactions
...

Instead, when an exception occurs, the program should write the exception into a file
and continue to analyze the transactions
...
In
particular, you learned how to catch and process an exception in the same block, as well
as process the caught exception in the calling environment
...

Partially process the exception and throw the same exception or a new
exception
...

In each of these cases, the function-call stack is unwound so that the exception can be
caught in the next try/catch block
...
The stack unwinding continues until either a
try/catch handles the exception or the program does not handle the exception
...

Examples 16-17 and 16-18 illustrate how the exceptions are propagated
...

#include
using namespace std;

Stack Unwinding |

981

class myException
{
public:
myException()
{
message = "Something is wrong!";
}
myException(string str)
{
message = str;
}
string what()
{
return message;
}
private:
string message;
};
In the definition of the class myException, the constructors can also be written
as follows:

myException() : message("Something is wrong!"){}
myException(string str) : message(str){}

The program in Example 16-17 illustrates how exceptions thrown in a function get
processed in the calling environment
...

#include
#include "myException
...
what() << " Caught in main
...
");
}

Sample Run:
Exception generated in function C
...


In this program, the function main calls functionA, functionA calls functionB, and
functionB calls functionC
...
The functions functionA and functionB do not process the
exception thrown by functionC
...
The parameter me in the catch block heading catches
the value of the exception and then uses the function what to return the string
stored in that object
...

The program in Example 16-18 is similar to the program in Example 16-17
...


EXAMPLE 16-18
// Processing exceptions, thrown by a function, in the
// immediate calling environment
...
h"

Stack Unwinding |

983

using namespace std;
void functionA();
void functionB();
void functionC() throw (myException);
int main()
{
try
{
functionA();
}
catch (myException e)
{
cout << e
...
" << endl;
}
}

return 0;

void functionA()
{
functionB();
}
void functionB()
{
try
{
functionC();
}
catch (myException me)
{
cout << me
...
" << endl;
}
}
void functionC() throw (myException)
{
throw myException("Exception generated in functionC
...
Caught in functionB
...
Even though the
function main contains the try/catch block, the try block does not throw any
exceptions because the exception thrown by functionC is caught and processed by
functionB
...

2
...

4
...


6
...

8
...


10
...

12
...


14
...


An exception is an occurrence of an undesirable situation that can be
detected during program execution
...

The function assert can check whether an expression meets the required
condition(s)
...

The try/catch block is used to handle exceptions within a program
...
The
try block also contains statements that should not be executed if an
exception occurs
...

A catch block specifies the type of exception it can catch and contains an
exception handler
...
(ellipses) in place of parameters,
then this catch block can catch exceptions of all types
...

If an exception is thrown in a try block, the remaining statements in the try
block are ignored
...
If
the type of the thrown exception matches the parameter type in one of the
catch blocks, then the code in that catch block executes and the remaining
catch blocks after this catch block are ignored
...

A catch block can have, at most, one catch block parameter
...

In order for an exception to occur in a try block and be caught by a catch
block, the exception must be thrown in the try block
...


in which expression is a constant value, variable, or object
...

C++ provides support to handle exceptions via a hierarchy of classes
...

18
...

20
...

22
...


24
...


26
...


28
...


30
...

The function what returns the string containing the exception object
thrown by C++’s built-in exception classes
...

The two classes that are immediately derived from the class exception
are logic_error and runtime_error
...

The class invalid_argument is designed to deal with illegal arguments
used in a function call
...

If a length greater than the maximum allowed for a string object is used, the
class length_error deals with the error that occurs when a length
greater than the maximum size allowed for the object being manipulated
is used
...

The class runtime_error is designed to deal with errors that can be
detected only during program execution
...

A catch block typically handles the exception or partially processes the
exception and then either rethrows the same exception or rethrows another
exception in order for the calling environment to handle the exception
...

C++ uses the same mechanism to process the exceptions you define as it
uses for built-in exceptions
...

In C++, any class can be considered an exception class
...
What makes a class an exception is
how it is used
...
The object
being thrown can be either a specific object or an anonymous object
...

32
...


Chapter 16: Exception Handling

A function specifies the exceptions it throws in its heading using the throw
clause
...
In each of these
cases, the function-call stack is unwound so that the exception can be
caught in the next try/catch block
...

If the program does not handle the exception, then the function terminate
is called to terminate the program
...


Mark the following statements as true or false
...

b
...

c
...

d
...

What is the difference between a try block and a catch block?
What will happen if an exception is thrown but not caught?
What happens if no exception is thrown in a try block?
What happens if an exception is thrown in a try block?
Consider the following C++ code:
a
...

3
...

5
...


double balance;
try
{
cout << "Enter the balance: ";
cin >> balance;
cout << endl;
if (balance < 1000
...
" << endl;
}
catch (double x)
{
cout << "Current balance: " << x << endl
<< "Balance must be greater than 1000
...

In this code, identify the catch block
...
In this code, identify the catch block parameter and its type
...
In this code, identify the throw statement
...


|

987

a
...


7
...
What is the output
c
...


8
...


...

try
{
cout << "Entering the try block
...
");
cout << "Exiting the try block
...
what() << endl;
}
cout << "After the catch block" << endl;

What is the output if:
The value of lowerLimit is 50?
b
...


9
...
" << endl;
if (divisor == 0)
throw 0;
if (lowerLimit < 100)
throw string("Lower limit violation
...
" << endl;
}
catch (int x)
{
cout << "Exception: " << x << endl;
result = 120;
}
catch (string str)
{
cout << "Exception: " << str << endl;
}
cout << "After the catch block" << endl;

What is the output if:
The value of lowerLimit is 50, and the value of divisor is 10?
b
...
The value of lowerLimit is 150, and the value of divisor is 10?
d
...
The class should
have two constructors, including the default constructor
...
The other constructor has a
single parameter, say, m, of the int type
...


10
...

12
...


14
...

Suppose the exception class myException is defined as follows:
class myException
{
public:
myException()
{
message = "myException thrown!";
cout << "Immediate attention required!"
<< endl;
}
myException(string msg)
{
message = msg;
cout << "Attention required!" << endl;
}

Programming Exercises

|

989

string what()
{
return message;
}
private:
string message;
}

Suppose that in a user program, the catch block has the following form:
catch (myException mE)
{
cout << mE
...

16
...


PROGRAMMING EXERCISES
1
...


3
...


Write a program that prompts the user to enter a length in feet and inches
and outputs the equivalent length in centimeters
...

Redo Programming Exercise 7 of Chapter 8 so that your program handles
exceptions such as division by zero and invalid input
...

The program then outputs the time in 24-hour notation
...
If the user enters an invalid value for hours, then the program
should throw and catch an invalidHr object
...

Write a program that prompts the user to enter a person’s date of birth in
numeric form such as 8-27-1980
...
Your program must contain at least two
exception classes: invalidDay and invalidMonth
...
Similar conventions for the invalid values of month
and year
...
)

1
6

This page intentionally left blank

17
CHAPTER

R ECURSION
I N T H I S C H A P T E R , YO U W I L L :


...


Explore the base case and the general case of a recursive definition


...


Learn about recursive functions


...
For certain problems, however, using the iterative technique
to obtain the solution is quite complicated
...


Recursive Definitions
The process of solving a problem by reducing it to smaller versions of itself is called
recursion
...
Let us consider a problem that is familiar
to most everyone
...
To find (n À 1)!, we apply the definition again
...
Thus, for an
integer n greater than 0, n! is obtained by first finding (n À 1)! (that is, n! is reduced to a
smaller version of itself) and then multiplying (n À 1)! by n
...
Here, n = 3
...
Because n > 0, we use Equation 17-2 to obtain:
2! ¼ 2 Â 1!
Now, to find 1!, we again use Equation 17-2 because n = 1 > 0
...
Substituting 0! into 1! gives 1! = 1
...

The solution in Equation 17-1 is direct—that is, the right side of the equation
contains no factorial notation
...
The definition of the factorial given in Equations 17-1 and
17-2 is called a recursive definition
...

Recursive definition: A definition in which something is defined in terms of a smaller

version of itself
...
Every recursive definition must have one (or more) base cases
...
The general case must eventually be reduced to a base case
...
The base case stops the recursion
...
Here, we talk about
recursive algorithms and recursive functions
...
The recursive algorithm must have one or more base cases, and the general
solution must eventually be reduced to a base case
...
That is, the body of the
recursive function contains a statement that causes the same function to execute again
before completing the current call
...

Next, let us write the recursive function that implements the factorial function
...

Let us note the following from the preceding example, involving the factorial function
...

• Every call to a recursive function—that is, every recursive call—has its
own code and its own set of parameters and local variables
...
The current (recursive)
call must execute completely before control goes back to the previous
call
...


Direct and Indirect Recursion
A function is called directly recursive if it calls itself
...
For example, if a function A calls a function B and function B calls function
A, then function A is indirectly recursive
...
For
example, suppose that function A calls function B, function B calls function C, function C
calls function D, and function D calls function A
...

Indirect recursion requires the same careful analysis as direct recursion
...
However,
tracing through indirect recursion can be tedious
...
For simplicity, the problems in this
book involve only direct recursion
...
The function fact is an example of a tail recursive function
...
That is, the sequence of recursive calls eventually reached a base
case
...
In theory, infinite
recursion executes forever
...
The system also saves this
information so that after completing a call, control can be transferred back to the right
caller
...

Recursive functions (algorithms) must be carefully designed and analyzed
...
This chapter provides several
examples that illustrate how to design and implement recursive algorithms
...
Understand the problem requirements
...
Determine the limiting conditions
...


1
7

996 |

Chapter 17: Recursion

c
...

d
...


Problem Solving Using Recursion
Examples 17-1 through 17-3 illustrate how recursive algorithms are developed and
implemented in C++ using recursive functions
...
In this example, we
use a recursive algorithm to find the largest element in an array
...


[0] [1] [2] [3] [4] [5] [6]
list

FIGURE 17-2

5

8

2

10

9

4

list with six elements

The largest element in the list in Figure 17-2 is 10
...
Also, suppose that
list[a]
...
, and
list[b]
...
list[5] represents the array elements
list[0], list[1], list[2], list[3], list[4], and list[5]
...
list[5] represents the array elements list[1], list[2], list[3],
list[4], and list[5]
...

If list is of length 1, then list has only one element, which is the largest element
...
To find the largest element in list[a]
...
list[b] and then compare this largest
element with list[a]
...
list[b] is given by:
maximum(list[a], largest(list[a + 1]
...
This
list has six elements, given by list[0]
...
Now, the largest element in list is:
maximum(list[0], largest(list[1]
...
list[5]
...
list[5], we use
the same formula again because the length of this list is greater than 1
...
list[5] is then:
maximum(list[1], largest(list[2]
...
We see that every time we use the preceding formula to find the largest
element in a sublist, the length of the sublist in the next call is reduced by one
...
From this point onward, we backtrack through
the recursive calls
...

Base Case: The size of the list is 1
The only element in the list is the largest element

General Case: The size of the list is greater than 1
To find the largest element in list[a]
...
Find the largest element in list[a + 1]
...
Compare the elements list[a] and max
if (list[a] >= max)
the largest element in list[a]
...
list[b] is max

This algorithm translates into the following C++ function to find the largest element in
an array:
int largest(const int list[], int lowerIndex, int upperIndex)
{
int max;
if (lowerIndex == upperIndex) //size of the sublist is one
return list[lowerIndex];
else
{
max = largest(list, lowerIndex + 1, upperIndex);

}

}

if (list[lowerIndex] >= max)
return list[lowerIndex];
else
return max;

Consider the list given in Figure 17-3
...
Figure 17-4 traces the execution
of largest(list, 0, 3)
...

The following C++ program uses the function largest to determine the largest element
in a list
...
In this
example, we write a recursive function, rFibNum, to determine the desired Fibonacci
number
...
The function rFibNum returns the nth Fibonacci number in the sequence
...

The fourth Fibonacci number in a sequence is the sum of the second and third Fibonacci
numbers
...
The following recursive algorithm calculates the nth Fibonacci
number, in which a denotes the first Fibonacci number, b the second Fibonacci number,
and n the nth Fibonacci number
...
That is, we want to determine the fourth Fibonacci number of
the sequence whose first number is 2 and whose second number is 5
...
rFibNum(2, 5, 4) = rFibNum(2, 5, 3) + rFibNum(2, 5, 2)
Next, we determine rFibNum(2, 5, 3) and rFibNum(2, 5, 2)
...
Here, a = 2, b = 5, and n is 3
...
a
...
In rFibNum(2, 5, 2), a = 2, b = 5, and n = 2
...
a
...
rFibNum(2, 5, 2) = 5
To find rFibNum(2, 5, 1), note that a = 2, b = 5, and n = 1
...
a
...
rFibNum(2, 5, 1) = 2
We substitute the values of rFibNum(2, 5, 2) and
rFibNum(2, 5, 1) into (1
...
As in (1
...
1), rFibNum(2,
5, 2) = 5
...

int rFibNum(int a, int b, int n)
{
if (n == 1)
return a;
else if (n == 2)
return b;
else
return rFibNum(a, b, n - 1) + rFibNum(a, b, n - 2);
}

1
7

Let us trace the execution of the following statement:
cout << rFibNum(2, 3, 5) << endl;

In this statement, the first number is 2, the second number is 3, and we want to determine
the fifth Fibonacci number of the sequence
...
The value returned is 13, which is the fifth Fibonacci
number of the sequence whose first number is 2 and second number is 3
...

Sample Run 1
Enter the first Fibonacci number: 2
Enter the second Fibonacci number: 5

Problem Solving Using Recursion |

1003

Enter the position of the desired Fibonacci number: 6
The Fibonacci number at position 6 is: 31

Sample Run 2
Enter the first Fibonacci number: 12
Enter the second Fibonacci number: 18
Enter the position of the desired Fibonacci number: 15
The Fibonacci number at position 15 is: 9582

E X A M P L E 1 7 - 3: T O W E R O F H A N O I
In the nineteenth century, a game called the Tower of Hanoi became popular in Europe
...
At the creation of
the universe, priests in the temple of Brahma were supposedly given three diamond
needles, with one needle containing 64 golden disks
...
The priests’ task is to move all 64 disks from the first needle to the
third needle
...
Only one disk can be moved at a time
...
The removed disk must be placed on one of the needles
...
A larger disk cannot be placed on top of a smaller disk
...

Our objective is to write a program that prints the sequence of moves needed to transfer
the disks from the first needle to the third needle
...


1
2
3

FIGURE 17-6

Tower of Hanoi problem with three disks

1
7

1004

| Chapter 17: Recursion

As before, we think in terms of recursion
...
In this case, the disk can be moved directly from needle 1
to needle 3
...

In this case, first we move the first disk from needle 1 to needle 2, and then we move the
second disk from needle 1 to needle 3
...
Next, we consider the case in which the first needle contains three disks and
then generalize this to the case of 64 disks (in fact, to an arbitrary number of disks)
...
To move disk number 3 to needle 3, the top
two disks must first be moved to needle 2
...
To move the top two disks from needle 2 to needle 3, we use the
same strategy as before
...
Figure 17-7
shows a solution to the Tower of Hanoi problem with three disks
...
To begin, the first needle
contains all 64 disks
...
So first, we move the top 63 disks from needle
1 to needle 2, and then we move disk number 64 from needle 1 to needle 3
...
To move disk number 63 from needle 2 to needle 3, we first
move the top 62 disks from needle 2 to needle 1, and then we move disk number 63
from needle 2 to needle 3
...

This discussion translates into the following recursive algorithm given in pseudocode
...

1
...

2
...

3
...

This recursive algorithm translates into the following C++ function:
void moveDisks(int count, int needle1, int needle3, int needle2)
{
if (count > 0)
{
moveDisks(count - 1, needle1, needle2, needle3);
cout << "Move disk " << count << " from " << needle1
<< " to " << needle3 << "
...

If needle 1 contains three disks, then the number of moves required to move all three
disks from needle 1 to needle 3 is 23 À 1 = 7
...

Because 210 ¼ 1024 % 1000 ¼ 103 , we have:
264 ¼ 24 Â 260 % 24 Â 1018 ¼ 1:6 Â 1019
The number of seconds in one year is approximately 3
...
Suppose the priests move
one disk per second and they do not rest
...
It is estimated that our universe is about 15 billion years old (1
...
Also,
5 Â 1011 = 50 Â 1010 % 33 Â (1
...
This calculation shows that our universe
would last about 33 times as long as it already has
...
Then the number
of moves that the computer can generate in one year is:
ð3:2 Â 107 Þ Â 109 ¼ 3:2 Â 1016
So the computer time required to generate 264 moves is:
264 % 1:6 Â 1019 ¼ 1:6 Â 1016 Â 103 ¼ ð3:2 Â 1016 Þ Â 500
Thus, it would take about 500 years for the computer to generate 264 moves at the rate of
1 billion moves per second
...
That
program used a loop to perform the calculation
...
More formally, iterative
control structures use a looping structure, such as while, for, or do
...
In Example 17-2, we designed a recursive function to calculate
a Fibonacci number
...
Moreover, a selection control
structure is used to control the repeated calls in recursion
...
In this chapter, we use recursion to determine the largest
element in a list
...
Using an iterative control structure, we can also
write an algorithm to find the factorial of a nonnegative integer
...

We thus see that there are usually two ways to solve a particular problem—iteration and
recursion
...
In addition to the nature of the problem, the other key factor in
determining the best solution method is efficiency
...
When the function terminates, that memory space is then deallocated
...
That is, every
(recursive) call requires the system to allocate memory space for its formal parameters and
(automatic) local variables and then deallocate the memory space when the function exits
...
Therefore, a recursive function executes more slowly
than its iterative counterpart
...

Today’s computers, however, are fast and have inexpensive memory
...
Keeping the power of today’s computers

Programming Example: Converting a Number from Binary to Decimal |

1007

in mind, the choice between the two alternatives—iteration or recursion—depends on the
nature of the problem
...

As a general rule, if you think that an iterative solution is more obvious and easier to
understand than a recursive solution, use the iterative solution, which would be more
efficient
...
(In fact, it turns out
that it is difficult to construct an iterative solution for the Tower of Hanoi problem
...


PROGRAMMING EXAMPLE:

Converting a Number from Binary to
Decimal

In Chapter 1, we explained that the language of a computer, called machine
language, is a sequence of 0s and 1s
...
Also, you know that the collating sequence of A
in the ASCII character set is 65
...

The numbering system we use is called the decimal system, or base 10 system
...
In this and the next programming example, we discuss how to convert a
number from base 2 to base 10 and from base 10 to base 2
...
The weight of each bit in the binary number is assigned from

right to left
...
The weight of the bit immediately
to the left of the rightmost bit is 1, the weight of the bit immediately to the left of it is
2, and so on
...
The weight of each bit is as
follows:
Weight 6 5 4 3 2 1 0
1 0 0 1 1 0 1
We use the weight of each bit to find the equivalent decimal number
...
For the above binary number, the equivalent decimal number is:
1 Â 26 þ 0 Â 25 þ 0 Â 24 þ 1 Â 23 þ 1 Â 22 þ 0 Â 21 þ 1 Â 20
¼ 64 þ 0 þ 0 þ 8 þ 4 þ 0 þ 1
¼ 77

1
7

1008

| Chapter 17: Recursion

To write a program that converts a binary number into the equivalent decimal
number, we note two things: (1) the weight of each bit in the binary number must be
known, and (2) the weight is assigned from right to left
...
After processing a bit, we can add 1 to its weight, giving the weight of the bit
immediately to the left of it
...
To extract a bit, we can use the mod
operator
...

if (binaryNumber > 0)
{
bit = binaryNumber % 10;
//extract the rightmost bit
decimal = decimal + bit * power(2, weight);
binaryNumber = binaryNumber / 10; //remove the rightmost
//bit
weight++;
convert the binaryNumber into decimal
}

This algorithm assumes that the memory locations decimal and weight have been
initialized to 0 before using the algorithm
...
0, weight));
binaryNumber = binaryNumber / 10;
weight++;
binToDec(binaryNumber, decimal, weight);
}

In this function, both decimal and weight are reference parameters
...
After extracting the
rightmost bit, this function updates the decimal number and the weight of the next
bit
...
Consider the
following statements:
decimalNumber = 0;
bitWeight = 0;
binToDec(1101, decimalNumber, bitWeight);

Figure 17-8 traces the execution of the last statement, that is, binToDec(1101,
decimalNumber, bitWeight);
...


Programming Example: Converting a Number from Binary to Decimal |

1009

binToDec(1101,decimalNumber,bitWeight)
before call
decimalNumber
bitWeight

binaryNumber 1101
0
0

bit

because binaryNumber > 0
bit = 1101 % 10 = 1;
decimal = 0 + 1 * 20 = 1;
weight = 1;
binaryNumber = 1101 / 10 = 110;
binToDec(110,decimal,weight);

1
7

binToDec(110,decimal,weight)
binaryNumber
before call
decimalNumber
bitWeight

110

bit

because binaryNumber > 0
bit = 110 % 10 = 0;
decimal = 1 + 0 * 21 = 1;
weight = 2;
binaryNumber = 110 / 10 = 11;
binToDec(11,decimal,weight);

1
1

binToDec(11,decimal,weight)
before call
decimalNumber
bitWeight

1
2

binaryNumber 11
bit
because binaryNumber > 0
bit = 11 % 10 = 1;
decimal = 1 + 1 * 22 = 5;
weight = 3;
binaryNumber = 11 / 10 = 1;
binToDec(1,decimal,weight);
binToDec(1,decimal,weight)

before call
decimalNumber
bitWeight

binaryNumber
5
3

1

bit

because binaryNumber > 0
bit = 1 % 10 = 1;
decimal = 5 + 1 * 23 = 13;
weight = 4;
binaryNumber = 1 / 10 = 0;
binToDec(0,decimal,weight);
binToDec(0,decimal,weight)

before call
decimalNumber
bitWeight

FIGURE 17-8

binaryNumber
13
4

0

bit

because binaryNumber is 0
the if statement fails and this
call exits

Execution of binToDec(1101, decimalNumber, bitWeight);

In Figure 17-8, each down arrow represents the successive function call
...
After the statement:

1010

| Chapter 17: Recursion

binToDec(1101, decimalNumber, bitWeight);

executes, the value of the variable decimalNumber is 13
...
S
...

//******************************************************
#include
#include
using namespace std;
void binToDec(int binaryNumber, int& decimal, int& weight);
int main()
{
int decimalNum;
int bitWeight;
int binaryNum;
decimalNum = 0;
bitWeight = 0;
cout << "Enter number in binary: ";
cin >> binaryNum;
cout << endl;
binToDec(binaryNum, decimalNum, bitWeight);
cout << "Binary " << binaryNum << " = " << decimalNum
<< " decimal" << endl;
}

return 0;

void binToDec(int binaryNumber, int& decimal, int& weight)
{
int bit;
if (binaryNumber > 0)
{
bit = binaryNumber % 10;
decimal = decimal
+ bit * static_cast(pow(2
...

Enter a number in binary: 11010110
Binary 11010110 = 214 decimal

PROGRAMMING EXAMPLE:

Converting a Number from Decimal to
Binary

The previous programming example discussed and designed a program to convert a
number from a binary representation to a decimal format—that is, from base 2 to base
10
...
First, we define some terms
...
We call the remainder of x after division by 2 the rightmost bit of x
...

We first illustrate the algorithm to convert an integer in base 10 to the equivalent
number in binary format, with the help of an example
...
First, we divide 35 by 2
...
Next, we
divide 17 by 2
...
Next, we divide 8 by 2
...
We continue this process until the quotient becomes 0
...
The rightmost bit of 17 cannot be printed until we have printed the rightmost bit
of 8, and so on
...

Thus, to convert an integer num in base 10 into the equivalent binary number, we
first convert the quotient num / 2 into an equivalent binary number and then append
the rightmost bit of num to the binary representation of num / 2
...


1
7

1012

| Chapter 17: Recursion

1
...

2
...

The following recursive function implements this algorithm:
void decToBin(int num, int base)
{
if (num > 0)
{
decToBin(num / base, base);
cout << num % base;
}
}

Figure 17-9 traces the execution of the following statement:
decToBin(13, 2);

in which num is 13 and base is 2
...
The first
output is produced by call 4, which prints 1; the second output is produced by call 3,
which prints 1; the third output is produced by call 2, which prints 0; and the fourth
output is produced by call 1, which prints 1
...

//******************************************************
// Author: D
...
Malik
//
// Program: Decimal to binary
// This program uses recursion to find the binary
// representation of a nonnegative integer
...

Enter a number in decimal: 57
Decimal 57 = 111001 binary

QUICK REVIEW
1
...

3
...

5
...

7
...

9
...

11
...

13
...

A recursive definition defines a problem in terms of smaller versions of itself
...

A recursive algorithm solves a problem by reducing it to smaller versions of
itself
...

The solution to the problem in a base case is obtained directly
...

Recursive algorithms are implemented using recursive functions
...

The general solution breaks the problem into smaller versions of itself
...

The base case stops the recursion
...

15
...


Logically, you can think of a recursive function as having an unlimited
number of copies of itself
...

• After completing a particular recursive call, control goes back to the
calling environment, which is the previous call
...
The execution in the previous call begins from the point immediately following the recursive call
...

A function that calls another function and eventually results in the original
function call is said to be indirectly recursive
...


Exercises

17
...


c
...


Understand the problem requirements
...
For example, for a list, the limiting
condition is the number of elements in the list
...

Identify the general cases and provide a solution to each general case in
terms of smaller versions of itself
...

Every recursive definition must have one or more base cases
...
Every recursive function must have one or more base cases
...
The general case stops the recursion
...
In the general case, the solution to the problem is obtained directly
...
A recursive function always returns a value
...


2
...

4
...

6
...


int mystery(int number)
{
if (number == 0)
return number;
else
return(number + mystery(number – 1));
}

//Line 1
//Line
//Line
//Line
//Line

2
3
4
5

Identify the base case
...
Identify the general case
...
What valid values can be passed as parameters to the function mystery?
d
...

e
...

f
...

Consider the following recursive function:
a
...


1015

To design a recursive function, you must do the following:
a
...


|

void funcRec(int u, char v)
{
if (u == 0)
cout << v;

//Line 1
//Line 2
//Line 3

1
7

1016

| Chapter 17: Recursion

}

else if (u == 1)
cout << static_cast
(static_cast(v) + 1);
else
funcRec(u - 1, v);

//Line 4
//Line 5
//Line 6
//Line 7

Answer the following questions:
a
...

c
...

Identify the general case
...


Consider the following recursive function:
void recFun(int x)
{
if (x > 10)
{
recFun(x / 10);
cout << x % 10 << endl;
}
else
cout << x << endl;
}

What is the output of the following statements?
a
...
recFun(7); c
...
recFun(-85);
10
...

11
...


recFun(3); c
...
exercise(0); b
...
exercise(10); d
...


Consider the following function:
int test(int x, int y)
{
if (x == y)
return x;
else if (x > y)
return (x + y);
else
return test(x + 1, y - 1);
}

What is the output of the following statements?
a
...

13
...

b
...


15
...


14
...
Also, suppose that low and high are two
integers such that 0 <= low < length, 0 <= high < length, and low < high
...
Write a recursive
definition that reverses the elements in intArray between low and high
...
Specify the base case and the recursive case
...


| Chapter 17: Recursion

Consider the following problem: How many ways can a committee of four
people be selected from a group of 10 people? There are many other similar
problems in which you are asked to find the number of ways to select a set
of items from a given set of items
...
Suppose
C(n, r) denotes the number of ways r different things can be chosen from a
set of n items
...
Moreover,
C(n, 0) = C(n, n) = 1
...

a
...


Write a recursive algorithm to determine C(n, r)
...

Using your recursive algorithm, determine C(5, 3) and C(9, 4)
...


Write a recursive function that takes as a parameter a nonnegative integer
and generates the following pattern of stars
...


Also, write a program that prompts the user to enter the number of lines in
the pattern and uses the recursive function to generate the pattern
...

Write a recursive function to generate a pattern of stars, such as the following:
*
**
***
****
****
***
**
*

Programming Exercises

3
...


6
...


8
...


10
...
For
example, specifying 4 as the number of lines generates the above pattern
...


|

Also, write a program that prompts the user to enter the number of lines in
the pattern and uses the recursive function to generate the pattern
...

Write a recursive function, vowels, that returns the number of vowels in a
string
...

Write a recursive function named sumSquares that returns the sum of the
squares of the numbers from 0 to num, in which num is a nonnegative int
variable
...
Also
write a program to test your function
...
Also, write a program to test your function
...
For
example, the string "madam" is a palindrome
...
Your program
must contain a value-returning recursive function that returns true if the
string is a palindrome and false otherwise
...

Write a program that uses a recursive function to print a string backward
...

Write a recursive function, reverseDigits, that takes an integer as a
parameter and returns the number with the digits reversed
...

Write a recursive function, power, that takes as parameters two integers x
and y such that x is nonzero and returns xy
...
If y ! 0:
8
if y ¼ 0
<1
powerðx; yÞ ¼ x
if y ¼ 1
:
x  powerðx; y À 1Þ if y > 1:

1
7

1020

| Chapter 17: Recursion

If y < 0:
powerðx; yÞ ¼

11
...

(Greatest Common Divisor) Given two integers x and y, the following
recursive definition determines the greatest common divisor of x and y,
written gcd(x,y)
...


12
...


14
...


16
...


18
...
Also, write a program
to test your function
...
Write a recursive function to
implement Ackermann’s function
...
What happens when you call the function with m ¼ 4 and n ¼ 3?
Write a recursive function to implement the recursive algorithm of Exercise
12 (reversing the elements of an array between two indices)
...

Write a recursive function to implement the recursive algorithm of Exercise
15 (multiplying two positive integers using repeated addition)
...

Write a recursive function to implement the recursive algorithm of Exercise
16 (determining the number of ways to select a set of things from a given set
of things)
...

(Recursive Sequential Search) The sequential search algorithm given in
Chapter 9 is nonrecursive
...

(Recursive Binary Search) The binary search algorithm given in Chapter 10
is nonrecursive
...

In the Programming Example, Converting a Number from Decimal to Binary,
given in this chapter, you learned how to convert a decimal number into the

Programming Exercises

equivalent binary number
...
In fact, in C++,
you can instruct the computer to store a number in octal or hexadecimal
...
The
digits in the hexadecimal number system are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B,
C, D, E, and F
...

The algorithm to convert a positive decimal number into an equivalent
number in octal (or hexadecimal) is the same as discussed for binary
numbers
...
Suppose ab represents the number a to the base b
...
Then:
75310 = 13618
75310 = 2F116

19
...
Suppose you want to convert a decimal
number n into an equivalent number in base b, in which b is between 2 and
36
...

Note that the digits in, say, base 20, are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C,
D, E, F, G, H, I, and J
...
Your program should
prompt the user to enter the number in decimal and in the desired base
...
Using Newton’s method, you
can also write an algorithm to find the square root of a nonnegative real
number within a given tolerance as follows: Suppose x is a nonnegative real
number, a is the approximate square root of x, and epsilon is the tolerance
...

a
...


If |a2 À x| epsilon, then a is the square root of x within the tolerance;
otherwise:
Replace a with (a2 + x) / (2a) and repeat Step a
in which |a2 À x| denotes the absolute value of a2 À x
...
Also, write a program to test your function
...


Learn about linked lists


...


Explore the insertion and deletion operations on linked lists


...


Learn how to construct a doubly linked list

1024

| Chapter 18: Linked Lists

You have already seen how data is organized and processed sequentially using an array
called a sequential list
...
You also found that if data is not sorted, then
searching for an item in the list can be very time consuming especially with large lists
...

However, in this case, insertion and deletion become time consuming especially with
large lists, because these operations require data movement
...
Thus,
there are limitations on when you organize data in an array
...
Chapter 14 showed how
memory (variables) can be dynamically allocated and deallocated using pointers
...
Recall that
when data is stored in an array, memory for the components of the array is contiguous—
that is, the blocks are allocated one after the other
...


Linked Lists
A linked list is a collection of components called nodes
...
Thus, every node in a linked list has two components:
one to store the relevant information (that is, data) and one to store the address, called the
link, of the next node in the list
...
Figure 18-1 is a pictorial representation of a node
...

The list in Figure 18-2 is an example of a linked list
...
The down arrow in the last node indicates that this link field is NULL
...
We thus have Figure 18-3
...
If no confusion arises, then
we will use the arrow notation whenever we draw the figure of a linked list
...
However, in computer memory,
the memory addresses are in binary
...
The data type of each node depends on the specific application—that
is, what kind of data is being processed
...
The data type of this pointer variable is the node type itself
...
(Suppose that the data type is int
...

Consider the linked list in Figure 18-4
...
The address of the first node is stored in the pointer head
...
For simplicity, we assume that info is of type int
...
Therefore,
the value of head is 2000, the value of the component link of the first node is 2800,
the value of the component link of the second node is 1500, and so on
...
The number at the top of each node is the
address of that node
...

Value
head
head->info

17

head->link

2800

head->link->info

Explanation

2000

92

Because head is 2000 and the info of
the node at location 2000 is 17
Because head->link is 2800 and the
info of the node at location 2800 is 92

Suppose that current is a pointer of the same type as the pointer head
...


head
2000

2800

2000
17

2800

info link

92

1500
1500

info link

63

3600
3600

info link

current 2000

FIGURE 18-5

Linked list after the statement current = head; executes

Clearly, in Figure 18-5:
current
current->info
current->link
current->link->info

Value
2000
17
2800
92

45

0

info link

Linked Lists

|

1027

Now consider the statement:
current = current->link;

This statement copies the value of current->link, which is 2800, into current
...

(When working with linked lists, we typically use these types of statements to advance a
pointer to the next node in the list
...


head
2000

2800

2000
17

2800

info link

92

1500
1500

info link

63

3600
3600

info link

45

0

info link

current 2800

FIGURE 18-6

List after the statement current = current->link; executes

In Figure 18-6:

current
current->info
current->link
current->link->info

Value
2800
92
1500
63

Finally, note that in Figure 18-6:

head->link->link
head->link->link->info
head->link->link->link
head->link->link->link->info
current->link->link
current->link->link->info
current->link->link->link
current->link->link->link->info

Value
1500
63
3600
45
3600
45
0 (that is, NULL)
Does not exist

From now on, when working with linked lists, we will use only the arrow notation
...


1
8

1028

| Chapter 18: Linked Lists

These operations require the list to be traversed
...

Suppose that the pointer head points to the first node in the list, and the link of the last
node is NULL
...
This problem occurs because
the links are in only one direction
...
If we move head to the second node, the first node
is lost (unless we save a pointer to this node)
...

Therefore, we always want head to point to the first node
...
Suppose that current is a pointer
of the same type as head
...
The following code
outputs the data stored in each node:
current = head;
while (current != NULL)
{
cout << current->info << " ";
current = current->link;
}

ITEM INSERTION AND DELETION
This section discusses how to insert an item into, and delete an item from, a linked list
...
(For simplicity, we assume that the info
type is int
...
)
struct nodeType
{
int info;
nodeType *link;
};

We will use the following variable declaration:
nodeType *head, *p, *q, *newNode;

Linked Lists

|

1029

INSERTION
Consider the linked list shown in Figure 18-7
...
Consider the following statements:
newNode = new nodeType; //create newNode
newNode->info = 50;
//store 50 in the new node
newNode->link = p->link;
p->link = newNode;

Table 18-1 shows the effect of these statements
...
Suppose that we reverse the sequence of the statements and execute the
statements in the following order:
p->link = newNode;
newNode->link = p->link;

Figure 18-8 shows the resulting list after these statements execute
...

Using two pointers, we can simplify the insertion code somewhat
...


head

45

65
p

34
q

newNode

FIGURE 18-9

76

50

List with pointers p and q

The following statements insert newNode between p and q
...
To illustrate this, suppose
that we execute the statements in the following order:
p->link = newNode;
newNode->link = q;

Table 18-2 shows the effect of these statements
...


head

45

65

34

76

p

FIGURE 18-10

Node to be deleted is with info 34

Suppose that the node with info 34 is to be deleted from the list
...

p->link = p->link->link;

Figure 18-11 shows the resulting list after the preceding statement executes
...

However, the memory is still occupied by this node, and this memory is inaccessible; that
is, this node is dangling
...
The

1
8

1032

| Chapter 18: Linked Lists

following statements delete the node from the list and deallocate the memory occupied
by this node
...

TABLE 18-3

Deleting a Node from a Linked List

Statement

Effect
head

45

q = p->link;

p->link = q->link;

65
p

head

34

45

head

34

65
p

delete q;

76

q

45

76

q

65

76

p

Building a Linked List
Now that we know how to insert a node in a linked list, let us see how to build a linked
list
...
If the data we read is unsorted, the linked
list will be unsorted
...
In the
forward manner, a new node is always inserted at the end of the linked list
...
We will
consider both cases
...
Let us
assume that we process the following data:
2 15 8 24 34

We need three pointers to build the list: one to point to the first node in the list, which
cannot be moved; one to point to the last node in the list; and one to create the new
node
...
Initially, the list is empty, so both
first and last are NULL
...

Next, consider the following statements:
1
2

3
4
5

5a
5b
6
6a
6b

cin >> num;
//read and store a number in num
newNode = new nodeType; //allocate memory of type nodeType
//and store the address of the
//allocated memory in newNode
newNode->info = num;
//copy the value of num into the
//info field of newNode
newNode->link = NULL;
//initialize the link field of
//newNode to NULL
if (first == NULL)
//if first is NULL, the list is empty;
//make first and last point to newNode
{
first = newNode;
last = newNode;
}
else
//list is not empty
{
last->link = newNode; //insert newNode at the end of the list
last = newNode;
//set last so that it points to the
//actual last node in the list
}

Let us now execute these statements
...

Therefore, we have the list as shown in Figure 18-12
...
Statement 2 creates a node and stores the address of
that node in newNode
...


newNode

FIGURE 18-13

newNode with info 2

2

1
8

1034

| Chapter 18: Linked Lists

Because first is NULL, we execute statements 5a and 5b
...


first
last

2

newNode

FIGURE 18-14

List after inserting newNode in it

We now repeat statements 1 through 6b
...
Statement
2 creates a node and stores the address of this node in newNode
...


first
last

2
newNode

FIGURE 18-15

15

List and newNode with info 15

Because first is not NULL, we execute statements 6a and 6b
...


first

2

15
last

FIGURE 18-16

newNode

List after inserting newNode at the end

We now repeat statements 1 through 6b three more times
...


Linked Lists

first

2

15

8

24

1035

34
last

FIGURE 18-17

|

newNode

List after inserting 8, 24, and 34

To build the linked list, we can put the previous statements in a loop and execute the
loop until certain conditions are met
...

Suppose that we read a list of integers ending with -999
...

nodeType* buildListForward()
{
nodeType *first, *newNode, *last;
int num;
cout << "Enter a list of integers ending with -999
...
For the previously given
data—2, 15, 8, 24, and 34—the linked list is as shown in Figure 18-18
...
Also, after inserting the new
node at the beginning, the new node becomes the first node in the list
...
We
see, then, that we need only two pointers to build the linked list: one to point to the list
and one to create the new node
...
In pseudocode, the algorithm is:
1
...

2
...

b
...

d
...

Store the item in newNode
...

Update the value of the pointer first
...

nodeType* buildListBackward()
{
nodeType *first, *newNode;
int num;
cout << "Enter a list of integers ending with -999
...
Because a linked list is a very important data structure, rather than
discuss specific lists such as a list of integers or a list of strings, this section discusses linked
lists as an abstract data type (ADT)
...
The
programming example at the end of this chapter also uses this generic definition of
linked lists
...

2
...

4
...

6
...

8
...

10
...


Initialize the list
...

Print the list
...

Destroy the list
...

Retrieve the info contained in the last node
...

Insert an item in the list
...

Make a copy of the linked list
...

The algorithms to implement the operations search, insert, and remove slightly differ for
sorted and unsorted lists
...
Using the principle
of inheritance, we, in fact, will derive two classes—unorderedLinkedList and
orderedLinkedList—from the class linkedListType
...
On the other hand, objects of the class
orderedLinkedList would arrange elements according to some comparison criteria,
usually less than or equal to
...
Moreover, after

1
8

1038

| Chapter 18: Linked Lists

inserting an element into or removing an element from an ordered list, the resulting list
will be ordered
...
Furthermore, you can build such a list in either a forward manner or a
backward manner
...
To
accommodate both operations, we will write two functions: insertFirst to insert
the new item at the beginning of the list and insertLast to insert the new item at
the end of the list
...


Structure of Linked List Nodes
Recall that each node of a linked list must store the data as well as the address for the next
node in the list (except the last node of the list)
...
To simplify operations such as insert and delete, we define the class to implement the node of a linked list as a struct
...
Programming
Exercise 9, at the end of this chapter, asks you to redefine the class to implement the nodes
of a linked list so that the member variables of the class nodeType are private
...
The pointer first points
to the first node in the list, and last points to the last node in the list
...
Therefore, the class linkedListType has three
member variables, as follows:
protected:
int count;

//variable to store the number of
//elements in the list
nodeType *first; //pointer to the first node
//of the list
nodeType *last; //pointer to the last node
//of the list

Linked List as an ADT

|

1039

Linked List Iterators
One of the basic operations performed on a list is to process each node of the list
...
Moreover, a specific application
requires each node to be processed in a very specific way
...
So what is an iterator? An iterator is an object
that produces each element of a container, such as a linked list, one element at a time
...
The increment operator advances the iterator to the next node
in the list, and the dereferencing operator returns the info of the current node
...
So we need to define a class, which we will call
linkedListIterator, to create iterators to objects of the class linkedListType
...

template
class linkedListIterator
{
public:
linkedListIterator();
//Default constructor
...

//Postcondition: current = ptr;
Type operator*();
//Function to overload the dereferencing operator *
...

linkedListIterator operator++();
//Overload the pre-increment operator
...

bool operator==(const linkedListIterator& right) const;
//Overload the equality operator
...

bool operator!=(const linkedListIterator& right) const;
//Overload the not equal to operator
...

private:
nodeType *current; //pointer to point to the current
//node in the linked list
};

1
8

1040

| Chapter 18: Linked Lists

Figure 18-19 shows the UML class diagram of the class linkedListIterator
...
current);
}

Linked List as an ADT

|

1041

template
bool linkedListIterator::operator!=
(const linkedListIterator& right) const
{
return (current != right
...

The following abstract class defines the basic properties of a linked list as an ADT
...

void initializeList();
//Initialize the list to an empty state
...

//Postcondition: Returns true if the list is empty,
//
otherwise it returns false
...

//Postcondition: none
int length() const;
//Function to return the number of nodes in the list
...

void destroyList();
//Function to delete all the nodes from the list
...

//Precondition: The list must exist and must not be
//
empty
...

Type back() const;
//Function to return the last element of the list
...

//Postcondition: If the list is empty, the program
//
terminates; otherwise, the last
//
element of the list is returned
...

//Postcondition: Returns true if searchItem is in the
//
list, otherwise the value false is
//
returned
...

//Postcondition: first points to the new list, newItem is
//
inserted at the beginning of the list,
//
last points to the last node in the list,
//
and count is incremented by 1
...

//Postcondition: first points to the new list, newItem
//
is inserted at the end of the list,
//
last points to the last node in the list,
//
and count is incremented by 1
...

//Postcondition: If found, the node containing
//
deleteItem is deleted from the list
...

linkedListIterator begin();
//Function to return an iterator at the begining of the
//linked list
...

linkedListIterator end();
//Function to return an iterator one element past the
//last element of the linked list
...

linkedListType();
//default constructor
//Initializes the list to an empty state
...

//Postcondition: The list object is destroyed
...

//Postcondition: A copy of otherList is created and
//
assigned to this list
...


linkedListType
#count: int
#*first: nodeType
#*last: nodeType
+operator=(const linkedListType&):
const linkedListType&
+initializeList(): void
+isEmptyList() const: bool
+print() const: void
+length() const: int
+destroyList(): void
+front() const: Type
+back() const: Type
+search(const Type&) const = 0: bool
+insertFirst(const Type&) = 0: void
+insertLast(const Type&) = 0: void
+deleteNode(const Type&) = 0: void
+begin(): linkedListIterator
+end(): linkedListIterator
+linkedListType()
+linkedListType(const linkedListType&)
+~linkedListType()
-copyList(const linkedListType&): void

FIGURE 18-20

UML class diagram of the class linkedListType

Note that typically, in the UML diagram, the name of an abstract class and abstract
function is shown in italics
...
Because each of the classes unorderedLinkedList

1
8

1044

| Chapter 18: Linked Lists

and orderedLinkedList will provide separate definitions of the functions search,
insertFirst, insertLast, and deleteNode and because these functions would access
the instance variable, to provide direct access to the instance variables, the instance variables
are declared as protected
...
For classes that include pointer data members, the assignment
operator must be explicitly overloaded (see Chapters 14 and 15)
...

Notice that the definition of the class linkedListType contains the member function
copyList, which is declared as a private member
...

Next, we write the definitions of the nonabstract functions of the class LinkedListClass
...
Therefore, the definition of the function isEmptyList
to implement this operation is as follows:
template
bool linkedListType::isEmptyList() const
{
return (first == NULL);
}

DEFAULT CONSTRUCTOR
The default constructor, linkedListType, is quite straightforward
...
Recall that when an object of the linkedListType type is
declared and no value is passed, the default constructor is executed automatically
...
We traverse
the list starting from the first node and deallocate the memory by calling the operator
delete
...
Once the entire list is
destroyed, we must set the pointers first and last to NULL and count to 0
...
Note that the
default constructor or the copy constructor has already initialized the list when the list
object was declared
...
This task can be accomplished by using the
destroyList operation, which also resets the pointers first and last to NULL and
sets count to 0
...
To do so, we must
traverse the list, starting at the first node
...
(If we use first to
traverse the list, the entire list will be lost
...
Therefore, this function returns the value of this variable:

1
8

1046

| Chapter 18: Linked Lists

template
int linkedListType::length() const
{
return count;
}

Retrieve the Data of the First Node
The function front returns the info contained in the first node, and its definition is
straightforward:
template
Type linkedListType::front() const
{
assert(first != NULL);
return first->info; //return the info of the first node
}//end front

Notice that if the list is empty, the assert statement terminates the program
...


Retrieve the Data of the Last Node
The function back returns the info contained in the last node, and its definition is
straightforward:
template
Type linkedListType::back() const
{
assert(last != NULL);
return last->info; //return the info of the last node
}//end back

Notice that if the list is empty, the assert statement terminates the program
...


Begin and End
The function begin returns an iterator to the first node in the linked list, and the
function end returns an iterator to one past the last node in the linked list
...
Therefore, we traverse
the list to be copied, starting at the first node
...
Create a node, and call it newNode
...
Copy the info of the node (in the original list) into newNode
...
Insert newNode at the end of the list being created
...
first == NULL) //otherList is empty
{
first = NULL;
last = NULL;
count = 0;
}
else
{
current = otherList
...
count;
//copy the first node
first = new nodeType; //create the node
first->info = current->info; //copy the info
first->link = NULL;
//set the link field of
//the node to NULL
last = first;
//make last point to the
//first node
current = current->link;
//make current point to
//the next node

1
8

1048

| Chapter 18: Linked Lists

//copy the remaining list
while (current != NULL)
{
newNode = new nodeType; //create a node
newNode->info = current->info; //copy the info
newNode->link = NULL;
//set the link of
//newNode to NULL
last->link = newNode; //attach newNode after last
last = newNode;
//make last point to
//the actual last node
current = current->link;
//make current point
//to the next node
}//end while
}//end else
}//end copyList

Destructor
The destructor deallocates the memory occupied by the nodes of a list when the class object
goes out of scope
...
We must traverse the
list, starting at the first node, and delete each node in the list
...
Therefore, the definition of the destructor is:
template
linkedListType:: ~linkedListType() //destructor
{
destroyList();
}

Copy Constructor
Because the class linkedListType contains pointer data members, the definition of
this class contains the copy constructor
...
The copy constructor also executes when an object is declared and initialized using
another object
...
)
The copy constructor makes an identical copy of the linked list
...
Because the function copyList checks whether the
original is empty by checking the value of first, we must first initialize the pointer
first to NULL before calling the function copyList
...
We give its
definition for the sake of completeness
...

The following class defines an unordered linked list as an ADT
...

//Postcondition: Returns true if searchItem is in the
//
list, otherwise the value false is
//
returned
...

//Postcondition: first points to the new list, newItem is
//
inserted at the beginning of the list,
//
last points to the last node in the
//
list, and count is incremented by 1
...

//Postcondition: first points to the new list, newItem
//
is inserted at the end of the list,
//
last points to the last node in the
//
list, and count is incremented by 1
...

//Postcondition: If found, the node containing

1
8

1050

| Chapter 18: Linked Lists

//
//
//
//

};

deleteItem is deleted from the list
...


Figure 18-21 shows a UML class diagram of the class unorderedLinkedList and the
inheritance hierarchy
...


Search the List
The member function search searches the list for a given item
...
Because a linked list is not a random-access
data structure, we must sequentially search the list, starting from the first node
...
Compare the search item with the current node in the list
...

2
...

template
bool unorderedLinkedList::
search(const Type& searchItem) const
{
nodeType *current; //pointer to traverse the list
bool found = false;
current = first; //set current to point to the first
//node in the list

Unordered Linked Lists

|

1051

while (current != NULL && !found)
//search the list
if (current->info == searchItem) //searchItem is found
found = true;
else
current = current->link; //make current point to
//the next node
return found;
}//end search
The function search can also be written as:

template
bool unorderedLinkedList::search(const Type& searchItem)
const
{
nodeType *current; //pointer to traverse the list
current = first; //set current to point to the first
//node in the list
while (current != NULL)
//search the list
if (current->info == searchItem) //searchItem is found
return true;
else
current = current->link; //make current point to
//the next node
return false; //searchItem is not in the list, return false
}//end search

Insert the First Node
The function insertFirst inserts the new item at the beginning of the list—that is,
before the node pointed to by first
...

2
...

4
...

Store the new item in the new node
...

Increment count by 1
...
Here, we insert the new node after last
...
We need to consider several
cases:

Case 1: The list is empty
...
In this case, we need to adjust
the pointer first
...
If the node to be
deleted is the last node, then we must adjust the pointer last
...

If list is empty, we can simply print a message indicating that the list is empty
...
After deleting the node, count is decremented by 1
...

}
}

Case 1: The list is empty
...

Case 2: The list is not empty
...

This case has two scenarios: list has only one node, and list has more than one node
...


list
first
last

37

count 1

FIGURE 18-22

list with one node

Suppose that we want to delete 37
...
Therefore,
after deletion, both first and last are set to NULL, and count is set to 0
...


1
8

1054

| Chapter 18: Linked Lists

list
28

first

17

37

24

54

last
count 5

FIGURE 18-23

list with more than one node

Suppose that the node to be deleted is 28
...
Therefore, after deleting this node, the value of the pointer first
changes; that is, after deletion, first contains the address of the node with info 17, and
count is decremented by 1
...


list
17

first

37

24

54

last
count 4

FIGURE 18-24

list after deleting node with info 28

Case 3: The node to be deleted is not the first node but is somewhere in the list
...
Let us illustrate both cases
...

Consider the list shown in Figure 18-25
...
After deleting this node, the resulting list is as
shown in Figure 18-26
...
The link field of the previous node—that is, 17—changes
...
)

list
first

28

17

24

54

last
count 4

FIGURE 18-26

1
8

list after deleting 37

Case 3b: The node to be deleted is the last node
...
Suppose that the node to be deleted is 54
...
Therefore, the
deletion of 54 requires us to change the value of the pointer last
...
Also, count is decremented
by 1
...


list
first

28

17

37

24

last
count 4

FIGURE 18-28

list after deleting 54

Case 4: The node to be deleted is not in the list
...
We simply output an error message, indicating that the item to be
deleted is not in the list
...
Because a linked list is not a random-access data structure, we must sequentially search the list
...
We sequentially search the list, starting at the second node
...
Thus, we need a pointer to the previous node
...
If the node to
be deleted is the last node, we must adjust the pointer last
...
"
<< endl;
else
{
if (first->info == deleteItem) //Case 2
{
current = first;
first = first->link;
count--;
if (first == NULL)
last = NULL;

//the list has only one node

delete current;
}
else //search the list for the node with the given info
{
found = false;
trailCurrent = first; //set trailCurrent to point
//to the first node
current = first->link; //set current to point to
//the second node
while (current != NULL && !found)
{
if (current->info != deleteItem)
{
trailCurrent = current;
current = current-> link;
}
else
found = true;
}//end while

Unordered Linked Lists

|

1057

if (found) //Case 3; if found, delete the node
{
trailCurrent->link = current->link;
count--;
if (last == current)

//node to be deleted
//was the last node
last = trailCurrent; //update the value
//of last
delete current; //delete the node from the list

}
else

cout << "The item to be deleted is not in "
<< "the list
...
(We assume that the
definition of the class linkedListType and the definitions of the functions to implement the operations are in the header file linkedlist
...
)
#ifndef H_UnorderedLinkedList
#define H_UnorderedLinkedList
#include "linkedList
...

//Postcondition: Returns true if searchItem is in the
//
list, otherwise the value false is
//
returned
...

//Postcondition: first points to the new list, newItem is
//
inserted at the beginning of the list,
//
last points to the last node in the
//
list, and count is incremented by 1
...

//Postcondition: first points to the new list, newItem
//
is inserted at the end of the list,
//
last points to the last node in the
//
list, and count is incremented by 1
...

//Postcondition: If found, the node containing
//
deleteItem is deleted from the list
...


//Place the definitions of the functions search,
//insertFirst, insertLast, and deleteNode here
...


...

#endif
The Web site accompanying this book contains several programs illustrating how to use
the class unorderedLinkedList
...
This section deals
with ordered linked lists
...
For
simplicity, we assume that elements of an ordered linked list are arranged in ascending order
...


The following class defines an ordered linked list as an ADT:
template
class orderedLinkedList: public linkedListType
{
public:
bool search(const Type& searchItem) const;
//Function to determine whether searchItem is in the list
...

void insert(const Type& newItem);
//Function to insert newItem in the list
...

void insertFirst(const Type& newItem);
//Function to insert newItem at the beginning of the list
...


void insertLast(const Type& newItem);
//Function to insert newItem at the end of the list
...

void deleteNode(const Type& deleteItem);
//Function to delete deleteItem from the list
...

//
If deleteItem is not in the list, an
//
appropriate message is printed
...


orderedLinkedList
linkedListType
+search(const Type&) const: bool
+insert(const Type&): void
+insertFirst(const Type&): void
+insertLast(const Type&): void
+deleteNode(const Type&): void

FIGURE 18-29

orderedLinkedList

UML class diagram of the class orderedLinkedList and the inheritance hierarchy

Next, we give the definitions of the member functions of the class orderedLinkedList
...
The algorithm to implement the search operation is similar to the search algorithm for general lists discussed earlier
...
As before, we start the
search at the first node in the list
...


1
8

1060

| Chapter 18: Linked Lists

The following steps describe this algorithm:
1
...
If the info of
the current node is greater than or equal to the search item, stop the
search; otherwise, make the next node the current node
...
Repeat Step 1 until either an item in the list that is greater than or equal
to the search item is found or no more data is left in the list to compare
with the search item
...
Thus, after the loop executes, we must check whether the search item is equal
to the item in the list
...
To find the place for the new item,
as before, we search the list
...
The pointer current points to the node whose info is being compared
with the item to be inserted, and trailCurrent points to the node just before current
...
The following cases
arise:
Case 1: The list is initially empty
...

Case 2: The new item is smaller than the smallest item in the list
...
In this case, we need to adjust the list’s head pointer—
that is, first
...

Case 3: The item is to be inserted somewhere in the list
...
In this case, the new item
is inserted at the end of the list
...
Also, count is incremented by 1
...
In this case,
the new item is inserted between trailCurrent and current
...

The following statements can accomplish both Cases 3a and 3b
...


1
8

trailCurrent->link = newNode;
newNode->link = current;

Let us next illustrate these cases
...

Consider the list shown in Figure 18-30(a)
...
To accomplish this task, we create a node, copy
27 into the node, set the link of the node to NULL, and make first point to the node
...
Notice that, after inserting 27, the values of both first and
count change
...
Consider the list shown in Figure 18-31
...
After inserting 10 in the list, the node with info 10
becomes the first node of list
...
Also,
count is incremented by 1
...


list
first

10

17

27

38

54

last
count 5

FIGURE 18-32

list after inserting 10

Case 3: The list is not empty, and the item to be inserted is larger than the first item in
the list
...

Case 3a: The item to be inserted is larger than the largest item in the list; that is, it goes at
the end of the list
...


list
first

17

27

38

54

last
count 4

FIGURE 18-33

list before inserting 65

Suppose that we want to insert 65 in the list
...


list
first

17

27

last
count 5

FIGURE 18-34

list after inserting 65

38

54

65

Ordered Linked Lists

|

1063

Case 3b: The item to be inserted goes somewhere in the middle of the list
...


list
first

17

38

45

54

last
count 4

FIGURE 18-35

1
8

list before inserting 27

Suppose that we want to insert 27 in this list
...
After inserting 27, the
resulting list is as shown in Figure 18-36
...
It also follows that we should traverse the list with two pointers—
say, current and trailCurrent
...
The pointer
trailCurrent points to the node just before current
...
The
item is inserted after trailCurrent
...

Essentially, the function insert is as follows:
template
void orderedLinkedList::insert(const Type& newItem)
{
nodeType *current; //pointer to traverse the list
nodeType *trailCurrent; //pointer just before current
nodeType *newNode; //pointer to create a node

1064

| Chapter 18: Linked Lists

bool found;
newNode = new nodeType; //create the node
newNode->info = newItem;
//store newItem in the node
newNode->link = NULL;
//set the link field of the node
//to NULL
if (first == NULL) //Case 1
{
first = newNode;
last = newNode;
count++;
}
else
{
current = first;
found = false;
while (current != NULL && !found) //search the list
if (current->info >= newItem)
found = true;
else
{
trailCurrent = current;
current = current->link;
}
if (current == first)
//Case 2
{
newNode->link = first;
first = newNode;
count++;
}
else
//Case 3
{
trailCurrent->link = newNode;
newNode->link = current;
if (current == NULL)
last = newNode;
count++;
}
}//end else
}//end insert

Insert First and Insert Last
The function insertFirst inserts the new item at the beginning of the list
...
Similarly, the function insertLast must insert the new item at the proper place
...

The definitions of these functions are:
template
void orderedLinkedList::insertFirst(const Type& newItem)
{
insert(newItem);
}//end insertFirst
template
void orderedLinkedList::insertLast(const Type& newItem)
{
insert(newItem);
}//end insertLast

Note that in reality, the functions insertFirst and insertLast do not apply to
ordered linked lists because the new item must be inserted at the proper place in the list
...


Delete a Node
To delete a given item from an ordered linked list, first we search the list to see whether
the item to be deleted is in the list
...
Here, because the list is sorted, we can
somewhat improve the algorithm for ordered linked lists
...
Similar to the operation insertNode, several cases arise:
Case 1: The list is initially empty
...
We cannot delete from an empty list
...
We must adjust
the head pointer of the list—that is, first
...
In this case, current points to
the node containing the item to be deleted, and trailCurrent points to the
node just before the node pointed to by current
...

After deleting a node, count is decremented by 1
...
" << endl;
else
{
current = first;
found = false;
while (current != NULL && !found) //search the list
if (current->info >= deleteItem)
found = true;
else
{
trailCurrent = current;
current = current->link;
}
if (current == NULL)
//Case 4
cout << "The item to be deleted is not
<< "list
...
" << endl;

}
}//end deleteNode

Header File of the Ordered Linked List
For the sake of completeness, we will show how to create the header file that defines the
class orderedListType, as well as the operations on such lists
...
h
...
h"
using namespace std;
template
class orderedLinkedList: public linkedListType
{
public:
bool search(const Type& searchItem) const;
//Function to determine whether searchItem is in the list
...

void insert(const Type& newItem);
//Function to insert newItem in the list
...

void insertFirst(const Type& newItem);
//Function to insert newItem at the beginning of the list
...

void insertLast(const Type& newItem);
//Function to insert newItem at the end of the list
...


};

void deleteNode(const Type& deleteItem);
//Function to delete deleteItem from the list
...

//
If deleteItem is not in the list, an
//
appropriate message is printed
...


...


...

//Program to test the various operations on an ordered linked list
#include
#include "orderedLinkedList
...
" << endl;
cin >> num;
while (num != -999)
{
list1
...
print();
cout << endl;

//Line 9
//Line 10
//Line 11

list2 = list1; //test the assignment operator Line 12
cout << "Line 13: list2: ";
list2
...
deleteNode(num);

//Line 19

cout << "Line 20: After deleting "
<< num << ", list2: " << endl;
list2
...

Line 3: Enter numbers ending with -999
...
The details are left as an exercise for you
...
Programming Exercise 8 at
the end of this chapter asks you to revise the definition of the function insert so
that before inserting the item, it checks whether it is already in the list
...
In
other words, duplicates are not allowed
...
Certain
applications, however, might require the data to be printed in descending order, which
means that we must print the list backward
...

Given a pointer to a list, this function prints the elements of the list in reverse order
...


first

FIGURE 18-37

5

10

15

20

Linked list

For the list in Figure 18-37, the output should be in the following form:
20 15 10 5

Because the links are in only one direction, we cannot traverse the list backward starting
from the last node
...


1
8

1070

| Chapter 18: Linked Lists

Let us think in terms of recursion
...
Similarly, we
cannot print the info of the second node until we have printed the tail of the second
node, and so on
...
Eventually, the size of the list will be reduced to zero, in which case the recursion
will stop
...
(Suppose that current is a
pointer to a linked list
...
The list is printed only if the pointer to
the list is not NULL
...
Because eventually the tail of the list will be empty, the if statement in
the next call will fail, and the recursion will stop
...

Recall that the function exits only after the last statement executes
...
)
Let us write the previous function in C++ and then apply it to a list
...

Let us trace the execution of this statement, which is a function call, for the list shown in
Figure 18-37
...
See Figure 18-38
...
Its definition is:
template
void linkedListType::printListReverse() const
{
reversePrint(first);
cout << endl;
}

1
8

1072

| Chapter 18: Linked Lists

Doubly Linked Lists
A doubly linked list is a linked list in which every node has a next pointer and a back
pointer
...


first

last

FIGURE 18-39

Doubly linked list

A doubly linked list can be traversed in either direction
...

As before, the typical operations on a doubly linked list are:
1
...

3
...

5
...

7
...

9
...

11
...

Destroy the list
...

Search the list for a given item
...

Retrieve the last element of the list
...

Delete an item from the list
...

Print the list
...


Next, we describe these operations for an ordered doubly linked list
...

//Definition of the node
template
struct nodeType
{
Type info;
nodeType *next;
nodeType *back;
};

Doubly Linked Lists

|

1073

template
class doublyLinkedList
{
public:
const doublyLinkedList& operator=
(const doublyLinkedList &);
//Overload the assignment operator
...

//Postcondition: first = NULL; last = NULL; count = 0;
bool isEmptyList() const;
//Function to determine whether the list is empty
...

void destroy();
//Function to delete all the nodes from the list
...

void reversePrint() const;
//Function to output the info contained in each node
//in reverse order
...

//Postcondition: The value of count is returned
...

//Precondition: The list must exist and must not be empty
...

Type back() const;
//Function to return the last element of the list
...

//Postcondition: If the list is empty, the program
//
terminates; otherwise, the last
//
element of the list is returned
...

//Postcondition: Returns true if searchItem is found in
//
the list, otherwise returns false
...

//Precondition: If the list is nonempty, it must be in
//
order
...

void deleteNode(const Type& deleteItem);
//Function to delete deleteItem from the list
...

doublyLinkedList();
//default constructor
//Initializes the list to an empty state
...

protected:
int count;
nodeType *first; //pointer to the first node
nodeType *last; //pointer to the last node
private:
void copyList(const doublyLinkedList& otherList);
//Function to make a copy of otherList
...

};

We leave the UML class diagram of the class doublyLinkedList as an exercise for
you
...
Here, because every node has two pointers, back and next, some of the
operations require the adjustment of two pointers in each node
...
Let us call this pointer current
...
We give the definition of each function here, with four exceptions
...
(See Programming Exercise 11 at the end
of this chapter
...


Default Constructor
The default constructor initializes the doubly linked list to an empty state
...

template
doublyLinkedList::doublyLinkedList()
{
first= NULL;
last = NULL;
count = 0;
}

isEmptyList
This operation returns true if the list is empty; otherwise, it returns false
...

template
bool doublyLinkedList::isEmptyList() const
{
return (first == NULL);
}

Destroy the List
This operation deletes all of the nodes in the list, leaving the list in an empty state
...
Furthermore, count
is set to 0
...
This task can be done
by using the operation destroy
...
Therefore, this function returns the value of this variable
...
We traverse the list,
starting from the first node
...
We traverse the
list in reverse order, starting from the last node
...
The search algorithm is exactly the same as the search algorithm for an
ordered linked list
...
If the list is empty, both functions terminate the program
...
As before, we find the place
where the new item is supposed to be inserted, create the node, store the new item, and
adjust the link fields of the new node and other particular nodes in the list
...
Cases 3 and
4 are similar
...
Next, we show
Case 4
...


first

8

15

24

40

last
count 4

FIGURE 18-40

Doubly linked list before inserting 20

Suppose that 20 is to be inserted in the list
...


Doubly Linked Lists

first

8

15

24

|

1079

40

20

last
count 5

FIGURE 18-41

Doubly linked list after inserting 20

From Figure 18-41, it follows that the next pointer of node 15, the back pointer of
node 24, and both the next and back pointers of node 20 need to be adjusted
...
As before, we
first search the list to see whether the item to be deleted is in the list
...
Similar to the insertNode operation, this operation
(if the item to be deleted is in the list) requires the adjustment of two pointers in certain
nodes
...

Case 2: The item to be deleted is in the first node of the list, which would require us to
change the value of the pointer first
...

Case 4: The item to be deleted is not in the list
...
Let us demonstrate Case 3
...


Doubly Linked Lists

first

5

17

44

|

1081

52

last
count 4

FIGURE 18-42

Doubly linked list before deleting 17

Suppose that the item to be deleted is 17
...


first

5

17

52

44

current
trailCurrent
last
count 4

FIGURE 18-43

List after adjusting the links of the nodes before and after the node with info 17

Next, we delete the node pointed to by current (see Figure 18-44)
...
" << endl;
else if (first->info == deleteItem) //node to be deleted is
//the first node
{
current = first;
first = first->next;
if (first != NULL)
first->back = NULL;
else
last = NULL;
count--;
delete current;
}
else
{
found = false;
current = first;
while (current != NULL && !found) //search the list
if (current->info >= deleteItem)
found = true;
else
current = current->next;
if (current == NULL)
cout << "The item to be deleted is not in "
<< "the list
...
"
<< endl;
}//end else
}//end deleteNode

Circular Linked Lists
A linked list in which the last node points to the first node is called a circular linked list
...


first
(a) Empty circular list

first
(b) Circular linked list with one node

first
(c) Circular linked list with more than one node

FIGURE 18-45

Circular linked lists

In a circular linked list with more than one node, as in Figure 18-45(c), it is convenient to
make the pointer first point to the last node of the list
...
For example, first points to the last
node, and first->link points to the first node
...

2
...

4
...

6
...

8
...


Initialize the list (to an empty state)
...

Destroy the list
...

Find the length of the list
...

Insert an item in the list
...

Copy the list
...
(See Programming Exercise 13 at the end of this chapter
...
A new video store in your neighborhood is about to open
...
The
store managers want someone to write a program for their system so that the video
store can function
...

2
...

4
...

6
...

8
...

Return, or check in, a video
...

Show the details of a particular video
...

Check whether a particular video is in the store
...

Print a list of all of the videos rented by each customer
...
This example further illustrates the objectoriented design methodology and, in particular, inheritance and overloading
...
We will describe these two components in detail
...
In Part 1, we design, implement, and test
the video component
...
That is, after
completing Parts 1 and 2, we can perform all of the operations listed previously
...
The common things

associated with a video are:





Name of the movie
Names of the stars
Name of the producer
Name of the director

Programming Example: Video Store




|

1085

Name of the production company
Number of copies in the store

From this list, we see that some of the operations to be performed on a video object are:
1
...

2
...

3
...

4
...
In other words, if the number of
copies is greater than zero, decrement the number of copies by one
...
Check in (that is, return) the video
...

6
...

The deletion of a video from the video list requires that the list be searched for the
video to be deleted
...
For simplicity, we assume that two videos are the
same if they have the same title
...

//************************************************************
// Author: D
...
Malik
//
// class videoType
// This class specifies the members to implement a video
...

//The member variables are set according to the
//parameters
...

//Postcondition: The value of copiesInStock is returned
...

//Postcondition: The number of copies in stock is
//
decremented by one
...

//Postcondition: The number of copies in stock is
//
incremented by one
...

void printInfo() const;
//Function to print the details of a video
...

bool checkTitle(string title);
//Function to check whether the title is the same as the
//title of the video
...

void updateInStock(int num);
//Function to increment the number of copies in stock by
//adding the value of the parameter num
...

//Postcondition: copiesInStock = num;
string getTitle() const;
//Function to return the title of the video
...

videoType(string title = "", string star1 = "",
string star2 = "", string producer = "",

Programming Example: Video Store

|

1087

string director = "", string productionCo = "",
int setInStock = 0);
//constructor
//The member variables are set according to the
//incoming parameters
...

//Postcondition: videoTitle = title; movieStar1 = star1;
//
movieStar2 = star2;
//
movieProducer = producer;
//
movieDirector = director;
//
movieProductionCo = productionCo;
//
copiesInStock = setInStock;
//Overload the relational operators
...

For easy output, we will overload the output stream insertion operator, <<, for the
class videoType
...
The
definitions of these functions, as given below, are quite straightforward and easy to
follow
...
videoTitle);
}
bool videoType::operator!=(const videoType& other) const
{
return (videoTitle != other
...
videoTitle << endl;
osObject << "Stars: " << video
...
movieStar2 << endl;
osObject << "Producer: " << video
...
movieDirector << endl;
osObject << "Production Company: "
<< video
...
copiesInStock
<< endl;
osObject << "_____________________________________"
<< endl;
}

return osObject;

Video List This program requires us to maintain a list of all of the videos in the store
...
In general, we would not know how
many videos are in the store, and adding or deleting a video from the store would
change the number of videos in the store
...


1
8

1090

| Chapter 18: Linked Lists

first

video
info

video
info


...
We also defined the basic operations such as insertion
and deletion of a video in the list
...
These operations are not available in the class
unorderedLinkedList
...

The definition of the class videoListType is:
//*************************************************************
// Author: D
...
Malik
//
// class videoListType
// This class specifies the members to implement a list of
// videos
...
h"
#include "videoType
...

//Postcondition: Returns true if the title is found,
//
and false otherwise
...

//Postcondition: Returns true if at least one copy of the
//
video specified by title is in the store,
//
and false otherwise
...

//Postcondition: copiesInStock is decremented by one
...

//Postcondition: copiesInStock is incremented by one
...

//Postcondition: Returns true if the video’s title is
//
the same as title, and false otherwise
...
The
//parameter title specifies the name of the video for
//which the number of copies is to be updated
...

//The parameter title specifies the name of the video
//for which the number of copies is to be reset, and the
//parameter num specifies the number of copies
...

private:
void searchVideoList(string title, bool& found,
nodeType* ¤t) const;
//This function searches the video list for a
//particular video, specified by the parameter title
...
The parameter current points
//
to the node containing the video
...
Furthermore,
unorderedLinkedList is a class template, and we have passed the class
videoType as a parameter to this class
...
Because we are now dealing with a very specific data type,

class videoListType is no longer required to be a template
...
Through
member functions of the class videoType, certain members—such as
videoTitle and copiesInStock of an object of type videoType—can now be

accessed
...


The primary operations on the video list are to check in a video and to check out a
video
...
Other operations, such
as determining whether a particular video is in the store, updating the number of
copies of a video, and so on, also require the list to be searched
...
If the video is found, it sets a parameter found to true and returns a pointer
to the video so that check-in, check-out, and other operations on the video object
can be performed
...
First, we describe the search procedure
...


video
info

FIGURE 18-47

Node of a video list

The component info is of type videoType and contains the necessary information
about a video
...
(See the definition of the
class videoType
...


Programming Example: Video Store

|

1093

videoTitle
movieStar1
movieStar2
movieProducer
movieDirector

1
8

movieProductionCo
copiesInStock
info

FIGURE 18-48

link

Video list node showing components of info

These member variables are all private and cannot be accessed directly
...

Suppose a pointer—say, current—points to a node in the video list (see Figure 18-49)
...
Suppose that we want to know whether the title
of the video stored in this node is the same as the title specified by the variable
title
...
checkTitle(title)

is true if the title of the video stored in this node is the same as the title specified by the
parameter title, and false otherwise
...
See its declaration in the class videoType
...

Because copiesInStock is a private member, it cannot be accessed directly
...
copiesInStock = 10;

//illegal

is incorrect and will generate a compile-time error
...
setCopiesInStock(10);

Now that we know how to access a member variable of a video stored in a node, let
us describe the algorithm to search the video list
...

void videoListType::searchVideoList(string title, bool& found,
nodeType* ¤t) const
{
found = false;
//set found to false
current = first; //set current to point to the first node
//in the list
while (current != NULL && !found)
//search the list
if (current->info
...
If it is unsuccessful, found is
set to false and current will be NULL
...
getNoOfCopiesInStock() > 0);
else
found = false;
}

return found;

void videoListType::videoCheckIn(string title)
{
bool found = false;
nodeType *location;
searchVideoList(title, found, location); //search the list

}

if (found)
location->info
...
checkOut();
else
cout << "The store does not carry " << title
<< endl;

1
8

1096

| Chapter 18: Linked Lists

bool videoListType::videoCheckTitle(string title) const
{
bool found = false;
nodeType *location;
searchVideoList(title, found, location); //search the list
}

return found;

void videoListType::videoUpdateInStock(string title, int num)
{
bool found = false;
nodeType *location;
searchVideoList(title, found, location); //search the list

}

if (found)
location->info
...
setCopiesInStock(num);
else
cout << "The store does not carry " << title
<< endl;

bool videoListType::videoSearch(string title) const
{
bool found = false;
nodeType *location;
searchVideoList(title, found, location);
}

return found;

Programming Example: Video Store

|

1097

void videoListType::videoPrintTitle() const
{
nodeType* current;

}

current = first;
while (current != NULL)
{
current->info
...


Every customer is a person
...
Therefore, we can derive the class customerType from the class personType and add the additional members that we need
...

Recall that the basic operations on an object of type personType are:
1
...

3
...


Print the name
...

Show the first name
...


Similarly, the basic operations on an object of type customerType are:
1
...

3
...

5
...

Set the name and the account number
...

Return a video; that is, delete the rented video from the list
...


The details of implementing the customer component are left as an exercise for you
...
)
Main Program We will now write the main program to test the video object
...
We will open the file and create the

1098

| Chapter 18: Linked Lists

list of videos owned by the video store
...

number of copies

...


...
We will also write a function, displayMenu, to show
the different choices—such as check in a movie or check out a movie—that the user
can make
...
Open the input file
...

2
...

3
...

4
...

Opening the input file is straightforward
...

createVideoList

This function reads the data from the input file and creates a linked list of videos
...
We also pass the video list pointer,
declared in the function main, to this function
...
Next, we read the data for each video and then insert the video in the
list
...
Read the data and store it in a video object
...
Insert the video in the list
...
Repeat steps a and b for each video’s data in the file
...
It contains the following output statements:
Select one of the following:
1
...
To check out a video

Programming Example: Video Store

3
...

5
...

9
...
get choice
b
...
get the movie name
b
...
if found, report success
else report "failure"
break;
case 2:
a
...
search the video list
c
...
get the movie name
b
...
if found, check in video
else report "failure"
break;
case 4:
a
...
search the video list
c
...
S
...
It also performs
// basic operations such as check in and check out videos
...
h"
"videoListType
...
open("videoDat
...
"
<< "The program terminates!!!" << endl;
return 1;
}
//create the video list
createVideoList(infile, videoList);
infile
...
get(ch);
cout << endl;

Programming Example: Video Store

|

1101

//process the requests
while (choice != 9)
{
switch (choice)
{
case 1:
cout << "Enter the title: ";
getline(cin, title);
cout << endl;
if (videoList
...
videoSearch(title))
{
if (videoList
...
videoCheckOut(title);
cout << "Enjoy your movie: "
<< title << endl;
}
else
cout << "Currently " << title
<< " is out of stock
...
videoSearch(title))
{
videoList
...
videoSearch(title))
{
if (videoList
...
" << endl;
else
cout << title << " is currently out "
<< "of stock
...
videoPrintTitle();
break;
case 6:
videoList
...
" << endl;
}//end switch
displayMenu();

//display menu

cout << "Enter your choice: ";
cin >> choice;
//get the next request
cin
...
get(ch);
newVideo
...
insertFirst(newVideo);
getline(infile, title);
}//end while
}//end createVideoList
void displayMenu()
{
cout << "Select one of the following:" << endl;
cout << "1: To check whether the store carries a "
<< "particular video
...
" << endl;
cout << "3: To check in a video
...
" << endl;
cout << "5: To print only the titles of all the videos
...
" << endl;
cout << "9: To exit" << endl;
}//end displayMenu

1
8

1104

| Chapter 18: Linked Lists

QUICK REVIEW
1
...

3
...

5
...

7
...

9
...

11
...

13
...

The pointer to a linked list—that is, the pointer to the first node in the
list—is stored in a separate location called the head or first
...

The length of a linked list is the number of nodes in the list
...

A (single) linked list is traversed in only one direction
...

The first (or head) pointer of a linked list is always fixed, pointing to the
first node in the list
...

In a doubly linked list, every node has two links: one points to the next
node, and one points to the previous node
...

In a doubly linked list, item insertion and deletion require the adjustment of
two pointers in a node
...


EXERCISES
1
...

In a linked list, the order of the elements is determined by the order in
which the nodes were created to store the elements
...
In a linked list, memory allocated for the nodes is sequential
...
A single linked list can be traversed in either direction
...
In a linked list, nodes are always inserted either at the beginning or the
end because a linked link is not a random-access data structure
...

What is the stored in the link field of the last node of a nonempty single linked list?
Suppose that first is a pointer to a linked list
...


2
...

4
...


Exercises

|

1105

Consider the linked list shown in Figure 18-50
...
Use this list to answer Exercises 6 through 12
...
(Assume that list, p, s, A, and B are
pointers of type nodeType
...


25

44

B

What is the output of each of the following C++ statements?
cout << list->info;

b
...


cout << B->link->info;

d
...


list->info >= 18

b
...


A->link->info == 16

d
...

8
...


7
...
If a statement is
invalid, explain why
...


A = B;

b
...


list->link->info = 45;

d
...


*A = *B;

f
...


A->info = B->info;

h
...


B = B->link->link->link;

1
8

1106

9
...

Make A point to the node containing info 23
...
Make list point to the node containing 16
...
Make B point to the last node in the list
...
Make list point to an empty list
...
Set the value of the node containing 25 to 35
...

Create and insert the node with info 10 after the node pointed to by A
...
Delete the node with info 23
...

What is the output of the following C++ code?
a
...


p = list;
while (p != NULL)
cout << p->info << " ";
p = p->link;
cout << endl;
11
...
If it is invalid, explain
why
...


If the following C++ code is valid, show the output
...

p = A;
p = p->link;
s = p;
p->link = NULL;
s = s->link;
cout << p->info << " " << s->info << endl;

13
...
Assume the node is in
the usual info-link form with the info of type int
...
)
list = new nodeType;
list->info = 10;
ptr = new nodeType;
ptr->info = 13;
ptr->link = NULL;
list->link = ptr;
ptr = new nodeType;
ptr->info = 18;
ptr->link = list->link;
list->link = ptr;

Exercises

|

1107

cout << list->info << " " << ptr->info << " ";
ptr = ptr->link;
cout << ptr->info << endl;
14
...
Assume the node is in
the usual info-link form with the info of type int
...
)
list = new nodeType;
list->info = 20;
ptr = new nodeType;
ptr->info = 28;
ptr->link = NULL;
list->link = ptr;
ptr = new nodeType;
ptr->info = 30;
ptr->link = list;
list = ptr;
ptr = new nodeType;
ptr->info = 42;
ptr->link = list->link;
list->link = ptr;
ptr = list;
while (ptr != NULL)
{
cout << ptr->info << endl;
ptr = ptr->link;
}

15
...
The following data, as described in parts (a) to (d), is
to be inserted into an initially linked list: 72, 43, 8, 12
...
After the linked list is created, head should
point to the first node of the list
...
Write the C++ code to create the linked list
...
What is the output of your code?
Insert 72 into an empty linked list
...
Insert 43 before 72
...
Insert 8 at the end of the list
...
Insert 12 after 43
...
(list and ptr are pointers of type nodeType
...

a
...


ptr = new nodeType;
ptr->info = 16;
list = new nodeType;
list->info = 25;
list->link = ptr;
ptr = new nodeType;

1
8

1108

| Chapter 18: Linked Lists

ptr->info = 12;
ptr->link = NULL;
list->link->link = ptr;

17
...

(These questions are independent of each other
...

a
...

Determine the order of the nodes of the linked list
...

Write a C++ code that creates and inserts a node with info 45 after
the node with info 16
...

Write a C++ code that creates and inserts a node with info 58 before
the node with info 25
...

Write a C++ code that deletes the node with info 25
...
(The class unorderedLinkedList is
as defined in this chapter
...
insertFirst(15);
list
...
insertFirst(30);
list
...
insertLast(45);
list
...
insertLast(25);
list
...
insertFirst(18);
list
...
deleteNode(12);
list
...


What is the output of this program segment?
Suppose the input is:
18 30 4 32 45 36 78 19 48 75 -999

What is the output of the following C++ code? (The class
unorderedLinkedList is as defined in this chapter
...
insertFirst(num);
else
list
...
print();
cout << endl;
copyList = list;
copyList
...
deleteNode(35);
cout << "Copy List = ";
copyList
...


20
...


Draw the UML diagram of the class doublyLinkedList as discussed in
this chapter
...

Draw the UML diagram of the class videoListType of the Video Store
programming example
...


(Online Address Book revisited) Programming Exercise 6 in Chapter 13
could handle a maximum of only 500 entries
...
Add the following operations
to your program:
Add or delete a new entry to the address book
...
Allow the user to save the data in the address book
...


2
...


b
...
(Delete only
the first occurrence and traverse the list only once
...
(Traverse
the list only once
...

Also, write a program to test these functions
...


| Chapter 18: Linked Lists

Extend the class linkedListType by adding the following operations:
Write a function that returns the info of the kth element of the linked
list
...

th
b
...
If no such
element exists, terminate the program
...

Also, write a program to test these functions
...
)
(Printing a single linked list backward) Include the functions
reversePrint and recursiveReversePrint, as discussed in this chapter,
in the class linkedListType
...
(Use either the class unorderedLinkedList or
the class orderedLinkedList to test your function
...


4
...


a
...

//Postcondition: first points to the first node and last
//
points to the last node of the first
//
sublist
...
first points to the first node
//
and sublist
...


Consider the following statements:
unorderedLinkedList myList;
unorderedLinkedList subList;

Suppose myList points to the list with elements 34 65 27 89 12 (in this
order)
...
divideMid(subList);

6
...

b
...
Also, write a program to test your function
...


|

1111

Add the following operation to the class linkedListType:
void divideAt(linkedListType &secondList,
const Type& item);
//Divide the list at the node with the info item into two
//sublists
...

//
secondList
...
last
//
point to the first and last nodes of the
//
second sublist
...
The statement:
myList
...


7
...


divides myList into two sublists: myList points to the list with the
elements 34 65, and otherList points to the sublist with the elements
18 39 27 89 12
...
Also, write a program to test your function
...

//Postcondition: first points to the merged list
//
list1 and list2 are empty

Consider the following statements:
orderedLinkedList newList;
orderedLinkedList list1;
orderedLinkedList list2;

Suppose list1 points to the list with the elements 2 6 7, and list2
points to the list with the elements 3 5 8
...
mergeLists(list1, list2);

1
8

1112

8
...


| Chapter 18: Linked Lists

creates a new linked list with the elements in the order 2 3 5 6 7 8, and
the object newList points to this list
...

b
...

The function insert of the class orderedLinkedList does not check if
the item to be inserted is already in the list; that is, it does not check for
duplicates
...
If the item to be inserted is already in the list, the function outputs an
appropriate error message
...

In this chapter, the class to implement the nodes of a linked list is defined as a
struct
...

template
class nodeType
{
public:
const nodeType& operator=(const nodeType&);
//Overload the assignment operator
...

//Postcondition: info = elem;
Type getInfo() const;
//Function to return the info of the node
...

void setLink(nodeType *ptr);
//Function to set the link of the node
...

//Postcondition: The value of link is returned
...

//Postcondition: info = elem; link = ptr

Programming Exercises

|

1113

nodeType(const nodeType &otherNode);
//Copy constructor
$nodeType();
//Destructor
private:
Type info;
nodeType *link;
};

10
...


12
...


Write the definitions of the member functions of the class nodeType
...

Programming Exercise 9 asks you to redefine the class to implement the nodes
of a linked list so that the instance variables are private
...
Rewrite the definitions of these classes so that they use
the member functions of the class nodeType to access the info and link
fields of a node
...

Write the definitions of the function copyList, the copy constructor,
and the function to overload the assignment operator for the class
doublyLinkedList
...

(Circular linked lists) This chapter defined and identified various
operations on a circular linked list
...
(You may assume that the elements of the circular
linked list are in ascending order
...
Write a program to test various operations of the class defined in (a)
...


14
...

b
...

(Video Store programming example) Complete the design and implementation of the video store program
...

a
...


1
8

1114

16
...


17
...
Use the class
unorderedLinkedList to create a linked list
...
The rules for converting a string into pig Latin
form are described in Programming Example: Pig Latin Strings of Chapter 8
...


19
CHAPTER

S TACKS

AND

I N T H I S C H A P T E R , YO U W I L L :

Q UEUES


...


Examine various stack operations


...


Learn how to implement a stack as a linked list


...


Learn how to use a stack to remove recursion


...


Examine various queue operations


...


Learn how to implement a queue as a linked list


...
Both stacks and
queues have numerous applications in computer science
...
To be specific, suppose that you
have functions A, B, C, and D in your program
...
When function
D terminates, control goes back to function C; when function C terminates, control goes
back to function B; and when function B terminates, control goes back to function A
...
What if you want to write a nonrecursive algorithm to print a linked list
backward?
This section discusses the data structure called the stack, which the computer uses to
implement function calls
...
Stacks
have numerous applications in computer science
...

A stack is a list of homogeneous elements in which the addition and deletion of elements
occur only at one end, called the top of the stack
...
For another
example, to get to your favorite computer science book, which is underneath your math
and history books, you must first remove the math and history books
...
Figure 19-1 shows some examples of stacks
...
The top element
of the stack is the last element added to the stack
...
For this reason, a stack is also called a Last In First Out (LIFO) data structure
...

Now that you know what a stack is, let us see what kinds of operations can be performed on
a stack
...
Similarly, because the top item can be
retrieved and/or removed from the stack, we can perform the operation top to retrieve the
top element of the stack and the operation pop to remove the top element from the stack
...
Initially, all of the boxes are on the floor, and
the stack is empty (see Figure 19-2)
...
After the push operation, the stack is as shown in
Figure 19-3(a)
...
After this push operation, the stack is as shown in
Figure 19-3(b)
...
After this push operation, the stack is
as shown in Figure 19-3(c)
...

After this operation, the stack is unchanged and shown in Figure 19-3(d)
...
After this push operation, the stack is as shown in Figure 19-3(e)
...
After the pop operation, the stack is as shown in Figure 19-3(f )
...
The two operations that
immediately follow from push, top, and pop are isFullStack (checks whether the
stack is full) and isEmptyStack (checks whether the stack is empty)
...
Thus, we need another operation, called initializeStack, which
initializes the stack to an empty state
...
We might also
need other operations on a stack, depending on the specific implementation
...

isEmptyStack: Determines whether the stack is empty
...

isFullStack: Determines whether the stack is full
...

push: Adds a new element to the top of the stack
...
Prior to this operation, the stack must exist and must not be full
...
Prior to this operation, the
stack must exist and must not be full
...
Prior to this operation, the
stack must exist and must not be empty
...

template
class stackADT
{
public:
virtual void initializeStack() = 0;
//Method to initialize the stack to an empty state
...

virtual bool isEmptyStack() const = 0;
//Function to determine whether the stack is empty
...


Stacks

|

1119

virtual bool isFullStack() const = 0;
//Function to determine whether the stack is full
...

virtual void push(const Type& newItem) = 0;
//Function to add newItem to the stack
...

//Postcondition: The stack is changed and newItem
//
is added to the top of the stack
...


};

stack
...

program
top element

virtual void pop() = 0;
//Function to remove the top element of the stack
...

//Postcondition: The stack is changed and the top
//
element is removed from the stack
...


stackADT

+initializeStack(): void
+isEmptyStack(): boolean
+isFullStack(): boolean
+push(Type): void
+top(): Type
+pop(): void

FIGURE 19-4

UML class diagram of the class stackADT

We now consider the implementation of our abstract stack data structure
...
Both implementations are useful and are discussed in this
chapter
...
The first element of the stack can be put in the first array slot, the
second element of the stack in the second array slot, and so on
...

In this implementation of a stack, stack elements are stored in an array, and an array is a
random access data structure; that is, you can directly access any element of the array
...
Thus, a
stack element is accessed only through the top, not through the bottom or middle
...

To keep track of the top position of the array, we can simply declare another variable
called stackTop
...
By using a pointer, we can dynamically allocate arrays, so we will leave it
for the user to specify the size of the array (that is, the stack size)
...
Because the class stackType has a pointer member variable
(the pointer to the array to store the stack elements), we must overload the assignment
operator and include the copy constructor and destructor
...
Depending on the specific application, we can pass the stack
element type when we declare a stack object
...

void initializeStack();
//Function to initialize the stack to an empty state
...

//Postcondition: Returns true if the stack is empty,
//
otherwise returns false
...

//Postcondition: Returns true if the stack is full,
//
otherwise returns false
...

//Precondition: The stack exists and is not full
...


Implementation of Stacks as Arrays

Type top() const;
//Function to return the top element of the
//Precondition: The stack exists and is not
//Postcondition: If the stack is empty, the
//
terminates; otherwise, the
//
of the stack is returned
...

empty
...

//Precondition: The stack exists and is not empty
...

stackType(int stackSize = 100);
//Constructor
//Create an array of the size stackSize to hold
//the stack elements
...

//Postcondition: The variable list contains the base
//
address of the array, stackTop = 0, and
//
maxStackSize = stackSize
...

//Postcondition: The array (list) holding the stack
//
elements is deleted
...

//Postcondition: A copy of otherStack is created and
//
assigned to this stack
...


1
9

1122

| Chapter 19: Stacks and Queues

stackType
-maxStackSize: int
-stackTop: int
-*list: Type
+operator=(const stackType&):
const stackType&
+initializeStack(): void
+isEmptyStack() const: bool
+isFullStack() const: bool
+push(const Type&): void
+top() const: Type
+pop(): void
-copyStack(const stackType&): void
+stackType(int = 100)
+stackType(const stackType&)
+~stackType()

FIGURE 19-5

UML class diagram of the class stackType

Because C++ arrays begin with the index 0, we need to distinguish between the value of
stackTop and the array position indicated by stackTop
...

Notice that the function copyStack is included as a private member
...
To copy a stack into another stack, the program can use the
assignment operator
...

Note that stackTop can range from 0 to maxStackSize
...
Suppose that maxStackSize = 100
...


...


...

stack

[3]
[2]

B

[0]

stackTop

C

[1]

maxStackSize

D

A

100

stack
elements

4

1
9

list

FIGURE 19-6

Example of a stack

Note that the pointer list contains the base address of the array (holding the stack
elements)—that is, the address of the first array component
...


Initialize Stack
Let us consider the initializeStack operation
...


[99]

...


...


...
If
stackTop is 0, the stack is empty; otherwise, the stack is not empty
...
It follows that the stack is full if stackTop is equal to maxStackSize
...
Recall that the value
of stackTop indicates the number of elements in the stack, and stackTop - 1 gives the
position of the top element of the stack
...
Store the newItem in the array component indicated by stackTop
...
Increment stackTop
...

Suppose that before the push operation, the stack is as shown in Figure 19-8
...


...


...

stack

n
n

[1]

S

stackTop

[2]

u

maxStackSize

[3]

[0]

100

stack
elements

4

list

FIGURE 19-8

Stack before pushing y

Assume newItem is 'y'
...


[99]

...


...

y
n

stack

[4]
[3]

u

stack
[2] elements
[1]

S

[0]

n
maxStackSize
stackTop
list

FIGURE 19-9

Stack after pushing y

100
5

1
9

1126

| Chapter 19: Stacks and Queues

Using the previous algorithm, the definition of the function push is:
template
void stackType::push(const Type& newItem)
{
if (!isFullStack())
{
list[stackTop] = newItem;
//add newItem to the
//top of the stack
stackTop++; //increment stackTop
}
else
cout << "Cannot add to a full stack
...

Error checking for an overflow can be handled in different ways
...
Or, we can check for an overflow before calling the function push, as shown
next (assuming stack is an object of type stackType)
...
isFullStack())
stack
...
Its definition is:
template
Type stackType::top() const
{
assert(stackTop != 0);
return list[stackTop - 1];
}//end top

//if stack is empty,
//terminate the program
//return the element of the
//stack indicated by
//stackTop - 1

Pop
To remove, or pop, an element from the stack, we simply decrement stackTop by 1
...

Suppose that before the pop operation, the stack is as shown in Figure 19-10
...


...


...

stack

D

[3]

L

[2]

O

[1]

B

[0]

maxStackSize 100
stackTop

stack
elements

4

list

FIGURE 19-10

Stack before popping D

After the pop operation, the stack is as shown in Figure 19-11
...


...


...

stack

D
L

list

FIGURE 19-11

Stack after popping D

stack
[1] elements

B

stackTop

[2]

O

maxStackSize

[3]

[0]

100
3

1
9

1128

| Chapter 19: Stacks and Queues

The definition of the function pop is:
template
void stackType::pop()
{
if (!isEmptyStack())
stackTop--;
//decrement stackTop
else
cout << "Cannot remove from an empty stack
...
Error checking for an underflow can be handled in different ways
...
Or, we can check for an underflow
before calling the function pop, as shown next (assuming stack is an object of type
stackType)
...
isEmptyStack())
stack
...
The stack to be copied is passed as a
parameter to the function copyStack
...
The definition of this
function is:
template
void stackType::copyStack(const stackType& otherStack)
{
delete [] list;
maxStackSize = otherStack
...
stackTop;
list = new Type[maxStackSize];
//copy otherStack into this stack
for (int j = 0; j < stackTop; j++)
list[j] = otherStack
...
The
constructor with parameters sets the stack size to the size specified by the user, sets
stackTop to 0, and creates an appropriate array in which to store the stack elements
...
The
destructor simply deallocates the memory occupied by the array (that is, the stack) and
sets stackTop to 0
...
" << endl;
cout << "Creating an array of size 100
...
It copies the values of the member variables of the actual parameter into the
corresponding member variables of the formal parameter
...
The definition of the function to overload the assignment operator
for the class stackType is:
template
const stackType& stackType::operator=
(const stackType& otherStack)

1
9

1130

| Chapter 19: Stacks and Queues

{
if (this != &otherStack) //avoid self-copy
copyStack(otherStack);
return *this;
} //end operator=

Stack Header File
Now that you know how to implement the stack operations, you can put the definitions
of the class and the functions to implement the stack operations together to create the
stack header file
...
(To save
space, only the definition of the class is shown; no documentation is provided
...
h
...

//Header file: myStack
...
h"
using namespace std;
template
class stackType: public stackADT
{
public:
const stackType& operator=(const stackType&);
void initializeStack();
bool isEmptyStack() const;
bool isFullStack() const;
void push(const Type& newItem);
Type top() const;
void pop();
stackType(int stackSize = 100);
stackType(const stackType& otherStack);
~stackType();

Implementation of Stacks as Arrays

|

1131

private:
int maxStackSize; //variable to store the maximum stack size
int stackTop;
//variable to point to the top of the stack
Type *list;
//pointer to the array that holds the
//stack elements
};

void copyStack(const stackType& otherStack);

template
void stackType::initializeStack()
{
stackTop = 0;
}//end initializeStack
template
bool stackType::isEmptyStack() const
{
return (stackTop == 0);
}//end isEmptyStack
template
bool stackType::isFullStack() const
{
return (stackTop == maxStackSize);
} //end isFullStack
template
void stackType::push(const Type& newItem)
{
if (!isFullStack())
{
list[stackTop] = newItem;
//add newItem to the
//top of the stack
stackTop++; //increment stackTop
}
else
cout << "Cannot add to a full stack
...
" << endl;
}//end pop

1
9

1132

| Chapter 19: Stacks and Queues

template
stackType::stackType(int stackSize)
{
if (stackSize <= 0)
{
cout << "Size of the array to hold the stack must "
<< "be positive
...
" << endl;
maxStackSize = 100;
}
else
maxStackSize = stackSize;

stackTop = 0;
list = new Type[maxStackSize];
}//end constructor

//set the stack size to
//the value specified by
//the parameter stackSize
//set stackTop to 0
//create the array to
//hold the stack elements

template
stackType::~stackType() //destructor
{
delete [] list; //deallocate the memory occupied
//by the array
}//end destructor
template
void stackType::copyStack(const stackType& otherStack)
{
delete [] list;
maxStackSize = otherStack
...
stackTop;
list = new Type[maxStackSize];
//copy otherStack into this stack
for (int j = 0; j < stackTop; j++)
list[j] = otherStack
...
Among others, we will test the
assignment operator and the copy constructor
...
h"

1
9

using namespace std;
void testCopyConstructor(stackType otherStack);
int main()
{
stackType stack(50);
stackType copyStack(50);
stackType dummyStack(100);
stack
...
push(23);
stack
...
push(38);
copyStack = stack; //copy stack into copyStack
cout << "The elements of copyStack: ";
while (!copyStack
...
top() << " ";
copyStack
...
isEmptyStack())
cout << "The original stack is not empty
...
top() << endl;
dummyStack = stack; //copy stack into dummyStack
cout << "The elements of dummyStack: ";

1134

| Chapter 19: Stacks and Queues

while (!dummyStack
...
top() << " ";
dummyStack
...
isEmptyStack())
cout << "otherStack is not empty
...
top() << endl;
}

Sample Run:
The elements of copyStack: 38 45 23
otherStack is not empty
...

The top element of the original stack: 38
The elements of dummyStack: 38 45 23

It is recommended that you do a walk-through of this program
...
The program then prints the highest
GPA and the names of all of the students who received that GPA
...
Moreover, we assume that there is a maximum of 100
students in the class
...
5
3
...
7
3
...
4
3
...
4

The program reads an input file consisting of each student’s GPA, followed
by the student’s name
...

For example, for the above data, the highest GPA is 3
...


We read the first GPA and the name of the student
...
Next, we read the second GPA and the name of the
student
...
Three
cases arise:
1
...
In this case, we:
a
...

b
...

c
...

2
...
In this case, we
add the name of the new student to the stack
...
The new GPA is smaller than the highest GPA so far
...

We then read the next GPA and the name of the student and repeat Steps 1 through 3
...

From this discussion, it is clear that we need the following variables:
double GPA;
//variable to hold
double highestGPA; //variable to hold
string name;
//variable to hold
stackType stack(100); //object

the current GPA
the highest GPA
the name of the student
to implement the stack

The preceding discussion translates into the following algorithm:
1
...

3
...


Declare the variables and initialize stack
...

If the input file does not exist, exit the program
...
Also, set the
precision to two decimal places
...
Read the GPA and the student name
...
highestGPA = GPA;

1
9

1136

| Chapter 19: Stacks and Queues

7
...
1
...
1
...

7
...
2
...
1
...

}

clearstack(stack);
push(stack, student name);
highestGPA = GPA;

7
...


else
if (GPA is equal to highestGPA)
push(stack, student name);

7
...


Read GPA and student name;

}

8
...

9
...

PROGRAM LISTING
//*********************************************************
// Author: D
...
Malik
//
// This program uses the class myStack to determine the
// highest GPA from a list of students with their GPA
...

//*********************************************************
#include
#include
#include
#include






#include "myStack
...
open("HighestGPAData
...
initializeStack();

//Step 7

1137

//Step 2

if (!infile)
{
cout << "The input file does not "
<< "exist
...
isFullStack())
stack
...
isFullStack())
stack
...
"
<< "Program terminates!"
<< endl;
return 1; //exit program
}
infile >> GPA >> name;

cout <<
<<
cout <<
<<

"Highest GPA = " << highestGPA
endl;
"The students holding the "
"highest GPA are:" << endl;

while (!stack
...
top() << endl;
stack
...
1
//Step 7
...
1
//Step 7
...
2
//Step 7
...
3
//Step 7
...
3

//Step 8

//Step 9

1
9

1138

| Chapter 19: Stacks and Queues

cout << endl;
}

return 0;

Sample Run:
Input File (HighestGPAData
...
4
3
...
5
3
...
8
3
...
6
3
...
8
3
...
9
3
...
9
2
...
9
3
...
90
The students holding the highest GPA are:
Vinay
Minnie
Andy

Note that the names of the students with the highest GPA are output in the reverse
order, relative to the order they appear in the input, due to the fact that the top
element of the stack is the last element added to the stack
...
If in a program the number of
elements to be pushed exceeds the size of the array, the program may terminate in an
error
...

We have seen that by using pointer variables, we can dynamically allocate and deallocate
memory, and by using linked lists, we can dynamically organize data (such as an ordered
list)
...


Linked Implementation of Stacks

|

1139

Recall that in the linear representation of a stack, the value of stackTop indicates the
number of elements in the stack, and the value of stackTop - 1 points to the top item in
the stack
...

Similar to the linear representation, in a linked representation, stackTop is used to locate
the top element in the stack
...
In the former case,
stackTop gives the index of the array
...

The following class implements the functions of the abstract class stackADT
...

bool isEmptyStack() const;
//Function to determine whether the stack is empty
...

bool isFullStack() const;
//Function to determine whether the stack is full
...

void initializeStack();
//Function to initialize the stack to an empty state
...

//Precondition: The stack exists and is not full
...


1
9

1140

| Chapter 19: Stacks and Queues

Type top() const;
//Function to return the top element of the stack
...

//Postcondition: If the stack is empty, the program
//
terminates; otherwise, the top
//
element of the stack is returned
...

//Precondition: The stack exists and is not empty
...

linkedStackType();
//Default constructor
//Postcondition: stackTop = NULL;
linkedStackType(const linkedStackType& otherStack);
//Copy constructor
~linkedStackType();
//Destructor
//Postcondition: All the elements of the stack are
//
removed from the stack
...

//Postcondition: A copy of otherStack is created and
//
assigned to this stack
...
Logically, the stack is never full
...
Therefore, in reality, the function isFullStack does not apply to
linked implementation of stacks
...


We leave the UML class diagram of the class linkedStackType as an exercise for you
...
)
EXAMPLE 19-2
Suppose that stack is an object of type linkedStackType
...


Linked Implementation of Stacks

stack

stackTop

1141

stack

stackTop

|

(a) Empty stack

C

B

A
(b) Nonempty stack

FIGURE 19-12

Empty and nonempty linked stack

In Figure 19-12(b), the top element of the stack is C; that is, the last element pushed onto
the stack is C
...


Default Constructor
The first operation that we consider is the default constructor
...
Thus, this function
sets stackTop to NULL
...
The stack is
empty if stackTop is NULL
...
(The stack is full only if we run out of
memory
...
The
definitions of the functions to implement these operations are:
template
bool linkedStackType::isEmptyStack() const

1
9

1142

| Chapter 19: Stacks and Queues

{
return (stackTop == NULL);
} //end isEmptyStack
template
bool linkedStackType:: isFullStack() const
{
return false;
} //end isFullStack

Recall that in the linked implementation of stacks, the function isFullStack does not
apply because, logically, the stack is never full
...


Initialize Stack
The operation initializeStack reinitializes the stack to an empty state
...

The definition of this function is:
template
void linkedStackType:: initializeStack()
{
nodeType *temp; //pointer to delete the node
while (stackTop != NULL)
{

//while there are elements in
//the stack

//set temp to point to the
//current node
stackTop = stackTop->link; //advance stackTop to the
//next node
delete temp;
//deallocate memory occupied by temp
temp = stackTop;

}
} //end initializeStack

Next, we consider the push, top, and pop operations
...
In the case of pop, the node pointed to by stackTop will
be removed
...
The operation
top returns the info of the node that stackTop is pointing to
...


Linked Implementation of Stacks

|

1143

stack
stackTop

C

B

A

FIGURE 19-13

1
9

Stack before the push operation

Figure 19-14 shows the steps of the push operation
...
)

newNode

newNode

D

D
stack

stack

stackTop

stackTop

newNode
stack
stackTop

C

B

B

A

A

D

C
C

B

A
(a) Create newNode
and store D

FIGURE 19-14

(b) Put newNode on
the top of stack

(c) Make stackTop point
to the top element

Push operation

The statements:
newNode = new nodeType; //create the new node
newNode->info = newElement;

1144

| Chapter 19: Stacks and Queues

create a node, store the address of the node into the variable newNode, and store
newElement into the info field of newNode
...

The statement:
newNode->link = stackTop;

inserts newNode at the top of the stack, as shown in Figure 19-14(b)
...

The definition of the function push is:
template
void linkedStackType::push(const Type& newElement)
{
nodeType *newNode; //pointer to create the new node
newNode = new nodeType; //create the node
newNode->info = newElement; //store newElement in the node
newNode->link = stackTop; //insert newNode before stackTop
stackTop = newNode;
//set stackTop to point to the
//top node
} //end push

We do not need to check whether the stack is full before we push an element onto the
stack because in this implementation, logically, the stack is never full
...
Its
definition is:
template
Type linkedStackType::top() const
{
assert(stackTop != NULL); //if stack is empty,
//terminate the program
return stackTop->info;
//return the top element
}//end top

Pop
Now we consider the pop operation, which removes the top element of the stack
...


Linked Implementation of Stacks

|

1145

stack
stackTop

C

B

A

FIGURE 19-15

1
9

Stack before the pop operation

Figure 19-16 shows the pop operation
...
See Figure 19-16(a)
...
See Figure
19-16(b)
...
See Figure 19-16(c)
...
" << endl;
}//end pop

Copy Stack
The function copyStack makes an identical copy of a stack
...
The definition of the
function copyStack is:
template
void linkedStackType::copyStack
(const linkedStackType& otherStack)
{
nodeType *newNode, *current, *last;
if (stackTop != NULL) //if stack is nonempty, make it empty
initializeStack();
if (otherStack
...
stackTop; //set current to point
//to the stack to be copied
//copy the stackTop element of the stack
stackTop = new nodeType; //create the node
stackTop->info = current->info; //copy the info

Linked Implementation of Stacks

|

1147

//set the link field of the
//node to NULL
last = stackTop;
//set last to point to the node
current = current->link;
//set current to point to
//the next node
stackTop->link = NULL;

//copy the remaining stack
while (current != NULL)
{
newNode = new nodeType;
newNode->info = current->info;
newNode->link = NULL;
last->link = newNode;
last = newNode;
current = current->link;
}//end while
}//end else
} //end copyStack

Constructors and Destructors
We have already discussed the default constructor
...
(These functions
are similar to those discussed for linked lists in Chapter 18
...
Also, as in the case of an array representation of a stack, in the
linked representation of a stack, we must put the definition of the stack and the functions
to implement the stack operations together in a (header) file
...

Example 19-3 illustrates how a linkedStack object is used in a program
...
h"
...
h"
using namespace std;
void testCopy(linkedStackType OStack);
int main()
{
linkedStackType stack;
linkedStackType otherStack;
linkedStackType newStack;
//Add elements into stack
stack
...
push(43);
stack
...
isEmptyStack())
{
cout << newStack
...
pop();
}

Linked Implementation of Stacks

|

1149

//Use the assignment operator to copy the elements
//of stack into otherStack
otherStack = stack;
cout << "Testing the copy constructor
...
isEmptyStack())
{
cout << otherStack
...
pop();
}
}

return 0;

//Function to test the copy constructor
void testCopy(linkedStackType OStack)
{
cout << "Stack in the function testCopy:" << endl;

}

while (!OStack
...
top() << endl;
OStack
...

Stack in the function testCopy:
27
43
34
After the copy constructor, otherStack:
27
43
34

1
9

1150

| Chapter 19: Stacks and Queues

Stack as Derived from the class unorderedLinkedList
If we compare the push function of the stack with the insertFirst function
discussed for general lists in Chapter 18, we see that the algorithms to implement these
operations are similar
...
Moreover, the functions pop and isFullStack can be implemented as in the previous section
...
However, the class unorderedLinkedListType is derived from the
class linkedListType and provides the definitions of the abstract functions of
the class linkedListType
...

Next, we define the class linkedStackType that is derived from the class
unorderedLinkedList
...

#include
#include "unorderedLinkedList
...

For example, in the expression a + b, the operator + is between the operands a and b
...
That is, we must evaluate expressions from
left to right, and multiplication and division have higher precedence than do addition and
subtraction
...
For example, in the expression a + b * c, we first evaluate * using the operands
b and c, and then we evaluate + using the operand a and the result of b * c
...
In the late 1950s, the Australian philosopher and early
computer scientist Charles L
...
This has the
advantage that the operators appear in the order required for computation
...


1
9

1152

| Chapter 19: Stacks and Queues

EXAMPLE 19-4
Infix Expression

Equivalent Postfix Expression

a+b

ab+

a+b*c

abc*+

a*b+c

ab*c+

(a + b ) * c

ab+c*

(a À b) * (c + d)

abÀcd+*

(a + b) * (c À d / e) + f

ab+cde/À*f+

Shortly after Lukasiewicz’s discovery, it was realized that postfix notation had important
applications in computer science
...
Postfix expressions can be evaluated using the following algorithm:
Scan the expression from left to right
...

Consider the following postfix expression:
63+2*=

Let us evaluate this expression using a stack and the previous algorithm
...


Expression: 6 3 + 2 * =
Push
6
into
stack 6
(a)

Push
2
into
stack

2
9
(e)

FIGURE 19-17

Push
3
into
stack

3
6
(b)

*
Pop
stack
twice
op2 = 2;
op1 = 9;
(f)

+
Pop
stack
twice
op2 = 3;
op1 = 6;
(c)

op1 + op2
= 9
Push 9
into
stack
9
(d)

op1 * op2
= 18
Push 18
into
stack
18
(g)

Evaluating the postfix expression: 6 3 + 2 * ¼

=
Pop
stack
and
print:
18
(h)

Application of Stacks: Postfix Expressions Calculator |

1153

Read the first symbol, 6, which is a number
...
Read the next symbol, 3, which is a number
...
Read the next symbol, +, which is an operator
...

Perform the operation and put the result back onto the stack (see Figure 19-17(d))
...
Push the number onto the stack (see
Figure 19-17(e))
...
Because an operator
requires two operands to be evaluated, pop the stack twice (see Figure 19-17(f ))
...

Scan the next symbol, =, which is the equal sign, indicating the end of the expression
...
The result of the expression is in the stack, so pop and print (see Figure 19-17(h))
...

From this discussion, it is clear that when we read a symbol other than a number, the
following cases arise:
1
...

If the symbol is +, -, *, or /, the symbol is an operator, so we must
evaluate it
...

b
...
At this step, the stack must contain exactly one
element; otherwise, the expression has an error
...
The symbol we read is something other than +, -, *, /, or =
...

a
...

Consider the following expressions:
a
...
14 + 2 3 * =
c
...
In the case of expression (c), when we
encounter the equal sign (=), the stack will have two elements, and this error cannot be
discovered until we are ready to print the value of the expression
...
If the symbol scanned is #, then
the next input is a number (that is, an operand)
...

Furthermore, we assume that each expression contains only the +, -, *, and / operators
...
If the
expression has an error, the expression is discarded
...
Because an expression may
contain an error, we must clear the stack before processing the next expression
...


Main Algorithm
Following the previous discussion, the main algorithm in pseudocode is:
Read the first character
while not the end of input data
{
a
...
process the expression
c
...
get the next expression
}

To simplify the complexity of the function main, we write four functions:
evaluateExpression, evaluateOpr, discardExp, and printResult
...
If the postfix expression is error free, the function printResult outputs the result
...


Function evaluateExpression
The function evaluateExpression evaluates each postfix expression
...
The general algorithm is:
while (ch is not = '=') //process each expression
//= marks the end of an expression
{
switch (ch)
{
case '#':
read a number
output the number;
push the number onto the stack;
break;
default:
assume that ch is an operation
evaluate the operation;
} //end switch

Application of Stacks: Postfix Expressions Calculator |

1155

if no error was found, then
{
read next ch;
output ch;
}
else
Discard the expression
} //end while

From this algorithm, it follows that this method has five parameters—one to access the input file,
one to access the output file, one to access the stack, one to pass a character of the expression,
and one to indicate whether there is an error in the expression
...
isFullStack())
stack
...
"
<< "Program terminates!" << endl;
exit(0); //terminate the program
}
break;
default:
evaluateOpr(outF, stack, ch, isExpOk);
}//end switch
if (isExpOk) //if no error
{
inpF >> ch;
outF << ch;
if (ch != '#')
outF << " ";

}

}
else
discardExp(inpF, outF, ch);
} //end while (!= '=')

1
9

1156

| Chapter 19: Stacks and Queues

Note that the function exit terminates the program
...
Two operands are needed to evaluate an
operation, and operands are saved in the stack
...
If the stack contains fewer than two numbers, then the expression has an error
...
This
function also checks for any illegal operations
...

switch (ch)
{
case '+':
//Perform the operation and push the result
//onto the stack
...
push(op1 + op2);
break;
case '-':
//Perform the operation and push the result
//onto the stack
...
push(op1 – op2);
break;
case '*':
//Perform the operation and push the
//result onto the stack
...
push(op1 * op2);
break;
case '/':
//If (op2 != 0), perform the operation and
//push the result onto the stack
...
push(op1 / op2);

Application of Stacks: Postfix Expressions Calculator |

}

1157

//Otherwise, report the error
...

break;
otherwise operation is illegal
{
output an appropriate message;
set expressionOk to false
}
} //end switch

Following this pseudocode, the definition of the function evaluateOpr is:
void evaluateOpr(ofstream& out, stackType& stack,
char& ch, bool& isExpOk)
{
double op1, op2;
if (stack
...
top();
stack
...
isEmptyStack())
{
out << " (Not enough operands)";
isExpOk = false;
}
else
{
op1 = stack
...
pop();
switch (ch)
{
case '+':
stack
...
push(op1 - op2);
break;
case '*':
stack
...
push(op1 / op2);

1
9

1158

| Chapter 19: Stacks and Queues

else
{
out << " (Division by 0)";
isExpOk = false;
}
break;
default:
out << " (Illegal operator)";
isExpOk = false;
}//end switch
} //end else
} //end else
} //end evaluateOpr

Function discardExp
This function is called whenever an error is discovered in the expression
...
The definiton
of this function is:
void discardExp(ifstream& in, ofstream& out, char& ch)
{
while (ch != '=')
{
in
...
The result of the expression is in
the stack, and the output is sent to a file
...
Suppose that no errors were encountered by the
method evaluateExpression
...
If either the stack is
empty or it has more than one element, then there is an error in the postfix
expression
...
The
definition of this method is:
void printResult(ofstream& outF, stackType& stack,
bool isExpOk)
{
double result;
if (isExpOk) //if no error, print the result

Application of Stacks: Postfix Expressions Calculator |

1159

{
if (!stack
...
top();
stack
...
isEmptyStack())
outF << result << endl;
else
outF << " (Error: Too many operands)" << endl;
} //end if
else
outF << " (Error in the expression)" << endl;

}
else
outF << " (Error in the expression)" << endl;
outF << "_________________________________"
<< endl << endl;
} //end printResult

PROGRAM LISTING
//***********************************************************
// Author: D
...
Malik
//
// Program: Postfix Calculator
// This program evaluates postfix expressions
...
h"

using namespace std;
void evaluateExpression(ifstream& inpF, ofstream& outF,
stackType& stack,
char& ch, bool& isExpOk);
void evaluateOpr(ofstream& out, stackType& stack,
char& ch, bool& isExpOk);
void discardExp(ifstream& in, ofstream& out, char& ch);
void printResult(ofstream& outF, stackType& stack,
bool isExpOk);
int main()
{
bool expressionOk;
char ch;

1
9

1160

| Chapter 19: Stacks and Queues

stackType stack(100);
ifstream infile;
ofstream outfile;
infile
...
txt");
if (!infile)
{
cout << "Cannot open the input file
...
open("RpnOutput
...
initializeStack();
expressionOk = true;
outfile << ch;
evaluateExpression(infile, outfile, stack, ch,
expressionOk);
printResult(outfile, stack, expressionOk);
infile >> ch; //begin processing the next expression
} //end while
infile
...
close();
return 0;
} //end main
//Place the definitions of the function evaluateExpression,
//evaluateOpr, discardExp, and printResult as described
//previously here
...
00 #27
...
00 * = 186
...
00 #28
...
00 #2
...
00 #30
...
00 * / = 0
...
00 #3
...
00 + = (Error: Too many operands)
_________________________________
#20
...
00 #9
...
00 #23
...
00 #24
...
00 #7
...
00 - = 52
...
In this section, you will
learn how a stack can be used to design a nonrecursive algorithm to print a linked list
backward
...


first

FIGURE 19-18

5

10

15

Linked list

To print the list backward, first we need to get to the last node of the list, which we can do by
traversing the linked list starting at the first node
...
Moreover, if we do this for every node in the list, the program might execute very
slowly
...

After printing the info of a particular node, we need to move to the node immediately
behind this node
...
Thus, while initially traversing the list to move to the last node, we must save a
pointer to each node
...
After printing 15, we go back to the node with
info 10; after printing 10, we go back to the node with info 5
...


Because the number of nodes in a linked list is usually not known, we will use the linked
implementation of a stack
...
Consider the following
statements:
current = first;

//Line 1

while (current != NULL)
{
stack
...
(See Figure 19-19
...
(See Figure 19-20
...
push(current); and current ¼

current->link; execute

Removing Recursion: Nonrecursive Algorithm to Print a Linked List Backward |

1163

After the statement in Line 4 executes, the loop condition in Line 2 is re-evaluated
...
(See Figure 19-21
...
push(current); and current =
current->link; execute

After the statement in Line 4 executes, the loop condition, in Line 2, is evaluated again
...
(See Figure 19-22
...
push(current); and current =
current->link; execute

After the statement in Line 4 executes, the loop condition in Line 2 is evaluated again
...
From Figure 19-22, it follows that a pointer to each node in the linked
list is saved in the stack
...
Let us now execute the following statements:
while (!stack
...
top();
stack
...
Therefore, the statements in Lines 6, 7, and 8 execute
...
The statement in Line 7 removes the top element of the
stack
...
)

stack
first

5

10

15
stackTop

current

10

5

FIGURE 19-23

List and stack after the statements current = stack
...
pop();
execute

The statement in Line 8 outputs current->info, which is 15
...
Because the loop condition evaluates to true, the statements in Lines 6,
7, and 8 execute
...


stack
first

5

10

15

stackTop

5

current

FIGURE 19-24

List and stack after the statements current = stack
...
pop();
execute

Queues

|

1165

The statement in Line 8 outputs current->info, which is 10
...
Because the loop condition evaluates to true, the statements in Lines 6,
7, and 8 execute
...


stack
first

5

10

15

stackTop

current

FIGURE 19-25

List and stack after the statements current = stack
...
pop();
execute

The statement in Line 8 outputs current->info, which is 5
...
Because the loop condition evaluates to false, the while loop
terminates
...
The notion of a
queue in computer science is the same as the notion of the queues to which you are
accustomed in everyday life
...
Similarly, because a computer can
send a print request faster than a printer can print, a queue of documents is often waiting to
be printed at a printer
...
That is, a queue is a First In First Out data structure
...
Whenever a system is modeled
on the First In First Out principle, queues are used
...
First,
however, we need to develop the tools necessary to implement a queue
...

A queue is a set of elements of the same type in which the elements are added at one end,
called the back or rear, and deleted from the other end, called the front
...
Each new customer gets in the line at
the rear
...

The rear of the queue is accessed whenever a new element is added to the queue, and the
front of the queue is accessed whenever an element is deleted from the queue
...

Queue: A data structure in which the elements are added at one end, called the rear, and

deleted from the other end, called the front; a First In First Out (FIFO) data structure
...
We
call the add operation addQueue and the delete operation deleteQueue
...

We also need an operation, initializeQueue, to initialize the queue to an empty state
...
Some of the queue operations are:











initializeQueue: Initializes the queue to an empty state
...
If the queue is
empty, it returns the value true; otherwise, it returns the value false
...
If the queue is full,
it returns the value true; otherwise, it returns the value false
...
Input to
this operation consists of the queue
...

back: Returns the last element of the queue
...
Prior to this operation, the queue must exist and
must not be empty
...
Input to this
operation consists of the queue and the new element
...

deleteQueue: Removes the front element from the queue
...
Prior to this operation, the queue must
exist and must not be empty
...
We will
consider both implementations
...


Queues

|

1167

The following abstract class queueADT defines these operations as an ADT
...

//Postcondition: Returns true if the queue is empty,
//
otherwise returns false
...

//Postcondition: Returns true if the queue is full,
//
otherwise returns false
...

//Postcondition: The queue is empty
...

//Precondition: The queue exists and is not empty
...

virtual Type back() const = 0;
//Function to return the last element of the queue
...

//Postcondition: If the queue is empty, the program
//
terminates; otherwise, the last
//
element of the queue is returned
...

//Precondition: The queue exists and is not full
...


};

virtual void deleteQueue() = 0;
//Function to remove the first element of the queue
...

//Postcondition: The queue is changed and the first
//
element is removed from the queue
...


1
9

1168

| Chapter 19: Stacks and Queues

Implementation of Queues as Arrays
Before giving the definition of the class to implement a queue as an ADT, we need to
decide how many member variables are needed to implement the queue
...
Thus, we need at least four member variables
...
How do
queueFront and queueRear indicate that the queue is empty or full? Suppose that
queueFront gives the index of the first element of the queue, and queueRear gives the
index of the last element of the queue
...
To delete an element from the queue, first we retrieve the
element that queueFront is pointing to, and then we advance queueFront to the next
element of the queue
...

Let us see what happens when queueFront changes after a deleteQueue operation and
queueRear changes after an addQueue operation
...

Initially, the queue is empty
...


[0] [1] [2] [3]

queueFront

0

queueRear

FIGURE 19-26

[97] [98] [99]

...


Queues

[0] [1] [2] [3]
A

B

1169

[97] [98] [99]

...

[0] [1] [2] [3]
A

B

queueFront

1

queueRear

FIGURE 19-28

[97] [98] [99]

...
Consider the following sequence of operations:
AAADADADADADADADA
...
However, the queue has
only two or three elements, and the front of the array is empty (see Figure 19-29)
...


queueFront
queueRear

FIGURE 19-29

97
99

Queue after the sequence of operations AAADADADADADA
...
If the value
of queueFront indicates that there is room in the front of the array, then when queueRear
gets to the last array position, we can slide all of the queue elements toward the first array
position
...

Another solution to this problem is to assume that the array is circular—that is, the first
array position immediately follows the last array position (see Figure 19-30)
...

Suppose that we have the queue as shown in Figure 19-31(a)
...


[98][99]
X
Y

queueFront 98 queueRear 99
(a) Before addQueue(Queue,'Z');

FIGURE 19-31

[0] [1]
[98][99]
Z

...


Queues

|

1171

Because the array containing the queue is circular, we can use the following statement to
advance queueRear (queueFront) to the next array position
...
If queueRear == maxQueueSize - 1 (that is, queueRear points to the last array position), queueRear + 1 ==
maxQueueSize, so (queueRear + 1) % maxQueueSize = 0
...

This queue design seems to work well
...

Case 1: Suppose that after certain operations, the array containing the queue is as shown
in Figure 19-32(a)
...

X

queueFront 98 queueRear 98

[0]

queueFront 99 queueRear 98
(b) After deleteQueue();

(a) Before deleteQueue();

FIGURE 19-32

[97] [98][99]

...

Case 2: Let us now consider the queue shown in Figure 19-33(a)
...

queue
elements

[0]

[97] [98][99]

...


1
9

1172

| Chapter 19: Stacks and Queues

The arrays in Figures 19-32(b) and 19-33(b) have identical values for queueFront and
queueRear
...
This latest queue
design has brought up another problem of distinguishing between an empty and a full queue
...
One solution is to keep a count
...
The value of count is incremented whenever a new element is
added to the queue, and it is decremented whenever an element is removed from the
queue
...
This solution
is very useful if the user of the queue frequently needs to know the number of elements in
the queue
...
In
this case, assuming queueRear still indicates the index of the last element in the queue,
the queue is empty if queueFront == queueRear
...
The
queue will be full if the next available space is the special reserved slot indicated by
queueFront
...


reserved slot
[0] [1] [2]

[97] [98][99]

...
That is, we use the variable count to
indicate whether the queue is empty or full
...
Because arrays can be allocated dynamically, we will
leave it for the user to specify the size of the array to implement the queue
...

template
class queueType: public queueADT
{
public:
const queueType& operator=(const queueType&);
//Overload the assignment operator
...

//Postcondition: Returns true if the queue is empty,
//
otherwise returns false
...

//Postcondition: Returns true if the queue is full,
//
otherwise returns false
...

//Postcondition: The queue is empty
...

//Precondition: The queue exists and is not empty
...

Type back() const;
//Function to return the last element of the queue
...

//Postcondition: If the queue is empty, the program
//
terminates; otherwise, the last
//
element of the queue is returned
...

//Precondition: The queue exists and is not full
...

void deleteQueue();
//Function to remove the first element of the queue
...

//Postcondition: The queue is changed and the first
//
element is removed from the queue
...
(See
Exercise 28 at the end of this chapter
...

EMPTY QUEUE AND FULL QUEUE
As discussed earlier, the queue is empty if count == 0, and the queue is full if count ==
maxQueueSize
...
The first element is added at
the first array position
...
See Figure 19-35
...


queueFront 0

FIGURE 19-35

queueRear 99

count 0

Empty queue

The definition of the function initializeQueue is:
template
void queueType::initializeQueue()
{
queueFront = 0;
queueRear = maxQueueSize - 1;
count = 0;
} //end initializeQueue

FRONT
This operation returns the first element of the queue
...


Queues

|

1175

template
Type queueType::front() const
{
assert(!isEmptyQueue());
return list[queueFront];
} //end front

BACK
This operation returns the last element of the queue
...

template
Type queueType::back() const
{
assert(!isEmptyQueue());
return list[queueRear];
} //end back

addQueue
Next, we implement the addQueue operation
...
We also increment count by 1
...
" << endl;
} //end addQueue

deleteQueue
To implement the deleteQueue operation, we access the index queueFront
...
So the function deleteQueue is:

1
9

1176

| Chapter 19: Stacks and Queues

template
void queueType::deleteQueue()
{
if (!isEmptyQueue())
{
count--;
queueFront = (queueFront + 1) % maxQueueSize; //use the
//mod operator to advance queueFront
//because the array is circular
}
else
cout << "Cannot remove from an empty queue
...
The constructor gets the
maxQueueSize from the user, sets the variable maxQueueSize to the value specified
by the user, and creates an array of size maxQueueSize
...
The constructor also initializes queueFront and queueRear to indicate
that the queue is empty
...
" << endl;
cout << "Creating an array of size 100
...
Therefore, when the queue
object goes out of scope, the destructor simply deallocates the memory occupied by the
array that stores the queue elements
...
(The definitions of these functions are similar to those discussed
for linked lists and stacks
...
Also, the array implementation of the queue
requires the array to be treated in a special way together with the values of the indices
queueFront and queueRear
...
This section discusses the linked
implementation of a queue
...
Thus, we need two pointers,
queueFront and queueRear, to maintain the queue
...

//Definition of the node
template
struct nodeType
{
Type info;
nodeType *link;
};
template
class linkedQueueType: public queueADT
{
public:
const linkedQueueType& operator=
(const linkedQueueType&);
//Overload the assignment operator
...

//Postcondition: Returns true if the queue is empty,
//
otherwise returns false
...

//Postcondition: Returns true if the queue is full,
//
otherwise returns false
...

//Postcondition: queueFront = NULL; queueRear = NULL
Type front() const;
//Function to return the first element of the queue
...

//Postcondition: If the queue is empty, the program
//
terminates; otherwise, the first
//
element of the queue is returned
...

//Precondition: The queue exists and is not empty
...

void addQueue(const Type& queueElement);
//Function to add queueElement to the queue
...

//Postcondition: The queue is changed and queueElement
//
is added to the queue
...

//Precondition: The queue exists and is not empty
...

linkedQueueType();
//Default constructor
linkedQueueType(const linkedQueueType& otherQueue);
//Copy constructor
~linkedQueueType();
//Destructor
private:
nodeType *queueFront; //pointer to the front of
//the queue
nodeType *queueRear; //pointer to the rear of
//the queue
};

The UML class diagram of the class linkedQueueType is left as an exercise for you
...
)
Next, we write the definitions of the functions of the class linkedQueueType
...
Memory to store the queue elements
is allocated dynamically
...
(The queue is full only if we run
out of memory
...
However, you must provide its
definition because it is included as an abstract function in the parent class queueADT
...
The queue is
empty if there are no elements in the queue
...
So this operation must remove all of the
elements, if any, from the queue
...
The definition of this function is:
template
void linkedQueueType::initializeQueue()
{
nodeType *temp;
while (queueFront!= NULL)
{

//while there are elements left
//in the queue

//set temp to point to the
//current node
queueFront = queueFront->link; //advance first to
//the next node
delete temp;
//deallocate memory occupied by temp
temp = queueFront;

}

queueRear = NULL; //set rear to NULL
} //end initializeQueue

addQueue, front, back, AND deleteQueue OPERATIONS
The addQueue operation adds a new element at the end of the queue
...


1
9

1180

| Chapter 19: Stacks and Queues

If the queue is nonempty, the operation front returns the first element of the queue, and
so the element of the queue indicated by the pointer queueFront is returned
...

If the queue is nonempty, the operation back returns the last element of the queue, so
the element of the queue indicated by the pointer queueRear is returned
...
Similarly, if the queue is nonempty,
the operation deleteQueue removes the first element of the queue, so we access the
pointer queueFront
...
The definition of
the function to implement the destructor is similar to the definition of the function
initializeQueue
...
Implementing these operations is left as an exercise for you
...
It uses the class
linkedQueueType to implement a queue
...
h"
using namespace std;
int main()

1
9

1182

| Chapter 19: Stacks and Queues

{
linkedQueueType queue;
int x, y;
queue
...
addQueue(x);
queue
...
front();
queue
...
addQueue(x + 5);
queue
...
addQueue(x);
queue
...
isEmptyQueue())
{
cout << queue
...
deleteQueue();
}
cout << endl;
}

return 0;

Sample Run:
Queue Elements: 5 9 16 4 2

Queue Derived from the class unorderedLinkedListType
From the definitions of the functions to implement the queue operations, it is clear that the
linked implementation of a queue is similar to the implementation of a linked list created in a
forward manner (see Chapter 18)
...
Likewise, the operations initializeQueue and initializeList and
isEmptyQueue and isEmptyList are similar
...
The pointer queueFront is the same as the pointer first, and the
pointer queueRear is the same as the pointer last
...
Note that the class linkedListType is an abstract class and does not implement all
of the operations
...
Therefore, we can derive the class linkedQueueType from the
class unorderedLinkedListType
...
See Programming Exercise 17 at the end of this chapter
...
For example, physical simulators include wind tunnels used to experiment
with the design of car bodies and flight simulators used to train airline pilots
...
You can also design computer models to study the behavior of real systems
...
)
Simulating the behavior of an expensive or dangerous experiment using a computer
model is usually less expensive than using the real system and is a good way to gain insight
without putting human life in danger
...
For
such systems, computer models can retain descriptive accuracy
...
Let us consider one
such problem
...
The theater currently has only one
cashier
...
The manager wants to hire enough cashiers so that a customer
does not have to wait too long to buy a ticket but does not want to hire extra cashiers on
a trial basis and potentially waste time and money
...
The manager wants
someone to write a program to simulate the behavior of the theater
...
For the
theater problem, some of the objects are the customers and the cashier
...
Actions are
implemented by writing algorithms, which in a programming language are implemented
with the help of functions
...
In C++, we can combine the data and the operations on that data into a single
unit with the help of classes
...
The member
variables of the class describe the properties of the objects, and the function members
describe the actions on that data
...
The main goal of a computer simulation is to
either generate results showing the performance of an existing system or predict the
performance of a proposed system
...
Because customers are served on a first come, first served basis and queues are an

1
9

1184

| Chapter 19: Stacks and Queues

effective way to implement a First In First Out system, queues are important data
structures for use in computer simulations
...
These simulations model the behavior of
systems, called queuing systems, in which queues of objects are waiting to be served by
various servers
...
We deal with a variety of queuing systems on a daily basis
...
Furthermore,
when you send a print request to a networked printer that is shared by many people, your
print request goes in a queue
...
Thus, the printer acts as the server when a queue of
documents is waiting to be printed
...
To
describe a queuing system, we use the term server for the object that provides the
service
...
We will call the object receiving the service the customer, and the
service time—the time it takes to serve a customer—the transaction time
...
The customer at the front of the queue waits for the next available server
...

When the first customer arrives, all servers are free and the customer moves to the first
server
...
To model a
queuing system, we need to know the number of servers, the expected arrival time of a
customer, the time between the arrivals of customers, and the number of events affecting
the system
...
The performance of the system depends
on how many servers are available, how long it takes to serve a customer, and how often a
customer arrives
...
This system can be modeled as a time-driven simulation
...
The simulation is
run for a fixed amount of time
...

For the simulation described in this section, we want to determine the average wait time for
a customer
...
When a customer arrives, he or she goes to the end of the queue and the
customer’s waiting time begins
...
On the other hand, if a
customer arrives and either the queue is nonempty or all of the servers are busy, the customer
must wait for the next available server and, therefore, this customer’s waiting time begins
...
When
a customer arrives, the timer is set to 0, which is incremented after each time unit
...
When a
server becomes free and the waiting customer’s queue is nonempty, the customer at the
front of the queue proceeds to begin the transaction
...
When the customer arrives at a server, the transaction
time is set to five and is decremented after each time unit
...
Hence, the two objects needed to implement a
time-driven computer simulation of a queuing system are the customer and the server
...


Customer
Every customer has a customer number, arrival time, waiting time, transaction time, and
departure time
...
Let us call the class to
implement the customer object customerType
...
The basic operations
that must be performed on an object of type customerType are as follows: set the
customer’s number, arrival time, and waiting time; increment the waiting time by one
time unit; return the waiting time; return the arrival time; return the transaction time;
and return the customer number
...

class customerType
{
public:
customerType(int cN = 0, int arrvTime = 0, int wTime = 0,
int tTime = 0);
//Constructor to initialize the instance variables
//according to the parameters
...

//Postcondition: customerNumber = cN;
//
arrivalTime = arrvTime;
//
waitingTime = wTime;
//
transactionTime = tTime

1
9

1186

| Chapter 19: Stacks and Queues

void setCustomerInfo(int customerN = 0, int inTime = 0,
int wTime = 0, int tTime = 0);
//Function to initialize the instance variables
...

//Postcondition: customerNumber = customerN;
//
arrivalTime = arrvTime;
//
waitingTime = wTime;
//
transactionTime = tTime;
int getWaitingTime() const;
//Function to return the waiting time of a customer
...

void setWaitingTime(int time);
//Function to set the waiting time of a customer
...

//Postcondition: waitingTime++;
int getArrivalTime() const;
//Function to return the arrival time of a customer
...

int getTransactionTime() const;
//Function to return the transaction time of a customer
...

int getCustomerNumber() const;
//Function to return the customer number
...

private:
int customerNumber;
int arrivalTime;
int waitingTime;
int transactionTime;
};

Figure 19-36 shows the UML class diagram of the class customerType
...
Next, we give the definitions of the member functions of the class
customerType
...
The definition
of setCustomerInfo is:
void customerType::setCustomerInfo(int customerN, int arrvTime,
int wTime, int tTime)
{
customerNumber = customerN;
arrivalTime = arrvTime;
waitingTime = wTime;
transactionTime = tTime;
}

The definition of the constructor is similar to the definition of the function
setCustomerInfo
...
To make debugging easier, we
use the function setCustomerInfo to write the definition of the constructor, which is
given next, as follows:

1
9

1188

| Chapter 19: Stacks and Queues

customerType::customerType(int customerN, int arrvTime,
int wTime, int tTime)
{
setCustomerInfo(customerN, arrvTime, wTime, tTime);
}

The function getWaitingTime returns the current waiting time
...
Its
definition is:
void customerType::incrementWaitingTime()
{
waitingTime++;
}

The

definitions of the functions setWaitingTime, getArrivalTime,
getTransactionTime, and getCustomerNumber are left as an exercise for you
...
We use
a string variable to set the status of the server
...
Thus, three
member variables are associated with a server: the status, the transactionTime,
and the currentCustomer
...
The following class, serverType,
implements the server as an ADT
...

//Postcondition: currentCustomer is initialized by its
//
default constructor; status = "free"; and
//
the transaction time is initialized to 0
...

//Postcondition: Returns true if the server is free,
//
otherwise returns false
...

//Postcondition: status = "busy";
void setFree();
//Function to set the status of the server to "free"
...

//Postcondition: transactionTime = t;
void setTransactionTime();
//Function to set the transaction time according to
//the transaction time of the current customer
...
transactionTime;
int getRemainingTransactionTime() const;
//Function to return the remaining transaction time
...

void decreaseTransactionTime();
//Function to decrease the transactionTime by one unit
...

//Postcondition: currentCustomer = cCustomer;
int getCurrentCustomerNumber() const;
//Function to return the customer number of the current
//customer
...

int getCurrentCustomerArrivalTime() const;
//Function to return the arrival time of the current
//customer
...

int getCurrentCustomerWaitingTime() const;
//Function to return the current waiting time of the
//current customer
...

int getCurrentCustomerTransactionTime() const;
//Function to return the transaction time of the
//current customer
...

private:
customerType currentCustomer;
string status;
int transactionTime;
};

Figure 19-37 shows the UML class diagram of the class serverType
...
getTransactionTime();
}

transactionTime = time;

void serverType::decreaseTransactionTime()
{
transactionTime--;
}

We

leave the definitions of the functions getRemainingTransactionTime,
setCurrentCustomer, getCurrentCustomerNumber, getCurrentCustomerArrivalTime,
getCurrentCustomerWaitingTime, and getCurrentCustomerTransactionTime as an
exercise for you
...
The next two sections describe
each of these classes
...
At any given time, a server is either free or busy
...
If all of
the servers are busy, then the customer must wait until one of the servers becomes free
...
Using dynamic arrays, depending
on the number of servers specified by the user, a list of servers is created during
program execution
...
The following class,
serverListType, implements the list of servers as an ADT
...


~serverListType();
//Destructor
//Postcondition: The list of servers is destroyed
...

//Postcondition: If a free server is found, returns
//
its ID; otherwise, returns -1
...

//Postcondition: The number of busy servers is returned
...

//Postcondition: The server specified by serverID is set
//
to "busy", to serve the customer
//
specified by cCustomer, and the
//
transaction time is set according to the
//
parameter tTime
...

//Postcondition: The server specified by serverID is set
//
to "busy", to serve the customer
//
specified by cCustomer
...

//Postcondition: The transaction time of each busy

Application of Queues: Simulation

//
//
//
//
//
//
//
//
//
//

|

1193

server is decremented by one unit
...
Moreover, if the actual
parameter corresponding to outFile is
cout, a message indicating which customer
has been served is printed on the screen,
together with the customer's departing
time
...


private:
int numOfServers;
serverType *servers;
};

Figure 19-38 shows the UML class diagram of the class serverListType
...

The definitions of the constructor and destructor are straightforward
...
If a free server is found, it
returns the server’s ID; otherwise, the value -1 is returned, which indicates that all of the
servers are busy
...
isFree())
{
serverID = i;
break;
}
}

return serverID;

The function getNumberOfBusyServers searches the list of servers and determines and
returns the number of busy servers
...
isFree())
busyServers++;
}

return busyServers;

The function setServerBusy sets a server to busy
...
The
serverID of the server that is set to busy is passed as a parameter to this function
...
The
transaction time is later needed to determine the average wait time
...
setBusy();
servers[serverID]
...
setCurrentCustomer(cCustomer);
}

Application of Queues: Simulation

|

1195

void serverListType::setServerBusy(int serverID,
customerType cCustomer)
{
int time;
time = cCustomer
...
setBusy();
servers[serverID]
...
setCurrentCustomer(cCustomer);

The definition of the function updateServers is quite straightforward
...
When a busy server is found, its
transactionTime is decremented by 1
...
If the transactionTime of a busy server reduces to zero, then the
transaction of the customer being served by the server is complete
...
Otherwise, the
output is sent to a file specified by the user
...
isFree())
{
servers[i]
...
getRemainingTransactionTime() == 0)
{
outFile << "From server number " << (i + 1)
<< " customer number "
<< servers[i]
...

getCurrentCustomerArrivalTime()
+ servers[i]
...

getCurrentCustomerTransactionTime()
<< endl;
servers[i]
...
When a server
becomes available, the customer at the front of the queue leaves to conduct the
transaction
...
The ADT queueType designed in this chapter has all the
operations needed to implement a queue, except the operation of incrementing the
waiting time of each customer in the queue by one time unit
...
The definition of the class
waitingCustomerQueueType is as follows:
class waitingCustomerQueueType: public queueType
{
public:
waitingCustomerQueueType(int size = 100);
//Constructor
//Postcondition: The queue is initialized according to
//
the parameter size
...


};

void updateWaitingQueue();
//Function to increment the waiting time of each
//customer in the queue by one time unit
...
You can also derive it from the
class linkedQueueType, which implements the queue in a linked list
...


The definitions of the member functions are given next
...
The class waitingCustomerQueueType is derived from
the class queueType
...
The
only way to access the elements of the queue is to use the deleteQueue operation
...


Application of Queues: Simulation

|

1197

The addQueue operation inserts the element at the end of the queue
...
Given that
each deleteQueue operation is followed by an addQueue operation, how do we
determine that all of the elements of the queue have been processed? We cannot use
the isEmptyQueue or isFullQueue operations on the queue, because the queue will
never be empty or full
...
Every element of the
original queue is removed, processed, and inserted into the temporary queue
...
We can
then copy the elements from the temporary queue back into the original queue
...

Also, if the queue is large, extra computer time is needed to copy the elements from the
temporary queue back into the original queue
...

In the second solution, before starting to update the elements of the queue, we can insert
a dummy customer with a wait time of, say, -1
...
If we do not process the customer with
the wait time of -1, this customer is removed from the queue and, after processing all of
the elements of the queue, the queue will contain no extra elements
...
We will use this solution to update the
queue
...
setWaitingTime(-1);
int wTime = 0;
addQueue(cust);
while (wTime != -1)
{
cust = front();
deleteQueue();

}

}

wTime = cust
...
incrementWaitingTime();
addQueue(cust);

1
9

1198

| Chapter 19: Stacks and Queues

Main Program
To run the simulation, we first need to get the following information:


The number of time units the simulation should run
...

• The number of servers
...

• The approximate time between customer arrivals
...
By changing the values of
these parameters, we can observe the changes in the performance of the system
...
The definition of this function is:
void setSimulationParameters(int&
int&
int&
{
cout << "Enter the simulation
cin >> sTime;
cout << endl;

sTime, int& numOfServers,
transTime,
tBetweenCArrival)
time: ";

cout << "Enter the number of servers: ";
cin >> numOfServers;
cout << endl;
cout << "Enter the transaction time: ";
cin >> transTime;
cout << endl;

}

cout << "Enter the time between customer arrivals: ";
cin >> tBetweenCArrival;
cout << endl;

When a server becomes free and the customer queue is nonempty, we can move the
customer at the front of the queue to the free server to be served
...
The waiting time of the customer
is added to the total waiting time
...
Remove the customer from the front of the queue
...
front();
customerQueue
...
Update the total wait time by adding the current customer’s wait time to
the previous total wait time
...
getWaitingTime();

Application of Queues: Simulation

|

1199

3
...

serverList
...
We use the Poisson distribution
from statistics, which says that the probability of y events occurring at a given time is
given by the formula:
PðyÞ ¼

y eÀ
; y ¼ 0; 1; 2;
...
Suppose that, on
average, a customer arrives every four minutes
...
Assuming an equal likelihood of each
of the four minutes, the expected value that a customer arrives in each of the four minutes
is, therefore, 1 / 4 =
...
Next, we need to determine whether or not the customer
actually arrives at a given minute
...
One of the basic
assumptions of the Poisson distribution is that the probability of more than one outcome
occurring in a short time interval is negligible
...
Thus, we use e-l as the cutoff point to determine
whether a customer arrives at a given time unit
...
Then, l = 0
...
We can use an algorithm to generate a number between
0 and 1
...
25, we can assume that the customer
arrived at a particular time unit
...
If rNum > e-0
...

We now describe the function runSimulation to implement the simulation
...
The average transaction time is five minutes—that is, five time units
...
When the server becomes
free at time unit 97, the customer arriving at time unit 93 starts the transaction
...
Moreover, customers arriving at time units 96 and 100 are
in the queue
...
The general algorithm for this function is:
1
...


1
9

1200

| Chapter 19: Stacks and Queues

2
...
1
...


2
...


If the customer’s queue is nonempty, increment the waiting time of each
customer by one time unit
...
3
...


2
...


If a server is free and the customer’s queue is nonempty, remove a
customer from the front of the queue and send the customer to
the free server
...
Print the appropriate results
...

Once you have designed the function runSimulation, the definition of the function
main is simple and straightforward because the function main calls only the function
runSimulation
...
(The program was executed two times
...

Sample Runs:
Sample Run 1:
Customer number 1 arrived at time unit
Customer number 2 arrived at time unit
From server number 1 customer number 1
departed at time unit 9
Customer number 3 arrived at time unit
Customer number 4 arrived at time unit
From server number 1 customer number 2
departed at time unit 14
From server number 1 customer number 3
departed at time unit 19
Customer number 5 arrived at time unit
From server number 1 customer number 4
departed at time unit 24
From server number 1 customer number 5
departed at time unit 29

4
8
9
12

21

Application of Queues: Simulation

Customer number 6 arrived at time unit 37
Customer number 7 arrived at time unit 38
Customer number 8 arrived at time unit 41
From server number 1 customer number 6
departed at time unit 42
Customer number 9 arrived at time unit 43
Customer number 10 arrived at time unit 44
From server number 1 customer number 7
departed at time unit 47
Customer number 11 arrived at time unit 49
Customer number 12 arrived at time unit 51
From server number 1 customer number 8
departed at time unit 52
Customer number 13 arrived at time unit 52
Customer number 14 arrived at time unit 53
Customer number 15 arrived at time unit 54
From server number 1 customer number 9
departed at time unit 57
Customer number 16 arrived at time unit 59
From server number 1 customer number 10
departed at time unit 62
Customer number 17 arrived at time unit 66
From server number 1 customer number 11
departed at time unit 67
Customer number 18 arrived at time unit 71
From server number 1 customer number 12
departed at time unit 72
From server number 1 customer number 13
departed at time unit 77
Customer number 19 arrived at time unit 78
From server number 1 customer number 14
departed at time unit 82
From server number 1 customer number 15
departed at time unit 87
Customer number 20 arrived at time unit 90
From server number 1 customer number 16
departed at time unit 92
Customer number 21 arrived at time unit 92
From server number 1 customer number 17
departed at time unit 97
The simulation ran for 100 time units
Number of servers: 1
Average transaction time: 5
Average arrival time difference between customers: 4
Total waiting time: 269
Number of customers that completed a transaction: 17
Number of customers left in the servers: 1
The number of customers left in queue: 3
Average waiting time: 12
...
95
************** END SIMULATION *************

QUICK REVIEW
1
...

3
...

5
...

7
...

9
...

A stack is a Last In First Out (LIFO) data structure
...

A stack can be implemented as an array or a linked list
...

Stacks are restricted versions of arrays and linked lists
...

In postfix notation, the operators are written after the operands
...

b
...

A queue is a data structure in which the items are added at one end and
removed from the other end
...

The basic operations on a queue are as follows: add an item to the queue,
remove an item from the queue, retrieve the first or last element of the
queue, initialize the queue, check whether the queue is empty, and check
whether the queue is full
...

The middle elements of a queue should not be accessed directly
...

a
...

11
...


13
...

15
...

2
...


Describe the two basic operations on a stack
...
What is the
difference between stack
...
top - 1?
Consider the following statements:
stackType stack;
int x, y;

Show what is output by the following segment of code:
x = 4;
y = 0;
stack
...
push(x);
stack
...
top();
stack
...
push(x + y);
stack
...
push(3);
x = stack
...
pop();
cout << "x = " << x << endl;
cout << "y = " << y << endl;
while (!stack
...
top() << endl;
stack
...


Consider the following statements:
stackType stack;
int x;

Suppose that the input is:
14 45 34 23 10 5 -999

Show what is output by the following segment of code:
stack
...
isFullStack())
stack
...
isEmptyStack())
{
cout << " " << stack
...
pop();
}
cout << endl;
5
...

b
...


70 14 4 5 15 3 / * - - / 6 + =

d
...


8 2 + 3 * 16 4 / - =

3 5 6 * + 13 - 18 2 / + =

Convert the following infix expressions to postfix notations
...

b
...

d
...


((A + B) / (C - D) + E) * F - G
A + B * (C + D) - E / F * G + H

Write the equivalent infix expression for the following postfix expressions
...

b
...

8
...
h"
using namespace std;
template
void mystery(stackType& s, stackType& t);
int main()
{
stackType s1;
stackType s2;
string list[] = {"Winter", "Spring", "Summer", "Fall",
"Cold", "Warm", "Hot"};

1
9

1206

| Chapter 19: Stacks and Queues

for (int i = 0; i < 7; i++)
s1
...
isEmptyStack())
{
cout << s2
...
pop();
}
cout << endl;

template
void mystery(stackType& s, stackType& t)
{
while (!s
...
push(s
...
pop();
}
}
9
...
h"
using namespace std;
void mystery(stackType& s, stackType& t);
int main()
{
int list[] = {5, 10, 15, 20, 25};
stackType s1;
stackType s2;
for (int i = 0; i < 5; i++)
s1
...
isEmptyStack())
{
cout << s2
...
pop();
}
cout << endl;

Exercises

|

1207

void mystery(stackType& s, stackType& t)
{
while (!s
...
push(2 * s
...
pop();
}
}
10
...


12
...


14
...

Suppose that stack is an object of type linkedStackType
...
top(); and stack
...
Assume that this function is a
member of the class linkedListType, designed in Chapter 18
...
The original stack
remains unchanged
...
addQueue(x);
queue
...
front();
queue
...
addQueue(x + 5);
queue
...
addQueue(x);
queue
...
isEmptyQueue())
{
cout << queue
...
deleteQueue();
}
cout << endl;
15
...
push(0);
queue
...
push(x);
break;
case 1:
if (!stack
...
top()
<< endl;
stack
...
" << endl;
break;
case 2:
queue
...
isEmptyQueue())
{
cout << "Queue Element = " << queue
...
deleteQueue();
}
else
cout << "Sorry, the queue is empty
...
isEmptyStack())
{
cout << stack
...
pop();
}
cout << endl;

Exercises

|

1209

cout << "Queue Elements: ";
while (!queue
...
front() << " ";
queue
...


What does the following function do?
void mystery(queueType& q)
{
stackType s;
while (!q
...
push(q
...
deleteQueue();
}

}
17
...
isEmptyStack())
{
q
...
top());
s
...
Also, suppose that the value of queueFront
is 50 and the value of queueRear is 99
...
What are the values of queueFront and queueRear after removing an
element from queue?
Suppose that queue is a queueType object and the size of the array
implementing queue is 100
...

a
...


What are the values of queueFront and queueRear after adding an
element to queue?
b
...
Also, suppose that the value of queueFront
is 25 and the value of queueRear is 75
...


19
...


What are the values of queueFront and queueRear after adding an
element to queue?

1
9

1210

| Chapter 19: Stacks and Queues

What are the values of queueFront and queueRear after removing an
element from queue?
Suppose that queue is a queueType object and the size of the array
implementing queue is 100
...

b
...


What are the values of queueFront and queueRear after adding an
element to queue?
b
...
Also, suppose that the size of the array
implementing queue is 100
...
Suppose that the size of the array implementing queue is 100
...

a
...


22
...
What are the values of queueFront and queueRear after removing an
element from queue? Also, what is the position of the removed queue element?
Write a function template, reverseStack, that takes as a parameter a
stack object and uses a queue object to reverse the elements of the stack
...

Add the operation queueCount to the class queueType (the array implementation of queues), which returns the number of elements in the queue
...

Draw the UML class diagram of the class linkedStackType
...

Draw the UML class diagram of the class queueType
...


23
...


25
...

27
...

29
...


Two stacks of the same type are the same if they have the same number of
elements and their elements at the corresponding positions are the same
...

2
...


Also, write the definition of the function template to overload this operator
...

a
...

void

reverseStack(stackType &otherStack);

This operation copies the elements of a stack in reverse order onto
another stack
...
reverseStack(stack2);

4
...


6
...


8
...


copies the elements of stack1 onto stack2 in reverse order
...

The old contents of stack2 are destroyed, and stack1 is unchanged
...
Write the definition of the function template to implement the operation reverseStack
...

Write a program that takes as input an arithmetic expression
...
For
example, the arithmetic expressions {25 + (3 – 6) * 8} and 7 + 8 * 2 contain
matching grouping symbols
...

Write a program that uses a stack to print the prime factors of a positive
integer in descending order
...
Write a program that uses a stack to convert a binary
number into an equivalent decimal number
...
Write a program that uses a stack
to convert a decimal number into an equivalent binary number
...
If
the string consists of a decimal number, the program must use a stack to
convert the decimal number to the numeric format
...


| Chapter 19: Stacks and Queues

(Infix to Postfix) Write a program that converts an infix expression into
an equivalent postfix expression
...
The rules to convert infx into pfx are as follows:
a
...


Initialize pfx to an empty expression and also initialize the stack
...

If sym is an operand, append sym to pfx
...
2
...

b
...
If sym is ), pop and append all of the symbols from the stack
until the most recent left parentheses
...

b
...
If sym is an operator:
b
...
1
...

b
...
2
...

After processing infx, some operators might be left in the stack
...

b
...


c
...
You may assume that the expressions you will process
are error free
...
The class must include
the following operations:




getInfix: Stores the infix expression
...

showPostfix: Outputs the postfix expression
...
The resulting postfix expression is stored in pfx
...
If the

first operator is of higher or equal precedence than the second operator, it
returns the value true; otherwise, it returns the value false
...

Test your program on the following expressions:

Programming Exercises

a
...


(A + B ) * C;

c
...


A + ((B + C) * (E - F) - G) / (H - I);

e
...


12
...


14
...
Also, write a program to
test these operations
...
Also, write a
program to test these operations
...
Write the definition of the class and the definitions of the
function members of this queue design
...

Write the definition of the function moveNthFront that takes as a parameter a positive integer, n
...
The order of the remaining elements remains
unchanged
...


After a call to the function moveNthFront:
queue = {34, 5, 11, 67, 43, 55}
...


16
...
Also, write a program to test
your method
...
The
program should then verify whether the line of text is a palindrome (a set of
letters or numbers that is the same whether read forward or backward)
...
You can
also use the variable count to return the number of elements in the queue
...
Redefine the class
linkedQueueType by adding the variable count to keep track of the
number of elements in the queue
...
Add the function queueCount to

17
...


return the number of elements in the queue
...

Write the definition of the class linkedQueueType, which is derived
from the class unorderedLinkedList, as explained in this chapter
...

a
...

b
...

c
...
Test run your program for a variety of data
...


APPENDIX A

R ESERVED W ORDS

and
bitand
case
compl
default
dynamic_cast
export
for
include
mutable
not_eq
private
reinterpret_cast
sizeof
switch
true
typename
virtual
while

and_eq
bitor
catch
const
delete
else
extern
friend
inline
namespace
operator
protected
return
static
template
try
union
void
xor

asm
bool
char
const_cast
do
enum
false
goto
int
new
or
public
short
static_cast
this
typedef
unsigned
volatile
xor_eq

1215

auto
break
class
continue
double
explicit
float
if
long
not
or_eq
register
signed
struct
throw
typeid
using
wchar_t

This page intentionally left blank

APPENDIX B

O PERATOR P RECEDENCE

The following table shows the precedence (highest to lowest) and associativity of the
operators in C++
...


Left to right

++

ÀÀ

(as postfix operators)

Right to left

typeid

Right to left

dynamic_cast

static_cast

Right to left

const_cast

Right to left

reinterpret_cast
++
~

ÀÀ (as prefix operators)

& (address of)

new

delete

->*

ÀÀ

*
+

/

!

+ (unary)

* (dereference)

Left to right
Left to right

>>
<=

==

Right to left

Left to right


...

ASCII
0

1

2

3

4

5

6

7

8

9

0

nul

soh

stx

etx

eot

enq

ack

bel

bs

ht

1

lf

vt

ff

cr

so

si

dle

dc1

dc2

dc3

2

dc4

nak

syn

etb

can

em

sub

esc

fs

gs

3

rs

us

b

!

"

#

$

%

&

'

4

(

)

*

+

,

-


...
For example,
1219

1220

| Appendix C: Character Sets

the character in the row marked 6 (the number in the first column) and the column
marked 5 (the number in the second row) is A
...
Moreover, the character b at position 32 represents the
space character
...
The following table shows the abbreviations and meanings of
these characters
...

EBCDIC
0

1

2

3

5

6

7

8

9


...
For
example, the character in the row marked 19 (the number in the first column) and the
column marked 3 (the number in the second row) is A
...
Moreover, the character b at position 64
represents the space character
...
In fact, the characters at positions 00-63 and 250-255 are
nonprintable control characters
...


Operators that can be overloaded
+

-

*

/

%

^

&

|

!

&&

||

=

==

<

<=

>

>=

!=

+=

-=

*=

/=

%=

^=

|=

&=

<<

>>

>>=

<<=

++



->*

,

->

[]

()

~

new

delete

The following table lists the operators that cannot be overloaded
...



...
Furthermore, the binary number
1000001 is the binary representation of 65
...
The number system that the
computer uses is called the binary number system or base 2 system
...

Consider 65
...
, k
...
a1a0 is called the binary or base 2 representation of m
...
a1a0 to the base 2
...

Thus, a6a5a4a3a2a1a0 = 1000001, so the binary representation of 65 is 1000001, that is:
6510 ¼ ð1000001Þ2 :
If no confusion arises, then we write (1000001)2 as 10000012
...
Thus:
71110 ¼ 10110001112 :
It follows that to find the binary representation of a nonnegative, we need to find the
coefficients, which are 0 or 1, of various powers of 2
...

First, note that:
010 ¼ 02 ; 110 ¼ 12 ; 210 ¼ 102 ; 310 ¼ 112 ; 410 ¼ 1002 ; 510 ¼ 1012 ; 610 ¼ 1102 ;
and 710 ¼ 1112 :
Let us consider the integer 65
...
Next, 32 / 2 = 16, and 32 % 2 = 0, and so on
...
We can show this continuous division and
obtaining the remainder with the help of Figure E-1
...
For example, in the second row, 65 / 2 = 32, and
65 % 2 = 1
...
For each row, the
number in the second column is divided by 2, the quotient is written in the next row,
below the current row, and the remainder is written in the third column
...
You can write the binary
representation of the number starting with the last remainder in the third column,
followed by the second last remainder, and so on
...
Figure E-2 shows the quotients and the remainders
...
The weight of each bit in the binary number is assigned from right to left
...
The weight of the bit immediately to the left of the
rightmost bit is 1, the weight of the bit immediately to the left of it is 2, and so on
...
The weight of each bit is as follows:
weight

6

5 4 3

2 1

0

1

0 0 1

1 0

1

1228

| Appendix E: Additional C++ Topics

We use the weight of each bit to find the equivalent decimal number
...
For
the above binary number, the equivalent decimal number is:
1 Â 26 þ 0 Â 25 þ 0 Â 24 þ 1 Â 23 þ 1 Â 22 þ 0 Â 21 þ 1 Â 20
¼ 64 þ 0 þ 0 þ 8 þ 4 þ 0 þ 1
¼ 77:

Converting a Binary Number (Base 2) to Octal (Base 8)
and Hexadecimal (Base 16)
The previous sections described how to convert a binary number to a decimal number
(base 2)
...
To effectively deal with binary
numbers, two more number systems, octal (base 8) and hexadecimal (base 16), are of
interest to computer scientists
...
The digits in the
hexadecimal number system are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F
...

The algorithm to convert a binary number into an equivalent number in octal (or
hexadecimal) is quite simple
...
Suppose ab represents the number a to the base b
...

First we describe how to convert a binary number into an equivalent octal number and
vice versa
...

TABLE E-1

Binary representation of first eight octal numbers

Binary

Octal

Binary

Octal

000

0

100

4

001

1

101

5

010

2

110

6

011

3

111

7

Consider the binary number 1101100010101
...
Note that the binary number 1101100010101 has only 13 digits
...
In this
case, we just add two 0s to the left of the binary number; the equivalent binary number is
001101100010101
...

To convert an octal number into an equivalent binary number, using Table E-1, write
the binary representation of each octal digit in the number
...

Next we discuss how to convert a binary number into an equivalent hexadecimal number
and vice versa
...
Table E-2 gives
the binary representation of the first 16 hexadecimal numbers
...
Now,
11111010100010101012 ¼ 111 1101 0100 0101 01012
¼ 0111 1101 0100 0101 01012, add one zero to the left
¼ 7D45516

Hence, 11111010100010101012 ¼ 7D45516
...
For example,
A7F3216 ¼ 1010 0111 1111 0011 00102
¼ 101001111111001100102

Thus, A7F3216 ¼ 101001111111001100102
...
This section
expands on the concepts introduced in that chapter
...

However, the files that the programs have used until now are called text files
...
For example, consider the number 45
...
The eight-bit machine representation of '4' is
00000100 and the eight-bit machine representation of '5' is 00000101
...
When this number is read by a C++
program, it must first be converted to its binary format
...
The 16-bit binary representation of 45 is then
0000000000101101
...
It thus follows that reading data from and
writing data to a text file is not efficient, because the data must be converted from the text
to the binary format and vice versa
...
Such files are called binary files
...
Data in a text file is also called formatted data, and in
a binary file it is called raw data
...
This section explains how to create
binary files and also how to read data from binary files
...
Suppose outFile is
an ofstream variable (object)
...
open("employee
...
dat
...
Therefore, the file opening mode ios::binary specifies that the file is
opened in the binary mode
...
dat
...
write(reinterpret_cast (buffer),
sizeof(buffer));

where fileVariableName is the object used to open the output file, and the first argument
buffer specifies the starting address of the location in memory where the data is stored
...

For example, suppose num is an int variable
...
write(reinterpret_cast (&num),
sizeof(num));

Similarly, suppose empSalary is an array of, say, 100 components and the component
type is double
...
write(reinterpret_cast (empSalary),
sizeof(empSalary));

Next, let us discuss how to read data from a binary file
...
First, the binary file must be
opened
...
dat
...
open("employee
...
open("employee
...
The syntax to use
the function read is:
fileVariableName
...
The expression sizeof(buffer) specifies the size of the data,
in bytes, to be read
...

EXAMPLE E-1
//Creating and reading binary files
#include
#include
using namespace std;
struct studentType
{
char firstName[15];
char lastName[15];
int ID;
};
int main()
{
//create and initialize an array of students’ IDs
int studentIDs[5] = {111111, 222222, 333333,
444444, 555555};
//Line 1
//declare and initialize the struct newStudent
studentType newStudent = {"John", "Wilson",
777777};
//Line 2
ofstream outFile;

//Line 3

//open the output file as a binary file
outFile
...
dat", ios::binary);

//Line 4

//write the array in the binary format
outFile
...
write(reinterpret_cast (&newStudent),
sizeof(newStudent));
//Line 6
outFile
...
open("ids
...
"
<< "The program terminates!!!!" << endl; //Line 13
return 1;
//Line 14
}
//input the data into the array arrayID
inFile
...
read(reinterpret_cast (&student),
sizeof(student));

//Line 19

//output studentData
cout << student
...
firstName
<< " " << student
...
close();
}

//close the file

return 0;

//Line 15

//Line 21
//Line 22

Sample Run:
111111 222222 333333 444444 555555
777777 John Wilson

The output of the preceding program is self-explanatory
...


In the program in Example E-1, the statement in Line 2 declares the struct variable
newStudent and also initializes it
...
In other words, struct variables can also be initialized when they are
declared
...


1234

| Appendix E: Additional C++ Topics

EXAMPLE E-2
//Creating and reading a binary file consisting of
//bank customers' data
#include
#include
#include
using namespace std;
struct customerType
{
char firstName[15];
char lastName[15];
int ID;
double balance;
};
int main()
{
customerType cust;
ifstream inFile;
ofstream outFile;
inFile
...
txt");

//Line 1
//Line 2
//Line 3
//Line 4

if (!inFile)
//Line 5
{
cout << "The input file does not exist
...
open("customer
...
ID >> cust
...
lastName
>> cust
...
write(reinterpret_cast (&cust),
sizeof(cust));
//Line 11
inFile >> cust
...
firstName >> cust
...
balance;
//Line 12
}
inFile
...
clear();
outFile
...
open("customer
...
"
<< "The program terminates!!!!" << endl; //Line 18
return 1;
//Line 19
}
cout <<
<<
<<
<<
cout <<

left << setw(8) << "ID"
setw(16) << "First Name"
setw(16) << "Last Name"
setw(10) << " Balance" << endl;
fixed << showpoint << setprecision(2);

//read and output the data from the binary
//file customer
...
read(reinterpret_cast (&cust),
sizeof(cust));
while (inFile)
{
cout << left << setw(8) << cust
...
firstName
<< setw(16) << cust
...
balance
<< endl;
inFile
...
close();
}

//close the file

//Line 24
//Line 25

//Line 27

Sample Run:
First Name
Ashley
Brad
Lisa
Sheila
Rita
Ajay
Jose
Sheila
Tommy
Salma
Jennifer
Steve

//Line 22
//Line 23

//Line 26

return 0;

ID
77234
12345
87123
81234
11111
23422
22222
54234
55555
23452
32657
82722

//Line 20
//Line 21

Last Name
White
Smith
Johnson
Robinson
Gupta
Kumar
Ramey
Duffy
Pitts
Quade
Ackerman
Sharma

Balance
4563
...
45
2345
...
00
14863
...
90
25345
...
00
892
...
90
9823
...
00

|

1235

1236

| Appendix E: Additional C++ Topics

Random File Access
In Chapter 3 and the preceding section, you learned how to read data from and write data
to a file
...
However, the files were read and/or written
sequentially
...
For example, consider a program that processes customers’ data in a bank
...
Suppose we want
to access a customer’s data from the file that contains such data, say, for an account
update
...

Similarly, in an airline’s reservation system to access a passenger’s reservation information
sequentially, this might also be very time consuming
...
A convenient way to do this is to be able to read the data randomly from a
file, that is, randomly access any record in the file
...

The stream function seekg is used to move the read position to any byte in the file
...
seekg(offset, position);

The stream function seekp is used to move the write position to any byte in the file
...
seekp(offset, position);

The offset specifies the number of bytes the reading/writing positions are to be
moved, and position specifies where to begin the offset
...

Moreover, offset is a long integer representation of an offset
...

TABLE E-3

Values of position

position

Description

ios::beg

The offset is calculated from the beginning of the file
...


ios::end

The offset is calculated from the end of the file
...
txt:
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ

Also, suppose that inFile is an ifstream object and the file digitsAndLetters
...
One byte is used to store each character of this
line of text
...

Statement

Explanation

inFile
...
That is, it
sets the reading position just after the digit 9 or
just before the letter A
...
seekp(5L, ios::cur);

Moves the reading position of inFile five bytes
to the right of its current position
...
seekp(-6L, ios::end);

Sets the reading position of inFile to the sixth
byte (character) from the end
...


The program in the following example further explains how the functions seekg and
seekp work
...
open("digitsAndAlphabet
...
"
<< "The program terminates!!!!" << endl;
return 1;
}

//Line 4
//Line 5
//Line 6

1238

| Appendix E: Additional C++ Topics

inFile
...
seekg(6L, ios::cur);
//Line 9
inFile
...
seekg(7L, ios::beg);
//Line 12
inFile
...
seekg(-26L, ios::end);
inFile
...

EXAMPLE E-5
Suppose customerType is a struct defined as follows:
struct customerType
{
char firstName[15];
char lastName[15];
int ID;
double balance;
};

More on File Input/Output

|

1239

The program in Example E-2 created the binary file customer
...
You can use the function seekg to move the reading position
of this file to any record
...
dat
...
For example, consider the following statement:
inFile
...

The following program further illustrates how the function seekg works with structs
...
open("customer
...
"
<< "The program terminates!!!!" << endl; //Line 6
return 1;
//Line 7

cout << fixed << showpoint << setprecision(2);
//randomly read the records and output them
inFile
...
read(reinterpret_cast (&cust),
sizeof(cust));
cout << "Seventh customer's data: " << endl;
printCustData(cust);
inFile
...
read(reinterpret_cast (&cust),
sizeof(cust));
cout << "Ninth customer's data: " << endl;
printCustData(cust);

//Line 8
//Line 9
//Line 10
//Line 11
//Line 12
//Line 13
//Line 14
//Line 15

inFile
...
read(reinterpret_cast (&cust),
sizeof(cust));
//Line 17
cout << "Eighth (from the end) customer's data: "
<< endl;
//Line 18
printCustData(cust);
//Line 19
inFile
...
ID <<< " First Name: " << customer
...
lastName <<< " Account Balance: $" << customer
...
35
Ninth customer's data:
ID: 55555
First Name: Tommy
Last Name: Pitts

More on File Input/Output

|

1241

Account Balance: $892
...
50

The program in Example E-6 illustrates how the function seekg works
...

Similarly, the function seekp can be used to move the write position in a file to any
location
...
For example, suppose there are at most, say, 100 students in a class
...
Using the students’ IDs, we can create a
random access binary file in such a way that in the file, a student’s data is written at the
location specified by its ID
...
The advantage is that,
once the file is created, a student’s data from the file can be read, directly, using the
student’s ID
...

Here, we are assuming that the student IDs are in the range 1 to 100
...
In other words, a lot of space could be used
just to store only a few students’ data
...

The program in Example E-7 illustrates how to use the students’ IDs to organize the data
in a binary file
...


EXAMPLE E-7
//Creating and reading a random access file
...
open("studentData
...
"
<< "The program terminates!!!!" << endl; //Line 7
return 1;
//Line 8
}
//open a binary output file
outFile
...
dat", ios::binary);

//Line 9

inFile >> st
...
firstName
>> st
...
GPA;

//Line 10

while (inFile)
//Line
{
outFile
...
ID - 1) * studentSize,
ios::beg);
//Line
outFile
...
ID >> st
...
lastName >> st
...
close();
inFile
...
close();

//Line 15
//Line 16
//Line 17

cout <<
<<
<<
<<
cout <<

//Line 18
//Line 19

left << setw(3) << "ID"
setw(16) << "First Name"
setw(16) << "Last Name"
setw(12) << "Current GPA" << endl;
fixed << showpoint << setprecision(2);

//open the input file, which is a binary file
inFile
...
dat", ios::binary);
//Line 20
if (!inFile)
{
cout << "The input file does not exist
...
read(reinterpret_cast (&st),
sizeof(st));
while (inFile)
{
if (st
...
read(reinterpret_cast (&st),
sizeof(st));
//Line 28

return 0;

//Line 29

void printStudentData(const studentType& student)
{
cout << left << setw(3) << student
...
firstName
<< setw(16) << student
...
GPA
<< endl;
}

Sample Run:
ID
2
10
12
16
23
34
36
41
45
56
67
75

//Line 24
//Line 25

First Name
Sheila
Ajay
Ashley
Tommy
Rita
Brad
Salma
Steve
Sheila
Lisa
Jose
Jennifer

Last Name
Duffy
Kumar
White
Pitts
Gupta
Smith
Quade
Sharma
Robinson
Johnson
Ramey
Ackerman

Current GPA
4
...
60
3
...
40
3
...
50
3
...
50
2
...
90
3
...
00

The data in the file studentData
...
9
34 Brad Smith 3
...
9
45 Sheila Robinson 2
...
4
10 Ajay Kumar 3
...
8
2 Sheila Duffy 4
...
4

|

1243

1244

| Appendix E: Additional C++ Topics

36 Salma Quade 3
...
0
41 Steve Sharma 3
...
As indicated
in Chapter 1, there are two versions of C++—ANSI/ISO Standard C++ and
Standard C++
...
The header
files in Standard C++ have the extension
...
Moreover, the names of certain header files, such
as math
...
The language C++
evolved from C
...
h, stdlib
...
h—were brought from C into C++
...
h, iomanip
...
h—were specially designed for C++
...
In ANSI/ISO
Standard C++, to take advantage of the namespace mechanism, all of the header
files were modified so that the identifiers are declared within a namespace
...

In ANSI/ISO Standard C++, the extension
...
For the header files that were brought from C into C++,
the extension
...

Following are the names of the most commonly used header files in Standard C++ and
ANSI/ISO Standard C++:
Standard C++ Header File Name

ANSI/ISO Standard C++ Header File Name

assert
...
h
float
...
h
iomanip
...
h
limits
...
h
stdlib
...
h

cassert
cctype
cfloat
fstream
iomanip
iostream
climits
cmath
cstdlib
cstring

Naming Conventions of Header Files in ANSI/ISO Standard C++ and Standard C++ |

1245

To include a header file, say, iostream, the following statement is required:
#include

Furthermore, to use identifiers, such as cin, cout, endl, and so on, the program should
use either the statement:
using namespace std;

or the prefix std:: before the identifier
...
This appendix discusses some of the most widely used library
routines (and several named constants)
...
The names of
the Standard C++ header files are shown in parentheses
...
h)
The following table describes the function assert
...
h)
...

If the value of expression
is 0 (false), execution of
the program terminates
immediately
...


To disable all of the assert statements, place the preprocessor directive #define
NDEBUG before the directive #include
...
h)
The following table shows various functions from the header file cctype (ctype
...

Function Name
and Parameters

Parameter(s) Types

isalnum(ch)

ch is a char value

Function Return Value
Function returns an int value as follows:

• If ch is a letter or a digit character, that is
('A'-'Z', 'a'-'z', '0'-'9'), it
returns a nonzero value (true)
• 0 (false), otherwise
iscntrl(ch)

ch is a char value

Function returns an int value as follows:

• If ch is a control character (in ASCII, a
character value 0-31 or 127), it returns a
nonzero value (true)

• 0 (false), otherwise
isdigit(ch)

ch is a char value

Function returns an int value as follows:

• If ch is a digit ('0'-'9'), it returns a
nonzero value (true)

• 0 (false), otherwise
islower(ch)

ch is a char value

Function returns an int value as follows:

• If ch is lowercase ('a'-'z'), it returns a
nonzero value (true)

• 0 (false), otherwise
isprint(ch)

ch is a char value

Function returns an int value as follows:

• If ch is a printable character, including blank
(in ASCII, ' ' through '~'), it returns
a nonzero value (true)

• 0 (false), otherwise
ispunct(ch)

ch is a char value

Function returns an int value as follows:

• If ch is a punctuation character, it returns a
nonzero value (true)

• 0 (false), otherwise
isspace(ch)

ch is a char value

Function returns an int value as follows:

• If ch is a whitespace character (blank,
newline, tab, carriage return, form feed), it
returns a nonzero value (true)

• 0 (false), otherwise

Header File cfloat (float
...
h)
In Chapter 2, we listed the largest and smallest values belonging to the floating-point data
types
...
These largest and
smallest values are stored in named constants
...
The following table lists some of these constants
...

#include
#include
using namespace std;
int main()
{
cout <<
<<
cout <<
<<
cout <<
<<
cout <<
<<
cout <<
<<
cout <<
<<
cout <<
<<
cout <<
<<
cout <<
<<
}

"Approximate number of significant digits "
"in a float value " << FLT_DIG << endl;
"Maximum positive float value " << FLT_MAX
endl;
"Minimum positive float value " << FLT_MIN
endl;
"Approximate number of significant digits "
"in a double value " << DBL_DIG << endl;
"Maximum positive double value " << DBL_MAX
endl;
"Minimum positive double value " << DBL_MIN
endl;
"Approximate number of significant digits "
"in a long double value " << LDBL_DIG << endl;
"Maximum positive long double value " << LDBL_MAX
endl;
"Minimum positive long double value " << LDBL_MIN
endl;

return 0;

Header File climits (limits
...

We also remarked that these values are system dependent
...
The header file climits contains many such
named constants
...

Named Constant

Description

CHAR_BIT

Number of bits in a byte

CHAR_MAX

Maximum char value

CHAR_MIN

Minimum char value

SHRT_MAX

Maximum short value

SHRT_MIN

Minimum short value

Header File climits (limits
...

#include
#include
using namespace std;
int main()
{
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
cout <<
<<
cout <<
<<
cout <<
cout <<
<<
}

"Number of bits in a byte " << CHAR_BIT << endl;
"Maximum char value " << CHAR_MAX << endl;
"Minimum char value " << CHAR_MIN << endl;
"Maximum short value " << SHRT_MAX << endl;
"Minimum short value " << SHRT_MIN << endl;
"Maximum int value " << INT_MAX << endl;
"Minimum int value " << INT_MIN << endl;
"Maximum long value " << LONG_MAX << endl;
"Minimum long value " << LONG_MIN << endl;
"Maximum unsigned char value " << UCHAR_MAX
endl;
"Maximum unsigned short value " << USHRT_MAX
endl;
"Maximum unsigned int value " << UINT_MAX << endl;
"Maximum unsigned long value " << ULONG_MAX
endl;

return 0;

1252

| Appendix F: Header Files

Header File cmath (math
...


Function Name
and Parameters

Parameter(s) Type

Function Return Value

acos(x)

x is a floating-point expression,
–1
...
0

Arc cosine of x, a value between 0
...
0
x
1
...
718
...
0

Natural logarithm (base e) of x

log10(x)

x is a floating-point expression,
in which x > 0
...
If x = 0
...
0, y must

x raised to the power of y

x; (‘‘floor’’ of x)

be a whole number
...
h)

Function Name
and Parameters

Parameter(s) Type

x is a floating-point expression,
in which x ! 0
...
h)
Among others, this header file contains the definition of the following symbolic constant:
NULL: The system-dependent null pointer (usually 0)

Header File cstring (string
...


Function Name and
Parameters

Parameter(s) Type

Function Return Value

strcat(destStr, srcStr)

destStr and srcStr
are null-terminated char
arrays; destStr must be

The base address of
destStr is returned;
srcStr, including the
null character, is
concatenated to the end of

large enough to hold the
result

destStr
strcmp(str1, str2)

str1 and str2 are nullterminated char arrays

The returned value is as
follows:

• An int value < 0 if
str1 < str2

• An int value 0 if
str1 = str2

• An int value > 0 if
str1 > str2

1254

| Appendix F: Header Files

Function Name and
Parameters

Parameter(s) Type

strcpy(destStr, srcStr)

destStr and
srcStr are
null-terminated char
arrays

strlen(str)

str is a null-terminated
char array

Function Return Value

The base address of

destStr is returned;
srcStr is copied into
destStr
An integer value ! 0
specifying the length of
the str (excluding the
'\0') is returned

HEADER FILE string

This header file—not to be confused with the header file cstring—supplies a programmerdefined data type named string
...
These are defined as follows:
string::size_type

An unsigned integer type

string::npos

The maximum value of type string::size_type

The type string contains several functions for string manipulation
...

In this table, we assume that strVar is a string variable and str is a string variable, a
string constant, or a character array
...

Characters until the newline character are input
from istreamVar and stored in strVar
...
) The value returned by this function is
usually ignored
...
append(str, n)

The first n characters of the character array str are
appended to strVar
...
c_str()

The base address of a null-terminated C-string
corresponding to the characters in strVar
...
h)

|

1255

Expression

Effect

strVar
...


strVar
...

Removes all of the characters from strVar starting
at index pos
...
resize(n, ch);

Changes the size of storage allocation for strVar
to n
...
If n is greater than the current storage size, the
string is expanded to size n and the additional space
is filled with copies of the character specified by the
char variable ch
...
(The output of the program shows the size of the built-in data type on
which this program was run
...
To use the function
rand, the program must include the header file cstdlib
...
Typically, the value of RAND_MAX is 32767
...
The function rand
generates an integer between 0 and RAND_MAX
...
It also prints the value of RAND_MAX:
#include
#include
#include
using namespace std;
int main()
{
cout << fixed << showpoint << setprecision(5);
cout << "The value of RAND_MAX: " << RAND_MAX << endl;
cout << "A random number: " << rand() << endl;
cout << "A random number between 0 and 9: "
<< rand() % 10 << endl;
cout << "A random number between 0 and 1: "
<< static_cast (rand())
/ static_cast(RAND_MAX)
<< endl;
}

return 0;

Sample Run:
The value of RAND_MAX: 32767
A random number: 41
A random number between 0 and 9: 7
A random number between 0 and 1: 0
...
With the help of class templates, we developed (and
used) a generic code to process lists
...
In Chapters 18 and 19, we studied the three
most important data structures: linked lists, stacks, and queues
...
In addition, using the
second principle of object-oriented programming (OOP), we developed generic codes to
process unordered and ordered lists
...
This appendix discusses many important features of the STL and shows how
to use the tools provided by the STL in a program
...
This
requires the ability to store data in computer memory, access a particular piece of data,
and write algorithms to manipulate the data
...
We can then use the index to access a particular component of
the array
...
Algorithms, such as initializing the array, sorting, and searching, are used to
manipulate the data stored in an array
...
The
STL is equipped with these and other features to effectively manipulate the data
...
Iterators are used to step through the
elements of a container
...
The ensuing sections
discuss each of these three components in detail
...
The STL containers are divided
into three categories:




Sequence containers (also called sequential containers)
Associative containers
Container adapters

This appendix discusses sequence and container adapters
...
The three predefined
sequence containers are:




vectors
deque
lists

Before discussing container types in general, let us first briefly describe the sequence
container vector
...
Also, with the help of vector containers, we can describe several
properties that are common to all containers
...
Of course, there are operations that are specific to a container,
which will be discussed when describing a specific container
...
Because an array is a
random access data structure, the elements of a vector can be accessed randomly
...
However, inserting an item at the end is quite fast
...
However, to make this appendix
a stand-alone section, we repeat some of the material in Chapter 10
...


The name of the class that implements the vector container is vector
...
) The name of the header file containing the class
vector is vector
...
For example, the statement:

Container Types |

1261

vector intList;

declares intList to be a vector and the component type is int
...

DECLARING VECTOR OBJECTS

The class vector contains several constructors, including the default constructor
...

Table H-1 describes how a vector container of a specific type can be declared and
initialized
...
(The default
constructor is invoked
...

vecList and otherVecList
are of the same type
...

vecList is initialized using the
default constructor
...
vecList is
initialized using n copies of the
element elm
...
vecList is
initialized to the elements in the
,
range [beg, end) that is, all
the elements in the range
beg
...
Both beg and
end are pointers, called iterators in
STL terminology
...
)

1262

| Appendix H: Standard Template Library (STL)

Now that we know how to declare a vector sequence container, let us now discuss how
to manipulate the data stored in a vector container
...
The name of the function is shown in bold
...
at(index)

Returns the element at the position specified by index
...


vecList
...
(Does not check whether the
container is empty
...
back()

Returns the last element
...
)

From Table H-2, it follows that the elements in a vector can be processed just as they can
in an array; see Example H-1
...
Similarly,
the first element in a vector container is at location 0
...

vector intList(5);

You can use a loop, such as the following, to store elements into intList:
for (int j = 0; j < 5; j++)
intList[j] = j;

Similarly, you can use a for loop to output the elements of intList
...
Table H-3 describes some of these operations
...
(Suppose that vecCont is a vector container
...
capacity()

Returns the maximum number of elements that can
be inserted into the container vecCont without
reallocation
...
empty()

Returns true if the container vecCont is empty,
false otherwise
...
size()

Returns the number of elements currently in the container
vecCont
...
max_size()

Returns the maximum number of elements that can be
inserted into the container vecCont
...
Suppose that vecList is a
container of type vector
...
These operations are implemented as member
functions of the class vector, and are shown in bold
...


TABLE H-4

Various Operations on a Vector Container

Statement

Effect

vecList
...


vecList
...


vecList
...


1264

| Appendix H: Standard Template Library (STL)

TABLE H-4

Various Operations on a Vector Container (continued)

Statement

Effect

vecList
...

The position of the new element is
returned
...
insert(position, n, elem)

the position specified by
position
...
insert(position, beg, end)

A copy of the elements, starting at
beg until end-1, is inserted into
vecList at the position
specified by position
...
push_back(elem)

A copy of elem is inserted into
vecList at the end
...
pop_back()

Deletes the last element
...
resize(num)

Changes the number of elements
to num
...


vecList
...
If size() increases, the
default constructor creates the
new elements
...
An iterator is just like a pointer
...
In other words, with the help of an iterator, we can walk through
the elements of a container and process them one at a time
...


Example H-1 used a for loop and the array subscripting operator, [], to access the
elements of intList
...
Does this
mean that we can store only five elements in intList? The answer is no
...
However, because when we declare intList we
specify the size to be 5, in order to add any elements past position 4, we use the function

Container Types |

1265

push_back
...

Example H-2 explains how to use the function push_back
...
push_back(34);
intList
...


In Example H-2, because intList is declared to be of size 0, we use the function
push_back to add elements to intList
...

For example, suppose that intList is declared as in Example H-2
...
resize(10);

Similarly, the following statement increases the size of intList by 10:
intList
...
size() + 10);

However, at times, the push_back function is more convenient because it does not
need to know the size of the vector; it simply adds the elements at the end
...

DECLARING AN ITERATOR TO A VECTOR CONTAINER

The class vector contains a typedef iterator, which is declared as a public
member
...
For
example, the statement:
vector::iterator intVecIter;

declares intVecIter to be an iterator to a vector container of type int
...

The expression:
++intVecIter

advances the iterator intVecIter to the next element in the container, and the
expression:
*intVecIter

returns the element at the current iterator position
...
Recall that when used as a unary operator, * is called the dereferencing
operator
...

Suppose that we have the following statements:
vector intList;
vector::iterator intVecIter;

//Line 1
//Line 2

The statement in Line 1 declares intList to be a vector container, and the element type
is int
...

CONTAINERS AND THE FUNCTIONS begin AND end

Every container has the member functions begin and end
...
Also, these functions have no
parameters
...
begin();

the iterator intVecIter points to the first element in the container intList
...
begin(); intVecIter != intList
...


Container Types |

1267

EXAMPLE H-3
Consider the following statements:
int intArray[7] = {1, 3, 5, 7, 9, 11, 13};
vector vecList(intArray, intArray + 7};
vector::iterator intVecIter;

//Line 1
//Line 2
//Line 3

The statement in Line 2 declares and initializes the vector container vecList
...
begin();
++intVecIter;
vecList
...
The statement in Line 6 inserts 22 at the position specified by intVecIter
...

Notice that the size of the container also increases
...


EXAMPLE H-4
#include
#include
using namespace std;
int main()
{
vector intList;
int i;

//Line 1
//Line 2

intList
...
push_back(75);
intList
...
push_back(35);

//Line
//Line
//Line
//Line

3
4
5
6

cout << "Line 7: List elements: ";
for(i = 0; i < 4; i++)
cout << intList[i] << " ";
cout << endl;

//Line
//Line
//Line
//Line

7
8
9
10

1268

| Appendix H: Standard Template Library (STL)

for(i = 0; i < 4; i++)
intList[i] *= 2;

//Line 11
//Line 12

cout << "Line 13: List elements: ";
for(i = 0; i < 4; i++)
cout << intList[i] << " ";
cout << endl;

//Line
//Line
//Line
//Line

vector::iterator listIt;

//Line 17

cout << "Line 18: List elements: ";
for (listIt = intList
...
end(); ++listIt)
cout << *listIt << " ";
cout << endl;

//Line 18
//Line 19
//Line 20
//Line 21

listIt = intList
...
insert(listIt, 88);

//Line 25

cout << "Line 25: List elements: ";
for (listIt = intList
...
end(); ++listIt)
cout << *listIt << " ";
cout << endl;
}

13
14
15
16

//Line 26
//Line 27
//Line 28
//Line 29

return 0;

Sample Run:
Line
Line
Line
Line

7: List elements: 13 75 28 35
13: List elements: 26 150 56 70
18: List elements: 26 150 56 70
25: List elements: 26 150 88 56 70

The statement in Line 1 declares a vector container (or vector for short), intList, of
type int
...
The statements in
Lines 3 through 6 use the operation push_back to insert four numbers—13, 75, 28,
and 35—into intList
...
In the output, see the line
marked Line 7, which contains the output of Lines 7 through 10
...
In the output, see the
line marked Line 13, which contains the output of Lines 13 through 16
...
Using the iterator listIt, the statements in

Container Types |

1269

Lines 19 and 20 output the elements of intList
...
The statements in Lines 23 and 24 advance
listIt twice; after these statements execute, listIt points to the third element of
intList
...
Because listIt points to the component at position 2 (the third
element of intList), 88 is inserted at position 2 in intList; that is, 88 becomes the third
element of intList
...


Member Functions Common to All Containers
The previous section discussed vector containers
...
For example, every container class has the default constructor, several constructors with parameters, the destructor, a function to insert an
element into a container, and so on
...
Because
every container is a class, several operations are directly defined for a container, and are
provided as part of the definition of the class
...
Table H-5 describes the member functions that are common to all containers; that is,
these functions are included as members of the class template implementing the container
...
In Table H-5, the name of
the function is shown in bold
...

TABLE H-5

Operations Common to All Containers

Member Function

Description

Default constructor

Initializes the object to an empty state
...
We
will describe these constructors when we discuss
a specific container
...


Destructor

Executes when the object goes out of scope
...
empty()

Returns true if container ct is empty, false
otherwise
...
size()

Returns the number of elements currently in
container ct
...
max_size()

Returns the maximum number of elements that
can be inserted in container ct
...
swap(ct2)

Swaps the elements of containers ct1 and ct2
...
begin()

Returns an iterator to the first element into
container ct
...
end()

Returns an iterator to the position after the last
element into container ct
...
rbegin()

Reverse begin
...
This function is used
to process the elements of ct in reverse
...
rend()

Reverse end
...


ct
...
Note that here
position is an iterator
...
erase(beg, end)

Deletes all the elements between beg
...
Both beg and end are
iterators
...
clear()

Deletes all the elements from the container
...


Operator Functions

ct1 = ct2;

Copies the elements of ct2 into ct1
...


ct1 == ct2

Returns true if containers ct1 and ct2 are
equal, false otherwise
...


Container Types |

1271

Because these operations are common to all containers, when discussing a specific
container, to save space, these operations will not be listed again
...
In
addition to these member functions, Table H-6 describes the member functions that are
common to all sequence containers, that is, containers of type vector, deque, and list
...
(Suppose that seqCont is a sequence container
...
insert(position, elem)

A copy of elem is inserted at the
position specified by the iterator
position
...


n copies of elem are inserted at
seqCont
...


seqCont
...
Also, beg and end
are iterators
...
push_back(elem)

A copy of elem is inserted into
seqCont at the end
...
pop_back()

Deletes the last element
...
erase(position)

Deletes the element at the position
specified by the iterator
position
...
erase(beg, end)

Deletes all the elements starting at
beg until end-1
...


seqCont
...


1272

| Appendix H: Standard Template Library (STL)

TABLE H-6

Member Functions Common to All Sequence Containers (continued)

Expression

Description

seqCont
...
If size() grows, the new
elements are created by their
default constructor
...
resize(num, elem)

Changes the number of elements
to num
...


copy Algorithm
Example H-4 used a for loop to output the elements of a vector container
...

The function copy is provided as a part of the generic algorithm and can be used with any
container type
...

The function copy does more than output the elements of a container
...
For
example, to output the elements of a vector, or to copy the elements of a vector into
another vector, we can use the function copy
...
The parameter first2 specifies
where to copy the elements
...

Note that the elements of the range first1
...

The definition of the function template copy is contained in the header file algorithm
...

Consider the following statement:
int intArray[] = {5, 6, 8, 3, 40, 36, 98, 29, 75};

Container Types |

1273

This statement creates an array intArray of nine components
...

The statement:
vector vecList(9);

creates an empty container of nine components of type vector, and the element type
is int
...
Therefore, intArray points to the first component of the array,
intArray + 1 points to the second component of the array, and so on
...
begin());

This statement copies the elements starting at the location intArray—which is the first
component of the array intArray, until intArray + 9 - 1 (that is, intArray + 8),
which is the last element of the array intArray—into the container vecList
...
begin()
...
Also, first2 is intArray,
that is, first2 points to the location of the first element of the array intArray
...
After the preceding statement executes:
intArray[] = {6, 8, 3, 40, 36, 98, 29, 75, 75}

Clearly, the elements of the array intArray are shifted to the left by one position
...
rbegin() + 2, vecList
...
rbegin());

Recall that the function rbegin, reverse begin, returns a pointer to the last element in a
container, and this function is used to process the elements of a container in reverse
...
rbegin() + 2 returns a pointer to the third to the last element in
the container vecList
...
The previous statement shifts the elements
of the container vecList to the right by two positions
...
Before
showing Example H-5, let us next describe a special type of iterators, called ostream
iterators, which work well with the function copy to copy the elements of a
container to an output device
...

However, the function copy can also be used to output the elements of a container
...
(ostream iterators are
discussed later in this appendix
...

The following statement illustrates how to create an ostream iterator of type int:
ostream_iterator screen(cout, " ");

//Line A

This statement creates screen to be an ostream iterator, and the element type is int
...
This means that
the iterator screen is initialized using the object cout, and when this iterator outputs
the elements, they are separated by a space
...

Similarly, the statement:
copy(vecList
...
end(), screen);

outputs the elements of the container vecList on the screen
...
Also, until we discuss ostream iterators in detail, we
will use statements similar to the statement in Line A to create an ostream
iterator
...
For
example, the statement (shown previously):
copy(vecList
...
end(), screen);

is equivalent to the statement:
copy(vecList
...
end(),
ostream_iterator(cout, " "));

Container Types |

1275

Finally, the statement:
copy(vecList
...
end(),
ostream_iterator(cout, ", "));

outputs the elements of vecList with a comma and space between them
...

EXAMPLE H-5
#include
#include
#include
#include






using namespace std;
int main()
{
int intArray[] = {5, 6, 8, 3, 40,
36, 98, 29, 75};

//Line 1

vector vecList(9);

//Line 2

ostream_iterator screen(cout, " ");

//Line 3

cout << "Line 4: intArray: ";
copy(intArray, intArray + 9, screen);
cout << endl;

//Line 4
//Line 5
//Line 6

copy(intArray, intArray + 9, vecList
...
begin(), vecList
...
rbegin() + 2, vecList
...
rbegin());
cout << "Line 16: After shifting the elements "
<< "down by two positions, "<< endl
<< "
vecList: ";

//Line 12
//Line 13
//Line 14
//Line 15
//Line 16

1276

| Appendix H: Standard Template Library (STL)

copy(vecList
...
end(), screen);
cout << endl;
}

//Line 17
//Line 18

return 0;

Sample Run:
Line 4: intArray: 5 6 8 3 40 36 98 29 75
Line 8: vecList: 5 6 8 3 40 36 98 29 75
Line 12: After shifting the elements one position to the left,
intArray: 6 8 3 40 36 98 29 75 75
Line 16: After shifting the elements down by two positions,
vecList: 5 6 5 6 8 3 40 36 98

Sequence Container: deque
This section describes the sequence container deque
...
Deque containers are implemented as dynamic arrays in such a way that the
elements can be inserted at both ends
...

Elements can also be inserted in the middle
...

The name of the class defining the deque containers is deque
...
Therefore, to use a deque container in
a program, the program must include the following statement:
#include

The class deque contains several constructors
...
Table H-7 describes various ways a deque object can
be declared
...
(The default constructor is
invoked
...


Container Types |

TABLE H-7

1277

Various Ways to Declare a deque Object (continued)

Statement

Description

deque deq(size);

Creates the deque container deq
of size size
...


deque deq(n, elm);

Creates the deque container deq
of size n
...


deque deq(beg, end);

Creates the deque container deq
...
end-1
...


In addition to the operations that are common to all containers (see Table H-6), Table H-8
describes operations that can be used to manipulate the elements of a deque container
...
The statement
also shows how to use a particular function
...
)
TABLE H-8

Various Operations that Can Be Performed on a deque Object

Expression

Description

deq
...


deq
...
end-1
...
push_front(elem)

Inserts elem at the beginning of deq
...
pop_front()

Removes the first element from deq
...
at(index)

Returns the element at the position specified by index
...


deq
...
(Does not check whether the
container is empty
...
back()

Returns the last element
...
)

1278

| Appendix H: Standard Template Library (STL)

Example H-6 illustrates how to use a deque container in a program
...
push_back(13);
intDeq
...
push_back(28);
intDeq
...
begin(), intDeq
...
push_front(0);
intDeq
...
begin(), intDeq
...
pop_front();
intDeq
...
begin(), intDeq
...
pop_back();
intDeq
...
begin(), intDeq
...
The statement in Line 2 declares screen to be an
ostream iterator initialized to the standard output device
...
The statement in Line 8 outputs the elements of intDeq
...

The statement in Line 10 inserts 0 at the beginning of intDeq; the statement in Line 11
inserts 100 at the end of intDeq
...

The statements in Lines 15 and 16 use the operation pop_front to remove the first two
elements of intDeq, and the statement in Line 18 outputs the modified intDeq
...


Sequence Container: list
This section describes the sequence container list
...
Thus, every element in a list points to its immediate predecessor and
immediate successor (except the first and the last elements)
...
Therefore, to access, say, the fifth
element in a list, we must first traverse the first four elements
...
Also, the
definition of the class list, and the definitions of the functions to implement the
various operations on a list, are contained in the header file list
...
Thus, a
list object can be initialized several ways when it is declared
...

TABLE H-9

Various Ways to Declare a list Object

Statement

Description

list listCont;

Creates the empty list
container listCont
...
)

list listCont(otherList);

Creates the list container
listCont and initializes
it to the elements of
otherList
...


list listCont(size);

Creates the list container
listCont of size size
...


list listCont(n, elm);

Creates the list container
listCont of size n
...


list listCont(beg, end);

Creates the list container
listCont
...
end-1
...


Table H-5 described the operations that are common to all containers, and Table H-6
described the operations that are common to all sequence containers
...
The name of the function implementing the operation is shown in bold
...
)

Container Types |

TABLE H-10

1281

Various Operations Specific to a list Container

Expression

Description

listCont
...


listCont
...
end-1
...


listCont
...


listCont
...


listCont
...
(Does not
check whether the container is empty
...
back()

Returns the last element
...
)

listCont
...


listCont
...


listCont
...


listCont
...


listCont
...
The sort criteria is <
...
sort(oper)

The elements of listCont are
sorted
...


1282

| Appendix H: Standard Template Library (STL)

TABLE H-10

Various Operations Specific to a list Container (continued)

Expression

Description

listCont1
...
This operation moves all the
elements of listCont2 into
listCont1
...

Moreover, after this operation,
listCont2 is empty
...
merge(listCont2,oper)

Suppose that the elements of
listCont1 and listCont2 are
sorted according to the sort criteria
oper
...
After this operation, the
elements in listCont1 are sorted
according to the sort criteria oper
...
reverse()

The elements of listCont are
reversed
...

EXAMPLE H-7
//List Container Example
#include
#include
#include
#include






using namespace std;
int main()
{
list intList1, intList2, intList3, intList4; //Line 1
ostream_iterator screen(cout, " ");

//Line 2

intList1
...
push_back(58);
intList1
...
push_back(58);
intList1
...
push_back(15);
intList1
...
push_back(98);
intList1
...
begin(), intList1
...
begin(), intList2
...
unique();

//Line 19

cout << "Line 20: After removing the consecutive "
<< "duplicates," << endl
<< "
intList1: ";
//Line 20
copy(intList1
...
end(), screen);
//Line 21
cout << endl;
//Line 22
intList2
...
begin(),intList2
...
push_back(13);
intList3
...
push_back(23);
intList3
...
push_back(136);

//Line
//Line
//Line
//Line
//Line

cout << "Line 32: intList3: ";
copy(intList3
...
end(), screen);
cout << endl;

//Line 32
//Line 33
//Line 34

intList3
...
begin(), intList3
...
merge(intList3);

//Line 39

cout << "Line 40: After merging intList2 and "
<< "intList3, intList2: " << endl
<< "
";

//Line 40

27
28
29
30
31

1283

1284

| Appendix H: Standard Template Library (STL)

copy(intList2
...
end(), screen);
cout << endl;
}

//Line 41
//Line 42

return 0;

Sample Run:
Line 12: intList1: 23 58 58 58 36 15 93 98 58
Line 16: intList2: 23 58 58 58 36 15 93 98 58
Line 20: After removing the consecutive duplicates,
intList1: 23 58 36 15 93 98 58
Line 24: After sorting, intList2: 15 23 36 58 58 58 58 93 98
Line 32: intList3: 13 25 23 198 136
Line 36: After sorting, intList3: 13 23 25 136 198
Line 40: After merging intList2 and intList3, intList2:
13 15 23 23 25 36 58 58 58 58 93 98 136 198

For the most part, the output of the preceding program is straightforward
...
The statement in Line 15 copies the elements of
intList1 into intList2
...
The statement in Line 19 removes any consecutive occurrences of the same
elements
...
The operation
unique removes two occurrences of 58
...

The statement in Line 23 sorts intList2
...
The statement in Line 35 sorts intList3, and the
statement in Line 39 merges intList2 and intList3 into intList2
...
The meanings of the remaining statements are similar
...
In general, an iterator points to the elements of a container
(sequence or associative)
...

The two most common operations on iterators are ++ (the increment operator) and * (the
dereferencing operator)
...
The statement:
++cntItr;

advances cntItr so that it points to the next element in the container
...


Iterators

|

1285

IOStream Iterators
A useful set of iterators is stream iterators—istream iterators and ostream iterators
...

istream_iterator

The istream iterator is used to input data into a program from an input stream
...
The
general syntax to use an istream iterator is:
istream_iterator isIdentifier(istream&);

where Type is either a built-in type or a user-defined class type, for which an input
iterator is defined
...

ostream_iterator

The ostream iterators are used to output data from a program to an output stream
...
We review them here for the sake of
completeness
...

The general syntax to use an ostream iterator is:
ostream_iterator osIdentifier(ostream&);

or:
ostream_iterator osIdentifier(ostream&, char* deLimit);

where Type is either a built-in type or a user-defined class type, for which an output
iterator is defined
...
In the second form of declaring an ostream
iterator, using the second argument (deLimit) of the initializing constructor, we can
specify the character separating the output
...
In addition to the containers
that work in a general framework, the STL also provides containers to accommodate
special situations
...
The three container adapters are:

1286





| Appendix H: Standard Template Library (STL)

Stack
Queue
Priority queues

The container adapters do not support any type of iterator
...
The next two sections describe the container adapters
stack and queue
...
Because a stack is an important data
structure, the STL provides a class to implement stacks in a program
...
Table H-11 defines various operations supported by the
stack container class
...


empty

Returns true if the stack is empty, false otherwise
...


top

Returns the top element of the stack, but does not remove the element
from the stack
...


pop

Removes the top element of the stack
...
For example, the relational
operator == can be used to determine whether two stacks are identical, and so on
...


EXAMPLE H-8
#include
#include
using namespace std;

Iterators

int main()
{
stack intStack;

1287

//Line 1

intStack
...
push(8);
intStack
...
push(3);

//Line
//Line
//Line
//Line

cout << "Line 6: The top element of "
<< "intStack: " << intStack
...
pop();

//Line 7

cout << "Line 8: After the pop operation, "
<< "the top element of intStack: "
<< intStack
...
empty())
{
cout << intStack
...
pop();
}

//Line 10
//Line 11
//Line 12

cout << endl;
}

|

2
3
4
5

//Line 13

return 0;

Sample Run:
Line 6: The top element of intStack: 3
Line 8: After the pop operation, the top element of intStack: 20
Line 9: intStack elements: 20 8 16

QUEUE

Chapter 19 discussed the data structure queue in detail
...
The name of
the class defining a queue is queue, and the name of the header file containing the
definition of the class queue is queue
...


1288

| Appendix H: Standard Template Library (STL)

TABLE H-12

Various Operations on a queue Object

Operation

Description

size

Returns the actual number of elements in the queue
...


push(item)

Inserts a copy of item into the queue
...
This operation is implemented
as a value-returning function
...
This operation is implemented as a value-returning
function
...


In addition to the operations size, empty, push, front, back, and pop, the queue
container class also provides relational operators to compare two queues
...

The program in Example H-9 illustrates how to use the queue container class
...
push(26);
intQueue
...
push(50);
intQueue
...
front()
<< endl;

//Line 6

Algorithms

cout << "Line 7: The last element of "
<< "intQueue: " << intQueue
...
empty())
{
cout << intQueue
...
pop();
}

//Line 11
//Line 12
//Line 13

cout << endl;
}

//Line 8

cout << "Line 9: After the pop operation, "
<< "the front element of intQueue: "
<< intQueue
...
pop();

|

//Line 14

return 0;

Sample Run:
Line
Line
Line
Line

6: The front element of intQueue: 26
7: The last element of intQueue: 33
9: After the pop operation, the front element of intQueue: 18
10: intQueue elements: 18 50 33

Algorithms
Several operations can be defined for a container
...
However, several operations—such as
find, sort, and merge—are common to all containers
...
The algorithms are bound to a particular container through an iterator pair
...
The ensuing
sections describe several of these algorithms and show how to use them in a program
...


STL Algorithm Classification
In earlier sections, you applied various operations on the sequence container, such as
clear, sort, merge, and so on
...
All those algorithms and a few
more are also available in a more general form, called generic algorithms, and can
be applied in a variety of situations
...

The STL contains algorithms that look only at the elements in a container and that move
the elements of a container
...
The STL also contains
algorithms for basic set theory operations, such as set union and intersection
...
The algorithms in the STL can be classified into the following
categories:





Nonmodifying algorithms
Modifying algorithms
Numeric algorithms
STL algorithms

The next four sections describe these algorithms
...
Certain algorithms, such as numeric, are
contained in the header file numeric
...
Table H-13 describes the nonmodifying algorithms
...
Table H-14 describes
the modifying algorithms
...
For example, next_permutation, partition,
previous_permutation, random_shuffle, reverse, reverse_copy, rotate,
rotate_copy, and stable_partition are mutating algorithms
...
Table H-15 defines these algorithms
...


STL Algorithms
The ensuing sections describe some of the STL algorithms
...
In the function prototypes, the parameter types indicate
for which type of container the algorithm is applicable
...
The element that is used as a filling element is passed as a
parameter to these functions
...
The prototypes of these functions are:
template
void fill(forwardItr first, forwardItr last, const Type& value);
template
void fill_n(forwardItr first, size n, const Type& value);

The first two parameters of the function fill are forward iterators that specify the
starting and ending positions of the container; the third parameter is the filling element
...
The program
in Example H-10 illustrates how to use these functions
...
begin(), vecList
...
begin(), vecList
...
begin(), 3, 5);

//Line 7

cout << "Line 8: After filling the first "
<< "three elements with 5's: "
<< endl << "
";
copy(vecList
...
end(), screen);
cout << endl;

//Line 8
//Line 9
//Line 10

}

return 0;

Sample Run:
Line 4: After filling vecList with 2’s: 2 2 2 2 2 2 2 2
Line 8: After filling the first three elements with 5's:
5 5 5 2 2 2 2 2

The statements in Lines 1 and 2 declare vecList to be a sequence container of size 8,
and screen to be an ostream iterator initialized to cout with the delimit character
space, respectively
...
The statement in Line 5 outputs the
elements of vecList using the copy function
...
In the statement in Line 7,
the first parameter of fill_n is vecList
...
The second parameter of fill_n is 3, which
specifies the number of elements to be filled, and the third parameter, 5, specifies the

1294

| Appendix H: Standard Template Library (STL)

filling element
...
The
statement in Line 9 outputs the elements of vecList
...
These
functions are defined in the header file algorithm
...
last-1 for the element
searchValue
...
The function
find_if searches the range of elements first
...
If an element satisfying op(rangeElement) true is
found, it returns the position in the given range where such an element is found;
otherwise, it returns last
...


EXAMPLE H-11
Consider the following statements:
char cList[10] = {'a', 'i', 'C', 'd', 'e', 'f',
'o', 'H', 'u', 'j'};

//Line 1

vector charList(cList, cList + 10);

//Line 2

vector::iterator position;

//Line 3

After the statement in Line 2 executes, the vector container charList is:
charList = {'a', 'i', 'C', 'd', 'e', 'f', 'o', 'H', 'u', 'j'};

Consider the following statement:
position = find(charList
...
end(), 'd');

Algorithms

|

1295

This statement searches charList for the first occurrence of 'd' and returns an iterator,
which is stored in position
...
Therefore, position points to the element at position 3 in charList
...
begin(), charList
...
(Note that the function isupper from the header file cctype is passed
as the third parameter to the function find_if
...
Therefore, after this statement executes, position
points to the third element of charList
...


Functions remove and replace
The function remove is used to remove certain elements from a sequence
...
Some of the prototypes of these functions are:
template
forwardItr remove(forwardItr first, forwardItr last,
const Type& value);
template
void replace(forwardItr first, forwardItr last,
const Type& oldValue, const Type& newValue);

The function remove removes each occurrence of a given element in the range
first
...
The element to be removed is passed as the third parameter to this
function
...

The function replace replaces all the elements in the range first
...

The program in Example H-12 shows how to use the functions remove and replace
...
begin(), charList1
...
begin(),
charList1
...
begin(), lastElem, screen);
cout << endl;

//Line 10
//Line 11
//Line 12

cout << "Line 13: Character list 2: ";
//Line 13
copy(charList2
...
end(), screen); //Line 14
cout << endl;
//Line 15
//replace
replace(charList2
...
end(),
'A', 'Z');

//Line 16

cout << "Line 17: Character list 2 after "
<< "replacing A with Z: " << endl;
//Line 17
copy(charList2
...
end(), screen); //Line 18
cout << endl;
//Line 19
}

return 0;

Sample Run:
Line 6: Character list 1: A a A B A c D e F A
Line 10: Character list 1 after removing A: a B c D e F
Line 13: Character list 2: A a A B A c D e F A
Line 17: Character list 2 after replacing A with Z:
Z a Z B Z c D e F Z

Algorithms

|

1297

The statements in Lines 2 and 3 create vector lists, charList1 and charList2, of type
char and initialize them using the array cList created in Line 1
...
The statement in Line 5 declares the ostream
iterator screen
...

The statement in Line 9 uses the function remove to remove all the occurrences of 'A'
from charList1
...
The statement in Line 11 outputs the
elements in the new range
...
The statement in List 18 outputs the elements of
charList2
...
The function search is used to search for elements
...
last1-1 and first2
...
last1-1
where the range first2
...
last1-1
...
last-1 in ascending
order
...
last-1,
false otherwise
...


1298

| Appendix H: Standard Template Library (STL)

EXAMPLE H-13
//STL functions search, sort, and binary_search
#include
#include
#include
#include






using namespace std;
int main()
{
int intList[15] = {12, 34, 56, 34, 34,
78, 38, 43, 12, 25,
34, 56, 62, 5, 49};

//Line 1

vector vecList(intList, intList + 15);
int list[2] = {34, 56};

//Line 2
//Line 3

vector::iterator location;

//Line 4

ostream_iterator screenOut(cout, " ");

//Line 5

cout << "Line 6: vecList: ";
copy(vecList
...
end(), screenOut);
cout << endl;

//Line 6
//Line 7
//Line 8

cout << "Line 9: list: ";
copy(list, list + 2, screenOut);
cout << endl;

//Line 9
//Line 10
//Line 11

//search
location = search(vecList
...
end(),
list, list + 2);
//Line 12
if (location != vecList
...
"
<< "The first occurrence of \n
"
<< " list in vecList is at position: "
<< (location - vecList
...
"
<< endl;

//Line 13

//Line 14
//Line 15
//Line 16

//sort
sort(vecList
...
end());

//Line 17

cout << "Line 18: vecList after sorting:\n"
<< "
";
copy(vecList
...
end(), screenOut);

//Line 18
//Line 19

Algorithms

cout << endl;

//Line 21

found = binary_search(vecList
...
end(), 78);

//Line 22

if (found)
cout << "Line 24: 43 found in vecList "
<< endl;
else
cout << "Line 26: 43 not in vecList" << endl;
}

1299

//Line 20

//binary_search
bool found;

|

//Line 23
//Line 24
//Line 25
//Line 26

return 0;

Sample Run:
Line 6: vecList: 12 34 56 34 34 78 38 43 12 25 34 56 62 5 49
Line 9: list: 34 56
Line 14: list found in vecList
...
The statement in Line 3 creates an array, list, of two
components and also initializes list
...
The
statement in Line 12 uses the function search and searches vecList to find the
position (of the first occurrence) in vecList where list occurs as a subsequence
...
See the line
marked Line 14 in the output
...
The statement in Line
19 outputs vecList
...

The statement in Line 22 uses the function binary_search to search vecList
...


This page intentionally left blank

APPENDIX I

ANSWERS TO
ODD-NUMBERED
EXERCISES
Chapter 1
1
...
false; b
...
true; d
...
false; f; false; g
...
true; i
...
false;
k
...
false
3
...

5
...
Some of these services include memory management, input/output activities, and storage management
...
In machine language, the programs are written using the binary codes, whereas in
high-level language, the programs are closer to the natural language
...

9
...

11
...
Therefore, for the
computer to execute a program written in a high-level language, the high-level
language program must be translated into the computer’s machine language
...
In linking, an object program is combined with other programs in the library used
in the program to create the executable code
...
To find the weighted average of the four test scores, first you need to know each
test score and its weight
...
Therefore:
1
...

3
...

5
...


To find the price per square inch, first we need to find the area of the pizza
...
Let radius denote the
radius, area denote the area of the circle, and price denote the price of the pizza
...

a
...
area = p * radius * radius
c
...
pricePerSquareInch = price / area

19
...
We can then use the following formula to find the
selling price
...
60

The algorithm is as follows:
a
...
Calculate the sellingPrice using the formula:
sellingPrice = originalPrice + originalPrice *
...

21
...
To calculate the
total charges, you need to know the number of pages faxed
...
20); otherwise, billing amount is service charges þ 10 Â 0
...
10
...
Get numOfPages
...
Calculate billing amount using the formula:
if (numOfPages is less than or equal to 10)
billingAmount = 3
...
20);

otherwise
billingAmount = 3
...
20 + (numOfPages - 10) Â 0
...


Suppose averageTestScore denotes the average test score, highestScore
denotes the highest test score, testScore denotes a test score, sum denotes the
sum of all of the test scores, count denotes the number of students in class, and
studentName denotes the name of a student
...
First, you design an algorithm to find the average test score
...
You then divide the sum by count to find the average
test score
...
Set sum and count to 0
...
Repeat the following for each student in class
...
Get testScore
2
...

iii
...

if (count is 0)
averageTestScore = 0;
otherwise
averageTestScore = sum / count;

b
...

Repeat the following for each student in class
...
Get studentName and testScore
ii
...
The following algorithm determines the highest test score
...
Get first student’s test score and call it highestTestScore
...
Repeat the following for each of the remaining students in class
1
...
if (testScore is greater than highestTestScore)
highestTestScore = testScore;

d
...
The following algorithm accomplishes this
...

i
...
if (testScore is equal to highestTestScore)
print studentName

You can use the solutions of the subproblems obtained in parts a through d to design
the main algorithm as follows:
1
...

3
...


Use the algorithm in part a to find the average test score
...

Use the algorithm in part c to find the highest test score
...


1304

| Appendix I: Answers to Odd-Numbered Exercises

Chapter 2
1
...

5
...
false; b
...
false; d
...
true; f
...
true; h
...
false; j
...
false
b, d, e
The identifiers firstName and FirstName are not the same
...
The first letter of firstName is lowercase f, whereas the first character
of FirstName is uppercase F
...

7
...
3
b
...
Both of the operands of the operator % must be integers
...

c
...
Both of the operands of the operator % must be integers
...

d
...
5
e
...
2
g
...
420
...
7
11
...

13
...
32 * a + b
b
...
"Julie Nelson"
d
...
(a + b) / c * (e * f) - g * h
f
...
x = 20
y
z
w
t

17
...

21
...
5
4
...
0
...
24
...
37
...
8
...
10; f
...
75
a and c are correct
...
int num1;
int num2;

b
...
" << endl;
c
...
cout << "num1 = " << num1 << "num2 = " << num2
<< "2 * num1 - num2 = " << 2 * num1 - num2 << endl;

Chapter 2 |

23
...
67;
// x = 25
...

27
...

b
...

d
...


identifier must be declared before it can be used
...

a = (b++) + 3;
c = 2 * a + (++b);
b = 2 * (++c) – (a++);

31
...
)
a = 25
Enter two integers : 20 15
The numbers you entered are 20 and 15
z = 45
...


#include
#include
using namespace std;
const double X = 13
...
a
...
true; c
...
false; e
...
true
3
...
x = 37, y = 86, z = 0
...
x = 37, y = 32, z = 86
...
Input failure: z = 37
...
(period) into y
...
Input failure: Trying to read A into y, which is an int variable
...
The values of y and z are unchanged
...
iomanip
9
...
a
...
name ¼ " ", age ¼ 23
13
...
open("input
...
open("output
...
close();
outfile
...

17
...
Same as before
...
The file contains the output produced by the program
...
The file contains the output produced by the program
...

d
...

19
...
outfile
...
dat ");
b
...
outfile >> day >> " " >> distance >> " " >> speed >> endl;
d
...


outfile >> travelTime;
fstream and iomanip
...
a
...
false; c
...
true; e
...
false; g
...
false; i
...
true
3
...
true; b
...
true; d
...
false
5
...
x = y: 0
b
...
y = = z – 3: 1
d
...
x + y < z: 0
7
...
The correct statement is:
if (score >= 60)
cout << "You pass
...
" << endl;

9
...
if (sale > 20000)
bonus = 0
...
05;
else
bonus = 0
...
The output is: Discount ¼ 10%
...
So the cout statement is not part of
the if statement
...

b
...
The semicolon at the end of the if
statement terminates the if statement
...
The cout statement will execute regardless of whether the
expression in the if statement evaluates to true or false
...
a
...
(hours >= 40
...
50 + 1
...
5 * (hours - 40)

13
...
50;

c
...
a
...
00
b
...
00
c
...
00
19
...
96
23
...
a
...
true; c
...
true; e
...
true; g
...
false
3
...
if ch > 'Z' or ch < 'A'
7
...
Sum = 158
11
...
Replace the while loop statement with the following:
while (response = = 'Y' || response = = 'y')
Replace the cout statement:
cout << num1 << " + " << num2 << " = " << (num1 - num2)
<< endl;

with the following:
cout << num1 << " + " << num2 << " = " << (num1 + num2)
<< endl;

15
...
0 3 8 15 24
19
...
2 7 17 37 77 157 317
23
...
*
b
...
infinite loop
d
...
******
f
...
The relationship between x and y is: 3y = x
...
0 - 24
25 - 49
50 - 74
75 - 99
100 - 124
125 - 149
150 - 174
175 - 200

1309

1310

| Appendix I: Answers to Odd-Numbered Exercises

29
...
both
b
...
while
c
...
while
31
...
In a posttest loop, the loop condition is evaluated after executing the body of
the loop
...

33
...


int i = 0, value = 0;
do
{
if (i % 2 == 0 &&
value = value
else if (i % 2 ==
value = value
else
value = value
i = i + 1;
}
while (i <= 20);

i
+
0
+

<= 10)
i * i;
&& i > 10)
i;

- i;

cout << "value = " << value << endl;
The Output is: Value = 200

37
...


a
...
number = 1;
do
{
cout << setw(3) << number;
number++;

}
while (number <= 10);

41
...

45
...
a
...
true; c
...
true; e
...
a
...
10
...
2
...
10
...
15
...
5

g
...
5

h
...
28

j
...
(iii)
7
...
In d, the function call in the output (cout) statement
requires one more argument
...
a
...
2; double
c
...
The function test requires four actual parameters
...

e
...
3, 5) << endl;
f
...
5, 18
...
cout << static_cast(static_cast
(three(4, 3, 'A', 17
...


bool isUppercaseLetter(char ch)
{
if (isupper(ch))
return true;
else
return false;
}

13
...
i
...
432
b
...


15
...


double funcEx17(double x, double y, double z)
{
return (x + y) * z;
}

Chapter 7
1
...
true; b
...
true; d
...
true; f
...
false; h
...
true
3
...
A variable declared in the heading of a function definition is called a formal
parameter
...

b
...
A reference
parameter receives the address of the actual parameter
...
A variable declared within a function or block is called a local variable
...

5
...
void initialize(int& x, double& y, string& str)
{
x = 0;
y = 0;
str = "";
}

9
...


#include
using namespace std;
void func(int val1, int val2);
int main()
{
int num1, num2;
__1__
cout << "Please enter two integers
...


void traceMe(double& x, double y, double& z)
{
if (x != 0)
z = sqrt(y) / x;
else
{
cout << "Enter a nonzero number: ";
cin >> x;
cout << endl;
z = floor(pow(y, x));
}
}

15
...


11,
16,
19,
24,

19
...


3
2
3
2

Chapter 8
1
...
true; b
...
true; d
...
false; f
...
true; h
...
false; j
...
false
3
...

5
...


1314

| Appendix I: Answers to Odd-Numbered Exercises

7
...

9
...


Going to the Amusement Park
14
10
musem
ABCDEFGHIJK
11
aBdDEFGHIJK

Chapter 9
1
...
true; b
...
false; d
...
true; f
...
false; h
...
true; j
...
false; l
...
a
...

b
...
This declaration should be: int numList[10];
d
...

e
...
0 to 49
7
...
5 6 9 19 23 37
11
...
C++ does not check for array indices within bound
...
a
...
2, 6
...
8, 4
...
2, 5
...
7, 7
...
10, 6
...
2, 6
...
8, 4
...
2, 5
...
7, 7
...
10, 6
...
int weights[7] = {120, 125, 137, 140, 150, 180, 210};
or
int weights[] = {120, 125, 137, 140, 150, 180, 210};
c
...

d
...


list[0] = 8, list[1] = 9, list[2] = 15, list[3] = 12, list[4] = 80,
list[5] = 0, list[6] = 0, list[7] = 0, list[8] = 0, and list[9] = 0
...


a
...

c
...

e
...


1 25000
...
00

Correct
...

Incorrect
...

Correct
...
The array gpa is of type double, whereas the parameter x of tryMe
is of type int
...


2 36500
...
00
3 85000
...
00
4 62500
...
00
5 97000
...
00

21
...


List elements: 11 16 21 26 30
1 3
...
70 235
...
20 6
...
05
3 10
...
00 791
...
80 10
...
54
5 6
...
00 326
...

27
...

a
...

b
...

c
...

d
...
a
...
length = strlen(str1);
c
...
if (strcmp(str1, str2) <= 0)
cout << str1 << endl;
else
cout << str2 << endl;

31
...

35
...
30; b
...
6; d
...
column
a
...


1316

| Appendix I: Answers to Odd-Numbered Exercises

b
...

d
...
a
...
true; c
...
false; e
...
a
...

5
...
3

i
...


7 iii
...
11

before the first iteration: 26, 45, 17, 65, 33, 55, 12, 18
after the first iteration: 26, 17, 45, 33, 55, 12, 18, 65
after the second iteration: 17, 26, 33, 45, 12, 18, 55, 65
after the third iteration: 17, 26, 33, 12, 18, 45, 55, 65
after the fourth iteration: 17, 26, 12, 18, 33, 45, 55, 65
after the fifth iteration: 17, 12, 18, 26, 33, 45, 55, 65
after the sixth iteration: 12, 17, 18, 26, 33, 45, 55, 65
after the seventh iteration: 12, 17, 18, 26, 33, 45, 55, 65

Chapter 11 |

9
...

13
...

17
...


1317

10, 12, 18, 21, 25, 28, 30, 71, 32, 58, 15

Bubble sort: 49,995,000; selection sort: 49,995,000; insertion sort: 25,007,499
26
To use a vector object in a program, the program must include the header file
vector
...
vector secretList;
b
...
push_back(56);

c
...
push_back(28);
secretList
...
push_back(96);
secretList
...
size(); i++)
cout << secretList[i] << " ";
cout << endl;

21
...
cout << myList
...
back() << endl;
b
...
size();
c
...
size(); i++)
cout << myListi] << " ";
cout << endl;

Chapter 11
1
...
false; b
...
true; d
...
true; f
...
false
3
...
name = "Jason Miller";
newAcct
...
balance = 24476
...
interestRate = 0
...
movieType newRelease;
newRelease
...
director = "Tom Blair";
newRelease
...
yearReleased = 2005;
newRelease
...
a
...
Specify the member
names to store the value "John Smith"
...
name
...
name
...


Invalid; the member name of newEmployee is a struct
...
A correct statement is:
cout << newEmployee
...
first << " "
<< newEmployee
...
last << endl;

c
...
Valid
e
...
There are no aggregate assignment operations
on arrays
...
partsType inventory [100];
11
...
partName;
cin >> pType
...
price;
cin >> pType
...
a
...
false; c
...
false; e
...
a
...
2; c
...
void xClass::func()
{
}

u = 10;
w = 15
...
void xClass::print()
{
}

cout << u << " " << w << endl;

Chapter 12 |

1319

f
...
x
...
xClass t(20, 35
...
a
...
One possible solution
...
h
...
h"
int main()
{
testClass one;
testClass two(4, 5);
one
...
print();
}

return 0;

7
...
personType student("Buddy", "Arora");
b
...
print();
c
...
setName("Susan", "Gilbert");

1320

| Appendix I: Answers to Odd-Numbered Exercises

9
...
A constructor is included in a class so that the objects are properly initialized
when they are declared
...
A destructor is a member of a class, and if it is included in a class, it executes
automatically when a class object goes out of scope
...

13
...
myClass::count = 0;
b
...
incrementCount();
c
...
printCount();
d
...
myClass myObject1(5);
f
...
The statements in Lines 1 and 2 are valid
...

The statement in Line 4 is invalid because the member function printX is not a
static member of the class, and so cannot be called by using the name of class
...


Chapter 13 |

1321

h
...
a
...
true; c
...
Some of the member variables that can be added to the class employeeType are:
department, salary, employeeCategory (such as supervisor and president),
and employeeID
...

5
...

7
...
The statement:
class bClass public aClass

should be:
class bClass: public aClass

Also missing semicolon after }
...
Missing semicolon after the statement cClass(int), and missing semicolon
after }
...
a
...
xClass::xClass()
{

c
...


z = 0;
}
void yClass::two(int u, int v)
{
a = u;
b = v;
}

The protected members of a base class can be directly accessed by the member
functions of the derived class, but they cannot be directly accessed in a program that
uses that class
...


1322

| Appendix I: Answers to Odd-Numbered Exercises

13
...
The private member x of class first is hidden in class third, and
it can be accessed in class third only through the protected and public
members of class first
...
Because the memberAccessSpecifier is not specified, it is a private inheritance
...

17
...
void two::setData(int a, int b, int c)
{

one::setData(a, b);
z = c;

b
...


}
void two::print() const
{
one::print();
cout << z << endl;
}

In base: x = 7
In derived: x = 3, y = 8; x + y = 11
****7
####11

Chapter 14
1
...
false; b
...
false; d
...
true; f
...
false; h
...
The operator * is used to declare a pointer variable and to access the memory space
to which a pointer variable points
...
98 98
98 98

7
...
78 78
11
...
4 4 5 7 10 14 19 25 32 40
15
...

17
...
num ¼ new int[10];
b
...


c
...
In
a deep copy of data, each pointer has its own copy of the data
...


Array p: 5 7 11 17 25
Array q: 25 17 11 7 5

23
...


The copy constructor makes a copy of the actual variable
...


27
...

31
...

a
...
Therefore, this statement is illegal
...
This statement is legal
...
This statement is legal
...
a
...
true; c
...
false; e
...
true; g
...
true; i
...
true; k
...
A friend function is a nonmember of a class, whereas a member function is a
member of a class
...
Because the left operand of << is a stream object, which is not of the type mystery
...
When the class has pointer data members
...
a
...
friend bool operator==(const strange&, const strange&);
c
...
In Line 2, the word friend before the word bool is missing
...


Because the leftmost operand of << is not an object of the class type for which << is
overloaded
...
A reference to an object of the class istream
...
Suppose that a class, say temp, overloads the pre- and post-increment operator ++,
and tempObj is an object of the class temp
...
operator++();, and the statement tempObj++; is compiled as tempObj
...
The dummy parameter distinguishes
between the pre- and post-increment operator functions
...

19
...


1324

| Appendix I: Answers to Odd-Numbered Exercises

21
...

25
...

Answer to this question is available at the Web site accompanying this book
...
A template instantiation can be for only a built-in type or a userdefined type
...

27
...
12 b
...
template
void swap(Type &x, Type &y)
{
Type temp;
temp = x;
x = y;
y = temp;
}

Chapter 16
1
...
false; b
...
true; d
...
The program will terminate with an error message
...
If an exception is thrown in a try block, the remaining statements in that try
block are ignored
...
If the
type of thrown exception matches the parameter type in one of the catch blocks,
the code of that catch block executes, and the remaining catch blocks after this
catch block are ignored
...
a
...

b
...
00

c
...
00

9
...
Entering the try block
...

c
...


11
...

After the catch block
Entering the try block
...

Exiting the try block
...

Exception: 0
After the catch block

A throw statement
...


1325

(Assume that the definition of the class tornadoException is in the header file
tornadoException
...
)
#include
#include "tornadoException
...
what() << endl;
}
}

15
...


Chapter 17
1
...
true; b
...
false; d
...
false
3
...

5
...

7
...
The statements in Lines 2 and 3
...
The statements in Lines 4 and 5
...
Any nonnegative integer
...
It is a valid call
...

e
...
The value of mystery(5) is 15
...
It is an invalid call
...


1326

| Appendix I: Answers to Odd-Numbered Exercises

9
...


2
5
8

b
...


3
6

d
...


a
...

b
...
It does not produce any output
...
It does not produce any output
...
a
...
3; c
...
21
15
...
The general case is specified by the
option otherwise
...
a
...
false; c
...
false
3
...
Before deletion, the link field of the third node stores the address of the fourth node
...
If there was no fifth node, then after deletion, the link
field will store the value NULL
...
So a pointer to the third node is needed
...
a
...
true; c
...
false; e
...
a
...
list = A->link->link;
c
...
list = NULL;
e
...
newNode = new nodeType;
newNode->info = 10;
newNode->link = A->link;
A->link = newNode;
g
...


This is an invalid code
...


Chapter 19 |

13
...


1327

10 18 13
nodeType head, p, q;
head = new nodeType;
head->info = 72;
head->link = NULL;
p = new nodeType;
p->info = 43;
p->link = head;
head = p;
p = head->link;
q = new nodeType;
q->info = 8;
q->link = NULL;
p->link = q;
q = new nodeType;
q->info = 12;
q->link = p;
head->link = q;
p = head;
while (p != NULL)
{
cout << p->info << " ";
p = p->link;
}
cout << endl;

The output of this code is: 43 12 72 8
17
...

18 38 2 15 45 25

19
...


Answer to this question is available at the Web site accompanying this book
...


Chapter 19
1
...

3
...
a
...
45; c
...
29
7
...
A * B + C
b
...
(A – B – C) * D
9
...
If the stack is nonempty, the statement stack
...
pop(); removes the top element of the stack
...
template
elemType second(stackType stack)
{
elemType temp1, temp2;
if (stack
...
" << endl;
exit(0); //terminate the program
}
temp1 = stack
...
pop();
if (stack
...
" << endl;
exit(0); //terminate the program
}
temp2 = stack
...
push(temp1);
}

return temp2;

15
...


a
...

a
...

51

19
...


queueFront = 50; queueRear = 0
...

queueFront = 25; queueRear = 76
...


Chapter 19 |

23
...
isEmptyStack())
{
elem = s
...
pop();
q
...
isEmptyQueue())
{
elem = q
...
deleteQueue();
s
...


template
int queueType::queueCount()
{
return count;
}

27
...


Answer to this question is available at the Web site accompanying this book
...


This page intentionally left blank

I NDEX

Note: Page numbers in boldface indicate key terms
...
(period), 129, 655
+ (plus sign), 654
# (pound sign), 145, 257, 880, 1154
; (semicolon), 85, 651, 836
[] (square brackets), 495
$ (tilde), 677
_ (underscore), 33, 34, 86, 453

A
abs function, 321, 325
abstract classes
described, 836
overview, 835–843
abstract data types
...
See also abstract classes
accessor functions, 664, 665–669
action statements, 189
actual parameter lists, 327, 363
addFirst function, 381

addQueue function, 1166, 1168–1170, 1175,
1179–1182, 1197
address of operator, 795–796, 844–846
addressOfX function, 845, 846
ADTs (abstract data types)
described, 678
linked lists and, 1037–1050, 1058–1059,
1072–1074
OOP and, relationship of, 757
overview, 678–680
queues and, 1165, 1167, 1185, 1188,
1192, 1196
structS and, 681
templates and, 927
aggregate operations, 497
aggregation
...
See also ANSI/ISO Standard C++,
434, 530
ANSI/ISO Standard C++, 434, 530
namespaces and, 452–453, 454
naming conventions for header files,
1244–1245
overview, 22
strings and, 49, 458, 530
append function, 462
Apple Computer, 3
application programs, 6
...
See also parameters
described, 125
overview, 127
arithmetic expressions, 40
arithmetic operators
described, 40
overview, 39–44
array(s)
...
h (cassert) header file, 1247
assignment operator, 56, 209–211, 656–657,
820–821
linked lists and, 1044, 1049
overloading, 887–895
stacks and, 1129–1130, 1147–1149
assignment statements, 489, 657
compound, 89–90
enumeration types and, 436
putting data into variables with, 53–56
records and, 616–617
simple, 89–90
types of, 89–97
associativity, 43, 56, 185
asterisk (*), 794, 796, 812
at function, 462, 582
Augusta, Ada, 2

Index |

B
Babbage, Charles, 2
back, of queues, 1165, 1166
back function, 582, 1046, 1166, 1175,
1179–1182
backslash (/), 69, 73
bad_alloc exception, 964, 805,
965–967
base addresses, 501, 502–503
base case, 992
base classes
...
See also binary numbers
binary files
described, 1230
working with, 1230–1234
binary numbers
described, 6
converting, to other number systems,
1007–1014, 1225–1230
overview, 6–7, 1225
binary operators
described, 40
overloading, 876–882
binary search algorithm
described, 576
overview, 576–580
performance of, 580
binary_search function, 1297–1299
bits, 6–7
blanks, use of, 85, 87, 120
blocks
described, 195
nested, 383
bool data type, 36, 37, 188
bottom-up design, 20
boxType class, 730–738, 739
break statement
overview, 289–291
switch structures and, 216, 217–220

1333

bubble sort algorithm
described, 565
overview, 565–569
bugs
...
See CPUs (central
processing units)
change-making program, 94–97
char data type, 36–38, 121, 537
c-Strings and, 510, 511
enumeration types and, 438–439
functions and, 364
pointers and, 795
records and, 615
templates and, 925, 927
character arrays (c-Strings)
arrays of strings and, 530–531
described, 510
execution time and, 516
operator overloading and, 918–824
overview, 510–537
reading and writing strings with, 513
specifying I/O files and, 516
string input and, 514–515
string output and, 515–516

1334

|

Index

character sets, 1219–1221
...
See also
character sets
charitable-donations program, 156–161
cin identifier, 33, 76, 119–124, 744
get function and, 127–128
ignore function and, 128–130
input/output (I/O) and, 118–119
circle class, 725, 726, 835–836
circular linked lists, 1083, 1084
class(es)
...
See also clockType
class
boxType class, 730–738, 739
circle class, 725, 726, 835–836
customerType class, 1185–1188
cylinderType class, 758
dateType class, 751–752
deque class, 1276–1279
divisionByZero class, 969, 970–972, 974
doublyLinkedList class, 1074
dummyClass class, 675
ellipse class, 835–836

employeeType class, 837–840
extClockType class, 724
fullTimeEmployee class, 837, 840–841
linkedListIterator class, 1039–1041
linkedListType class, 1037–1044,
1048–1049, 1057–1059, 1067,
1150–1151, 1162, 1182
linkedQueueType class, 1181–1182
linkedStackType class, 1140–1141,
1147–1149
list class, 1279–1280
listType class, 680, 927–929
newString class, 918–824, 930, 952
orderedLinkedList class, 1043–1044, 1058
orderedListType class, 1066
partTimeEmployee class, 724, 740–742,
837, 841–843
personalInfo class, 753–755
personType class, 689–690, 724, 740, 742,
750–751, 837, 867–870
queueADT class, 1167, 1172, 1177–1178
queueType class, 1196
rectangle class, 725, 835–837
rectangleType class, 728–731, 734–736,
738, 874–888, 895–902
serverListType class, 1192–1194
serverType class, 1188–1191
shape class, 725, 835–837
stackADT class, 1119, 1120, 1139–1140,
1142
stackType class, 1120–1123, 1129–1134
testAddress class, 845, 846
unorderedLinkedList class, 1043–1044,
1049–1050, 1090, 1150–1151
unorderedListedListType class, 1182–1183
vector class, 1260–1269
videoListType class, 1090–1092, 1095–1097
videoType class, 1087–1089, 1092–1094
waitingCustomerQueueType class,
1196–1197
classifying-numbers program, 281–284
clear function, 135–136, 462, 463, 582
clients, of classes, 663
clockType class, 651–652, 654–663, 696,
862–863, 902–810
arrays and, 676–677

Index |

constructors and, 669–675
data abstraction and, 678
declaring, 667–669
destructors and, 677–678
executable code and, 685–690
information hiding and, 681–685
inheritance and, 724
member functions and, 664–669
clockType
...
See also
compile-time errors
described, 9
functions and, 340
inheritance and, 743–744
namespaces and, 452
compile-time binding, 830
compile-time errors
...
See programs
conditional operator, 211
const keyword, 51, 658, 659
constant functions, 664
constructor(s)
arrays of, 675–677
composition and, 754–755
containers and, 1280
conversion, 922
default, 669, 671, 674, 738, 1044, 1075,
1141
inheritance and, 734–741
invoking, 671–673
linked lists and, 1044, 1048, 1075
overview, 669–670
parameters and, 671–675
precautions regarding, 674–675
properties of, 669
queues and, 1176–1177
stacks and, 1128–1129, 1141, 1147
container(s)
adapters, 1285, 1286–1289
member functions common to, 1269–1272
types, 1260–1284
vector, 1260–1269
continue statement, 289–291
control structure(s)
...
cpp filename extension, 682
CPUs (central processing units), 3, 4, 5
cstdlib header file, 1258
c-Strings (character arrays)
arrays of strings and, 530–531
described, 510
execution time and, 516
operator overloading and, 918–824
overview, 510–537
reading and writing strings with, 513
specifying I/O files and, 516
string input and, 514–515
string output and, 515–516
ctype
...
See also specific types
anonymous, 442–443
control structures and, 178–179
described, 35
functions and, 324, 326, 328
overview, 35–39
simple, 53, 433–483, 486
structured, 486
data-comparison program, 404–414
dateType class, 751–752
debugging
...
See also inheritance
constructors and, 734–741
default parameters and, 738
described, 724–725
destructors and, 741–743
overriding functions and, 731–732
overview, 726–727
protected members in, accessing,
747–750
destroyList function, 822, 824, 1044–1045,
1048
destructor(s)
linked lists and, 1048
overview, 677–678
pointers and, 818–819
queues and, 1176–1177
stacks and, 1128–1129, 1147
virtual, 835
dice-rolling program, 336–337
digital signals, 6
directly recursive, use of the term, 995
discardExp function, 1154, 1158
‘‘divide and conquer’’ technique, 477

Index |

divisibility test, 287–288
divisionByZero class, 969, 970–972, 974
divisor, use of the term, 287
do keyword, 285
do
...
See compile-time binding
EBCDIC (Extended Binary Coded Decimal
Interchange Code), 8, 37, 510,
1220–1221
election-results program, 585–601
ellipse class, 835–836
employeeType class, 837–840
empty function, 582, 462, 463, 1286, 1288
end function, 1266–1267
enumeration types, 35, 506
anonymous data types and, 442–443
described, 434, 442
functions and, 440–442
input/output of, 438–440
loops and, 438
operations on, 437
overview, 434–444
two-dimensional arrays and, 521–524
enumerators, 435

1337

eof function, 263–264
EOF-controlled while loops, 263, 264–268,
294–295
equal sign (=), 1153
equality operator, 209–211
equalTime function, 651, 652–653, 655, 659,
663, 664
erase function, 462, 463
errors
...
See also errors
semantic, 194
stacks and, 1128, 1158
escape sequences, 69–74
evaluateExpression function, 1154–1156, 1158
evaluateOpr function, 1154, 1156–1158
example function, 499
exception handling
bad_alloc exception and, 964, 805, 965–967
C++ mechanisms of, 956–963
exception classes and, 963–977
overview, 952–989
within a program, 952–956
rethrowing exceptions, 973–977
stack unwinding and, 980–983
techniques, 978–980
throwing exceptions and, 957–958,
967–968, 973–977
try/catch blocks and, 956–965, 967,
973–977, 979–983

...
h (cfloat) header file, 1249–1250
floating-point data types, 35, 38, 39, 44,
200–201
floor function, 321, 322
for keyword, 274
for loops
arrays and, 493, 524, 525, 526, 810, 813
constructors and, 828
enumeration types and, 438
exception handling and, 966–967
functions and, 365, 383
nested, 292–293
operator overloading and, 893
overview, 273–280
vectors and, 585, 583
formal parameter lists, 326, 362, 395
formatted data, use of the term, 1230
forward slash (/), 32
friend functions, 870, 871–873, 901
friend keyword, 870
front, of queues, 1165
front function, 582, 1046, 1077, 1166,
1174–1175, 1179–1182, 1288

fstream header file, 745
fullTimeEmployee class, 837, 840–841
funcArrayAsParam function, 498
funcExp function, 397
function(s)
...
See also functions;
main function
abs function, 321, 325
addFirst function, 381
addQueue function, 1166, 1168–1170,
1175, 1179–1182, 1197
addressOfX function, 845, 846
append function, 462
assert function, 223–231, 952, 955–956
at function, 462, 582
back function, 582, 1046, 1166, 1175,
1179–1182

Index |

begin function, 1046–1047, 1266–1267
binary_search function, 1297–1299
buildListBackward function, 1036–1037,
1038
buildListForward function, 1035–1036,
1038
calculatePay function, 837
callPrint function, 829–830, 834
ceil function, 321
clear function, 135–136, 462, 463, 582
compare function, 462
compareThree function, 331, 332–333
copy function, 1272–1276
copyList function, 1044, 1047–1048, 1075
copyStack function, 1128, 1146–1147
cos function, 321
decToBin function, 1012–1014
deleteNode function, 1044, 1049, 1052,
1058, 1065–1066, 1082–1083
deleteQueue function, 1166, 1168–1169,
1170, 1175–1176, 1179–1182, 1197
destroyList function, 822, 824, 1044–1045,
1048
discardExp function, 1154, 1158
doDivision function, 972, 976
doubleFirst function, 381
draw function, 836
empty function, 582, 462, 463, 1286,
1288
end function, 1266–1267
eof function, 263–264
equalTime function, 651, 652–653, 655,
659, 663, 664
erase function, 462, 463
evaluateExpression function, 1154–1156,
1158
evaluateOpr function, 1154, 1156–1158
example function, 499
exp function, 321
fabs function, 321
fill function, 815, 1292–1294
fill_n function, 1292–1294
find function, 462, 465–467, 1294–1295
find_if function, 1294–1295
floor function, 321, 322

1339

front function, 582, 1046, 1077, 1166,
1174–1175, 1179–1182, 1288
funcArrayAsParam function, 498
funcExp function, 397
get function, 127–128, 514, 744
getFirstName function, 868
getLastName function, 868
getLength function, 733
getLine function, 515
getNumberOfBusyServers function, 1194
getScore function, 369–370
getTime function, 651, 652, 653, 659
getWaitingTime function, 1188
getWidth function, 733
ignore function, 128–130, 744
incrementHours function, 651, 652, 664
incrementMinutes function, 651, 652, 662,
664
initializeList function, 1045, 1076
initializeQueue function, 1166, 1171, 1174,
1179, 1181
initializeStack function, 1118, 1123–1124
insert function, 462, 467–468, 1063,
1079–1080
insertFirst function, 1038, 1044, 1049,
1051, 1058, 1064–1065
insertionSort function, 575–576
insertLast function, 1038, 1044, 1049,
1058, 1064–1065
isEmptyList function, 1044
isEmptyQueue function, 1166, 1197
isEmptyStack function, 1118, 1124,
1141–1142
isFullQueue function, 1166, 1179
isFullStack function, 1118, 1124,
1140–1142
islower function, 322
isNumPalindrome function, 338–340
isupper function, 322
larger function, 328–331, 332, 341–343,
925–927
largerChar function, 396
largerInt function, 396
largestInRows function, 528–529
length function, 462, 463, 464–465
max_size function, 582

1340

|

Index

functions (listed by name) (Continued)
peek function, 130–132
poolCapacity function, 394
poolFillTime function, 394
pop function, 1117–1118, 1126–1128,
1144–1146, 1286, 1288
pop_back function, 582
pow function, 321–326, 456
print function, 735, 740, 749, 831, 837,
868, 872, 1076
printListReverse function, 1071
printMatrix function, 528–529
printResult function, 453, 454, 457, 1154,
1158–1161
printStars function, 364–366
printTime function, 651, 652, 653, 656,
659, 664
push function, 1117–1118, 1124–1126,
1142–1144, 1150, 1286, 1288
push_back function, 582, 583–584
rand function, 1258
rbFibNum function, 999–1003
read function, 1236
readIn function, 619
remove function, 1295–1297
replace function, 463, 467–468, 1295–97
resize function, 583–584
reversePrint function, 1069–1071
rollDice function, 687
runSimulation function, 1199–1200
search function, 1044, 1058, 1077,
1297–1299
seekg function, 1236, 1237–1241
seekp function, 1236, 1237–1238
selectionSort function, 571
seqSearch function, 508–509, 621–622
setCustomerInfo function, 1187
setData function, 748, 749, 752, 753
setDimension function, 733
setLastName function, 868
setName function, 868
setServerBusy function, 1194
setTime function, 651, 652, 653, 656, 659,
660, 664, 670
size function, 463, 582, 1286, 1288
sort function, 1297–1299

sqrt function, 321, 322
squareFirst function, 381
strcmp function, 512, 513
strlen function, 512
substr function, 463, 469–470, 964
sumRows function, 528–529
swap function, 463, 470
terminate function, 980
test function, 392
testCopyConst function, 828
testTime function, 658, 659
tolower function, 322
top function, 1117–1118, 1126, 1286,
1288
toupper function, 322
updateServers function, 1195
updateWaitingQueue function, 1196
write function, 1236

G
general case, 992
get function, 127–128, 514, 744
getFirstName function, 868
getLastName function, 868
getLength function, 733
getLine function, 515
getNumberOfBusyServers function, 1194
getScore function, 369–370
getTime function, 651, 652, 653, 659
getWaitingTime function, 1188
getWidth function, 733
grade-calculation programs, 162–165,
369–372
grade-point average (GPA) program,
1134–1138
grade-report program, 758–779

...
else statements with,
198–199
functions and, 334
linked lists and, 1070
nested, 195, 196, 197–199
if
...
See array indexes
indirectly recursive, use of the term, 995
infinite loops, 250
infix notation, 1151, 1152
information hiding, 681–685
inheritance
described, 724
hierarchy, 738, 740–741
linked lists and, 1037
overview, 723–792
pointers and, 828–835
initializeList function, 1045, 1076
initializeQueue function, 1166, 1171, 1174,
1179, 1181
initializeStack function, 1118, 1123–1124
input
...
See also input; output
c-Strings and, 515–517
debugging and, 149–152
enumeration types and, 438
EOF-controlled while loops and, 263, 264
file, 152–165, 516
functions and, 321

1342

|

Index

input/output (Continued)
inheritance and, 744–745
overview, 1230–1244
records and, 618, 619
stream variables, 132–133
string data type and, 148–152, 458
insert function, 462, 467–468, 1063,
1079–1080
insertFirst function, 1038, 1044, 1049, 1051,
1058, 1064–1065
insertion operator, 515
insertion sort algorithm, 572–576
insertionSort function, 575–576
insertLast function, 1038, 1044, 1049, 1058,
1064–1065
instance variables, 663
int data type, 36–37, 121, 333–335, 364
arrays and, 508, 809, 810, 813, 815
control structures and, 187–188
exception handling and, 957, 960
inheritance and, 749
linked lists and, 1025, 1028, 1032
pointers and, 794, 795, 797, 799, 808
records and, 616, 625
templates and, 925–927
vector objects and, 581
int keyword, 87
integral data type, 35–36, 506
integral expressions, 44
iomanip header file, 458
iostream header file, 321, 452, 456–455,
458, 743, 744–745
isEmptyList function, 1044
isEmptyQueue function, 1166, 1197
isEmptyStack function, 1118, 1124,
1141–1142
isFullQueue function, 1166, 1179
isFullStack function, 1118, 1124, 1140–1142
islower function, 322
isNumPalindrome function, 338–340
ISO (International Standards Organization), 22
istream member functions, 124
isupper function, 322
iterative control structures, 1106, 1107–1014
iterators, 1039, 1040–1045, 1265–1266,
1284–1289

J
Jacquard, Joseph, 2
Jobs, Steven, 3

K
keys (items), 565
keywords
...
See also keywords
class keyword, 651
const keyword, 51, 658, 659
do keyword, 285
extern keyword, 386
for keyword, 274
friend keyword, 870
int keyword, 87
namespace keyword, 76
new keyword, 804
operator keyword, 864
return keyword, 77, 328
static keyword, 491, 691
struct keyword, 613
this keyword, 865
throw keyword, 958
using keyword, 76, 454
virtual keyword, 830
kilobytes (KB), 6–7

L
larger function, 328–331, 332, 341–343,
925–927
largerChar function, 396
largerInt function, 396
largestInRows function, 528–529
largest-number program, 342–343
left manipulator, 146–148
length function, 462, 463, 464–465
length-conversion program, 91–94
libraries
...
h (climits) header file, 1250–1251
linked lists
...
h header file, 1057–1058,
1067–1069
linkedListIterator class, 1039–1041
linkedListType class, 1037–1044,
1048–1049, 1057–1059, 1067,
1150–1151, 1162, 1182
linkedQueueType class, 1181–1182
linkedStack
...
See also linked lists
described, 565
processing, 564–580
listType class, 680, 927–929
loaders, 11
local declaration, 328
logic errors, 149–152, 964
...
See also recursion; specific types
arrays and, 491
binary search algorithm and, 579, 580
enumeration types and, 438
nested, 291–296, 525, 526
records and, 623
selection sort algorithm and, 571
loop control variables (LCVs), 250, 251, 256,
274

M
machine language, 6
main function, 31, 78, 80, 124, 324, 369,
381, 456–457, 872–873
arrays and, 815
constructors and, 826
information hiding and, 682
pointers and, 802
virtual functions and, 843
void functions and, 362
main memory
...
h (cmath) header file, 1252–1255
max_size function, 582
member access operator, 133, 655, 656, 657,
615
member functions
binary operators as, 876
common to containers, 1269–1272
implementation of, 659–663
operator functions as, 873–876, 896–898,
901–902
redefining (overriding), 727–734
members, of classes
accessing, 655–656
described, 650
order of, 667–669
overview, 650–651
static, 691–696
memory
...
See also functions
movie-ticket-sales program, 156–161
multidimensional arrays, 518–533
...
h header file, 1130–1134

N
named constants, 51, 52, 386–390, 461
namespace keyword, 76
namespaces, 76, 452–458
naming conventions, for header files,
1244–1245
n-dimensional arrays, 532, 533
...
obj filename extension, 77–78
object(s)
arrays of, 675–677
declaring, 654–655
described, 650
identifying, 757–758
programs, 10–11
reference parameters and, 648
object-oriented design
...
See also arrays
OOD (object-oriented design)
...
See also
objects
described, 21
OOD and, relationship of, 756
overview, 755–758
operands, 40
operating system software, 6
operations
data abstraction and, 679
described, 679
identifying, 757–758
operator(s)
...
See also assignment
operator; operators
address of operator, 795–796, 844–846
array index operator, 916–924
array subscript operator, 459, 488
cast operator, 47
conditional operator, 211
delete operator, 804, 805–807
dereferencing operator, 796–801, 1039
equality operator, 209–211
extraction operator, 119–124, 129, 148
insertion operator, 515
member access operator, 133, 655, 656,
657, 615
new operator, 804–805, 809, 965–966
post-increment operator, 897–901
scope resolution operator, 386, 454, 457,
659, 691
stream extraction operator, 59, 882–887
stream insertion operator, 31, 68, 882–887
ordered linked lists
...
See also I/O (input/output)
devices, 5
formatting, 137–148
overview, 67–74, 117–174
statements, 68
stream variables, 119
streams, 118
string, 515–516
overflow condition, 126
overflow_error exception, 964

1345

P
palindrome number program, 338–340
parallel arrays, 537, 538
parameter(s)
actual, 326
arrays as, 497–498
constructors and, 671–675
default, 396–399, 738
formal, 325–326, 498–500
linked lists and, 1048, 1070–1071
passing, to functions, 527–530
queues and, 1198
reference, 363, 372–382
stacks and, 1155
value, 363, 372–382
parameterized stream manipulators, 148
parameterized types, 927
parentheses, 187, 327, 801
partTimeEmployee class, 724, 740–742, 837,
841–843
Pascal, Blaise, 2
patches, 296–299
PCs (personal computers), history of, 3
...
), 129, 655
personalInfo class, 753–755
personType class, 689–690, 724, 740, 742,
750–751, 837, 867–870
pig-latin strings, 471–475
plus sign (+), 654
pointer variable(s)
classes and, 902
declaring, 794–795
described, 794
initializing, 803
operations on, 807–809
operators, 795–800
structS and, 800–803
pointers
classes and, 800–803, 818–828
constant, 811
dangling, 807
destructors and, 818–819
dynamic variables and, 803–807
functions and, 812

1346

|

Index

pointers (Continued)
inheritance and, 828–835
linked lists and, 1030–1038, 1044, 1048,
1054–1056, 1060, 1063
operator overloading and, 865
overview, 818–828
shallow versus deep copy and, 816–818
structS and, 800–803
polymorphism
described, 756
parametric, 757
poolCapacity function, 394
poolFillTime function, 394
pop function, 1117–1118, 1126–1128,
1144–1146, 1286, 1288
pop_back function, 582
postconditions, 683
post-increment operator, 897–901
postfix expressions calculator, 1151–1161
posttest loops, 286
pound sign (#), 145, 257, 880, 1154
pow function, 321–326, 456
precision
described, 39
double, 39
single, 39
preconditions, 683
predefined functions
described, 125
overview, 31
using, 124–133
prefix (Polish) notation, 1151
preprocessors, 10, 75–76
...
See also programming;
programming languages
basic elements of, 28–34
creating, overview of, 77–80
described, 28
form, 84–89, 211–212
overview, 6
processing, overview of, 10–12
source, 10
style, 84–89, 211–212
terminating, 223–231, 978, 980
programming
...
See also programming
described, 31
evolution of, 8–9
overview, 1–26
prompt lines, 86
protected members, 651, 654, 870
inheritance and, 725, 746–750
linked lists and, 1043
prototypes, 331, 332–333, 397, 398, 877,
881, 884, 896–899
pseudocode
described, 212
linked lists and, 1070
overview, 212–215
stacks and, 1154, 1157
public members, 651–655, 667–669, 691,
694
friend functions and, 870
inheritance and, 725–727, 731–732,
746–747
push function, 1117–1118, 1124–1126,
1142–1144, 1150, 1286, 1288
push_back function, 582, 583–584

Index |

Q
queue(s)
application of, 1183–1203
back of, 1165, 1166
described, 1165
empty, 1174, 1178–1179
front of, 1165
full, 1174, 1178–1179
implementation of, 1168–1174,
1177–1182
initializing, 1174, 1179
operations, 1166–1167
overview, 1165–1183
STL and, 1287–1289
queueADT class, 1167, 1172, 1177–1178
queueType class, 1196
queuing systems, 1184, 1185

R
RAM (random access memory), 4, 5
...
See also StructS
arrays and, 619–624
assignment statements and, 616–617
overview, 611–648
rectangle class, 725, 835–837
rectangleType class, 728–731, 734–736, 738,
874–888, 895–902
recursion
described, 992
direct, 995
indirect, 995
infinite, 995–996
iteration and, 1006–1014
linked lists and, 1069–1071

1347

overview, 991–1021
problem solving using, 996–1006
removing, 1161–1165
stacks and, 1161–1165
recursive algorithms
described, 993
problem solving using, 996–1006
recursive definitions
described, 992
overview, 992–996
recursive functions
described, 993
infinite recursion and, 995–996
overview, 993–995
reference variables, as parameters, 368–372
relational operators, 201–203, 437–438
described, 178
overview, 177–182
records and, 617–618
remove function, 1295–1297
repetition structures
...
See keywords
resize function, 583–584
return keyword, 77, 328
return statement, 208, 324, 327–331,
333–335
return type, of functions, 326, 877
Reverse Polish notation, 1151
reversePrint function, 1069–1071
right manipulator, 146–148
rightmost bit, 1011
‘‘rock, paper, and scissors’’ game, 444–452
rollDice function, 687
row(s)
arrays and, 523, 525
largest element in, 526
order form, 527
processing, 523
sum by, 525
runSimulation function, 1199–1200
run-time (late binding), 830
run-together words, 86

1348

|

Index

S
sales data analysis program, 628–641
scope resolution operator, 386, 454, 457, 659,
691
search function, 1044, 1058, 1077,
1297–1299
searching
...
See also programs
operating system, 6
overview of, 6
sort function, 1297–1299
source
code, 10, 77
file, 77
program, 10
sqrt function, 321, 322
square brackets ([]), 495
squareFirst function, 381
stack(s)
container adapters and, 1286
copying, 1128, 1146–1147
described, 1116
emptying, 1124, 1141–1142
full, 1124, 1141–1142
implementation of, as arrays, 1120–1138
initializing, 1123–1124
linked implementation of, 1138–1151
operations, 1118–1119
overview, 1116–1165
recursion and, 1161–1165
top element of, returning to, 1144
stackADT class, 1119, 1120, 1139–1140,
1142
stackType class, 1120–1123, 1129–1134
Standard C++
library, 458
naming conventions for header files, 1244–1245

Index |

statement(s)
action, 189
declaration, 78
executable, 78
nested, 195, 196, 197–199, 280
terminators, 85
static binding
...
h (cstddef) header file, 1253
stepwise refinement, 20
STL (C++ Standard Template Library), 585,
1259–1299
algorithms and, 1289–1292
components of, 1259–1260
containers and, 1260–1284
vectors and, 1260–1269
strcmp function, 512, 513
stream(s)
classes, 744–745
described, 118
extraction operator, 59, 882–887
functions, 124
insertion operator, 31, 68, 882–887
variables, 119, 373
string(s)
...
See also strings
functions, list of, 462–463
overview, 458–470
templates and, 927
string
...
See also records
arrays and, 619–624
assignment statements and, 616–617
classes versus, 680–681

1349

described, 612
linked lists and, 1038
overview, 611–648
pointer variables and, 800–803
structS within, 624–627
syntax of, 612–613
variables and, 618–622
struct keyword, 613
struct members, 614–616
structured data types, 486
structured design, 20
structured programming, 20
structures
...
See also
debugging; errors; syntax rules
control structures and, 215
fixing, 80–84
syntax rules, 31, 84–85
...
See also STL (C++
Standard Template Library)
terminate function, 980
ternary operators, 211
test function, 392
testAddress class, 845, 846
testCopyConst function, 828
testing, of control structures, 212–215
testTime function, 658, 659
text processing program, 540–547
this keyword, 865
this pointer, 865–870, 895
throw keyword, 958

1350

|

Index

tilde ($), 677
time-driven simulation, 1184
tokens, 32–33, 34
tolower function, 322
top, of stacks, 116
top function, 1117–1118, 1126, 1286, 1288
top-down design, 20
toupper function, 322, 323
Tower of Hanoi problem, 1003–1006
transaction time, 1184, 1185, 1194–1195
try/catch blocks, 956–963, 964–965, 967,
973–977, 979, 980–983
two-dimensional arrays
...
See
also UML class diagrams
UML class diagrams, 654, 680, 689–690,
728–731, 740–741, 752, 754
linked lists and, 1040, 1043, 1050, 1059,
1074
queues and, 1186–1187, 1190, 1193
stacks and, 1119, 1121–1122, 1140
unary operators, 40, 895–901
underflow condition, 1128
underscore (_), 33, 34, 86, 453
Unicode, 8
UNIX, 265
unordered linked lists
Title: c++ easy learning
Description: C++ (pronounced as cee plus plus, /ˈsiː plʌs plʌs/) is a general-purpose programming language. It has imperative, object-oriented and generic programming features, while also providing facilities for low-level memory manipulation. It was designed with a bias toward system programming and embedded, resource-constrained and large systems, with performance, efficiency and flexibility of use as its design highlights.[3] C++ has also been found useful in many other contexts, with key strengths being software infrastructure and resource-constrained applications,[3] including desktop applications, servers (e.g. e-commerce, web search or SQL servers), and performance-critical applications (e.g. telephone switches or space probes).[4] C++ is a compiled language, with implementations of it available on many platforms and provided by various organizations, including the FSF, LLVM, Microsoft, Intel and IBM. C++ is standardized by the International Organization for Standardization (ISO), with the latest (and current) standard version ratified and published by ISO in December 2014 as ISO/IEC 14882:2014 (informally known as C++14).[5] The C++ programming language was initially standardized in 1998 as ISO/IEC 14882:1998, which was then amended by the C++03, ISO/IEC 14882:2003, standard. The current C++14 standard supersedes these and C++11, with new features and an enlarged standard library. Before the initial standardization in 1998, C++ was developed by Bjarne Stroustrup at Bell Labs since 1979, as an extension of the C language as he wanted an efficient and flexible language similar to C, which also provided high-level features for program organization. Many other programming languages have been influenced by C++, including C#, Java, and newer versions of C (after 1998)