Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Тема 6 Файловый ввод-вывод.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
119.3 Кб
Скачать

6.3 Форматированный ввод/вывод (текстовые файлы)

Запись и чтение текстовых файлов внешне очень похоже на консольный ввод/вывод (т.е. вывод на экран и ввод с клавиатуры). Его особенностью является то, что каждая переменная записывается и читается по отдельности. Для этих целей существует множество специализированных библиотечных функций для работы с переменными различных типов данных. Функции fprintf() и fscanf() можно использовать вместо любой из этих функций, поскольку они универсальны, т. к. позволяют работать с данными любого типа. Интерфейс этих функций следующий:

int fprintf ( FILE *уф, const char *управляющая_строка, ...);

int fscanf ( FILE *уф, const char *управляющая_строка, ...);

где уф – указатель файла, возвращаемый в результате вызова fopen(). Операции ввода/вывода функции fprintf() и fscanf() выполняют с тем файлом, на который указывает уф. Иными словами, параметрами этих функций являются файловая переменная, управляющая строка и список вывода.

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

FILE *fp;

char FileName[16];

printf ( "\n Enter file name " );

scanf ( "%s", FileName );

fp = fopen ( FileName, "wt");

if ( fp == NULL ) {

printf ( "\n Error opening the file\n");

exit(1);

}

fprintf ( fp, "%5d%5d\n", N, M ); // запись размерности

for ( int i = 0; i < N; i++ )

{

for ( int j = 0; j < M; j++ )

fprintf ( fp, "%5d", Mas[i][j]); // запись матрицы

fprintf ( fp, "\n");

}

fclose (fp);

Далее приведём аналогичный фрагмент программы для чтения матрицы из файла. Данные должны читаться в том же порядке, что и записывались: сначала размерность, затем сама матрица.

FILE *fp;

char FileName[16];

printf ( "\n Enter file name " );

scanf ( "%s", FileName );

fp = fopen ( FileName, "rt");

if ( fp == NULL ) {

printf ( "\n Error opening the file\n");

exit(1);

}

fscanf ( fp, "%d%d ", &N, &M ); // чтение размерности

for ( int i = 0; i < N; i++ )

for ( int j = 0; j < M; j++ )

fscanf ( fp, "%d", &Mas[i][j]); // чтение матрицы

fclose (fp);

6.4 Блоковый ввод/вывод (двоичные файлы)

Для чтения и записи двоичных файлов в файловой системе языка С имеется две функции: fread() и fwrite(). Эти функции позволяют читать и записывать блоки данных любого типа. Их прототипы следующие:

size_t fread (void *буфер, size_t колич_байт, size_t счетчик, FILE *уф);

size_t fwrite (const void *буфер, size_t колич_байт, size_t счетчик, FILE *уф);

Для fread() буфер – это указатель на область памяти, в которую будут прочитаны данные из файла. А для fwrite() буфер – это указатель на данные, которые будут записаны в файл. Значение счетчик определяет, сколько считывается или записывается элементов данных, причем длина каждого элемента в байтах равна колич_байт. (Тип size_t определяется как одна из разновидностей целого типа без знака.) И, наконец, уф – это указатель файла, то есть на уже открытый поток.

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

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

В качестве иллюстрации работы с двоичным файлом приведём фрагменты программ для записи в файл и чтения из файла одномерного массива. Для краткости функции открытия fopen() и закрытия fclose() файла опущены.

Запись в файл:

1) поэлементная запись

const int Nmax = 10; // максимальная размерность массива

int Mas[Nmax];

int N; // реальная размерность массива

for ( int i = 0; i < N; i++ )

fwrite( Mas, sizeof(Mas[i]), N, fp );

Вместо Mas можно использовать &Mas[0] , а вместо sizeof(Mas[i]) – sizeof(int).

2) блоковая запись – 1-й вариант. Здесь в качестве размера блока указан размер одного элемента массива sizeof(int), а в качестве количества блоков – количество элементов массива N.

fwrite( Mas, sizeof(int), N, fp );

3) блоковая запись – 2-й вариант. Здесь в качестве размера блока указан размер всего массива sizeof(int) * N, а количество блоков, соответственно, равно единице.

fwrite( Mas, sizeof(int) * N, 1, fp );

4) блоковая запись – 3-й вариант. Используется тогда, когда реальная размерность массива совпадает с максимальной.

fwrite( Mas, sizeof(Mas), 1, fp );

Пример чтения из файла представлен для случая, когда известен тип массива Mas (например, int), но не известно количество элементов. В примере использовано то обстоятельство, что функция fread() является типизированной и возвращает количество прочитанных блоков.

int Mas[Nmax];

int i, temp, N;

i = 0;

while ( fread( &temp, sizeof(int), 1, fp ) != 0)

{

Mas[i] = temp;

i++;

}

N = i;

Поскольку размерность массива, записанного в файл, не известна, чтение продолжается до тех пор, пока не будет достигнут конец файла. До начала цикла номер элемента массива i принимает начальное значение. Затем очередной элемент массива считывается из файла в промежуточную переменную temp. Если чтение было успешным, то функция fread() возвращает 1 (т.е. количество прочитанных элементов). Тогда прочитанное значение копируется из переменной temp в соответствующий элемент массива Mas[i], после чего номер элемента i увеличивается на единицу. Если же был достигнут конец файла и очередной элемент прочесть не удалось, то функция fread() возвращает 0, и цикл чтения массива из файла завершается. При этом количество реально прочитанных элементов N будет равно текущему значению переменной i.