2854

Потоковый ввод-вывод

Контрольная

Информатика, кибернетика и программирование

Потоковый ввод-вывод Поток – это программный канал для обмена данными между приложением и ОС или другим приложением. При взаимодействии приложения с ОС потоки как правило используются для работы с устройствами и представляют собой абстрактный у...

Русский

2012-10-20

91.5 KB

19 чел.

Потоковый ввод-вывод

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

Данные, поступающие в поток, как правило, буферизуются, то есть помещаются в специальный буфер данных, в котором они могут храниться. Передача данных из буфера получателю данных происходит при запросе от получателя или в случае заполнения буфера данных. Если получатель производит чтение данных, когда буфер потока пуст, то данная ситуация расценивается как достижение конца потока, как правило функции, работающие с потоками, в данном случае возвращают константу EOF (равную -1), определённую в файле stdio.h.

Существуют два основных типа ввода-вывода: форматированный и неформатированный. При форматированном вводе-выводе производится преобразование типов и структуры данных. При неформатированном вводе-выводе подобное преобразование не производится. Например, при форматированном выводе числа типа float функцией printf() можно задавать форму отображения числа на экране. Форматированный и неформатированный ввод-вывод выполняется соответствующими функциями ввода-вывода.

Поток для работы может быть отрыт в текстовом или бинарном режиме. Если поток открыт в текстовом режиме, то нет однозначного соответствия между данными, помещаемыми в поток, и данными, извлекаемыми из потока (например, символ ‘\n’ при выводе на экран преобразуется в пару символов: перевод строки и возврат каретки, а символ ‘Ctrl+Z’ интерпретируется как EOF). Если поток открыт в бинарном режиме, то данные, помещаемые в поток, однозначно соответствуют данным, извлекаемым из потока. Это существенно при работе с символьной информацией, содержащей escape-последовательности.

С потоками можно производить следующие действия: открывать и закрывать потоки; посылать данные в поток и получать данные из потока; анализировать ошибки потокового ввода-вывода; управлять буферизацией потока и размером буфера; позиционировать указатель чтения-записи данных в потоке (если возможно).

Все потоки и функции для работы с ними объявлены в файле stdio.h.

Понятие «файл» в языке C несколько отличается от общепринятого в информатике. Под «файлом» понимается некоторое устройство, работа с которым организуется через поток (это может быть и файл на диске). Файл определяет способ хранения информации на физическом устройстве, поэтому файлы бывают различные, в отличии от потоков, которые одинаковы. Например, если под «файлом» понимается файл на диске, то можно производить произвольный доступ к любому байту файла, если же под «файлом» понимается принтер, до будет возможен только последовательный обмен данными.

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

Операция открытия файла связывает поток с определённым файлом, операция закрытия разрывает эту связь. Каждый поток, связанный с файлом, имеет управляющую структуру типа FILE. Указатель на данную структуру, называемый также указателем на файловую переменную, является связующим звеном между потоком и файлом, работа с потоком, а значит, и со связанным с ним файлом, осуществляется через связанный с потоком указатель на файловую переменную. Работа с потоком, который не связан ни с каким файлом, либо невозможна, либо может привести к неправильной работе как программы, так и системы в целом.

Указатель на файловую переменную.

В заголовочном файле stdio.h следующая структура объявлена как файловая переменная:

typedef struct  {

       int             level;          

       unsigned        flags;          

       char            fd;             

       unsigned char   hold;           

       int             bsize;          

       unsigned char *buffer;   

       unsigned char *curp;    

       unsigned        istemp;

       short           token;

}       FILE;                           

Поле level определяет состояние буфера (пуст, полон), поле flags – флаги состояния файла, поле fd – дескриптор (префикс) файла, поле hold – непереданный символ, поле bsize – размер внутреннего буфера, поле buffer – указатель на буфер данных, поле curp – текущий указатель чтения-записи файла, поле istemp – флаг временного файла, поле token – права доступа к файлу. Поле flags может иметь следующие значения, определенные как макросы.

Макрос

Значение

Пояснение

_F_RDWR

0x0003

Файл открыт для чтения и записи

_F_READ

0x0001

Файл открыт только для чтения

_F_WRIT

0x0002

Файл открыт только для записи

_F_BUF

0x0004

Имеется буфер данных

_F_LBUF

0x0008

Построчно буферизуемый файл

_F_ERR

0x0010

Индикатор ошибки

_F_EOF

0x0020

Индикатор EOF

_F_BIN

0x0040

Индикатор бинарного файла

_F_IN

0x0080

Буфер содержит входные данные

_F_OUT

0x0100

Буфер содержит выходные данные

_F_TERM

0x0200

Файл является терминалом

