С++. Лекция 9. Работа с потоками в С++

Работа с потоками в С++

9.1. Структура стандартной библиотеки ввода-вывода.

В языке программирования С++ стандартная библиотека ввода-вывода организована как иерархия шаблонов классов. Эта библиотека содержит два стандартных множества конкретизированных шаблонов этой иерархии: одно для работы с символами типа char, другое для работы с символами типа wchar_t. Классы для работы с символами типа wchar_t имеют те же имена, что и классы для работы с символами типа char, но с префиксом w.

Ниже перечислены заголовочные файлы, которые содержат интерфейсы классов из стандартной библиотеки ввода-вывода:

<ios> ios_base, ios
<istream> istream
<ostream> ostream
<iostream> iostream, cin, cout, cerr
<fstream> ifstream, fstream, ofstream, filebuf
<sstream> istringstream, stringstream, ostringstream, stringbuf
<streambuf> streambuf

9.2. Классы ios_base и ios.

В классах ios_base и ios определены методы, которые являются общими для входных и выходных потоков. Класс ios_base содержит методы, которые не зависят от параметров шаблона. Наоборот, класс ios содержит шаблонно-зависимые методы. Объект класса ios_base не может быть создан непосредственно, а только в наследуемых классах.

Объекты типа ios_base поддерживают следующую информацию о состоянии потока.

Информацию о форматировании ввода-вывода:

- флаги форматирования,

- длину полей ввода-вывода,

- разрешимость дисплея.

Информацию о состоянии потока:

- состояние ошибки,

- маску исключений,

Другая информация:

- стек вызовов callback функций при наступлении некоторых событий,

- внутренний массив с элементами типа long,

- внутренний массив с элементами типа void*.

Перечислим некоторые методы класса ios_base:

flags                       чтение-установка флагов форматирования,

precision               чтение-установка точности double,

setf                         установка некоторых флагов форматирования,

unsetf                    сброс флагов форматирования.

Например, в следующей программе показано как установить в качестве базовой 16 с/с.

Класс ios поддерживает следующую информацию о потоке:

-          символ заполнитель,

-          указатель на поток вывода, связанный с объектом типа ios,

-          указатель на объект типа streambuf, связанный с объектом типа ios.

Перечислим некоторые методы класса ios:

operator!               возвращает true, если установлен любой из флагов failbit или badbit, иначе возвращает false,

bad                        возвращает true в случае неустранимой ошибки ввода-вывода,

clear                       сбрасывает управляющие состояния,

eof                         проверяет на конец файла,

exception              читает-устанавливает маску исключений,

fail                          проверяет на ошибку, исключая конец файла,

fill                           читает-устанавливает символ заполнитель,

good                      возвращает true, если нет ошибок,

rdstate                   читает управляющие состояния,

setstate                  устанавливает управляющие состояния.

Кроме того, класс ios поддерживает режимы работы потока, которые задаются следующими флагами:

ios::app                 данные всегда записываются в конец файла,

ios::ate                  первый байт записывается в конец файла, остальные байты с текущей позиции,

ios::binary            бинарный файл,

ios::in                    входной файл,

ios::nocreate        открыть существующий файл, если файла нет, то ошибка,

ios::noreplace      открыть новый файл, если файл уже есть, то ошибка,

ios::out                  выходной файл,

ios::trunc              файл открывается и его содержимое стирается,

Например, в следующей программе показано, как проверить, успешно ли открыт файл.

9.3. Потоки вывода.

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

operator<<           форматированный вывод данных в поток,

flush                      очищает буфер,

put                         выводит символ,

seekp                     устанавливает позицию для функции put,

tellp                        читает позицию указателя для функции put,

write                       пишет последовательность байтов,

От класса ostream наследуются класс ofstream, который содержит дополнительные методы:

open                      открыть файл,

close                      закрыть файл,

is_open                 проверка открыт ли файл.

Сейчас приведем прототипы этих функций и примеры их использования.

