register int elem_cnt = text_words-size();

if ( elem_cnt != text_locs-size() )

{

cerr

"oops! internal error: word and position vectors "

"are of unequal size\n"

"words: " elem_cnt " "

"locs: " text_locs-size()

" -- bailing out!\n";

exit( -2 );

}

for ( int ix=0; ix elem_cnt; ix++ )

{

cout "word: " (*text_words)[ ix ] "\t"

"location: ("

(*text_locs)[ix].first ","

(*text.locs)[ix].second ")"

"\n";

}

cout endl;

}

Упражнение 6.25

Объясните, почему нам потребовался специальный класс inserter для заполнения набора стоп-слов (это упоминается в разделе 6.13.1, а детально рассматривается в 12.4.1).

setstring exclusion_set;

ifstream infile( "exclusion_set" );

copy( default_excluded_words, default_excluded_words+25,

inserter(exclusion_set, exclusion_set.begin() ));

Упражнение 6.26

Первоначальная реализация поисковой системы отражает процедурный подход: набор глобальных функций оперирует набором независимых структур данных. Окончательный вариант представляет собой альтернативный подход, когда мы инкапсулируем функции и данные в класс TextQuery. Сравните оба способа. Каковы недостатки и преимущества каждого?

Упражнение 6.27

В данной версии программы имя файла с текстом вводится по запросу. Более удобно было бы задавать его как параметр командной строки; в главе 7 мы покажем, как это делается. Какие еще параметры командной строки желательно реализовать?

<p>6.15. Контейнеры multimap и multiset</p>

Контейнеры map и set не допускают повторяющихся значений ключей, а multimap (мультиотображение) и multiset (мультимножество) позволяют сохранять ключи с дублирующимися значениями. Например, в телефонном справочнике может понадобиться отдельный список номеров для каждого абонента. В перечне книг одного автора может быть несколько названий, а в нашей программе с одним словом текста сопоставляется несколько позиций. Для использования multimap и multiset нужно включить соответствующий заголовочный файл – map или set:

#include map

multimap key_type, value_type multimapName;

Для прохода по мультиотображению или мультимножеству можно воспользоваться комбинацией итератора, который возвращает find() (он указывает на первый найденный элемент), и значения, которое возвращает count(). (Это работает, поскольку в данных контейнерах элементы с одинаковыми ключами обязательно являются соседними). Например:

#include map

#include string

void code_fragment()

{

multimap string, string authors;

string search_item( "Alain de Botton" );

// ...

int number = authors.count( search_item );

mu1timap string,string ::iterator iter;

iter = authors.find( search_item );

for ( int cnt = 0; cnt number; ++cnt, ++-iter )

do_something( *iter );

// ...

}

Более элегантный способ перебрать все значения с одинаковыми ключами использует специальную функцию-член equal_range(), которая возвращает пару итераторов. Один из них указывает на первое найденное значение, а второй – на следующее за последним найденным. Если последний из найденных элементов является последним в контейнере, второй итератор содержит величину, равную end():

#include map

#include string

#include utility

void code_fragment()

{

multimap string, string authors;

// ...

string search_item( "Haruki Murakami" );

while ( cin cin search_item )

switch ( authors.count( search_item ))

{

// не найдено

case 0:

break;

// найден 1, обычный find()

case 1: {

multimap string, string : iterator iter;

iter = authors.find( search_item );

// обработка элемента ...

break;

}

// найдено несколько ...

default:

{

typedef multimapstring,string::iterator iterator;

pair iterator, iterator pos;

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

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