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.
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)
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
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
ffi
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
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
...
0
= static_cast
...
0 / 2
(because static_cast
...
0 / 2
...
5
= static_cast
= 7
...
8 +
static_cast
static_cast
...
8 + 7
...
3)
= 15
= static_cast
...
0)
= static_cast
...
#include
using namespace std;
int main()
{
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
cout <<
<<
<<
}
"static_cast
...
9)
endl;
"static_cast
...
3)
endl;
"static_cast
static_cast
endl;
"static_cast
static_cast
endl;
"static_cast
static_cast
endl;
"static_cast
static_cast
endl;
"static_cast
...
8 + static_cast
endl;
"static_cast
...
8 + static_cast
endl;
return 0;
Sample Run:
static_cast
...
3) = 3
static_cast
static_cast
static_cast
...
8 + static_cast
static_cast
...
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
...
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
2 *8 þ
static_cast
...
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
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
...
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
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
<< 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<
>>lastName;cout<
cin>>num;cout<
cout<<"Name: "<
}
34
...
Write a program that produces the following output:
**********************************
*
Programming Assignment 1
*
*
Computer Programming I
*
*
Author: ???
*
*
Due Date: Thursday, Jan
...
If necessary, adjust the
positions and the number of the stars to produce a rectangle
...
Write a program that produces the following output:
CCCCCCCCC
++
CC
++
CC
++++++++++++++
CC
++++++++++++++
CC
++
CCCCCCCCC
++
3
...
b
...
d
...
f
...
//return statement
Write C++ statements that include the header files iostream
...
Write C++ statements that declare the following variables: num1, num2,
num3, and average of type int
...
Write a C++ statement that stores the average of num1, num2, and
num3, into average
...
Compile and run your program
...
5
...
Store 75
...
56 into num2, and 15
...
Consider the following C++ program in which the statements are in the
incorrect order
...
#include
{
int main()
cout << "Enter the length: ";
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);
(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
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
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
...
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
<
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
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
...
b
{
int tenTopwr = static_cast
...
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
b
...
static_cast
d
...
static_cast
f
...
static_cast
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
ffi
2
2
2
2
2
ðx1 À xÞ þ ðx2 À xÞ þ ðx3 À xÞ þ ðx4 À xÞ þ ðx5 À xÞ
s¼
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
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
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
...
" << 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
For example, static_cast
...
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
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
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
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
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
...
length())
endl;
//Line
"Line 19: Length of \"" << str1 << "\" = "
static_cast
...
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
...
find(str))
endl;
//Line 7
cout << "Line 8: The position of \"the\" in sentence = "
<< static_cast
...
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
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
- static_cast
//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
+ static_cast
<< " 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
- static_cast
//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
+ static_cast
<< " 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
s¼
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
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
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
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
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
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