1. Функции open, close и is_open имеют следующие прототипы:

void open ( const char * filename, openmode mode = out | trunc );

void close ( );

bool is_open ( );

При открытии потока вывода нужно указать имя файла и режимы работы потока с этим файлом. При этом нужно запомнить, что режимы работы с потоками ввода и вывода совпадают.

Например, следующая программа добавляет предложение в конец текстового файла и показывает, как использовать вышеперечисленные функции.

2. Функцияflush очищает буфер. Эта функция имеет следующий прототип:

ostream& flush ( );

Ниже приведен пример использования функции flush. Этот пример также показывает, как можно создавать текстовый файл

3. Функция put выводит символ в файл. Эта функция имеет следующий прототип:

ostream& put ( char ch );

В следующем примере показано, как водить символы с консоли и выводить их в файл.

4. Функция seekp устанавливает, а функция tellp читает позицию в файле для функции put. Эти функции имеют следующие прототипы:

streampos tellp ( );

ostream& seekp ( streampos pos );

где pos - новая позиция в потоке;

ostream& seekp ( streamoff off, ios_base::seekdir dir );

где параметры имеют следующее назначение:

off           смещение в потоке относительно позиции, указанной в параметре dir.

dir          направление поиска позиции, может принимать одно из следующих значений:

  • ios_base::beg – поиск от начала файла;
  • ios_base::cur  - поиск от текущей позиции;
  • ios_base::end – поиск от конца файла.

Ниже приведен пример использования этих функций.

5. Функция write пишет последовательность символов (байтов) в файл. Эта функция имеет следующий прототип:

ostream& write ( const char* s , size n );

где s указывает на область памяти, из которой данные записываются в файл, а n – количество записываемых символов (байтов). Отметим, что эта функция используется для записи данных в бинарные файлы, то есть содержимое области памяти записывается в файл без изменения. Ниже приведен пример создания бинарного файла, используя функцию write.

От класса ostream также наследуются класс ostringstream, который обеспечивает интерфейс для работы со строками.

Класс ostringstream содержит дополнительный метод:

str – чтение и запись строки в поток.

6. Функция str выполняет запись и чтение строки в поток. Эта функция имеет следующий прототип:

 

string str ( ) const                     чтение строки из потока

void str ( string & s );                запись строки s в поток

 

Например, в следующей программе показано, как ввести строку в поток типа ostringstream, а затем прочитать его содержимое в объект типа string.

1.4. Потоки ввода.

 

Потоки ввода являются объектами класса istream, который обеспечивает методы для чтения информации из буфера потока. Перечислим основные методы класса istream:

 

operator >>          форматированный ввод,

gcount                   возвращает количество символов, прочитанных последней операцией ввода,

get                          ввод символа,

getline                    ввод строки,

ignore                    удаление символов из буфера,

peek                       читает символ, но не удаляет его из буфера,

putback                возвращает символ в буфер,

read                       читает блок данных,

seekg                     устанавливает указатель позиции файла для метода get,

sync                       синхронизирует буфер потока с внешним устройством,

tellg                        получает указатель позиции файла для метода get,

unget                     возвращает символ в поток,

 

От класса istream наследуется класс ifstream, который обеспечивает интерфейс для работы с файлами. Класс ifstream содержит дополнительные методы:

 

open                      открыть файл,

close                      закрыть файл,

is_open                 проверить, открыт ли файл.

 

Как работать с этими функциями, было показано в предыдущем параграфе. Сейчас же подробно рассмотрим работу с функциями класса istream.

 

1. Функция gcount возвращает количество символов, прочитанных последней не форматирующей операцией ввода. Эта функция имеет следующий прототип:

 

streamsize gcount ( ) const;

 

К не форматирующим операциям ввода относятся следующие операции: get, getline, ignore, read и readsome. Пример использования функции gcount показан в следующей программе:

2. Функция get вводит символ из входного потока. Эта функция имеет следующий прототип:

 

int get();

возвращает символ, извлеченный из потока;

 