Функции для работы с файлами.

FILE * fopen(const char * path, const char * mode);

Функция открывает файл, имя которого принимает в качестве параметра path, и связывает его с потоком. В случае успеха функция возвращает указатель на файловую переменную, в случае ошибки – NULL. Параметр mode задает режим открытия файла.

Режим

Действие

«r»

Открыть существующий файл для чтения (файл должен существовать на диске). Указатель чтения-записи устанавливается в начало файла.

«w»

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

«a»

Открыть существующий или создать новый файл для добавления (запись в конец файла). Указатель чтения-записи устанавливается в конец файла.

«r+»

Открыть файл для чтения и записи. Указатель чтения-записи устанавливается в начало файла. При закрытии файла размер не усекается.

«w+»

Создать или открыть файл для чтения и записи, если файл существует, он перезаписывается. Указатель чтения-записи устанавливается в начало файла. При закрытии файла размер усекается.

«a+»

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

«rb»

Аналогично «r», бинарный режим

«wb»

Аналогично «w», бинарный режим

«ab»

Аналогично «a», бинарный режим

«r+b»

Аналогично «r+», бинарный режим

«w+b»

Аналогично «w+», бинарный режим

«a+b»

Аналогично «a+», бинарный режим

«rt»

Аналогично «r», текстовый режим

«wt»

Аналогично «w», текстовый режим

«at»

Аналогично «a», текстовый режим

«r+t»

Аналогично «r+», текстовый режим

«w+t»

Аналогично «w+», текстовый режим

«a+t»

Аналогично «a+», текстовый режим

Если текстовый или бинарный режим не задан явно, он устанавливается по умолчанию в зависимости от значения внешней переменной _fmode.

Возвращаемый функцией указатель всегда следует проверять на равенство константе NULL (как и при использовании динамического распределения памяти).

FILE * freopen(const char * path, const char * mode, FILE * stream);

Функция закрывает поток stream и открывает файл, имя которого принимает в качестве параметра path, и связывает его с потоком. В случае успеха функция возвращает указатель на файловую переменную, в случае ошибки – NULL. Параметр mode задает режим открытия файла. Данная функция может быть использована для перенаправления стандартных потоков.

FILE * tmpfile(void);

Открывает временный файл с правами доступа «w+b», который можно закрывать, а можно и не закрывать – при завершении программа сама автоматически закроет его. В случае успеха функция возвращает указатель на файловую переменную, в случае ошибки – NULL.

int rmtmp(void);

Функция закрывает и удаляет все открытые временные файловые потоки. Возвращает число закрытых и удалённых файловых потоков.

int fflush(FILE * stream);

Функция выполняет передачу данных из внутреннего буфера файла stream на устройство. Функция возвращает 0, если операция прошла успешно, и EOF в случае ошибки. Данная операция необходима, чтобы предотвратить потерю данных в буфере в случае внезапного сбоя системы.

int flushall(void);

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

int unlink(const char* filename);

Функция удаляет файл filename, имя файла должно быть абсолютным. Файл, имеющий атрибут read-only, не может быть удалён данной функцией. Кроме того, не может быть удалён открытый файл (его нужно предварительно закрыть). В случае успеха, функция возвращает 0, в случае ошибки функция возвращает –1 и устанавливает значение переменной errno в одно из следующих значений: ENOENT – файл не существует, EACCES – нет прав доступа.

int remove(const char* filename);

Макрос, выполняющий вызов функции unlink(). Аналогичен функции unlink().

int rename(const char* oldname, const char* newname);

Функция переименовывает файл oldname в файл newname. В случае успеха функция возвращает 0, в случае ошибки функция возвращает –1 и устанавливает значение переменной errno в одно из следующих значений: ENOENT – файл не существует, EACCES – нет прав доступа, ENOTSAM – неверно задано устройство.

void setbuf(FILE * stream, char * buf);

Функция задает для файла stream область памяти, которая будет использоваться под буфер. Адрес начала буфера передается в качестве параметра buf, который должен быть указателем на блок памяти размером BUFSIZ (макрос, результат макрорасширения – 512). Если buf==NULL, то обмен данными будет небуферирован. По умолчанию для обычных файлов используется буфер размером 512 байтов, для стандартных потоков – 128 байтов.

int setvbuf(FILE * stream, char * buf, int type, size_t size);

Функция задает для файла stream область памяти, которая будет использоваться под буфер. Адрес начала буфера передается в качестве параметра buf, который должен быть указателем на блок памяти размером size (0<size<32K). Параметр type определяет способ буферизации и может иметь следующие значения, определенные как макросы.

Макрос

Значение

Способ буферизации

_IOFBF

0

Полная буферизация, если buf==NULL, то функция сама выделяет буфер размером size

_IOLBF

1

Построчная буферизация

_IONBF

2

Буферизация отсутствует

void rewind(FILE * stream);

Функция устанавливает указатель чтения-записи в начало файла (потока) stream.

int fseek(FILE * stream, long offset, int whence);

Функция позиционирует указатель чтения-записи для потока stream на offset байтов от точки отсчёта, задаваемой параметром whence. Для задания точки отсчёта определены следующие макросы.

Макрос

Значение

Точка отсчёта

SEEK_SET

0

Начало файла

SEEK_CUR

1

Текущая позиция

SEEK_END

2

Конец файла

В случае успеха функция возвращает 0, в случае ошибки – значение, отличное от 0.

long ftell(FILE * stream);

Функция возвращает в случае успеха смещение текущей позиции указателя чтения- записи для файла stream от начала файла, в случае ошибки -1L.

int fclose(FILE * stream);

Функция выполняет закрытие файла stream, при этом происходит освобождение буфера. Функция возвращает 0, если операция закрытия прошла успешно, и EOF в случае ошибки.

int fcloseall(void);

Функция выполняет закрытие всех открытых файлов и возвращает число закрытых файлов, если операция закрытия прошла успешно, и EOF в случае ошибки.

int feof(FILE * fp);

Макрос feof() выполняет проверку, достигнут ли конец файла (потока) fp, и возвращает 0, если конец файла не достигнут, или значение, отличное от 0, если при последней операции чтения из файла был достигнут конец файла.

int ferror(FILE * fp);

Макрос ferror() выполняет проверку, была ли ошибка ввода-вывода в файле fp, и возвращает 0, если ошибки не было, или значение, отличное от 0, если ошибка была. Если же следующая после ошибочной операция с файлом пройдет успешно, то функция возвратит 0 и сообщение об ошибке будет потеряно.

Функции потокового ввода-вывода можно разделить на 4 группы.

  1.  Функции посимвольного ввода-вывода – за одно обращение к файлу передаётся один символ.
  2.  Функции построчного ввода-вывода – за одно обращение передаётся строка.
  3.  Функции блочного ввода-вывода – за одно обращение передаётся блок информации (байтов), при работе с ними лучше открывать файлы в бинарном режиме.
  4.  Функции форматированного ввода-вывода – за одно обращение передаётся строка, формируемая по заданной строке формата, в которую могут быть подставлены значения переменных разных типов.

int getc(FILE * stream);

int putc(const int c, FILE * stream);

Макрос getc() производит ввод символа из потока stream. Макрос putc() производит вывод символа, код которого принимает в качестве аргумента c, в поток stream. Оба макроса в случае успеха возвращают код символа, в случае ошибки – EOF.

int fgetc(FILE * stream);

int fputc(int c, FILE * stream);

Функция fgetc() производит ввод символа из потока stream. Функция fputc() производит вывод символа, код которого принимает в качестве аргумента c, в поток stream. Обе функции в случае успеха возвращают код символа, в случае ошибки – EOF. Они аналогичны макросам getc() и putc().

char * fgets(char* s, int n, FILE * stream);

Функция fgets() производит ввод символов из потока stream в буфер, адрес которого принимает в качестве параметра s, пока не встретится символ перевода строки или пока не будет прочитано (n-1) символов. После последнего введенного символа функция помещает нулевой байт, либо преобразует символ перевода строки в нулевой байт. Функция в случае успеха возвращает s, в случае ошибки – NULL.

int fputs(const char * s, FILE * stream);

Функция fputs() производит вывод строки, адрес которой принимает в качестве параметра s, в поток stream. Функция в случае успеха возвращает неотрицательное значение, в случае ошибки – EOF.

size_t fread(void * ptr, size_t size, size_t n, FILE * stream);

size_t fwrite(const void * ptr, size_t size, size_t n, FILE * stream);

Функции fread() и fwrite() осуществляют чтение и запись соответственно блока данных в файл или из файла. Указатель ptr указывает на начало блока данных, n – число записей длиной size байтов, которые будут считаны или записаны, size – размер одной записи в байтах, stream – указатель на поток. В случае успеха функции возвращают число считанных или записанных записей, в случае ошибки – 0.

int fscanf(FILE * stream, const char * format, ...);

int fprintf(FILE * stream, const char * format, ...);

Функции fscanf() и fprintf() осуществляют форматированный ввод и вывод соответственно (аналогично функциям scanf() и printf()) в поток (из потока) stream.

int sscanf(const char * buffer, const char * format, ...);

int sprintf(char * buffer, const char * format, ...);

Функции sscanf() и sprintf() осуществляют форматированный ввод и вывод соответственно (аналогично функциям scanf() и printf()) в стороку (из строки) buffer.

В случае успеха функции fprintf() и sprintf() возвращают число выведенных символов, в случае ошибки – EOF. В случае успеха функции fscanf() и sscanf() возвращают число удачно введённых и распознанных полей, 0 – если ни одного поля не распознано, в случае ошибки – EOF.

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

При запуске программы системой создаются структуры типа FILE, связанные со стандартными потоками:

stdin – стандартный поток ввода (связан с клавиатурой);

stdout – стандартный поток вывода (связан с монитором);

stderr – стандартный поток ошибок (связан с монитором);

stdaux – стандартный поток дополнительного устройства (связан с  портом COM1);

stdprn – стандартный поток принтера (связан с принтером).

Два последние потока являются дополнительными, данные устройства могут и не поддерживаться ОС или не входить в состав ПК.

Эти имена описаны в файле stdio.h в виде макросов, результатом макрорасширения и будет адрес структуры типа FILE. С помощью данных потоков осуществляется ввод-вывод на стандартные устройства компьютера.

При завершении работы программы данные потоки закрываются автоматически.

Предопределённые префиксы файлов стандартного ввода-вывода приведены в таблице ниже.

Префикс

Имя устройства

Имя потока

00h

CON

stdin

01h

CON

stdout

02h

CON

stderr

03h

AUX

stdaux

04h

PRN

stdprn

Функции для работы со стандартными потоками.

Для функций ввода окончание ввода осуществляется нажатием клавиши ENTER.

Функции printf() и scanf() были рассмотрены на практических занятиях ранее.

int getchar(void);

int putchar(const int c);

Макрос getchar() производит ввод символа из стандартного потока ввода. Макрос putchar() производит вывод символа, код которого принимает в качестве аргумента, в стандартный поток вывода. Оба макроса в случае успеха возвращают код символа, в случае ошибки – EOF.

char * gets(char * s);

Функция gets() производит ввод строки из стандартного потока ввода в буфер, адрес начала которого принимает в качестве параметра. Функция в случае успеха возвращает s, в случае ошибки – NULL.

int puts(const char * s);

Функция puts() производит вывод строки, адрес которой принимает в качестве параметра, в стандартный поток вывода. Функция в случае успеха возвращает последний записанный символ, в случае ошибки – EOF.

void perror(const char * s);

Функция выводит в стандартный поток ошибок stderr строку, адрес которой принимает в качестве параметра.


 

А также другие работы, которые могут Вас заинтересовать

67677. Сталь 40ХНМА и прочая полезная информация 1.66 MB
  При выборе термической обработки необходимо представлять себе сущность изменений, происходящих в стали при этой обработке. Для этого необходимо знать основные положения металловедения, в частности строение стали и механизм протекания фазовых превращений.
67678. Разработка считывателя системы контроля за персоналом на основе микроконтроллера AVR 494.5 KB
  На основании анализа функциональной спецификации можно выделить следующие блоки которые необходимо реализовать аппаратным способом: Входы: модуль контактного устройства модуль связи с компьютером модуль часов Выходы: модуль светодиодных индикаторов модуль переноса данных Функции: модуль защиты...
67681. Проект отделения ремонта двигателей на обслуживание 459 автомобилей ГАЗ-33075 569.5 KB
  Основной объём работ по ЕО приходится на УМР. Рабочий пост предназначен для выполнения основных работ по ТО и ТР автомобилей и представляет собой участок пола здания производственное площади для постановки автомобилей и размещения одного или нескольких рабочих мест.
67683. Проект устройства управления стиральной машины 380 KB
  На основании анализа функциональной спецификации можно выделить следующие блоки которые необходимо реализовать аппаратным способом: ВХОДЫ: модуль датчика температуры; модуль переключателя режимов; модуль датчика уровня воды; ВЫХОДЫ: модуль управления двигателем; модуль управления насосом...
67684. ЭЛЕКТРОМАГНИТНОЕ ПОЛЕ В ПРЯМОУГОЛЬНОМ ВОЛНОВОДЕ 143.39 KB
  Стенки волновода являются идеально проводящими. Проверить выполнение граничных условий на стенках волновода при x=0 и y=0 b. Определить максимальные значения плотностей продольного и поперечного поверхностных токов на всех стенках волновода на частоте f2.
67685. Изучение электромагнитных волн 61.57 KB
  Элементарный электрический вибратор создает в свободном пространстве монохроматическое поле с частотой f. Сопротивление излучения вибратора равно R∑, а среднее за период значение излученной мощности равняется P∑ср. Фаза комплексной амплитуды электрического тока, протекающего по вибратору, равна нулю.