Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
Шрифт:
Интервал:
Закладка:
Для того чтобы извлечь информацию, мы просто ищем все упоминания ключа "John Doe", используя функцию equal_range() (раздел Б.4.10). Затем перемещаемся по всем элементам в последовательности [first,second], возвращаемой функцией equal_range(), извлекая темы сообщений с помощью функции find_subject().
typedef multimap<string, const Message*>::const_iterator MCI;
pair<MCI,MCI> pp = sender.equal_range("John Doe");
for (MCI p = pp.first; p!=pp.second; ++p)
cout << find_subject(p–>second) << 'n';
Перемещаясь по элементам объекта класса map, мы получаем последовательность пар (ключ,значение), в которых, как в любом другом объекте класса pair, первый элемент (в данном случае ключ класса stringkey) называется first, а второй (в данном случае объект класса Message) — second (см. раздел 21.6).
23.4.1. Детали реализации
Очевидно, что мы должны реализовать используемые нами функции. Соблазнительно, конечно, сэкономить бумагу и спасти дерево, предоставив читателям самостоятельно решить эту задачу, но мы решили, что пример должен быть полным.
Конструктор класса Mail_file открывает файл и создает векторы lines и m.
Mail_file::Mail_file(const string& n)
// открывает файл с именем "n"
// считывает строки из файла "n" в вектор lines
// находит сообщения в векторе lines и помещает их в вектор m,
// для простоты предполагая, что каждое сообщение заканчивается
// строкой "––––" line
{
ifstream in(n.c_str()); // открываем файл
if (!in) {
cerr << " нет " << n << 'n';
exit(1); // прекращаем выполнение программы
}
string s;
while (getline(in,s)) lines.push_back(s); // создаем вектор
// строк
Line_iter first = lines.begin(); // создаем вектор сообщений
for (Line_iter p = lines.begin(); p!=lines.end(); ++p) {
if (*p == "––––") { // конец сообщения
m.push_back(Message(first,p));
first = p+1; // строка –––– не является частью
// сообщения
}
}
}
Обработка ошибок носит слишком элементарный характер. Если бы писали эту программу для своих друзей, то постарались бы сделать ее лучше.
ПОПРОБУЙТЕ
Что значит “более хорошая обработка ошибок”? Измените конструктор класса Mail_file так, чтобы он реагировал на ошибки форматирования, связанные с использованием строки “––––”.
Функции find_from_addr() и find_subject() не имеют конкретного содержания, пока мы не выясним, как идентифицировать информацию в файле (используя регулярные выражения и из разделов 23.6–23.10).
int is_prefix(const string& s, const string& p)
// Является ли строка p первой частью строки s?
{
int n = p.size();
if (string(s,0,n)==p) return n;
return 0;
}
bool find_from_addr(const Message* m, string& s)
{
for(Line_iter p = m–>begin(); p!=m–>end(); ++p)
if (int n = is_prefix(*p,"From: ")) {
s = string(*p,n);
return true;
}
return false;
}
string find_subject(const Message* m)
{
for(Line_iter p = m.begin(); p!=m.end(); ++p)
if (int n = is_prefix(*p,"Subject: "))
return string(*p,n);
return "";
}


• Функция find_from_addr() различает поиск пустой строки адреса ("") и поиск отсутствующей строки адреса. В первом случае функция find_from_addr() возвращает значение true (поскольку она нашла адрес) и присваивает строке s значение "" (потому что адресная строка просто оказалась пустой). Во втором случае она возвращает значение false (поскольку в файле вообще не оказалось адресной строки).
• Функция find_subject() возвращает строку "" и когда строка темы сообщения оказалась пустой, и когда ее вообще нет.
Насколько полезным является такое различие, которое проводит функция find_from_addr()? Необходимо ли это? Мы считаем, что это полезно и необходимо. При поиске информации в файле данных это различие проявляется снова и снова: нашли ли мы искомую строку и содержит ли она то, что нам нужно? В реальной программе обе функции, find_from_addr() и find_subject(), следовало бы написать в стиле функции find_from_addr(), чтобы дать пользователям возможность проводить такое различие.
Эта программа не является оптимальной с точки зрения производительности, но мы надеемся, что в типичных ситуациях она работает достаточно быстро. В частности, она считывает входной файл только один раз и не хранит несколько копий текста из этого файла. Для крупных файлов было бы целесообразно заменить класс multimap классом unordered_multimap, но без испытаний невозможно сказать, насколько это повысит эффективность программы.
Введение в стандартные ассоциативные контейнеры (map, multimap, set, unordered_map и unordered_multimap) см. в разделе 21.6.
23.5. Проблема
Потоки ввода-вывода и класс string помогают нам считывать и записывать последовательности символов, хранить их и выполнять над ними основные операции. Однако при работе с текстом во многих случаях необходимо анализировать контекст строки или рассматривать много аналогичных строк. Рассмотрим тривиальный пример. Возьмем сообщение электронной почты (последовательность слов) и посмотрим, содержит ли оно аббревиатуру U.S. и почтовый код (две буквы, за которыми следуют пять цифр).
string s;
while (cin>>s) {
if (s.size()==7
&& isalpha(s[0]) && isalpha(s[1])
&& isdigit(s[2]) && isdigit(s[3]) && isdigit(s[4])
&& isdigit(s[5]) && isdigit(s[6]))
cout << " найдена " << s << 'n';
}
Здесь значение isalpha(x) равно true, если x — это буква, а
Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.
Оставить комментарий
-
Гость Татьяна24 сентябрь 22:20 Как то не очень... Невеста по ошибке. Я не дам тебе развод - Майя Линн
-
Римма24 сентябрь 21:52 Почему главные героинитпкие идиотки? И сюжет не плохой, и написано хорошо. Но как героиня - так дура дурой.... Хозяйка маленького дома, или Любимая для дракона - Кира Рамис
-
Римма20 сентябрь 12:27 Много ненужных пояснений и отступлений. Весь сюжет теряет свою привлекательность. Героиня иногда так тупит, что читать не... Хозяйка приюта для перевертышей и полукровок - Елена Кутукова