Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс ПЯВУ 2 сем / Лекции 2 сем / Л№34.Потоковый ввод / Лекция № 32.Потоковый ввод вывод.odt
Скачиваний:
11
Добавлен:
17.04.2015
Размер:
153.09 Кб
Скачать

Лекция №32. Потоковый ввод вывод.

Содержание лекции.

1.

1. Директива препроцессора для ввода вывода в С++

Под "программированием на языке С++" обычно понимается "программирование в среде С++". Дело в том, что никакая полезная программа не может быть написана на языке С++ без привлечения библиотек, включаемых в конкретную среду (в компилятор) языка. Конкретная среда С++, в которой разрабатывается программа, обычно обеспечивает программиста удобными средствами для работы с ее библиотеками. При этом по утверждению Б.Страуструпа: "Для использования библиотеки совсем не нужно знание методов, которые применялись для ее реализации". Однако знание правил использования средств библиотеки совершенно необходимо. Самая незаменимая из этих библиотек - библиотека ввода-вывода, так как средства ввода-вывода непосредственно в язык С++ (также как и в язык С) не входят. В программах на языке С++ можно равноправно использовать две библиотеки ввода-вывода: стандартную библиотеку функций языка С (стандарт ANSI С) и библиотеку классов, специально созданную для языка С++. Библиотека функций языка С становится доступной в программе, как только в ее заголовок будет включен файл stdio.h. Для обращения к функциям требуются сведения об их прототипах и соблюдение соглашений стандарта. Подробную информацию можно получить из технической документации того компилятора, с которым вы работаете.

На протяжении всех шагов в программах постоянно использовалась препроцессорная директива:

#include <iostream.h>

Назначение указанного в директиве заголовочного файла iostream.h - связать компилируемую программу с одной из основных частей библиотеки ввода-вывода, построенной на основе механизма классов. Эта библиотека ввода-вывода почти стандартна, так как включена практически во все компиляторы С++. Однако о стандарте библиотеки ввода-вывода С++ можно говорить только неформально. Библиотека создана позже, чем появился язык, она разрабатывалась в некотором смысле независимо от создания языка С++, не входит в формальное описание языка и написана на языке С++.

2. Потоки ввода-вывода

В соответствии с названием заголовочного файла iostream.h (stream - поток; "i" - сокращение от input - ввод; "o" - сокращение от output - вывод) описанные в этом файле средства ввода-вывода обеспечивают программиста механизмами для извлечения данных из потоков и для включения (внесения) данных в потоки. Поток определяется как последовательность байтов (символов) и с точки зрения программы не зависит от тех конкретных устройств (файл на диске, принтер, клавиатура, дисплей, стример и т.п.), с которыми ведется обмен данными. При обмене с потоком часто используется вспомогательный участок основной памяти - буфер потока (рисунок 1- буфер вывода, рисунок 2 - буфер ввода).

Рис.1. Буферизированный выходной поток

В буфер потока помещаются выводимые программой данные перед тем, как они будут переданы к внешнему устройству. При вводе данных они вначале помещаются в буфер и только затем передаются в область памяти выполняемой программы. Использование буфера как промежуточной ступени при обменах с внешними устройствами повышает скорость передачи данных, так как реальные пересылки осуществляются только тогда, когда буфер уже заполнен (при выводе) или пуст (при вводе).

Работу, связанную с заполнением и очисткой буферов ввода-вывода, операционная система очень часто берет на себя и выполняет без явного участия программиста. Поэтому поток в прикладной программе обычно можно рассматривать просто как последовательность байтов. При этом очень важно, что никакой связи значений этих байтов с кодами какого-либо алфавита не предусматривается. Задача программиста при вводе-выводе с помощью потоков - установить соответствие между участвующими в обмене типизированными объектами и последовательностью байтов потока, в которой отсутствуют всякие сведения о типах представляемой (передаваемой) информации.

Рис.2. Буферизированный входной поток

Используемые в программах потоки логически делятся на три типа:

входные, из которых читается информация;

выходные, в которые вводятся данные;

двунаправленные, допускающие как чтение, так и запись.

Все потоки библиотеки ввода-вывода последовательные, т.е. в каждый момент для потока определены позиции записи и (или) чтения, и эти позиции после обмена перемещаются по потоку на длину переданной порции данных.

В соответствии с особенностями "устройства", к которому "присоединен" поток, потоки принято делить на

стандартные,

консольные,

строковые и

файловые.

