Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих.pdf
Скачиваний:
183
Добавлен:
01.05.2014
Размер:
3.97 Mб
Скачать

В конце концов build_word_map() возвращает построенное отображение:

return word_map;

int main()

{

// считываем файл и выделяем слова vector<string, allocator> *text_file =

retrieve_text(); text_loc *text_locations =

separate_words( text_file );

//обработаем слова

//...

//построим отображение слов на векторы позиций map<string,lос*,less<string>,allocator>

*text_map = build_word_map( text_locatons );

// ...

Вот как выглядит вызов этой функции из main():

}

6.12.2. Поиск и извлечение элемента отображения

Оператор взятия индекса является простейшим способом извлечения элемента.

// map<string,int> word_count;

Например:

int count = word_count[ "wrinkles" ];

Однако этот способ работает так, как надо, только при условии, что запрашиваемый ключ действительно содержится в отображении. Иначе оператор взятия индекса поместит в отображение элемент с таким ключом. В данном случае в word_count занесется пара

string( "wrinkles" ), 0

Класс map предоставляет две операции для того, чтобы выяснить, содержится ли в нем определенное значение ключа.

count(keyValue): функция-член count() возвращает количество элементов с данным ключом. (Для отображения оно равно только 0 или 1). Если count() вернула 1, мы можем смело использовать индексацию:

int count = 0; if

( word_count.count( "wri nkles" ))

count = word_count[ "wrinkles" ];

find(keyValue): функция-член find() возвращает итератор, указывающий на

int count = 0; map<string,int>::iterator it =

word_count.find( "wrinkles" ); if ( it != word_count.end() )

элемент, если ключ найден, и итератор end() в противном случае. Например: count = (*it).second;

Значением итератора является указатель на объект pair, в котором first содержит ключ, а second – значение. (Мы вернемся к этому в следующем подразделе.)

6.12.3. Навигация по элементам отображения

После того как мы построили отображение, хотелось бы распечатать его содержимое. Мы можем сделать это, используя итератор, начальное и конечное значение которого получают с помощью функций-членов begin() и end(). Вот текст функции display_map_text():

void

display_map_text( map<string,loc*> *text_map )

{

typedef map<string,loc*> tmap; tmap::iterator iter = text_map->begin(), iter_end = text_map->end();

while ( iter != iter_end )

{

cout << "word: " << (*iter).first << " ("; int loc_cnt = 0;

loc *text_locs = (*iter).second; loc::iterator liter = text_locs->begin(),

liter_end = text_locs-

>end();

while (liter != liter_end ) { if ( loc_cnt )

cout << ','; else ++loc_cnt;

cout << '(' << (*liter).first

<< ',' << (*liter).second << ')';

++liter;

}

cout << ")\n"; ++iter;

}

cout << endl;

}

Если наше отображение не содержит элементов, данная функция не нужна. Проверить,

if ( text_map- >size() )

пусто ли оно, можно с помощью функции-члена size(): display_map_text( text_map );

Но более простым способом, без подсчета элементов, будет вызов функции-члена

if ( ! text_map- >empty() )

empty():

display_map_text( text_map );

6.12.4. Словарь

Вот небольшая программа, иллюстрирующая построение отображения, поиск в нем и обход элементов. Здесь используются два отображения. Первое, необходимое для преобразования слов, содержит два элемента типа string. Ключом является слово,

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

#include <map> #include <vector> #include <iostream> #include <string>

int main()

{

map< string, string > trans_map;

typedef map< string, string >::value_type valType;

//первое упрощение:

//жестко заданный словарь

trans_map.insert( va1Type( "gratz", "grateful" ));

trans_map.insert( va1Type( "'em",

"them"

));

trans_map.insert( va1Type( "cuz",

"because"

));

trans_map.insert( va1Type( "nah",

"no"

));

trans_map.insert( va1Type( "sez",

"says"

));

trans_map.insert( va1Type( "tanx",

"thanks"

));

trans_map.insert( va1Type( "wuz",

"was"

));

trans_map.insert( va1Type( "pos",

"suppose"

));

// напечатаем словарь

 

 

map< string,string >::iterator it;

 

 

cout << "Наш словарь подстановок: \n\n"; for ( it = trans_map.begin();

it != trans_map.end(); ++it )

cout << "ключ: " << (*it).first << "\t"

<< "значение: " << ("it).second << "\n";

cout << "\n\n";

// второе упрощение: жестко заданный текст string textarray[14]={ "nah", "I", "sez", "tanx",

"cuz", "I", "wuz", "pos", "to", "not", "cuz", "I", "wuz", "gratz" };

vector< string > text( textarray, textarray+14 ); vector< string >::iterator iter;

// напечатаем текст

cout << "Исходный вектор строк:\n\n"; int cnt = 1;

for ( iter = text-begin(); iter != text.end(); ++iter,++cnt )

cout << *iter << ( cnt % 8 ? " " : "\n" );

cout << "\n\n\n";

// map для сбора статистики map< string,int > stats;

typedef map< string,int >::value_type statsValType; // здесь происходит реальная работа

for ( iter=text.begin(); iter != text.end(); ++iter ) if (( it = trans_map.find( *iter ))

!= trans_map.end() )

{

if ( stats.count( *iter )) stats [ *iter ] += 1;

else stats.insert( statsVa1Type( *iter, 1 )); *iter = (*it).second;

}

// напечатаем преобразованный текст

cout << "Преобразованный вектор строк:\n\n"; cnt = 1;

for ( iter = text.begin(); iter != text.end(); ++iter, ++cnt )

cout << *iter << ( cnt % 8 ? " " : "\n" ); cout << "\n\n\n";

// напечатаем статистику

cout << "И напоследок статистика:\n\n"; map<string,int,less<string>,allocator>::iterator

siter;

for (siter=stats.begin(); siter!=stats.end(); ++siter)

cout << (*siter).first

<< " "

<< "было заменено "