Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Липпман.doc
Скачиваний:
14
Добавлен:
14.08.2019
Размер:
8 Мб
Скачать
☆

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( "wrinkles" ))


count = word_count[ "wrinkles" ];

  • find(keyValue): функция-член find() возвращает итератор, указывающий на элемент, если ключ найден, и итератор end() в противном случае. Например:

int count = 0;

map<string,int>::iterator it = word_count.find( "wrinkles" );

if ( it != word_count.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;


}

Если наше отображение не содержит элементов, данная функция не нужна. Проверить, пусто ли оно, можно с помощью функции-члена size():

if ( text_map->size() )


display_map_text( text_map );

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

if ( ! text_map->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 << " "

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

<< (*siter).second

<< (" раз(а)\n" );


}

Вот результат работы программы:

Наш словарь подстановок:

key: 'em value: them

key: cuz value: because

key: gratz value: grateful

key: nah value: no

key: pos value: suppose

key: sez value: says

key: tanx value: thanks

key: wuz value: was

Исходный вектор строк:

nah I sez tanx cuz I wuz pos

to not cuz I wuz gratz

Преобразованный вектор строк:

no I says thanks because I was suppose

to not because I was grateful

И напоследок статистика:

cuz было заменено 2 раз(а)

gratz было заменено 1 раз(а)

nah было заменено 1 раз(а)

pos было заменено 1 раз(а)

sez было заменено 1 раз(а)

tanx было заменено 1 раз(а)

wuz было заменено 2 раз(а)