Программирование >>  Разработка устойчивых систем 

1 ... 124 125 126 [ 127 ] 128 129 130 ... 196


вариантов вставки нового элемента вы создаете объект value type, присваиваете компонентам пары нужные объекты и вызываете функцию insertQ контейнера тар. Однако в следующем примере задействован другой способ, основанный на уже упоминавшейся особенности контейнера тар: если ключ, переданный при поиске объекта оператору [ ], отсутствует в контейнере, то оператор [ ] автоматически вставляет пару ключ-значение , создавая объект значения конструктором по умолчанию. С учетом сказанного рассмотрим следующую реализацию программы с подсчетом слов:

: C07:WordCount.cpp

Подсчет вхождений слов в файле

с использованием отображения.

#include <iostream>

#include <fstream>

#include <map>

#1nclude <str1ng>

#1nclude ../require.h

using namespace std:

int main(int argc. char* argv[]) {

typedef map<string, int> WordMap:

typedef WordMap::iterator WMIter:

const char* fname = WordCount.cpp :

ifCargc > 1) fname = argv[l]:

ifstream in(fname):

assureCin. fname):

WordMap wordmap:

string word:

while(in word) wordmap[word]++:

forCWMIter w = wordmap.beginO: w != wordmap.endO: w++) cout w->first : w->second endl: } III:-

Заодно этот пример демонстрирует мощь нулевой инициализации. Обратим внимание на следующую строку программы: wordmap[word]++:

Выражение увеличивает значение int, ассоциированное с word. При отсутствии ключа word в отображении автоматически создается новая пара, в которой значение инициализируется нулем, возвращаемым при вызове псевдоконструктора int().

Вывод всего списка требует перебора с применением итератора (чтобы использовать для контейнера тар сокращенную запись с алгоритмом сору(), придется написать операторную функцию operator для объекта pair). Как уже отмечалось, разыменование этого итератора дает объект pair, в котором переменная first содержит 1С71ЮЧ, а переменная second - значение.

Чтобы получить счетчик вхождений для конкретного слова, можно воспользоваться оператором индексирования:

cout the: wordmap[ the ] endl;

В этой записи проявляется одно из важнейших преимуществ отображений - наглядность синтаксиса; операции с ассоциативным массивом понятны читателю программы на уровне здравого смысла (заметьте: если слово the отсутствует в wordmap, для него автоматически создается новый элемент!)



Мультиотображения и дубликаты ключей

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

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

: C07:WildL1feMonitor.cpp #inc1ude <algorithm> #include <cstd11b> linclude <cstddef> linclude <ctime> linclude <iostream> linclude <iterator> linclude <map> linclude <sstream> linclude <string> linclude <vector> using namespace std:

class DataPoint {

int X. y: Координаты

time t time: Время наблюдения public:

DataPointO : x(0). y(0). time(O) {} DataPointCint xx. int yy. time t tm) :

x(xx). y(yy). time(tm) {} Сгенерированный оператор = и копирующий конструктор годятся int getXO const { return x: } int getYO const { return y: } const time t* getTimeO const { return &time: }

string animal[] = { chipmunk , beaver , marmot , weasel , squirrel , ptarmigan , bear , eagle , hawk , vole , deer , otter , hummingbird ,

const int ASZ = sizeof animal/sizeof *animal: vector<string> animalsCanimal. animal + ASZ):

Информация 0 наблюдении в объекте Sighting, содержимое которого можно направить в ostream: typedef pair<string. DataPoint> Sighting:

ostream&

operator (ostream& os, const Sighting& s) { return OS s.first sighted at x= s.second.getXО . y= s.second.getYO . time = ctimeCs.second.getTimeO):

Генератор объектов Sighting:



class SightingGen {

vector<str1ng>& animals:

enum { D = 100 }: public:

SightingGen(vector<string>& an) : animals(an) {} Sighting operatorOO { Sighting result:

int select = randO % animals.sizeO: result.first = animalsEselect]: result.second = DataPoint(

randO % D. randO !i; D. time(O)): return result:

Функция выводит меню с названиями животных, предлагает пользователю выбрать один из пунктов и возвращает индекс: int menuO {

cout select an animal or q* to quit: :

for(int i = 0: i < animals.sizeO; i++) cout [ i ] animals[i] :

cout endl:

string reply:

cin reply:

if(reply.at(0) == q ) return 0: istringstream r(reply): int i:

г i; Преобразование в int i %= animals.SizeO: return i:

int mainO { typedef multimap<string, DataPoint> DataMap: typedef DataMap::iterator DMIter: DataMap sightings:

srand(time(0)); Раскрутка генератора случайных чисел generate n(inserter(sightings, sightings.beginO),

50, SightingGen(animals)): Вывод всех элементов: copyCsightings.begin(). sightings.end(),

ostream iterator<Sighting>(cout. )); Вывод данных no выбранному типу животных: forCint count = 1: count < 10: count++) {

Выбор типа через меню:

int i = menuO;

Случайный выбор (для автоматизации тестирования): int i - randO % animals.sizeO:

Итераторы range определяют начальную и конечную позиции интервала с искомым ключом: pair<DMIter. DMIter> range -

s i ght i ngs.equal range(ani ma 1 s[i]): copy(range.first, range.second,

ostreamjterator<Sighting>(cout, )):

} /:-

Вся информация о наблюдении инкапсулируется в классе DataPoint. Этот класс достаточно прост, чтобы мы могли положиться на сгенерированный оператор при-



1 ... 124 125 126 [ 127 ] 128 129 130 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика