- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Обычной ошибкой программирования является присвоение значения,возвращаемого функцией get() или peek(), возвращающей тип int, переменной типа char, а не int. Это, безусловно, будет ошибкой, но компилятор ее не обнаружит. То, что произойдет в результате этой ошибки, зависит от конкретной машины и введенных данных. Например, если машина интерпретирует символ как беззнаковое целое число, приведенный ниже цикл окажется бесконечным.
char ch; // применение типа char здесь приведет к катастрофе!
// значение, возвращенное функцией get() объекта с in,
// преобразуется из int в char, а затем сравнивается с int
while ((ch = cin.get()) != EOF)
cout.put(ch);
Проблема в том, что когда функция get() возвращает значение EOF, оно преобразуется в беззнаковое значение типа unsigned char. Это преобразованное значение не будет равно целочисленному значению EOF, поэтому цикл не закончится никогда. Такие ошибки обычно обнаруживаются при проверке.
Но нельзя быть уверенным в том, что на тех машинах, где символы интерпретируются как знаковый топ, поведение цикла будет аналогичным. Ведь результат переполнения переменной беззнакового типа зависит от компилятора. На большинстве машин этот цикл будет работать нормально, если только во вводимых данных не встретится символ, соответствующий значению EOF. Поскольку в обычных данных такие символы маловероятны, низкоуровневые операторы ввода-вывода могут пригодиться при чтении только бинарных значений, которые не соответствуют непосредственно обычным символам и числовым значениям. На машине автора, например, цикл преждевременно завершается в случае ввода символа, значением которого является '377'. Когда значение '377' на машине автора преобразуется в тип signed char, получается значение -1. Если во введенных данных встретится это значение, оно будет рассматриваться как символ (преждевременного) конца файла.
При чтении и записи типизированных значений такие ошибки не возникают. Поэтому по возможности следует использовать предоставляемые библиотекой высокоуровневые операторы, что гораздо безопасней.
Многобайтовые операцииНекоторые операции не форматированного ввода-вывода работают с порциями данных за раз. Эти операции могут быть полезны, если важна скорость, но, как и другие низкоуровневые операции, они подвержены ошибкам. В частности эти операции требуют резервирования и управления символьными массивами (см. раздел 12.2), используемыми для сохранения и возвращения данных. Многобайтовые операции перечислены в табл. 17.20.
Таблица 17.20. Многобайтовые низкоуровневые операции ввода-вывода
is.get(sink, size, delim) Читает до size байтов из потока is и сохраняет их в символьном массиве, начиная с адреса, на который указывает sink. Чтение продолжается, пока не встретится символ delim, либо пока не прочитано size байтов, либо пока не кончится файл. Если параметр delim присутствует, то его значение остается во входном потоке и не читается в sink is.getline(sink, size, delim) To же поведение, что и версии функции get() с тремя аргументами, но читает и отбрасывает delim is.read(sink, size) Читает до size байтов в символьный массив sink. Возвращает поток is is.gcount() Возвращает количество байтов, прочитанных из потока is при последним вызове функции не форматированного чтения os.write(source, size) Записывает size байтов из символьного массива source в поток os is.ignore(size, delim) Читает и игнорирует до size символов, включая delim. В отличие от других не форматированных функций, ignore() имеет аргументы по умолчанию: для size — 1 и для delim — конец файлаФункции get() и getline() имеют схожие, но не идентичные параметры. В каждом случае sink — это символьный массив, в который помещаются данные. Обе функции читают, пока не будет выполнено одно из следующих условий:
• Прочитано size - 1 символов.
• Встретился конец файла.
• Встретился символ разделения.
Эти функции отличаются обработкой разделителя: функция get() оставляет разделитель как следующий символ потока istream, а функция getline() читает и отбрасывает разделитель. В любом случае разделитель не сохраняется в массиве sink.
Весьма распространенная ошибка: намереваться удалить разделитель из потока, но забыть сделать это.
Определение количества читаемых символовНекоторые из операций читают из ввода неизвестное количество байтов. Для определения количества символов, прочитанных последней операцией не форматированного ввода, можно вызвать функцию gcount(). Имеет смысл вызывать функцию gcount() перед любым вмешательством в операции не форматированного ввода. В частности, операции с единичными символами, возвращающими их в поток, также являются операциями не форматированного ввода. Если функции peek(), unget() или putback() будут вызваны перед вызовом функции gcount(), то будет возвращено значение 0.
Упражнения раздела 17.5.2Упражнение 17.37. Используйте не форматированную версию функции getline() для чтения файла по строке за раз. Проверьте программу на примере файла с пустыми строками, а также со строками, длинна которых больше символьного массива, переданного функции getline().
Упражнение 17.38. Дополните программу из предыдущего упражнения так, чтобы выводить каждое прочитанное слово в отдельной строке.
17.5.3. Произвольный доступ к потоку
Некоторые из потоковых классов обеспечивают произвольный доступ к данным связанного с ними потока. Положение в потоке можно изменить так, чтобы прочитать сначала последнюю строку, затем первую и т.д. Для установки (seek) необходимой позиции и сообщения (tell) текущей позиции в потоке библиотека предоставляет пару функций.
Произвольный доступ для чтения и записи напрямую зависит от системы. Чтобы выяснить способ применения этой возможности, следует обратиться к документации на систему.
Хотя функции seek() и tell() определены для всех потоковых классов, возможные для них действия определяются видом объекта, с которым связан поток. В большинстве систем поток, с которым связан потоковый объект cin, cout, cerr или clog, не обеспечивает возможности произвольного доступа — в конце концов, как можно перейти на десять позиций обратно, если запись осуществляется непосредственно в объект cout? Применить функции seek() и tell(), конечно, можно, но во время выполнения это приведет к ошибке и переходу потока в недопустимое состояние.
Поскольку классы istream и ostream обычно не обеспечивают произвольного доступа, в остальной части этого раздела речь идет только о классах fstream и sstream.
Функции установки и сообщенияДля обеспечения произвольного доступа типы ввода-вывода обладают маркером (marker), который указывает позицию следующей операции чтения или записи. Они обладают также двумя функциями: одна устанавливает (seek) маркер в новую позицию, а вторая сообщает (tell) текущую позицию маркера. Фактически в библиотеке определены две пары функций установки и сообщения, которые описаны в табл. 17.21. Одна пара функций используется потоками ввода, а вторая — потоками вывода. Версии для ввода и вывода различаются суффиксом. Суффикс g (getting) означает получение данных (чтение), а суффикс p (putting) — помещение данных (запись).
Таблица 17.21. Функции установки и сообщения
tellg() tellp() Возвращает текущую позицию маркера потока ввода (tellg()) или потока вывода (tellp()) seekg(pos) seekp(pos) Переустанавливает маркер потока ввода или вывода на заданный параметром pos абсолютный адрес в потоке. Значение pos обычно возвращается предыдущим вызовом в соответствующей функции tellg() или tellp() seekp(off, from) seekg(off, from) Переустанавливает маркер потока ввода или вывода на off символов вперед или назад от значения from, которое может быть: beg — от начала потока; cur — от текущей позиции потока; end — от конца потокаВполне логично, что для класса istream, а также производных от него классов ifstream и istringstream (см. раздел 8.1) можно использовать только версии g, а для классов ostream и классов ofstream и ostringstream, производных от него, можно использовать только версии p. Классы iostream, fstream и stringstream способны читать и записывать данные в поток, поэтому для них можно использовать обе версии, g и p.

