Язык программирования C++. Вводный курс


Использование обобщенных алгоритмов - часть 7


/p>

};

void process_vocab( vector<textwords, allocator> *pvec )

{

   // ...

 

   for_each( texts.begin(), texts.end(), PrintElem() );

}

Вот и все. Мы получили законченную программу, для чего пришлось лишь последовательно записать обращения к нескольким обобщенным алгоритмам. Для удобства мы приводим ниже полный листинг вместе с функцией main() для ее тестирования (здесь используются специальные типы итераторов, которые будут обсуждаться только в разделе 12.4). Мы привели текст реально исполнявшегося кода, который не полностью удовлетворяет стандарту C++. В частности, в нашем распоряжении были лишь устаревшие реализации алгоритмов count() и count_if(), которые не возвращают результат, а требуют передачи дополнительного аргумента для вычисленного значения. Кроме того, библиотека iostream

отражает предшествующую принятию стандарта реализацию, в которой требуется заголовочный файл iostream.h.

#include <vector>

#include <string>

#include <algorithm>

#include <iterator>

 

// предшествующий принятию стандарта синтаксис <iostream>

#include <iostream.h>

 

class GreaterThan {

public:

   GreaterThan( int size = 6 ) : _size( sz ){}

   int size() { return _size; }

 

   bool operator()(const string &s1)

                  { return s1.size() > _size; }

private:

   int _size;

};

 

class PrintElem {

public:

 

   PrintElem( int lineLen = 8 )

      : _line_length( lineLen ), _cnt( 0 )

   {}

 

   void operator()( const string &elem )

   {

      ++_cnt;

      if ( _cnt % _line_length == 0 )

         { cout << '\n'; }

 

      cout << elem << " ";

   }

 

private:

   int _line_length;

   int _cnt;

};

class LessThan {

public:

   bool operator()( const string & s1,

                   const string & s2 )

   { return s1.size() < s2.size();    }

};

 

typedef vector<string, allocator> textwords;

void process_vocab( vector<textwords, allocator> *pvec )

{

   if ( ! pvec ) {

            // вывести предупредительное сообщение

     return;

   }

 

   vector< string, allocator > texts;

 

   vector<textwords, allocator>::iterator iter;

   for ( iter = pvec->begin() ; iter != pvec->end(); ++iter )

      copy( (*iter).begin(), (*iter).end(),

              back_inserter( texts ));

 

   // отсортировать вектор texts

   sort( texts.begin(), texts.end() );

 

   // теперь посмотрим, что получилось

   for_each( texts.begin(), texts.end(), PrintElem() );

 

   cout << "\n\n";   // разделить части выведенного текста

 

   // удалить дубликаты

   vector<string, allocator>::iterator it;

   it = unique( texts.begin(), texts.end() );

   texts.erase( it, texts.end() );

 

   // посмотрим, что осталось

   for_each( texts.begin(), texts.end(), PrintElem() );

   cout << "\n\n";

 

   // отсортировать элементы

   // stable_sort сохраняет относительный порядок равных элементов

   stable_sort( texts.begin(), texts.end(), LessThan() );

   for_each( texts.begin(), texts.end(), PrintElem() );

 

   cout << "\n\n";

 

   // подсчитать число строк, длина которых больше 6

   int cnt = 0;

 

   // устаревшая форма count - в стандарте используется другая

   count_if( texts.begin(), texts.end(), GreaterThan(), cnt );

 

   cout << "Number of words greater than length six are "

        << cnt << endl;

 

   static string rw[] = { "and", "if", "or", "but", "the" };

   vector<string,allocator> remove_words( rw, rw+5 );

 

   vector<string, allocator>::iterator it2 = remove_words.begin();

 

   for ( ; it2 != remove_words.end(); ++it2 )

   {

      int cnt = 0;

 

      // устаревшая форма count - в стандарте используется другая

      count( texts.begin(), texts.end(), *it2, cnt );

          

      cout << cnt    << " instances removed:  "

           << (*it2) << endl;

 

      texts.erase(

         remove(texts.begin(),texts.end(),*it2),

                texts.end()

      );

   }

   cout << "\n\n";

   for_each( texts.begin(), texts.end(), PrintElem() );

}

 

// difference_type - это тип, с помощью которого можно хранить результат

// вычитания двух итераторов одного и того же контейнера

// - в данном случае вектора строк ...

// обычно это предполагается по умолчанию

 

typedef vector<string,allocator>::difference_type diff_type;

 

// предшествующий принятию стандарта синтаксис для <fstream>

#include <fstream.h>

 

main()

{

     vector<textwords, allocator> sample;

     vector<string,allocator> t1, t2;

     string t1fn, t2fn;

 

           // запросить у пользователя имена входных файлов ...

           // в реальной программе надо бы выполнить проверку

     cout << "text file #1: "; cin >> t1fn;

     cout << "text file #2: "; cin >> t2fn;

 

           // открыть файлы

     ifstream infile1( t1fn.c_str());

     ifstream infile2( t2fn.c_str());

 

           // специальная форма итератора

           // обычно diff_type подразумевается по умолчанию ...

     istream_iterator< string, diff_type > input_set1( infile1 ), eos;

     istream_iterator< string, diff_type > input_set2( infile2 );

 

           // специальная форма итератора

     copy( input_set1, eos, back_inserter( t1 ));

     copy( input_set2, eos, back_inserter( t2 ));

 

     sample.push_back( t1 ); sample.push_back( t2 );

     process_vocab( &sample );

<


Начало  Назад  Вперед