Changes Made from the Second Printing to the Third

Chapter 9

Page

Line

Change

To

520

25

introduce vector<T>, a C++ standard class template

introduce valarrays and vector<T>, C++ standard class templates

523

8-11 of Fig. 9.1

iostream.h
fstream.h
iomanip.h
Insert after line 11:

iostream
fstream
iomanip
using namespace std;

 

11B

InteractiveInput

InteractiveOpen

527

8T

int

count

533

19T

#include <iostream.h>

. . .

534

4 of Fig. 9.2

iostream.h
Insert after this line:

iostream
using namespace std;

535

1T

iomanip.h
Insert after this line:

iomanip
using namespace std;

536

11T

<string.h>, stdlib.h>, <stdio.h>

<cstring>, <cstdlib>, <cstdio>

 

10B

(or other) arrays

(or other) C-style arrays

537-540

 

Replace last 8 lines of p. 537, all of p. 538, all of p. 539, Fig. 9.4 and the 6 lines following with the following new subsection:

 

    There are, therefore, two significant problems with C-style arrays:

  1. The capacity of a C-style array cannot change during program execution
  2. One of the principles of object-oriented programming is that an object should be self-contained, which means that it should carry within itself all of the information necessary to describe and operate on it. Operations on C-style arrays, however, need at least two pieces of information: the array and some way to identify its final value (e.g., its size). In particular, C-style arrays carry neither their size nor their capacity within them, and so C-style arrays are not self-contained objects.

    With respect to the second problem, we have seen that the C++ class mechanism allows different data members to be stored within a single object. This provides a solution to the second problem – by storing an array, its capacity, and its size within a class structure, a single class object can encapsulate all three pieces of information. This is the approach used by valarrays that we describe next and vectors described in the next section. As we shall see, they also provide solutions to the first problem.


An OOP Approach – valarrays

    An important use of arrays is in vector processing and other numeric computation in science and engineering. In mathematics the term vector refers to a sequence (one-dimensional array) of real values on which various arithmetic operations are performed; for example, +, —, scalar multiplication, and dot product. Because much numeric work relies on the use of such vectors, highly-efficient libraries are essential in many fields. For this reason, C++ provides the standard library <valarray>, which is designed to carry out vector operations very efficiently.

Declarations of valarrays. A valarray declaration has one of the forms

valarray<T> v;

valarray<T> v(n);

valarray<T> v(value, n);

valarray<T> v(array);

valarray<T> v(w);

where T is a numeric type; n is an integer specifying the capacity of v; value is a value of type T; array is an array of T values; and w is a valarray.3 To illustrate, consider the following examples:

valarray<double> v0;

valarray<float> v1(100);

valarray<int> v2(999, 100);

const double a[] = {1.1, 2.2, 3.3, 4.4, 5.5};

valarray<double> v3(a, 4), v4(4, -1.0);

The first declaration creates v0 as an empty valarray of doubles (which can be resized later); the second constructs v1 as a valarray containing 100 float values, initially 0; the third creates v2 as a valarray of 100 int values, initially 999; the last declarations construct v3 as a valarray of 4 doubles, initially the first four values (1.1, 2.2, 3.3, 4.4) stored in array a, and v4 as a valarray of 4 doubles, initially —1.0.

    There also are four auxiliary types that specify subsets of a valarray: slice_array, gslice_array, mask_array, and indirect_array. These seem inappropriate, however, for a first course in computing and are thus left for the sequel to this text.

valarray Operations. The function members for valarrays are:

  • the subscript operator []
  • assignment of same-size valarrays
  • unary operations (applied elementwise): +, -, ~, !
    Example: -v3 gives —1.1, —2.2, —3.3, —4.4
  • assignment ops: +=, -=, *=, /=, =, &=, |=, ^=, <<=, >>=
    If D denotes one of these operations, v D= x; is equivalent to:
	for (int i = 0; i < v.size(); i++)
           v[i] = v[i] D x;

Example: v3 += v4 changes v3 to 0.1, 1.2, 2.3, 3.4

  • size(): the number of elements in the valarray (its capacity)
    Example: v3.size() is 4
  • resize(n, val): reinitialize valarray to have n elements with (optional) value val
    Example:
        cin >> n;
        v0.resize(n);
  • shift(n) and cshift(n): Shift values in the valarray |n| positions left if n > 0, right if n < 0. For shift, vacated positions are filled with 0; for cshift, values are shifted circularly with values from the left end moving into the right end.
    Examples:

       
    v3.shift(2); would change v3 to 3.3, 4.4, 0, 0
       
    v3.shift(-2); would change v3 to 0, 0, 1.1, 2.2
       
    v3.cshift(2); would change v3 to 3.3, 4.4, 1.1, 2.2

 

   There also are several nonmember operations, which are applied elementwise:

  • The following binary operators (applied elementwise):

+, -, *, /, , &, |, ^, <<, >>, &&, ||, ==, !=, <, >, <=, >=

  • mathematical functions (from cmath): atan2(), pow()
    These operations and functions are applied elementwise. The operands may be valarrays or a valarray and a scalar
  • The following mathematical functions, which are applied elementwise:

    acos(), asin(), atan(), cos(), cosh(), exp(), log(), log10(), sin(), sinh()(), sqrt(), tan(), tanh()

    For example, the assignment statements

        v4 = 2.0 * v3;
        w = pow(v3, 2);

    assign to v4 the values 2.2, 4.4, 6.6, 8.8 and to w the squares of the elements of v3, namely, 1.21, 4.84, 10.89, 19.36.

   Some other operations that are useful with valarrays are found in the standard <algorithm> and <numeric> libraries (described in the Section 9.4). For example, <numeric> contains functions for calculating the sum of the elements in a sequence, the inner (dot) product of two sequences, the partial sums of a sequence, and differences of adjacent elements in a sequence

Input. No predefined input operations are provided for valarrays, and so we must write our own input function to read values and store them in a valarray one at a time. Figure 9.3 presents an input function template. For maximum reusability, it receives the stream from which the values are to be extracted, so that the valarray can be input from the keyboard or from a file. Note that because a valarray carries its capacity (size()) along with it, there is no need to pass it as a parameter.

Figure 9.3 Input Operation for valarrays.

/* Read() fills a valarray<T> with input from a stream. 
 * Note: Must #include <valarray> to use this function. 
 *
 *  Receives: type parameter t
 * in, an istream 
 * theValArray, a valarray
 * Input: a sequence of T values
 * Precondition: operator >> is defined for type T.
 * Passes back: the modified istream and the modified valarray<T>
 ****************************************************************/

template <class T>
void Read(istream & in, valarray<T> & theValarray)
{
  for (int i = 0; i < theValarray.size(); i++)
    in >> theValarray[i];
}

Output. As with input, there is no output operation defined for valarrays and so a function to perform this operation must display the values in the valarray one at a time. Using a for loop like that in Read() is the approach in the function Print() in Figure 9.4. Again note that because a valarray carries its size along with it, there is no need to pass it as a parameter.

 

Figure 9.4 Output Operation for valarrays.


/* Print() displays the T values stored in a valarray.
 * Note: Must #include <valarray> to use this function.
 *
 * Receives: type parameter t
 * out, an ostream 
 * theValArray, a valarray
 * Output: each value in theArray to the ostream out
 * Precondition: operator << is defined for type T.
 * Passes back: the modified ostream out
 ************************************************************/

template <class T>
void Print(ostream & out, const valarray<T> & theValarray)
{
  for (int i = 0; i < theValarray.size(); i++) 
    out << theArray[i] << " ";
}

 

542

6

int i, j, n = 9;

int i, j, n = 9,

543

21B & 18B

open an fstream

open a stream

 

17B

to the fstream

to the file stream

 

16B

close the fstream

close the stream

 

2B

Open an fstream

Open a stream

 

1B

from an fstream

from a file stream

544

1T

an fstream

a file stream

 

3T

Open an fstream

Open a stream

 

4T

to an fstream

to a file stream

546

1-6T

iostream.h
fstream.h
assert.h
Insert after line 6:

iostream
fstream
cassert
using namespace std;

548

Last sentence of first para.

Replace

The ISO/ANSI standard includes STL among the standard C++ libraries.

 

9T

The simplest container

One of the simplest containers

550

2 above table

array but without the limitations of C-style arrays

array or valarray but without the limitations of C-style arrays and valarrays

551

5-8T

Replace

v.size() returns the number of values in v. As with C-style arrays and valarrays, the index of the first value of a vector<T> is always 0; but unlike arrays and valarrays, which provide no way to identify the final values stored in them, the index of the last value stored in a vector<T> object v is always v.size() - 1.

554

8-9T

As with C-style arrays,

As we have noted,

 

11T

the elements

the values stored

 

18T

C-style arrays

C-style arrays and valarrays.

 

19-20T

Replace last sentence of paragraph

To illustrate the difference, suppose we modified the Read() function in Figure 9.3 to read values into a vector<T> as follows:

555

4 of Fig. 9.6

Insert a comment line

* Input: a sequence of T values

 

4 of Fig. 9.7

Insert a comment line

* Output: each T value stored in theVector to ostream out

562

Paragraph above table

Replace

STL provides over 80 algorithm templates. An in-depth examination of these algorithms is beyond the scope of this text and is left for the sequel. The table that follows provides a brief introduction to what is available. All of these algorithms are in the <algorithm> library except for accumulate(), which was moved to the<numeric> library in the final ISO/ANSI standard.

 

Footnote

Delete

 

563

6T

count(begin,end,value,0)

count(begin,end,value)

 

9-10T

Delete entry for function iota()

 

 

1B

Insert comment line before this line

* Note: Must #include <numeric> to use accumulate()

564

11T

algorithm

algorithm from the <numeric> library

 

13-14T

Famility with the algorithms provided by STL

Famility with the standard algorithms in C++

565

9B

Insert before last sentence of paragraph.

(We will not consider valarrays here because they can be used only for numeric values.)

566

10T

Append:

and valarray operations are limited to numeric applications.

 

12T

both the C-style array and

the C-style array, valarrays, and

 

16T

in an array or

in an array, valarray<int>, or

 

4B

Footnote number 8

7

 

Footnote

8

7

568

3T

an fstream

a stream

 

4T

the fstream

the file stream

571

10 of Fig. 9.10

iomanip.h
Insert after this line:

iomanip
using namespace std;

572

In Fig. 9.11:
line 11
line 12

line 16


iostream.h
fstream.h

Replace


iostream
fstream

using namespace std;

573

10-20

Replace definition of function Read()

void Read(string & fileName, vector<T> theVector)
{
  ifstream inStream(fileName.data());
  if (!inStream.is_open())
  { 
    cerr << "\n*** Read(): unaable to open " 
         << fileName << endl;
    exit(1);
  }
  T inputValue;
  for (;;)
  {
    in >> inputValue;
    if (in.eof()) break;
    theVector.push_back(inputValue);
  }
  inStream.close()
}

578

20

ANSI/ISO draft standard for C++ in 1995

ISO/ANSI standard for C++ in 1997

 

22

are becoming a reality

have become a reality

579

24B

arrays and

arrays, valarrays, and

 

20B

C-style array.

C-style array of a valarray.

 

4B

array or vector<T>

array, valarray, or vector<T>

580

13T

array or vector<T>

array, valarray, or vector<T>

 

Changes in Chapter 10