|
Программирование >> Немодифицирующие последовательные алгоритмы
19723 Shaw, 12345 Johnson, J. 19723 Shaw, A. 54321 Smith, P. /Johnson, J. 19723 Shaw, A. 54321 Smith, P. ?Shaw, A. Number: 19723 Строки хранятся в памяти, размещаемой с помощью оператора р = new char[strlen{buf) + 1] ; как при чтении строк из входного файла, так и при вводе пользователем. Освобождение строк с помощью delete[] (*i).first; также происходит в двух случаях: когда пользователь вводит команду удаления и при выходе из программы для освобождения ресурсов. Эти операции не потребуется программировать вручную в версии, которую мы обсудим в разделе 2.12. Выражение равенства через отношение меньше Имеется еще один интересный аспект, относящийся к использованию С-указателей в качестве ключей. Когда в словаре происходит поиск по ключу, можно ожидать, что это осуществляется с помощью оператора эквивалентности -. Теперь предположим, что в нашей программе мы ищем в словаре имя John и существует элемент словаря, содержащий этот ключ выводится с помощью команды *, имена появляются в алфавитном порядке. Помните, что имена являются ключами, хотя и следуют после номеров: Entries read from file phone.txt: 54321 Smith, P. 12345 Johnson, J. Commands: ?name : find phone number, /name : delete Inumber name: insert (or update) * : list whole phonebook = : save in file # : exit John . Каждый программист на С(++) должен знать, что такой поиск не может быть произведен с помощью оператора ==, поскольку приведет к сравнению адресов, а не самих строк. Вместо == необходимо использовать функцию strcmp. Например, при char *s = John , *t = John ; выражения s == t strcmp(s, t) == 0 будут иметь значения О {= false) и 1 (=true) соответственно. В нашей программе сравнение на равенство символьных ключей выполнятся правильно, потому что для этой цели используется класс compare. Если бы потребовалось сравнить два числа, а и Ь, мы могли бы выразить оператор == через <, заменив а == b !(а < b II b < а) Точно так же проверка на равенство двух ключей sn tтипа char* осуществляется в нашей программе следующим образом: !(compare()(s, t) II compare()(t, s)) Посмотрев на определение функции operatorQ в классе compare, мы увидим, что это эквивалентно !(strcmp(s, t) < О II strcmp(t, s) < 0) Хотя наше выражение вычисляется медленнее, оно, в свою очередь, эквивалентно strcmp(S, t) == О 2.10. Функции insert Добавление новых записей в предыдущем разделе осуществляется с помощью оператора доступа по индексу в следующем выражении D[p] = nr; Вместо этого оператора присваивания мы могли бы написать выражение D.insert(directype::value type(р, nr)); которое основано на нашем определении функции insert 73 typedef map<char*, long, compare> directype; И на следующем определении типа value type в шаблоне тар, приведенном в заголовке тар: typedef pair<const Key, Т> value type; где Key - тип ключа, а Г - тип сопутствующих данных. Приведенный выше довольно сложный вызов функции insert не имеет преимуществ перед более простым оператором присваивания, если нас не интересует возвращаемое функцией insert значение. Это значение может дать нам информацию о результате процесса добавления элемента в словарь. Давайте посмотрим, как определяется функция insert в заголовке тар: pair<iterator, bool> insert(const value type &x); Очевидно, что insert возвращает объект типа pair, который содержит итератор, указывающий позицию добавленной (или обновленной) записи и значение типа bool, которое показывает, произошло ли добавление новой записи. Это может быть полезным в некоторых приложениях, но в программе тар2.срр не имеет значения, потому что, когда пользователь вводит имя, мы начинаем с проверки, является ли это имя новым. Если нет, заменяем только телефонный номер, выполняя (*i).second = nr; без выделения или освобождения памяти. Напомним, что ключи, представляющие имена, являются на самом деле указателями в стиле С. Рассмотрим теперь другую функцию insert для словарей. Если мы знаем позицию, в которой должен быть расположен новый элемент, эта информация может быть использована для того, чтобы операция вставки стала более эффективной по времени выполнения. С этой целью можно использовать функцию insert, объявленную как iterator insert(iterator position, const value type &x); Она возвращает итератор, ссылающийся на элемент, который только что был добавлен в словарь; мы можем использовать это значение, если следующим добавить элемент с большим ключом. Например, если знаем, что элементы будут добавляться по возрастанию ключей, то можем использовать итератор i, как это сделано в следующей программе: mapins.cpp: Быстрая вставка в словарь, ♦include <iostream> ♦include <map> using namespace std;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |