cin.get();

    }

    cout << "Thank you. You entered the following:\n"

          << "Rating\tBook\n";

    for (i = 0; i < NUM; i++)

    {

        cout << ratings[i] << "\t" << titles[i] << endl;

    }

    return 0;

}

Here’s a sample run of the program in Listing 16.7:

You will do exactly as told. You will enter

5 book titles and your ratings (0-10).

Enter title #1: The Cat Who Knew C++

Enter your rating (0-10): 6

Enter title #2: Felonious Felines

Enter your rating (0-10): 4

Enter title #3: Warlords of Wonk

Enter your rating (0-10): 3

Enter title #4: Don't Touch That Metaphor

Enter your rating (0-10): 5

Enter title #5: Panic Oriented Programming

Enter your rating (0-10): 8

Thank you. You entered the following:

Rating  Book

6       The Cat Who Knew C++

4       Felonious Felines

3       Warlords of Wonk

5       Don't Touch That Metaphor

8       Panic Oriented Programming

All this program does is use the vector template as a convenient way to create a dynamically allocated array. The next section shows an example that uses more of the class methods.

Things to Do to Vectors

Besides allocating storage, what else can the vector template do for you? All the STL containers provide certain basic methods, including size(), which returns the number of elements in a container, swap(), which exchanges the contents of two containers, begin(), which returns an iterator that refers to the first element in a container, and end(), which returns an iterator that represents past-the-end for the container.

What’s an iterator? It’s a generalization of a pointer. In fact, it can be a pointer. Or it can be an object for which pointer-like operations such as dereferencing (for example, operator*()) and incrementing (for example, operator++()) have been defined. As you’ll see later, generalizing pointers to iterators allows the STL to provide a uniform interface for a variety of container classes, including ones for which simple pointers wouldn’t work. Each container class defines a suitable iterator. The type name for this iterator is a class scope typedef called iterator. For example, to declare an iterator for a type double specialization of vector, you would use this:

vector::iterator pd;  // pd an iterator

Suppose scores is a vector object:

vector scores;

Then you can use the iterator pd in code like the following:

pd = scores.begin();  // have pd point to the first element

*pd = 22.3;           // dereference pd and assign value to first element

++pd;                 // make pd point to the next element

As you can see, an iterator behaves like a pointer. By the way, here’s another place the C++11 automatic type deduction can be useful. Instead of, say,

vector::iterator pd = scores.begin();

you can use this:

auto pd = scores.begin();   // C++11 automatic type deduction

Returning to the example, what’s past-the-end? It is an iterator that refers to an element one past the last element in a container. The idea is similar to the idea of the null character being one element past the last actual character in a C-style string, except that the null character is the value in the element, and past-the-end is a pointer (or iterator) to the element. The end() member function identifies the past-the-end location. If you set an iterator to the first element in a container and keep incrementing it, eventually it will reach past-the-end, and you will have traversed the entire contents of the container. Thus, if scores and pd are defined as in the preceding example, you can display the contents with this code:

for (pd = scores.begin(); pd != scores.end(); pd++)

    cout << *pd << endl;;

All containers have the methods just discussed. The vector template class also has some methods that only some STL containers have. One handy method, called push_back(), adds an element to the end of a vector. While doing so, it attends to memory management so that the vector size increases to accommodate added members. This means you can write code like the following:

vector scores;  // create an empty vector

double temp;

while (cin >> temp && temp >= 0)

    scores.push_back(temp);

cout << "You entered " << scores.size() << " scores.\n";

Each loop cycle adds one more element to the scores object. You don’t have to pick the number of element when you write the program or when you run the program. As long as the program has access to sufficient memory, it will expand the size of scores as necessary.

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги