|
Программирование >> Разработка устойчивых систем
Подготовительная фаза работы функции main() не отличается от таковой в программе WordCount.cpp, но затем каждое слово просто вставляется в контейнер multiset<string>. Мы создаем итератор и инициализируем его началом мультимножества; разыменование этого итератора дает текущее слово. Функция equal range() (не обобщенный алгоритм!) возвращает начальный и конечный итераторы для текущего слова, а алгоритм distance() (определяемый в заголовке <iterator>) подсчитывает количество элементов в этом интервале. Итератор it перемещается в конец интервала, то есть к следующему слову. Если вы недостаточно хорощо разбираетесь в специфике мультимножеств, эта программа может показаться более сложной. С другой стороны, ее компактность и отсутствие вспомогательных классов вроде Count являются несомненными достоинствами. Насколько удачен выбор названия мультимножество ? Может, стоило назвать контейнер как-нибудь иначе? В некоторых библиотеках контейнеров присутствует контейнер bag, в котором могут храниться любые объекты, в том числе и одинаковые. Он близок к мультимножествам STL, но для контейнера bag не задан способ упорядочения элементов. Мультимножество, требующее, чтобы все дубликаты находились в смежных позициях, на концептуальном уровне устанавливает еще более жесткие ограничения, чем множество. В реализации множества может применяться хеширование, в результате чего элементы не будут располагаться в порядке сортировки. Наконец, если вам потребуется просто хранить набор объектов без специальных критериев упорядочения, обычно бывает удобнее воспользоваться вектором, деком или списком. Объединение контейнеров STL Тезаурус содержит все слова, связанные с некоторым словом. Ключом здесь является одно слово, а зкачекием - сиисок слов. Для реал\1за;щи подобного мехапиг-ма хранения мультиконтейнеры (multimap и multiset) не подходят. Чтобы добиться нужного результата, нужно создать комбинацию контейнеров; к счастью, в STL это делается просто. Конкретное средство для решения задачи - отображение, в котором строки ассоциируются с векторами - подводит нас к мощной общей концепции объединения контейнеров. : С07:Thesaurus.срр Отображение со значениями-векторами #1 nclude <map> linclude <vector> linclude <string> linclude <iostreani> linclude <iterator> linclude <algorithm> linclude <ctinie> linclude <cstdlib> using namespace std; typedef map<string. vector<string> > Thesaurus: typedef pair<string. vector<string> > TEntry; typedef Thesaurus:;iterator Titer; Для правильного разрешения имен: namespace std { ostreamS operator (ostream& os.const TEntryS t){ OS t.first : : copy(t.second.beginO. t.second.endO. ostream iterator<string>(os. )): return os: Генератор тестовых данных для тезауруса: class ThesaurusGen { static const string letters: static int count: public: int maxSizeO { return letters.sizeO: } TEntry OperatorOO { TEntry result: if (count >- maxSizeO) count = 0: result.first - letters[count++]: int entries - (randO !i; 5) + 2: for(int i - 0: i < entries: i++) { int choice - randO % maxSizeO: char cbuf[2] = { 0 }: cbuf[0] - lettersLchoice]: result.second.push back(cbuf): return result; int ThesaurusGen::count - 0: const string ThesaurusGen::letters( ABCDEFGHIJKL MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ): Запрос искомого слова : string menu(Thesaurus& thesaurus) { while(true) { cout Select a \ word\ . 0 to quit: : for(TIter it = thesaurus.beginO: it !- thesaurus.endO: it++) cout (*it).first : cout endl: string reply: cin reply; if(reply.at(0) = 0) exit(O): Выход if (thesaurus. find( reply) -- thesaurus. endO) continue; Слово отсутствует в списке, повторить попытку return reply: int mainO { srand(time(0)): Раскрутка генератора случайных чисел Thesaurus thesaurus: Заполнение тезауруса 10 объектами: generate n( inserter(thesaurus. thesaurus.begin()). 10. ThesaurusGenO): Вывод всего содержимого: copy(thesaurus.begin(). thesaurus.end(). Строго говоря, пользователи не должны расширять стандартное пространство имен, но это самый простой способ решения всех проблем разрешения имен. К тому же он поддерживается всеми известными компиляторами. ostream iterator<TEntry>(cout. \п )): Построение списка ключей: string keys[10]: int i = 0: fordlter it = thesaurus.begin(): it != thesaurus.endO: it++) keys[i++] = (*it).first: for(int count = 0: count < 10: count++) { Ввод с консоли: string reply = menu(thesaurus): Случайные данные: string reply = keys[rand() % 10]: vector<string>& v = thesaurus[reply]: copy(v.begin(). v.endO. ostream iterator<string>(cout. )): cout endl: } /:- Контейнер Thesaurus связывает объект string (слово) с объектом vector<string> (синонимы). Класс TEntry представляет одну запись тезауруса. Создание операторной функции ostream& operator для TEntry позволяет легко выводить отдельные записи тезауруса (а также вывести все его содержимое алгоритмом сору()). Обратите внимание на очень странное размещение потокового итератора вставки: мы включаем его в пространство имен std! При первом вызове сору() в ma1n() щаблон ostreamjterator использует функцию operator . Когда компилятор создает необходимую специализацию ostreamjterator, по правилам поиска с учетом аргументов (ADL) он проводит поиск только в пространстве std, в котором объявлены все аргументы сору(). Если бы итератор объявлялся в глобальном пространстве имен (для чего достаточно удалить окружающий блок namespace), он не был бы найден. Размещение итератора в std позволит механизму ADL найти его. Класс ThesaurusGen создает слова (в нащем примере это просто буквы) и синонимы (другие случайно сгенерированные буквы) для заполнения тезауруса. Количество синонимов выбирается случайно, но не может быть меньще двух. Буквы выбираются индексированием статической строки, которая является частью ThesaurusGen. Функция main() создает контейнер, заполняет его 10 объектами и выводит алгоритмом сору(). Функция menu() предлагает пользователю выбрать искомое слово (то есть ввести соответствующую букву). Функция find() проверяет, присутствует ли заданный элемент в отображении (вспомните: мы не используем оператор [ ], потому что он автоматически создает новый элемент при отсутствии совпадения!). Если элемент присутствует, мы получаем вектор vector<string> оператором [ ] и выводим его содержимое. Строка reply генерируется случайным образом для автоматизации тестирования. Поскольку щаблоны упрощают выражение многих сложных концепций, можно пойти еще дальше и создать отображение векторов, элементами которых являются отображения, и т. д. В таких комбинациях могут использоваться любые контейнеры STL.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |