- •Table of Contents
- •Introduction
- •What Is C++?
- •Conventions Used in This Book
- •How This Book Is Organized
- •Part I: Introduction to C++ Programming
- •Part III: Introduction to Classes
- •Part IV: Inheritance
- •Part V: Optional Features
- •Part VI: The Part of Tens
- •Icons Used in This Book
- •Where to Go from Here
- •Grasping C++ Concepts
- •How do I program?
- •Installing Dev-C++
- •Setting the options
- •Creating Your First C++ Program
- •Entering the C++ code
- •Building your program
- •Executing Your Program
- •Dev-C++ is not Windows
- •Dev-C++ help
- •Reviewing the Annotated Program
- •Examining the framework for all C++ programs
- •Clarifying source code with comments
- •Basing programs on C++ statements
- •Writing declarations
- •Generating output
- •Calculating Expressions
- •Storing the results of expression
- •Declaring Variables
- •Declaring Different Types of Variables
- •Reviewing the limitations of integers in C++
- •Solving the truncation problem
- •Looking at the limits of floating-point numbers
- •Declaring Variable Types
- •Types of constants
- •Special characters
- •Are These Calculations Really Logical?
- •Mixed Mode Expressions
- •Performing Simple Binary Arithmetic
- •Decomposing Expressions
- •Determining the Order of Operations
- •Performing Unary Operations
- •Using Assignment Operators
- •Why Mess with Logical Operations?
- •Using the Simple Logical Operators
- •Storing logical values
- •Using logical int variables
- •Be careful performing logical operations on floating-point variables
- •Expressing Binary Numbers
- •The decimal number system
- •Other number systems
- •The binary number system
- •Performing Bitwise Logical Operations
- •The single bit operators
- •Using the bitwise operators
- •A simple test
- •Do something logical with logical calculations
- •Controlling Program Flow with the Branch Commands
- •Executing Loops in a Program
- •Looping while a condition is true
- •Using the for loop
- •Avoiding the dreaded infinite loop
- •Applying special loop controls
- •Nesting Control Commands
- •Switching to a Different Subject?
- •Writing and Using a Function
- •Divide and conquer
- •Understanding the Details of Functions
- •Understanding simple functions
- •Understanding functions with arguments
- •Overloading Function Names
- •Defining Function Prototypes
- •Variable Storage Types
- •Including Include Files
- •Considering the Need for Arrays
- •Using an array
- •Initializing an array
- •Accessing too far into an array
- •Using arrays
- •Defining and using arrays of arrays
- •Using Arrays of Characters
- •Creating an array of characters
- •Creating a string of characters
- •Manipulating Strings with Character
- •String-ing Along Variables
- •Variable Size
- •Address Operators
- •Using Pointer Variables
- •Comparing pointers and houses
- •Using different types of pointers
- •Passing Pointers to Functions
- •Passing by value
- •Passing pointer values
- •Passing by reference
- •Limiting scope
- •Examining the scope problem
- •Providing a solution using the heap
- •Defining Operations on Pointer Variables
- •Re-examining arrays in light of pointer variables
- •Applying operators to the address of an array
- •Expanding pointer operations to a string
- •Justifying pointer-based string manipulation
- •Applying operators to pointer types other than char
- •Contrasting a pointer with an array
- •Declaring and Using Arrays of Pointers
- •Utilizing arrays of character strings
- •Identifying Types of Errors
- •Choosing the WRITE Technique for the Problem
- •Catching bug #1
- •Catching bug #2
- •Calling for the Debugger
- •Defining the debugger
- •Finding commonalities among us
- •Running a test program
- •Single-stepping through a program
- •Abstracting Microwave Ovens
- •Preparing functional nachos
- •Preparing object-oriented nachos
- •Classifying Microwave Ovens
- •Why Classify?
- •Introducing the Class
- •The Format of a Class
- •Accessing the Members of a Class
- •Activating Our Objects
- •Simulating real-world objects
- •Why bother with member functions?
- •Adding a Member Function
- •Creating a member function
- •Naming class members
- •Calling a Member Function
- •Accessing a member function
- •Accessing other members from a member function
- •Defining a Member Function in the Class
- •Keeping a Member Function After Class
- •Overloading Member Functions
- •Defining Arrays of and Pointers to Simple Things
- •Declaring Arrays of Objects
- •Declaring Pointers to Objects
- •Dereferencing an object pointer
- •Pointing toward arrow pointers
- •Passing Objects to Functions
- •Calling a function with an object value
- •Calling a function with an object pointer
- •Calling a function by using the reference operator
- •Returning to the Heap
- •Comparing Pointers to References
- •Linking Up with Linked Lists
- •Performing other operations on a linked list
- •Hooking up with a LinkedListData program
- •A Ray of Hope: A List of Containers Linked to the C++ Library
- •Protecting Members
- •Why you need protected members
- •Discovering how protected members work
- •Protecting the internal state of the class
- •Using a class with a limited interface
- •Creating Objects
- •Using Constructors
- •Why you need constructors
- •Making constructors work
- •Dissecting a Destructor
- •Why you need the destructor
- •Working with destructors
- •Outfitting Constructors with Arguments
- •Justifying constructors
- •Using a constructor
- •Defaulting Default Constructors
- •Constructing Class Members
- •Constructing a complex data member
- •Constructing a constant data member
- •Constructing the Order of Construction
- •Local objects construct in order
- •Static objects construct only once
- •Global objects construct in no particular order
- •Members construct in the order in which they are declared
- •Destructors destruct in the reverse order of the constructors
- •Copying an Object
- •Why you need the copy constructor
- •Using the copy constructor
- •The Automatic Copy Constructor
- •Creating Shallow Copies versus Deep Copies
- •Avoiding temporaries, permanently
- •Defining a Static Member
- •Why you need static members
- •Using static members
- •Referencing static data members
- •Uses for static data members
- •Declaring Static Member Functions
- •What Is This About, Anyway?
- •Do I Need My Inheritance?
- •How Does a Class Inherit?
- •Using a subclass
- •Constructing a subclass
- •Destructing a subclass
- •Having a HAS_A Relationship
- •Why You Need Polymorphism
- •How Polymorphism Works
- •When Is a Virtual Function Not?
- •Considering Virtual Considerations
- •Factoring
- •Implementing Abstract Classes
- •Describing the abstract class concept
- •Making an honest class out of an abstract class
- •Passing abstract classes
- •Factoring C++ Source Code
- •Defining a namespace
- •Implementing Student
- •Implementing an application
- •Project file
- •Creating a project file under Dev-C++
- •Comparing Operators with Functions
- •Inserting a New Operator
- •Overloading the Assignment Operator
- •Protecting the Escape Hatch
- •How Stream I/O Works
- •The fstream Subclasses
- •Reading Directly from a Stream
- •Using the strstream Subclasses
- •Manipulating Manipulators
- •Justifying a New Error Mechanism?
- •Examining the Exception Mechanism
- •What Kinds of Things Can I Throw?
- •Adding Virtual Inheritance
- •Voicing a Contrary Opinion
- •Generalizing a Function into a Template
- •Template Classes
- •Do I Really Need Template Classes?
- •Tips for Using Templates
- •The string Container
- •The list Containers
- •Iterators
- •Using Maps
- •Enabling All Warnings and Error Messages
- •Insisting on Clean Compiles
- •Limiting the Visibility
- •Avoid Overloading Operators
- •Heap Handling
- •Using Exceptions to Handle Errors
- •Avoiding Multiple Inheritance
- •Customize Editor Settings to Your Taste
- •Highlight Matching Braces/Parentheses
- •Enable Exception Handling
- •Include Debugging Information (Sometimes)
- •Create a Project File
- •Customize the Help Menu
- •Reset Breakpoints after Editing the File
- •Avoid Illegal Filenames
- •Include #include Files in Your Project
- •Executing the Profiler
- •System Requirements
- •Using the CD with Microsoft Windows
- •Using the CD with Linux
- •Development tools
- •Program source code
- •Index
Chapter 7
Storing Sequences in Arrays
In This Chapter
Considering the need for something like an array
Introducing the array data type
Using an array
Using the most common type of array — the character string
An array is a sequence of variables that shares the same name and that is referenced using an index. Arrays are useful little critters that allow
you to store a large number of values of the same type and that are related in some way — for example, the batting averages of all the players on the same team might be a good candidate for storage within an array. Arrays can be multidimensional, too, allowing you, for example, to store an array of batting averages within an array of months, which allows you to work with the bat ting averages of the team as they occur by month. If you think about it long enough, you get a headache.
In this chapter, you find out how to initialize and use arrays for fun and profit. You also find out about an especially useful form of array, a string, which in C++ is really just an array of type char.
Considering the Need for Arrays
Consider the following problem. You need a program that can read a sequence of numbers from the keyboard. You guessed it — the program stops reading in numbers as soon as you enter a negative number. Unlike similar programs in Chapters 5 and 6, this program is to output all the numbers entered before displaying the average.
94 |
Part II: Becoming a Functional C++ Programmer |
You could try to store numbers in a set of independent variables, as in
cin >> value1; if (value1 >= 0)
{
cin >> value2; if (value2 >= 0)
{
...
You can see that this approach can’t handle sequences involving more than just a few numbers. Besides, it’s ugly. What we need is some type of structure that has a name like a variable but that can store more than one value. May I present to you, Ms. A. Ray.
An array solves the problem of sequences nicely. For example, the following snippet declares an array valueArray that has storage for up to 128 int values. It then populates the array with numbers entered from the keyboard.
int value;
//declare an array capable of holding up to 128 ints int valueArray[128];
//define an index used to access subsequent members of
//of the array; don’t exceed the 128 int limit
for (int i = 0; i < 128; i++)
{
cin >> value;
//exit the loop when the user enters a negative
//number
if (value < 0)
{
break;
}
valueArray[i] = value;
}
The second line of this snippet declares an array valueArray. Array declara tions begin with the type of the array members: in this case, int. This is fol lowed by the name of the array. The last element of an array declaration is an open and closed bracket containing the maximum number of elements that the array can hold. In this code snippet, valueArray can store up to 128 integers.
This snippet reads a number from the keyboard and stores it into each sub sequent member of the array valueArray. You access an individual element of an array by providing the name of the array followed by brackets contain ing the index. The first integer in the array is valueArray[0], the second is valueArray[1], and so on.
Chapter 7: Storing Sequences in Arrays |
95 |
In use, valueArray[i] represents the ith element in the array. The index variable i must be a counting variable — that is, i must be a char, an int, or a long. If valueArray is an array of ints, valueArray[i] is an int.
Using an array
The following program inputs a sequence of integer values from the keyboard until the user enters a negative number. The program then displays the num bers input and reports their sum.
//ArrayDemo - demonstrate the use of arrays
//by reading a sequence of integers
//and then displaying them in order #include <cstdio>
#include <cstdlib> #include <iostream> using namespace std;
//prototype declarations
int sumArray(int integerArray[], int sizeOfloatArray); void displayArray(int integerArray[], int sizeOfloatArray);
int main(int nNumberofArgs, char* pszArgs[])
{
// input the loop count int nAccumulator = 0;
cout << “This program sums values entered “ << “by the user\n”;
cout << “Terminate the loop by entering “ << “a negative number\n”;
cout << endl;
// store numbers into an array int inputValues[128];
int numberOfValues; for(numberOfValues = 0;
numberOfValues < 128; numberOfValues++)
{
//fetch another number int integerValue;
cout << “Enter next number: “; cin >> integerValue;
//if it’s negative...
if (integerValue < 0)
96 |
Part II: Becoming a Functional C++ Programmer |
{
// ...then exit break;
}
//... otherwise store the number
//into the storage array inputValues[numberOfValues] = integerValue;
}
//now output the values and the sum of the values displayArray(inputValues, numberOfValues);
cout << “The sum is “
<<sumArray(inputValues, numberOfValues)
<<endl;
//wait until user is ready before terminating program
//to allow the user to see the program results system(“PAUSE”);
return 0;
}
// displayArray - display the members of an
// array of length sizeOfloatArray void displayArray(int integerArray[], int sizeOfArray)
{
cout << “The value of the array is:” << endl; for (int i = 0; i < sizeOfArray; i++)
{
cout.width(3);
cout << i << “: “ << integerArray[i] << endl;
}
cout << endl;
}
//sumArray - return the sum of the members of an
//integer array
int sumArray(int integerArray[], int sizeOfArray)
{
int accumulator = 0;
for (int i = 0; i < sizeOfArray; i++)
{
accumulator += integerArray[i];
}
return accumulator;
}
The program ArrayDemo begins with a prototype declaration of the functions sumArray() and displayArray() that it will need later. The main body of the program contains an input loop (boring). This time, however, the input values are stored off in the array inputValues.
Chapter 7: Storing Sequences in Arrays |
97 |
If the input value is negative, control exits the loop by executing the break. If not, integerValue is copied into the array. The int variable numberOfValues is used as an index into the array. numberOfValues was initialized to 0 up
at the beginning of the for loop. The index is incremented on each iteration of the loop. The test in the for loop keeps the program from storing more than the 128 integers allocated by the program. (The program goes immedi ately to the output portion after 128 entries whether or not the user enters a negative number.)
The array inputValues is declared as 128 integers long. If you’re thinking that this is enough, don’t count on it. Writing more data than an array causes your program to perform erratically and often to crash. No matter how large you make the array, always put a check to make sure that you do not exceed the limits of the array.
The main function ends by calling displayArray() to print the contents of the array and the sum.
The Dev-C++ environment can help keep you and your functions straight. Figure 7-1 shows the contents of the Classes tab. The name and prototype of each function appear there. Double-clicking a function name takes you straight to the function in the .CPP source file.
Figure 7-1:
The Classes tab displays information about the functions that make up the program.
The displayArray() function contains the typical for loop used to traverse an array. Each entry in the array is added to the variable accumulator. The sizeOfArray passed to the function indicates the number of values contained in integerArray.
Notice, yet again, that the index is initialized to 0 and not to 1. In addition, notice how the for loop terminates before i is equal to sizeOfArray. None of the elements after the sizeOfArray element contains valid data. The output appears as follows: