Читаем Программирование полностью

В нашей маленькой программе мы считываем слова, а затем упорядочиваем их. Пока все, что мы делаем, кажется очевидным, но почему мы записываем слова в “неправильные” ячейки, так что потом вынуждены их сортировать? Кроме того, что еще хуже, оказывается, что мы записываем слова и выводим их на печать столько раз, сколько они появляются в потоке ввода.

Последнюю проблему можно решить, используя алгоритм unique_copy() вместо алгоритма copy(). Функция unique_copy() просто не копирует повторяющиеся идентичные значения. Например, при вызове обычной функции copy() программы введет строку


the man bit the dog


и выведет на экран слова


bit

dog

man

the

the


Если же используем алгоритм unique_copy(), то программа выведет следующие слова:


bit

dog

man

the


  Откуда взялись переходы на новую строку? Вывод с разделителями настолько распространен, что конструктор класса ostream_iterator позволяет вам (при необходимости) указывать строку, которая может быть выведена после каждого значения.


ostream_iterator oo(os,"\n"); // создает итератор для

                                      // потока вывода


Очевидно, что переход на новую строку — это распространенный выбор для вывода, позволяющий людям легче разбираться в результатах, но, возможно, вы предпочли бы использовать пробелы? Мы могли бы написать следующий код:


ostream_iterator oo(os," ");  // создает итератор для потока

                                      // вывода


В этом случае результаты вывода выглядели бы так:


bit dog man the

21.7.3. Использование класса set для поддержания порядка

Существует еще более простой способ получить такой вывод: использовать контейнер set, а не vector.


int main()

{

  string from, to;

  cin >> from >> to;          // имена исходного и целевого файлов


  ifstream is(from.c_str());  // создаем поток ввода

  ofstream os(to.c_str());    // создаем поток вывода


  istream_iterator ii(is);     // создаем итератор ввода

                                       // из потока

  istream_iterator eos;        // сигнальная метка для ввода

  ostream_iterator oo(os," "); // создаем итератор

                                       // вывода в поток

  set b(ii,eos);      // b — вектор, который инициализируется

                              // данными из потока ввода

  copy(b.begin(),b.end(),oo); // копируем буфер в поток вывода

}


  Когда мы вставляем значение в контейнер set, дубликаты игнорируются. Более того, элементы контейнера set хранятся в требуемом порядке. Если в вашем распоряжении есть правильные инструменты, то большинство задач можно решить без труда.

21.7.4. Алгоритм copy_if()

Алгоритм copy() выполняет копирование без каких-либо условий. Алгоритм unique_copy() отбрасывает повторяющиеся соседние элементы, имеющие одинаковые значения. Третий алгоритм копирует только элементы, для которых заданный предикат является истинным.


template

Out copy_if(In first,In last,Out res,Pred p)

  // копирует элементы, удовлетворяющие предикату

{

  while (first!=last) {

    if (p(*first)) *res++ = *first;

    ++first;

  }

  return res;

}


Используя наш объект-функцию Larger_than из раздела 21.4, можем найти все элементы последовательности, которые больше шести.


void f(const vector& v)

  // копируем все элементы, которые больше шести

{

  vector v2(v.size());

  copy_if(v.begin(),v.end(),v2.begin(),Larger_than(6));

  // ...

}


  Из-за моей ошибки этот алгоритм выпал из стандарта 1998 ISO Standard. В настоящее время эта ошибка исправлена, но до сих пор встречаются реализации языка С++, в которых нет алгоритма copy_if. В таком случае просто воспользуйтесь определением, данным в этом разделе.

21.8. Сортировка и поиск

  Часто мы хотим упорядочить данные. Мы можем добиться этого, используя структуры, поддерживающие порядок, такие как map и set, или выполняя сортировку. Наиболее распространенной и полезной операцией сортировки в библиотеке STL является функция sort(), которую мы уже несколько раз использовали. По умолчанию функция sort() в качестве критерия сортировки использует оператор <, но мы можем задавать свои собственные критерии.


Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже