Читаем Thinking In C++. Volume 2: Practical Programming полностью

  copy(IsbIt(in2), IsbIt(), back_inserter(dc));

  TokenIterator::iterator,Delimiters>

    dcIter(dc.begin(), dc.end(), delimiters),

    end3;

  vector wordlist3;

  copy(dcIter, end3, back_inserter(wordlist3));

  copy(wordlist3.begin(), wordlist3.end(), out);

  *out++ = "-----------------------------------";

  // Reproduce the Wordlist.cpp example:

  ifstream in3("TokenIteratorTest.cpp");

  TokenIterator

    wordIter2((IsbIt(in3)), isbEnd, delimiters);

  set wordlist4;

  while(wordIter2 != end)

    wordlist4.insert(*wordIter2++);

  copy(wordlist4.begin(), wordlist4.end(), out);

} ///:~

When using an istreambuf_iterator, you create one to attach to the istream object and one with the default constructor as the past-the-end marker. Both are used to create the TokenIterator that will actually produce the tokens; the default constructor produces the faux TokenIterator past-the-end sentinel. (This is just a placeholder and, as mentioned previously, is actually ignored.) The TokenIterator produces strings that are inserted into a container which must, naturally, be a container of string—here a vector is used in all cases except the last. (You could also concatenate the results onto a string.) Other than that, a TokenIterator works like any other input iterator.

The strangest thing in the previous program is the declaration of wordIter2. Note the extra parentheses in the first argument to the constructor. Without these, a conforming compiler will think that wordIter2 is a prototype for a function that has three arguments and returns a TokenIterator.[98] (Microsoft’s Visual C++ .NET compiler accepts it without the extra parentheses, but it shouldn’t.).

<p>stack</p>

The stack, along with the queue and priority_queue, are classified as adapters, which means they adapt one of the basic sequence containers to store their data. This is an unfortunate case of confusing what something does with the details of its underlying implementation—the fact that these are called "adapters" is of primary value only to the creator of the library. When you use them, you generally don’t care that they’re adapters, but instead that they solve your problem. Admittedly at times it’s useful to know that you can choose an alternate implementation or build an adapter from an existing container object, but that’s generally one level removed from the adapter’s behavior. So, while you may see it emphasized elsewhere that a particular container is an adapter, we’ll only point out that fact when it’s useful. Note that each type of adapter has a default container that it’s built upon, and this default is the most sensible implementation. In most cases you won’t need to concern yourself with the underlying implementation.

The following example shows stack implemented in the three ways: the default (which uses deque), with a vector, and with a list:

//: C07:Stack1.cpp

// Demonstrates the STL stack

#include

#include

#include

#include

#include

#include

using namespace std;

// Rearrange comments below to use different versions.

typedef stack Stack1; // Default: deque

// typedef stack > Stack2;

// typedef stack > Stack3;

int main() {

  ifstream in("Stack1.cpp");

  Stack1 textlines; // Try the different versions

  // Read file and store lines in the stack:

  string line;

  while(getline(in, line))

    textlines.push(line + "\n");

  // Print lines from the stack and pop them:

  while(!textlines.empty()) {

    cout << textlines.top();

    textlines.pop();

  }

} ///:~

The top( ) and pop( ) operations will probably seem non-intuitive if you’ve used other stack classes. When you call pop( ), it returns void rather than the top element that you might have expected. If you want the top element, you get a reference to it with top( ). It turns out this is more efficient, since a traditional pop( ) would have to return a value rather than a reference and thus invoke the copy-constructor. More important, it is exception safe, as we discussed in Chapter 1. If pop( ) both changed the state of the stack and attempted to return the top element, an exception in the element’s copy-constructor could cause the element to be lost. When you’re using a stack (or a priority_queue, described later), you can efficiently refer to top( ) as many times as you want and then discard the top element explicitly using pop( ). (Perhaps if some term other than the familiar "pop" had been used, this would have been a bit clearer.)

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

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

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

Программирование, программы, базы данных / Программное обеспечение / Книги по IT