istream& get (char& c );

извлекает символ из потока и сохраняет его в переменной с;

 

istream& get (char* s, streamsize n, char delim = ‘\n’ );

вводит из потока символы и записывает их в массив s, ввод символов прекращается в следующих случаях:

 

-          если введен (n-1) символ;

-          если в потоке встретился символ разделитель delim, сам символ разделитель из потока не извлекается;

-          файл закончился раньше, чем прочитан (n-1) символ.

 

После записи прочитанных символов в массив s функция get записывает в этот массив пустой символ NULL, отмечающий конец строки. Ниже приведена программа, которая распечатывает содержимое текстового файла.

А теперь приведена программа, которая читает символы из входного потока, используя функцию get.

 

3. Функция getline вводит строки из файла. Эта функция имеет следующий прототип:

 

istream& getline (char* s, streamsize n, char delim = ‘\n’);

вводит из потока символы и записывает их в массив s, ввод символов прекращается в следующих случаях:

 

-          если введен (n-1) символ;

-          если в потоке встретился символ разделитель delim, причем сам символ разделитель извлекается из потока, но не записывается в массив s;

-          файл закончился раньше, чем прочитан (n-1) символ.

 

После записи прочитанных символов в массив s функция getline записывает в этот массив пустой символ NULL, отмечающий конец строки. Ниже приведена программа, которая вводит строки из потока и распечатывает их на консоли.

4. Функция ignore удаляет символы из буфера потока. Эта функция имеет следующий прототип:

 

istream& ignore ( streamsize n = 1, int delim = EOF );

 

где n – количество символов, которые необходимо удалить из потока, а delim – это символ ограничитель. Функция удаляет символы из потока до тех пор, пока не удалит n символов или не встретит символ разделитель. Например, в следующей программе выводятся только первые символы введенных слов.

 

5. Функция peek читает символ, но не удаляет его из буфера. Эта функция имеет следующий прототип:

 

int peek ( );       возвращает прочитанный символ, а если файл закончился или в потоке произошла ошибка, то возвращает EOF.

Ниже приведена программа, в которой используется функция peek.

6. Функция putback возвращает символ в буфер. Эта функция имеет следующий прототип:

 

istream& putback (char ch );     если введенный символ совпадает с символом ch, то функция возвращает его в буфер ввода, иначе поведение функции непредсказуемо.

Использование функции putback показано в следующей программе.

7. Функция read читает блок данных из файла и имеет следующий прототип:

istream& read (char* s, streamsize n );

где s указывает на область памяти, в которую данные читаются из файла, а n – количество читаемых символов (байтов). Отметим, что эта функция используется для чтения данных из бинарных файлов, то есть содержимое файла без изменения читается в область памяти. Ниже приведен пример чтения записей бинарного файла, используя функцию read.

8. Функция seekg устанавливает указатель позиции файла для метода get, а функция tellg получает указатель позиции файла для метода get. Эти функции имеют следующие прототипы:

istream& seekg ( streampos pos );        устанавливает позицию файла на значение pos, тип streampos эквивалентен типу long.

istream&  seekg ( streamoff off, ios_base::seekdir dir ); сдвигает позицию файла на значение off относительно значения параметра dir, который может принимать следующие значения:

  • ios_base::beg            смещение относительно начала файла;
  • ios_base::cur            смещение относительно текущей позиции;
  • ios_base::end            смещение относительно конца файла.

streampos tellg ( );       возвращает указатель позиции файла для функции get, тип streampos эквивалентен типу long.

Ниже приведена программа, которая демонстрирует использование вышеуказанных функций.

9. Функция sync                 синхронизирует буфер потока с внешним устройством. Эта функция имеет следующий прототип:

int sync ( );

Как работает эта функция, и что такое синхронизация буфера потока с внешним устройством смотри в параграфе 1.6.

 

10. Функция unget возвращает в поток символ, предварительно извлеченный из потока. Эта функция имеет следующий прототип:

int unget();        возвращает символ, извлеченный из потока.

Ниже приведена программа, в которой показано использование функции unget.

От класса istream наследуется класс istringstream, который обеспечивает интерфейс для работы со строками. Класс istringstream содержит дополнительный метод:

str                           чтение или запись строки в поток.

 

11. Функция str для записи и чтения строки в поток.

Прототипы этой функции были рассмотрены в предыдущем параграфе пункт 6. Сейчас же приведем только программу, в которой показано, как записать строку в поток типа istringstream, а затем вывести содержимое этого потока.

 

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

Потоки ввода-вывода создаются на базе класса iostream, который является производным классом от классов istream и ostream и поэтому наследует все их методы. Для работы с файлами и со строками из класса iostream наследуются соответственно классы fstream и stringstream, которые позволяют, как писать данные в потоки, так и читать данные из потоков. Для наглядного представления отношения наследования между этими классами смотри диаграмму наследования в параграфе 1.1.

Здесь же заметим, что заголовочный файл <iostream> содержит потоки ввода-вывода: cin, cout, cerr и clog, примеры работы с которыми смотри в параграфе 1.8.

 

1.6. Буферы и синхронизация.

 

Потоки выполняют обмен данными между прикладной программой и файлом через буферы, которые являются объектами классов filebuf и stringbuf соответственно. Эти классы являются производными от абстрактного класса streambuf. Каждый буфер содержит в зависимости от режима доступа один или два символьных массива: один для ввода, а второй для вывода данных. Каждый поток поддерживает внутренний указатель на буфер. Ввод-вывод данных из буфера в файл или в строку называется синхронизацией буфера с внешним устройством ввода-вывода. Синхронизация буфера с внешним устройством может выполняться неявно или явно. Неявно синхронизация выполняется в случае закрытия файла или заполнения буфера. Для явной синхронизации используют манипуляторы flush и endl или функцию sync.

Например, в следующей программе показана синхронизация буфера с входным потоком.

 

1.7. Манипуляторы.

Манипулятором называется глобальная функция, которая изменяет поток. Манипуляторы предназначены для включения в последовательность операторов ввода или вывода и могут изменять состояние потока, управляя его флагами. Манипуляторы подразделяются на две группы: простые манипуляторы и параметризованные манипуляторы.

Простые манипуляторы не требуют аргументов. Ниже перечислены простые манипуляторы:

 

endl        помещает в выходной поток символ ‘\n’ и вызывает манипулятор flush,

ends       помещает в поток символ ‘\0’,

flush       освобождает поток,

dec         устанавливает 10 c/c,

hex         устанавливает 16 c/c,

oct          устанавливает 8 c/c,

ws           игнорирует при вводе ведущие пробелы.

 

Манипуляторы с аргументами называются параметризованными. Ниже перечислены параметризованные манипуляторы, которые объявлены в заголовочном файле <iomanip>:

 

resetiosflags         сбрасывает флаги форматирование,

setiosflags             устанавливает флаги форматирования,

setbase                  устанавливает систему счисления,

setfill                      устанавливает символ заполнитель,

setprecision          устанавливает точность для плавающих чисел,

setw                       устанавливает ширину поля для символа заполнителя.

 

Можно написать свой манипулятор. Например, следующая функция является манипулятором, который выполняет переход на новый абзац.

9.8. Стандартные потоки ввода-вывода.

Стандартный входной поток cin является объектом класса istream и по умолчанию связан с клавиатурой. Стандартные потоки cout, cerr и clog являются объектами класса ostream и по умолчанию связаны с дисплеем. Для работы со стандартными потоками в программу необходимо включить заголовочный файл <iostream>. Например,

А. П. Побегайло

Комментариев 2 к “С++. Лекция 9. Работа с потоками в С++

  1. А че у тебя подсветки кода то нету? - скопипастил и даже код тегами выделить поленился?
    Упырь тупой. Репетитор еще...

Добавить комментарий для Владимир Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *