- •Introduction
- •Saving Time with This Book
- •Conventions Used in This Book
- •Part II: Working with the Pre-Processor
- •Part III: Types
- •Part IV: Classes
- •Part V: Arrays and Templates
- •Part VI: Input and Output
- •Part VII: Using the Built-in Functionality
- •Part VIII: Utilities
- •Part IX: Debugging C++ Applications
- •Part X: The Scary (or Fun!) Stuff
- •Icons Used in This Book
- •Creating and Implementing an Encapsulated Class
- •Creating a Mailing-List Application
- •Testing the Mailing-List Application
- •Customizing a Class with Polymorphism
- •Testing the Virtual Function Code
- •Why Do the Destructors Work?
- •Delayed Construction
- •The cDate Class
- •Testing the cDate Class
- •Creating the Header File
- •Testing the Header File
- •The Assert Problem
- •Fixing the Assert Problem
- •Using the const Construct
- •Identifying the Errors
- •Fixing the Errors
- •Fixing What Went Wrong with the Macro
- •Using Macros Appropriately
- •Using the sizeof Function
- •Evaluating the Results
- •Using sizeof with Pointers
- •Implementing the Range Class
- •Testing the Range Class
- •Creating the Matrix Class
- •Matrix Operations
- •Multiplying a Matrix by a Scalar Value
- •Multiplying a Matrix by Scalar Values, Take 2
- •Testing the Matrix Class
- •Implementing the Enumeration Class
- •Testing the Enumeration Class
- •Implementing Structures
- •Interpreting the Output
- •Defining Constants
- •Testing the Constant Application
- •Using the const Keyword
- •Illustrating Scope
- •Interpreting the Output
- •Using Casts
- •Addressing the Compiler Problems
- •Testing the Changes
- •Implementing Member-Function Pointers
- •Updating Your Code with Member-Function Pointers
- •Testing the Member Pointer Code
- •Customizing Functions We Wrote Ourselves
- •Testing the Default Code
- •Fixing the Problem
- •Testing the Complete Class
- •Implementing Virtual Inheritance
- •Correcting the Code
- •Rules for Creating Overloaded Operators
- •Using Conversion Operators
- •Using Overloaded Operators
- •Testing the MyString Class
- •Rules for Implementing new and delete Handlers
- •Overloading new and delete Handlers
- •Testing the Memory Allocation Tracker
- •Implementing Properties
- •Testing the Property Class
- •Implementing Data Validation with Classes
- •Testing Your SSN Validator Class
- •Creating the Date Class
- •Testing the Date Class
- •Some Final Thoughts on the Date Class
- •Creating a Factory Class
- •Testing the Factory
- •Enhancing the Manager Class
- •Implementing Mix-In Classes
- •Testing the Template Classes
- •Implementing Function Templates
- •Creating Method Templates
- •Using the Vector Class
- •Creating the String Array Class
- •Working with Vector Algorithms
- •Creating an Array of Heterogeneous Objects
- •Creating the Column Class
- •Creating the Row Class
- •Creating the Spreadsheet Class
- •Testing Your Spreadsheet
- •Working with Streams
- •Testing the File-Reading Code
- •Creating the Test File
- •Reading Delimited Files
- •Testing the Code
- •Creating the XML Writer
- •Testing the XML Writer
- •Creating the Configuration-File Class
- •Setting Up Your Test File
- •Building the Language Files
- •Creating an Input Text File
- •Reading the International File
- •Testing the String Reader
- •Creating a Translator Class
- •Testing the Translator Class
- •Creating a Virtual File Class
- •Testing the Virtual File Class
- •Using the auto_ptr Class
- •Creating a Memory Safe Buffer Class
- •Throwing and Logging Exceptions
- •Dealing with Unhandled Exceptions
- •Re-throwing Exceptions
- •Creating the Wildcard Matching Class
- •Testing the Wildcard Matching Class
- •Creating the URL Codec Class
- •Testing the URL Codec Class
- •Testing the Rot13 Algorithm
- •Testing the XOR Algorithm
- •Implementing the transform Function to Convert Strings
- •Testing the String Conversions
- •Implementing the Serialization Interface
- •Creating the Buffer Class
- •Testing the Buffer Class
- •Creating the Multiple-Search-Path Class
- •Testing the Multiple-Search-Path Class
- •Testing the Flow Trace System
- •The assert Macro
- •Logging
- •Testing the Logger Class
- •Design by Contract
- •Adding Logging to the Application
- •Making Functions Inline
- •Avoiding Temporary Objects
- •Passing Objects by Reference
- •Choosing Initialization Instead of Assignment
- •Learning How Code Operates
- •Testing the Properties Class
- •Creating the Locking Mechanism
- •Testing the Locking Mechanism
- •Testing the File-Guardian Class
- •Implementing the Complex Class
- •Creating the Conversion Code
- •Testing the Conversion Code
- •A Sample Program
- •Componentizing
- •Restructuring
- •Specialization
- •Index
33 Working with Arrays
Technique
Save Time By
Understanding the vector class
Implementing array classes
Working with various algorithms with the vector class
The Standard Template Library (STL) provides access to a number of different forms of storage classes. One of these is the vector class, which allows the programmer to store arbitrary arrays of objects.
Unfortunately, the vector class also requires that you “pull in” (link) the entire STL to use it. This can cause significant overhead in your application and can consume large amounts of memory. Because the vector class is a templated class, it copies large chunks of code each time it’s used. Although this is normally insignificant for large-scale
applications — and well worth the expense of memory and size — it can be quite costly when your applications are smaller or have to operate in more restricted memory areas, as with embedded applications. For this reason, it makes sense to get handy with not only the vector class but also with implementing your own simple array classes that can use restricted memory. This technique shows you how to use vector classes — and techniques for working with various algorithms with the vector class. The next technique, Technique 34, shows you how to use array classes with limited overhead.
Using the Vector Class
The vector class is amazingly powerful and, after you get the hang of it, very easy to use in your own code. Let’s look at an example of working with vectors. We will examine how to add data to a vector, step through (iterate) the values in the array, and print out the data in the array. Here’s how:
1.
2.
In the code editor of your choice, create a new file to hold the code for the implementation of the source file.
In this example, the file is named ch33.cpp, although you can use whatever you choose.
Type the code from Listing 33-1 into your file.
Better yet, copy the code from the source file on this book’s companion Web site.
Using the Vector Class 193
LISTING 33-1: WORKING WITH VECTORS
#include <stdio.h> #include <string> #include <vector> #include <iostream>
using namespace std;
template < class A >
void print_array( vector<A> array )
{
vector<A>::iterator iter;
for ( iter = array.begin(); iter != array.end(); ++iter ) cout << (*iter) << “\n”;
}
void reverse_array( const vector<string>& arrayIn, vector<string>& arrayOut )
{
vector<string>::const_iterator iter;
for ( iter = arrayIn.begin(); iter != arrayIn.end(); ++iter )
{
arrayOut.insert( arrayOut.begin(), (*iter) );
}
}
int main(int argc, char **argv)
{
vector<string> stringArray;
//First, add all of the arguments to the
//array that were passed into the application. for ( int i=0; i<argc; ++i )
stringArray.insert( stringArray.end(), argv[i] );
//Print them out using an iterator vector<string>::iterator iter;
for (iter = stringArray.begin(); iter != stringArray.end(); ++iter )
{
//This isn’t necessary, but illustrates how to get
//the actual item stored in an array element. Note that
//the copy constructor will be invoked on this line. string s = (*iter);
cout << “Element: “ << s << “\n”;
}
1
2
(continued)
194 Technique 33: Working with Arrays
LISTING 33-1 (continued)
//Now, we want to remove any element in the array which is the number
//3
for ( iter = stringArray.begin(); iter != stringArray.end(); iter ++ )
{
if ( (*iter) == “3” )
{
cout << “Erasing element “ << (*iter) << “\n”; stringArray.erase( iter );
}
}
//Display the results for the user printf(“Array after removal\n”); print_array( stringArray );
//Next, reverse the array vector<string> outArray; reverse_array( stringArray, outArray ); printf(“Array after reversal\n”); print_array( outArray );
return 0;
}
3
4
3. Save the source file in your code editor and close the code editor.
This source code utilizes the power and functionality of the Standard Template Library to do simple array manipulations, including adding new data to an array, reversing the elements in an array, and iterating over the elements in an array.
4. Compile the source code with the compiler of your choice, on the operating system of your choice.
When the program is run, if you have done everything properly, you should see the following output in the shell window:
$ ./a.exe 1 2 3 4 Element: ./a Element: 1
Element: 2
Element: 3
Element: 4 Erasing element 3
Array after removal
./a
1
2
4
Array after reversal 4 2 1
./a
As you can see, the program reads in the arguments from the command line, places them into an array (shown at the line marked 1), then prints out the array by iterating over each element and printing out the data contained at that array element (shown at 2). Next, the program removes all values of 3 from the array, illustrating how you can delete from an array (shown at 3) and leave the rest of the
Using the Vector Class 195
elements in order. Finally, the values in the array are reversed, by copying them into a new array in reverse order (shown at 4) and the result is printed out once more.
This example illustrates how easy it is to work with the vector class in the C++ STL — and the result is very powerful. Unfortunately, the class is also quite
large. On my system, the resulting executable file takes up over 400KB for this simple little program. This illustrates how the STL pulls in a lot of code when you utilize it. Admittedly, in today’s world, 400 KB is not that large, but it’s a lot for such a small program.