Из перечисленных потоков мы не будем рассматривать только консольные потоки. Причин для этого несколько. Во-первых, консольные потоки отсутствовали в классических реализациях библиотеки потокового ввода-вывода. Во-вторых, консольные потоки несовместимы с операционной средой Microsoft Windows и могут использоваться только при разработке программ, работающих под управлением MS-DOS. Консольные потоки поддерживаются классом constream и обеспечивают удобный доступ к терминалу. В них есть возможности работы с клавиатурой и средства манипуляции с участками экрана и с экраном в целом.

Если символы потока в совокупности образуют символьный массив (строку) в основной памяти, то это строковый поток. Если при использовании потока его символы размещаются на внешнем носителе данных (например, на диске или на магнитной ленте), то говорят о файловом потоке или просто о файле. Стандартные и консольные потоки соответствуют передаче данных от клавиатуры и к экрану дисплея. До сих пор во всех программах выполнялся обмен только со стандартными потоками. Рассмотрим их возможности подробнее. Однако предварительно остановимся на некоторых принципиальных особенностях потоковой библиотеки ввода-вывода языка С++.

В отличие от стандартной библиотеки (в которой находятся средства, например, для работы со строками, или математические функции), унаследованной компиляторами языка С++ от языка С, библиотека ввода-вывода С++ является не библиотекой функций, а библиотекой классов. Это первая "промышленная" библиотека классов, разработанная для распространения совместно с компиляторами. Именно эту библиотеку рекомендуют изучать, начиная знакомиться с принципами объектно-ориентированного программирования. Одним из базовых принципов ООП является предположение о том, что объекты "знают", что нужно делать при появлении обращения (сообщения) определенного типа, т.е. для каждого типа адресованного ему обращения объект имеет соответствующий механизм обработки. Если мы используем объект cout, представляющий выходной поток, то как уже неоднократно показано на примерах, для каждого из базовых типов (int, long, double, ...) этот объект cout выбирает соответствующую процедуру обработки и выводит значение в соответствующем виде. Объект cout не может перепутать и вывести, например, целое число в формате с плавающей точкой. От таких ошибок, которые были возможны в языках С или FORTRAN, когда программист сам определял форму внешнего представления, библиотека классов ввода-вывода хорошо защищена.

Библиотека потоковых классов построена на основе двух базовых классов: ios и streambuf. Класс streambuf обеспечивает буферизацию данных во всех производных классах, которыми явно или неявно пользуется программист. Обращаться к его методам и данным из прикладных программ обычно не нужно. Класс streambuf обеспечивает взаимодействие создаваемых потоков с физическими устройствами. Он обеспечивает производные классы достаточно общими методами для буферизации данных. Класс ios и производные классы содержат указатель на класс streambuf, но об этом можно до времени не вспоминать. Методы и данные класса streambuf программист явно обычно не использует. Этот класс нужен другим классам библиотеки ввода-вывода. Он доступен и программисту-пользователю для создания новых классов на основе уже существующего класса из iostream. Однако необходимость в построении таких производных классов возникает достаточно редко, и мы не будем рассматривать класс streambuf. Класс ios содержит компоненты (данные и методы), которые являются общими, как для ввода, так и для вывода.

При работе с потоковой библиотекой ввода-вывода программист обычно достаточно активно использует следующие классы:

ios - базовый потоковый класс;

istream - класс входных потоков;

ostream - класс выходных потоков;

iostream - класс двунаправленных потоков ввода-вывода;

istrstream - класс входных строковых потоков;

ostrstream - класс выходных строковых потоков;

strstream - класс двунаправленных строковых потоков (ввода-вывода);

ifstream - класс входных файловых потоков;

ofstream - класс выходных файловых потоков;

fstream - класс двунаправленных файловых потоков (ввода-вывода);

constream - класс консольных выходных потоков.

Диаграмма взаимозависимости перечисленных классов изображена на рисунке 1. Следует отметить, что эта диаграмма потоковых классов упрощена. В реальной схеме присутствуют промежуточные классы и реализовано более сложное множественное наследование. Кроме того, программист, как упоминалось, обычно не учитывает наличия второго базового класса streambuf, и он не показан на схеме.

Рис.3. Упрощенная схема иерархии потоковых классов

Как наглядно видно из диаграммы классов, класс ios является базовым для классов ostream, istream, и опосредовано базовым для всех остальных потоковых классов. Все общие средства потоковых классов помещаются в класс ios. Например, при помощи методов и данных класса ios осуществляется управление процессом передачи символов из буфера и в буфер. При выполнении этих действий необходимы, например, сведения о нужном основании счисления (восьмеричное, десятичное, шестнадцатеричное), о точности представления вещественных чисел, и т.д. Класс ios содержит эти сведения, т.е. (методы) функции и данные, относящиеся к состояниям потоков и позволяющие менять их свойства.

Потоковые классы, их данные и методы становятся видимыми и доступными в программе, если в нее включен нужный заголовочный файл: