Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЯП - ПОИТ (Бахтизин) часть 1 редакт.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
1.76 Mб
Скачать

10.4. Произвольный доступ к файлу

Каждый открытый файл имеет так называемый указатель на текущую позицию в файле. Все операции над файлами (чтение и запись) работают с данными с этой позиции. При открытии файла указатель текущей позиции в файле устанавливается на начало файла (кроме режимов ‘a’ и ‘a+’).

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

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

...

char ch;

...

К примеру, мы вызвали функцию fscanf(f,“%c”, &ch);

f – указатель на файл, открытый функцией fopen();

После этого указатель сместится на sizeof(ch), т.е. на 1 байт.

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

Но иногда необходимо читать или писать данные в произвольном порядке. Это достигается путем установки указателя на некоторую заданную позицию в файле функцией fseek().

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

Параметр offset задает количество байт, на которое необходимо сместить указатель в направлении, указанном whence в файле stream.

В таблице 10.2 приведены возможные значения параметра whence:

Таблица 10.2. Значения параметра whence

SEEK_SET

0

Смещение от начала файла

SEEK_CUR

1

Смещение от текущей позиции

SEEK_END

2

Смещение от конца файла

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

...

fseek(f, 8, SEEK_SET); // смещает указатель на текущую

// позицию в файле на восемь байт от

// его текущего положения

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

long int ftell(FILE *file);

file – указатель на файл, возвращенный функцией fopen().

Функция ftell() возвращает текущее положение указателя файла в байтах относительно начала файла. В случае ошибки возвращается значение -1L.

#include <stdio.h>

// Функция возвращает число байтов в файле

long filesize(FILE *f1)

{

long pos, length;

pos = ftell(f1);

fseek(f1,0L,SEEK_END);

length = ftell(f1);

fseek(f1,pos,SEEK_SET);

return (length);

}

int main()

{

FILE *f;

f = fopen("D:\\main.cpp","r");

printf("%ld",filesize(f));

fclose(f);

return 0;

}

Также часто возникает потребность в проверке достижения конца файла.

Для этого используется функция feof().

Прототип:

int feof(FILE *file);

file – указатель на файл, открытый функцией fopen();

Если достигнут конец файла, то функция возвращает ненулевое значение, иначе – нуль.

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

#include <stdio.h>

#include <conio.h>

void main(void)

{

struct man

{

char im[10];

char fam[10];

char ot[10];

int vozr;

};

FILE *out;

man m;

int c;

clrscr();

if (!(out = fopen("d:\\Ex2_bin.txt", "rb"))) return;

//открывается файл со структурами, созданными в примере 4

do

{

clrscr();

puts("Vvedite nomer zapisi");

if ((c = getch()) != '0') // считывается номер структуры

if ((c > '0') && (c <= '3')) // т.к у нас было создано

// только 3 структуры

{

c = (c - '0') - 1;

puts("Reading from file");

// смещаемся на кол-во байт, равное размеру одной

// структуры, умноженный на с

fseek(out, sizeof(m) * c, 0);

fread(&m, sizeof(m), 1, out); // считываем структуру

//выводим структуру

printf("%s %s %s, vozrast (let) %i \n",

m.im, m.fam, m.ot, m.vozr);

getch();

}

}

while (c != '0'); // 0 – признак выхода

fclose(out);

}