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

Since iterators are identical to pointers in all essential ways, you can write the algorithms in the standard library in such a way as to allow both pointer and iterator arguments. For this reason, the implementation of copy( ) looks more like the following code.

template

void copy(Iterator begin, Iterator end, Iterator dest) {

  while (begin != end)

    *begin++ = *dest++;

}

Whichever argument type you use in the call, copy( ) assumes it properly implements the indirection and increment operators. If it doesn’t, you’ll get a compile-time error.

<p>Predicates</p>

At times, you might want to copy only a well-defined subset of one sequence to another, such as only those elements that satisfy a certain condition. To achieve this flexibility, many algorithms have alternate calling sequences that allow you to supply a predicate, which is simply a function that returns a Boolean value based on some criterion. Suppose, for example, that you only want to extract from a sequence of integers those numbers that are less than or equal to 15. A version of copy( ) called remove_copy_if( ) can do the job, like this:.

//: C06:CopyInts2.cpp

// Ignores ints that satisfy a predicate

#include

#include

#include

using namespace std;

// You supply this predicate

bool gt15(int x) {

  return 15 < x;

}

int main() {

  int a[] = {10, 20, 30};

  const size_t SIZE = sizeof a / sizeof a[0];

  int b[SIZE];

  int* endb = remove_copy_if(a, a+SIZE, b, gt15);

  int* beginb = b;

  while (beginb != endb)

    cout << *beginb++ << endl; // Prints 10 only

} ///:~.

The remove_copy_if( ) function template takes the usual range-delimiting pointers, followed by a predicate of your choosing. The predicate must be a pointer to function[79] that takes a single argument of the same type as the elements in the sequence, and it must return a bool. In this case, the function gt15 returns true if its argument is greater than 15. The remove_copy_if( ) algorithm applies gt15( ) to each element in the input sequence and ignores those elements when writing to the output sequence.

The following program illustrates yet another variation of the copy algorithm.

//: C06:CopyStrings2.cpp

// Replaces strings that satisfy a predicate

#include

#include

#include

#include

using namespace std;

// The predicate

bool contains_e(const string& s) {

  return s.find('e') != string::npos;

}

int main() {

  string a[] = {"read", "my", "lips"};

  const size_t SIZE = sizeof a / sizeof a[0];

  string b[SIZE];

  string* endb =

    replace_copy_if(a, a + SIZE, b, contains_e,

     string("kiss"));

  string* beginb = b;

  while (beginb != endb)

    cout << *beginb++ << endl;

} ///:~.

Instead of just ignoring elements that don’t satisfy the predicate, replace_copy_if( ) substitutes a fixed value for such elements when populating the output sequence. The output in this case is

kiss

my

lips

because the original occurrence of "read", the only input string containing the letter e, is replaced by the word "kiss", as specified in the last argument in the call to replace_copy_if( ).

The replace_if( ) algorithm changes the original sequence in place, instead of writing to a separate output sequence, as the following program shows.

//: C06:ReplaceStrings.cpp

// Replaces strings in-place

#include

#include

#include

#include

using namespace std;

bool contains_e(const string& s) {

  return s.find('e') != string::npos;

}

int main() {

  string a[] = {"read", "my", "lips"};

  const size_t SIZE = sizeof a / sizeof a[0];

  replace_if(a, a + SIZE, contains_e, string("kiss"));

  string* p = a;

  while (p != a + SIZE)

    cout << *p++ << endl;

} ///:~

<p>Stream iterators</p>

Like any good software library, the Standard C++ Library attempts to provide convenient ways to automate common tasks. We mentioned in the beginning of this chapter that you can use generic algorithms in place of looping constructs. So far, however, our examples have still used an explicit loop to print their output. Since printing output is one of the most common tasks, you would hope for a way to automate that too.

That’s where stream iterators come in. A stream iterator allows you to use a stream as either an input or an output sequence. To eliminate the output loop in the CopyInts2.cpp program, for instance, you can do something like the following.

//: C06:CopyInts3.cpp

// Uses an output stream iterator

#include

#include

#include

#include

using namespace std;

bool gt15(int x) {

  return 15 < x;

}

int main() {

  int a[] = {10, 20, 30};

  const size_t SIZE = sizeof a / sizeof a[0];

  remove_copy_if(a, a + SIZE,

  ostream_iterator(cout, "\n"), gt15);

} ///:~.

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

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

3ds Max 2008
3ds Max 2008

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

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

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