- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
Например, можно приказать объекту класса Punct_stream прочитать строку
Man bites dog!
как
man
bites
dog
Конструктор класса Punct_stream получает поток istream, используемый как источник символов, и присваивает ему локальное имя source. Кроме того, конструктор по умолчанию делает поток чувствительным к регистру, как обычно. Можно создать объект класса Punct_stream, считывающий данные из потока cin, рассматривающий точку с запятой, двоеточие и точку как разделители, а также переводящий все символы в нижний регистр.
Punct_stream ps(cin); // объект ps считывает данные из потока cin
ps.whitespace(";:."); // точка с запятой, двоеточие и точка
// также являются разделителями
ps.case_sensitive(false); // нечувствительный к регистру
Очевидно, что наиболее интересной операцией является оператор ввода >>. Он также является самым сложным для определения. Наша общая стратегия состоит в том, чтобы считать всю строку из потока istream в строку line. Затем мы превратим все наши разделители в пробелы (' '). После этого отправим строку в поток istringstream с именем buffer. Теперь для считывания данных из потока buffer можно использовать обычные разделители и оператор >>. Код будет выглядеть немного сложнее, поскольку мы только пытаемся считать данные из потока buffer и заполняем его, только если он пуст.
Punct_stream& Punct_stream::operator>>(string& s)
{
while (!(buffer>>s)) { // попытка прочитать данные
// из потока buffer
if (buffer.bad() || !source.good()) return *this;
buffer.clear();
string line;
getline(source,line); // считываем строку line
// из потока source
// при необходимости заменяем символы
for (int i =0; i<line.size(); ++i)
if (is_whitespace(line[i]))
line[i]= ' '; // в пробел
else if (!sensitive)
line[i] = tolower(line[i]); // в нижний регистр
buffer.str(line); // записываем строку в поток
}
return *this;
}
Рассмотрим этот код шаг за шагом. Сначала обратим внимание не нечто необычное.
while (!(buffer>>s)) {
Если в потоке buffer класса istringstream есть символы, то выполняется инструкция buffer>>s и объект s получит слово, разделенное разделителями; больше эта инструкция ничего не делает. Эта инструкция будет выполняться, пока в объекте buffer есть символы для ввода. Однако, когда инструкция buffer>>s не сможет выполнить свою работу, т.е. если выполняется условие !(buffer>>s), мы должны наполнить объект buffer символами из потока source. Обратите внимание на то, что инструкция buffer>>s выполняется в цикле; после попытки заполнить объект buffer мы должны снова попытаться выполнить ввод.
while (!(buffer>>s)) { // попытка прочитать символы из буфера
if (buffer.bad() || !source.good()) return *this;
buffer.clear();
// заполняем объект buffer
}
Если объект buffer находится в состоянии bad() или существуют проблемы с источником данных, работа прекращается; в противном случае объект buffer очищается и выполняется новая попытка. Мы должны очистить объект buffer, потому что попадем в “цикл заполнения”, только если попытка ввода закончится неудачей. Обычно это происходит, если вызывается функция eof() для объекта buffer; иначе говоря, когда в объекте buffer не остается больше символов для чтения. Обработка состояний потока всегда запутанна и часто является причиной очень тонких ошибок, требующих утомительной отладки. К счастью, остаток цикла заполнения вполне очевиден.
string line;
getline(source,line); // вводим строку line из потока source
// при необходимости выполняем замену символов
for (int i =0; i<line.size(); ++i)
if (is_whitespace(line[i]))
line[i]= ' '; // в пробел
else if (!sensitive)
line[i] = tolower(line[i]); // в нижний регистр
buffer.str(line); // вводим строку в поток
Считываем строку в объект buffer, затем просматриваем каждый символ строки в поисках кандидатов на замену. Функция is_whitespace() является членом класса Punct_stream, который мы определим позднее. Функция tolower() — это стандартная библиотечная функция, выполняющая очевидное задание, например превращает символ A в символ a (см. раздел 11.6).
После правильной обработки строки line ее необходимо записать в поток istringstream. Эту задачу выполняет функция buffer.str(line); эту команду можно прочитать так: “Поместить строку из объекта buffer класса istringstream в объект line”.
Обратите внимание на то, что мы “забыли” проверить состояние объекта source после чтения данных с помощью функции getline(). Это не обязательно, поскольку в начале цикла выполняется проверка условия !source.good().
Как всегда, оператор >> возвращает ссылку на поток *this (раздел 17.10).
Проверка разделителей проста; мы сравниваем символ с каждым символом из строки, в которой записаны разделители.
bool Punct_stream::is_whitespace(char c)
{
for (int i = 0; i<white.size(); ++i)
if (c==white[i]) return true;
return false;
}
Напомним, что поток istringstream обрабатывает обычные разделители (например, символы перехода на новую строку или пробел) по-прежнему, поэтому никаких особых действий предпринимать не надо.
Осталась одна загадочная функция.
Punct_stream::operator bool()
{
return !(source.fail() || source.bad()) && source.good();
}
Обычное использование потока istream сводится к проверке результата оператора >>. Рассмотрим пример.
while (ps>>s) { /* ... */ }
Это значит, что нам нужен способ для проверки результата выполнения инструкции ps>>s, представленного в виде булевого значения. Результатом инструкции ps>>s является объект класса Punct_stream, поэтому нам нужен способ неявного преобразования класса Punct_stream в тип bool. Эту задачу решает функция operator bool() в классе Punct_stream.
Функция-член operator bool() определяет преобразование класса Punct_stream в тип bool. В частности, она возвращает значение true, если эта операция над классом Punct_stream прошла успешно.
Теперь можем написать программу.
int main()
// вводит текст и создает упорядоченный список всех слов
// из

