Материал: lectures_3

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

42.1.Понятие потока

Поток – это своего рода обобщенное устройство ввода-вывода. Такое понятие введено в рассмотрение для того, чтобы при программировании операций ввода – вывода можно было не учитывать особенности:

конкретного типа внешнего устройства,

среды, в которой выполняется программа.

Все потоки ведут себя похожим образом. Работа их не зависит от типа физического устройства.

Различают потоки двух видов:

текстовые,

двоичные.

Текстовый поток

Текстовый поток – это последовательность символов, организованная в строки. Каждая строка такого потока должна заканчиваться символом новая строка ‘\n’. В конце последней строки такой символ не является обязательным.

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

При работе потока в режиме вывода картина обратная. На входе потока строка гарантировано заканчивается символом новая строка. Организация строки на выходе потока может быть любой.

В зависимости от среды, в которой выполняется программа, при использовании текстового потока могут иметь место некоторые преобразования. Например, в среде Windows символ новая строка ‘\n’ преобразуется в последовательность символов CR LF.

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

Кроме того, при использовании текстового потока в режиме чтения особым способом обрабатывается символ конца файла. В таблице кодов ASCII этот символ имеет код 0x1A. Эта особенность состоит в том, что вся часть содержимого файла, расположенная справа от этого символа (от конца файла) не читается.

Двоичный поток

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

126

42.2.Файлы

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

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

Если работа программы завершается нормально, то все файлы автоматически закрываются. В случае аварийного завершения работы программы файлы автоматически не закрываются.

Указатель файла

У каждого потока, связанного с файлом, имеется структура, содержащая информацию о файле. Эта структура имеет тип FILE. Этот тип объявлен в заголовочном файле stdio.h. Для каждого файла, с которым она будет работать, должен существовать так называемый указатель файла. Указатель файла – указатель на структуру типа FILE.

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

Функция fopen()

Объявление этой функции имеет следующий вид.

#include<stdio.h>

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

Эта функция открывает поток и связывает с ним определенный файл. Первый параметр (filename) рассматриваемой функции определяет открываемый файл. Второй параметр функции (mode) задает режим, в котором должен быть открыт файл.

Вслучае успеха функция вернет указатель типа FILE* на созданную структуру данных. Этот указатель может использоваться файловыми функциями для выполнения операций ввода – вывода. В случае возникновения ошибки функция fopen() вернет нулевой указатель.

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

FILE* fp;

if((fp = fopen(“file1.txt”, “w”)) == NULL)

{

printf(“Не могу открыть файл file1.txt”);

127

exit(1);

}

Возможные режимы открытия потоков представлены в приводимой ниже таблице

Режим

Пояснение

r

Открыть текстовый поток и связать его с существующим файлом

w

Открыть текстовый поток и связать его с вновь созданным файлом

a

Открыть текстовый файл в режиме дозаписи. Если файл еще не существует,

 

то он будет создан.

rb, wb и ab

Отличаются соответственно от режимов r, w и a только тем, что открывают

 

двоичный поток.

r+, w+ и a+

Отличаются соответственно от режимов r, w и a только тем, что поток

 

открывается в режиме чтения / записи.

r+b, w+b и a+b

Отличаются соответственно от режимов rb, wb и ab только тем, что поток

 

открываются в режиме чтения / записи.

Функция fclose()

Объявление этой функции имеет следующий вид.

#include<stdio.h>

int fсlose(FILE* stream);

Функция fclose() закрывает поток stream. Перед закрытием потока все связанные с ним буферы сбрасываются. При успешном выполнении функция fclose() возвращает 0, а в случае ошибки – EOF.

Функция feof()

Объявление рассматриваемой функции имеет следующий вид:

#include<stdio.h>

int feof(FILE* stream);

Функция feof() проверяет, достигнут ли конец файла при выполнении очередной операции чтения. Параметр stream является указателем на поток, с которым работает файл.

Если указатель текущей позиции файла установлен на конец файла, то функция feof() вернет ненулевое значение, в противном случае возвращается нуль.

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

В начале выполнения программы автоматически открываются три

стандартных потока.

Файловый указатель

Внешнее устройство

Поток

Ввода

stdin

клавиатура

Вывода

stdout

Экран дисплея

Ошибок

stderr

Экран дисплея

Классификация функций потокового ввода – вывода

Все функции потокового ввода – вывода можно разделить на четыре категории:

128

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

посимвольный ввод – вывод,

построковый ввод – вывод,

блоковый ввод – вывод.

Форматированный ввод – вывод

При форматированном вводе - выводе используются следующие функции:

fprintf() – для записи в файл,

fsсanf() - для чтения из файла. Функция fprintf() объявлена следующим образом:

#include<stdio.h>

int fpintf(FILE* stream, const char* format[, аргумент, …] );

Рассматриваемая функция является обобщенным вариантом функции printf(). Здесь появился дополнительный параметр stream, которого нет в функции printf. Параметр stream является указателем на поток, который должен быть предварительно открыт функцией fopen().

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

Функция fscanf() объявлена следующим образом:

#include<stdio.h>

int fscanf(FILE* stream, const char* format[, указатель, …]

);

Эта функция в свою очередь является обобщенным вариантом функции scanf(). Здесь также появился дополнительный параметр stream – указатель на поток.

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

Построковый ввод – вывод

Для организации построкового ввода – вывода могут использоваться следующие функции:

fputs(),

fgets().

Функция fputs() объявлена следующим образом:

#include<stdio.h>

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

Функция fputs() выводит строку, на которую установлен указатель s в поток, на который установлен указатель stream. Символ ‘\0’, завершающий выводимую строку в поток не записывается. Если в процессе записи имела место ошибка, то рассматриваемая функция вернет EOF, в случае успеха возвращаемым значением функции fputs() является неотрицательное числа.

129

Функция fgets() объявлена следующим образом:

#include<stdio.h>

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

Функция fgets() читает не более n – 1 символов из потока на, который установлен указатель stream, в символьный массив, на который установлен указатель s. Существуют два способа завершения процесса чтения символов:

прочитан символ новая строка (‘\n’) ,

прочитан n – 1 символ.

Впервом случае прочитанный символ новая строка записывается в символьный массив, а затем строка завершается нуль – символом. Во втором случае символ новая строка оказывается непрочтенным и незаписанным в символьный массив. Однако и в этом случае в символьный массив будет записан нуль – символ.

После успешного выполнения функция fgets() возвращает указатель на символьный массив, в который производилась запись. Если имело место достижение конца файла при условии, что ни один символ не был прочитан, возвращаемым значением функции fscanf() является NULL, а содержимое массива, на который установлен указатель s, оказывается неименным.

Блоковый ввод – вывод

Блоковый ввод – вывод обеспечивается функциями fread() и fwrite(). Объявление функции fwrite() имеет следующий вид:

#include<stdio.h>

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

Функция fwrite() помещает до nmemb элементов (блоков), каждый из которых размером size, из массива адресуемого указателем ptr, в поток, на который установлен указатель stream.

Функция fwrite() возвращает число успешно записанных элементов (блоков). Это значение может оказаться меньше, чем nmemb, если имеет

место ошибка.

#include<stdio.h>

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

Функция fwrite() читает до nmemb элементов (блоков), каждый из которых размером size, в массив адресуемого указателем ptr, из потока, на который установлен указатель stream.

Функция fread() возвращает число успешно прочитанных элементов (блоков). Это значение может оказаться меньше, чем nmemb, если имеет место ошибка или обнаружен конец файла.

Примеры решенных задач

Пример 1 Табулирование функции с записью результатов на диск. Постановка задачи. Табулировать функцию y = x2 в n равноостоящих

точках, начиная от значения x = xn вплоть до x = xk. Результаты табулирования записать в текстовый файл.

130

Источник: https://studfile.net/preview/16544272/