|
Программирование >> Разработка устойчивых систем
сваивания и конструктор по умолчанию. Для сохранения времени наблюдения используются стандартные библиотечные функции С. При инициализации массива animal объектов string автоматически используется конструктор char*, что существенно упрощает процедуру инициализации. Так как названия животных удобнее хранить в векторе, мы вычисляем размер массива и инициализируем vector<string> конструктором vector с двумя итераторами. Пары ключ-значение , составляющие объекты Sighting, состоят из объекта string (название животного) и объекта DataPoint (место и время наблюдения). Эти два типа объединяются стандартным шаблоном pair, и для него создается определение типа Sighting. Затем для типа Sighting определяется операторная функция ostream& operator , чтобы мы могли перебрать элементы отображения/мультиотоб-ражения с элементами Sighting и вывести их. Класс SightingGen генерирует тестовые данные со случайным временем и местом наблюдения. Он использует оператор (), необходимый для объекта функции, но также для него определен конструктор с сохранением ссылки на вектор vector<string> с названиями животных. В мультиотображении DataMap хранятся пары string/DataPoint (то есть объекты Sighting). Мы заполняем DataMap 50 объектами Sighting при помощи алгоритма generate n() и выводим его содержимое (существование оператора для типа Sighting позволяет создать итератор ostreamjterator). Далее программа предлагает пользователю выбрать животное, для которого выводится информация о наблюдениях. Если нажать клавишу Q, программа завершается, а при выборе номера вызывается функция equal range(). Она возвращает два итератора, определяющих начало и конец набора элементов с искомым значением ключа. Так как функция может возвращать только один объект, equal range() возвращает свой результат в виде объекта pair. Полученные итераторы передаются алгоритму сору() для вывода информации обо всех наблюдениях животных заданного вида. Мультимножества Мы уже рассматривали множество (контейнер set), в котором каждое значение может храниться только в одном экземпляре. Мультимножество (контейнер multiset) может содержать несколько одинаковых значений. На первый взгляд это противоречит самой идее множества, к которому можно обратиться с вопросом: Присутствует ли такой-то элемент во множестве? Если таких элементов может быть несколько, как понимать вопрос? Если немного подумать, становится ясно, что хранение нескольких абсолютно одинаковых объектов действительно не имеет особого смысла (исключение составляет разве что подсчет экземпляров объектов, но, как было показано в этой главе, подобная задача имеет другое, более изящное решение). Таким образом, у каждого дубликата должна быть некая особенность, которая отличает его от других дубликатов; как правило, это разная информация состояния, не используемая при вычислении ключа в процессе сравнения. Итак, с точки зрения операции сравнения объекты выглядят одинаково, но в действительности они обладают разным внутренним состоянием. Как и любой контейнер STL с упорядочением элементов, шаблон multiset по умолчанию определяет порядок следования элементов при помощи объекта функ- ции less. При этом используется оператор < класса элементов, но вы всегда можете предоставить собственный критерий сравнения. Рассмотрим простой класс с двумя переменными; одна переменная задействована в сравнении, а другая - нет: : C07:MuUiSetl.cpp Мультимножества linclude <algorithm> linclude <cstdlib> linclude <ctime> linclude <iostream> linclude <iterator> linclude <set> using namespace std; class X { char c; Используется при сравнении int i; He используется при сравнении Конструктор no умолчанию и оператор = не нужны X8i operator=(const Х&); Обычно нужен копирующий конструктор (но в данном случае подойдет и сгенерированная версия) public; X(char сс. int ii) ; с(сс). i(ii) {} Обратите внимание; оператор == может отсутствовать friend bool operator<(const Х& х. const Х& у) { return х.с < у.с; friend ostreamS operator (ostream& os. X x) { return OS x.c ; x.i; class Xgen { Static int i; Количество возможных символов; enum { span = 6 }; public; X operatorOO { char с = A + randO % span; return X(c. i++); int Xgen;:i = 0; typedef multiset<X> Xmset: typedef Xmset;:const iterator Xmit; int mainO { Xmset mset: Заполнение объектами X: srand(time(0)); Раскрутка генератора случайных чисел generate n(inserter(mset. mset.begin()). 25. XgenO); Инициализация обычного множества на базе mset; set<X> unique(mset.begin(). mset.endO); copy (uni que. begi nO. uni que. end О. ostream 1terator<X>(cout. )): cout \n----\n ; Перебор уникальных значений: for(set<X>::iterator i = unique.begin(): i != unique.endO: i++) { pair<Xmit. Xmit> p = mset.equal range(*i): copy(p.first, p.second. ostream iterator<X>(cout. )): cout endl: } III:- В классе X объекты сравниваются по значению поля char с. Сравнение выполняется оператором <; для мультимножества этого достаточно, потому что в нашем примере по умолчанию используется критерий less. Класс Xgen генерирует случайные объекты X, при этом символы, по которым производится сравнение, лежат в интервале от А до Е . Функция ma1n() создает контейнер multiset<X> и заполняет его 25 объектами X, используя Xgen. Контейнер заведомо содержит одинаковые ключи. Чтобы получить набор уникальных значений, мы создаем на базе мультимножества обычное множество set<X> (при этом задействован итератор с двумя конструкторами). Программа выводит эти значения, а затем для каждого из них вызывается функция equal range() (в мультимножествах она делает то же, что в мультиотображениях: ищет элементы с одинаковыми ключами). В завершение программа выводит все наборы с одинаковыми ключами. Рассмотрим другой пример - более элегантную реализацию программы WordCount.cpp на базе мультимножества: : C07:MultiSetWordCount.cpp Подсчет вхождений слов в файле с использованием мультимножества. #include <fstream> linclude <iostream> linclude <iterator> linclude <set> linclude <string> linclude ../require.h using namespace std: int main(int argc. char* argv[]) { char* fname = MultiSetWordCount.cpp : if(argc > 1) fname = argv[l]: ifstream in(fname): assureCin. fname): multiset<string> wordmset: string word: whileCin word) wordmset.insert(word): typedef multiset<string>::iterator MSit: MSit it = wordmset.begin(): while(it != wordmset.endO) { pair<MSit. MSit> p = wordmset.equal range(*it): int count = distance(p.first, p.second): cout *it ; count endl: it = p.second: Переход к следующему слову } /:-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |