Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lektsii_po_si.doc
Скачиваний:
13
Добавлен:
12.11.2018
Размер:
11.78 Mб
Скачать

Позиционирование в потоке.

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

Операция чтения (или записи) для потока всегда производится, начиная с текущей позиции в потоке. Начальная позиция чтения/записи в потоке устанавливается при открытии потока и может соответствовать начальному или конечному байту потока в зависимости от режима открытия потока. При открытии потока в режимах "r" и "w" указатель текущей позиции чтения/записи в потоке устанавливается на начальный байт потока, а при открытии в режиме "а" - в конец файла (за конечным байтом). При выполнении каждой операции ввода-вывода указатель текущей позиции в потоке перемещается на новую текущую позицию в соответствии с числом прочитанных (записанных) байтов.

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

В библиотеку языка Си включена функция fseek( ) для перемещения (установки) указателя текущей позиции в потоке на нужный байт потока (файла). Она имеет следующий прототип:

int fseek (указатель_напоток, смещение, начало_отсчета);

Смещение задается переменной или выражением типа long и может быть отрицательным, т.е. возможно перемещение по файлу в прямом и обратном направлениях. Начало отсчета задается одной из предопределенных констант, размещенных в заголовочном файле stdio.h:

SEEK_SET (имеет значение 0) - начало файла;

SEEK_CUR (имеет значение 1) -текущая позиция;

SEEK_END (имеет значение 2) - конец файла.

Здесь следует напомнить некоторые особенности данных типа long. Этот тип определяется для целочисленных констант и переменных, которым в памяти должно быть выделено больше места, чем данным типа int. Обычно переменной типа long выделяется 4 байта, чем и определен диапазон ее значений. Описание данных типа long:

Константа типа long записывается в виде последовательности десятичных цифр, вслед за которыми добавляется разделитель L или 1. Примеры констант типа long:

331

В текстах программ лучше использовать L, чтобы не путать I с цифрой 1.

Функция fseek( ) возвращает 0, если перемещение в потоке (файле) выполнено успешно, в противном случае возвращается ненулевое значение.

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

Перемещение к концу потока (файла) из произвольной позиции:

В обоих примерах смещение задано явно в виде нулевой десятичной константы 0L типа long.

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

Тогда при следующем обращении к функции fseek( ) указатель текущей позиции в потоке будет перемещен на одну структуру назад относительно текущей позиции:

Для иллюстрации работы с файлом в режиме произвольного доступа рассмотрим пример небольшого трехъязычного словаря, содержащего названия цифр от 1 до 9 на английском, немецком и французском языках. Для обслуживания словаря необходимы 2 программы: программа загрузки словаря в файл на диске и программа поиска слова в словаре (в ней используется функция fseek( ) ).

"База данных" словаря организована в файле vac.dat. Функция загрузки запрашивает названия для цифр от 1 до 9. Названия конкретной цифры (в предположении, что каждое название не превышает 9 букв) на всех трех языках записываются в одной строке через пробелы. Сформированная строка по нажатию клавиши <Enter> прочитывается в массив символов buf[ ]. Текст программы:

Введенные данные (представление цифры в формате целого числа и названия цифр на трех языках) побайтно выводятся в файл vac.dat, образуя в нем "записи", структура которых показана на рис. 7.2.

Рис. 7.2. Состав записи "Цифра"

Следующая программа перевода (trans) запрашивает сначала язык, на котором нужно выводить названия цифр, а затем в цикле запрашиваются цифры. Язык идентифицируется первой буквой своего русского наименования: 'а' или 'А' - для английского; 'н' или 'Н' - для немецкого; 'ф' или 'Ф' - для французского. Признаком завершения программы служит ввод цифры 0. Текст программы trans:

При вычислении позиции (pos) в файле, с которой начинается строка перевода, участвуют следующие составляющие:

k-1 - выбирает подстроку (длиной 32 байта), в которой содержится перевод;

2 - учитывает длину поля цифры (2 байта);

lang*10 - задает смещение до требуемого значения цифры в подстроке перевода.

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

Рис. 7.3. Составляющие смещения для записей в файле словаря

Предлагаем самостоятельно разработать функцию поиска в файле заданной подстроки и на ее основе написать программу перевода названий цифр с одного языка на другой. В табл. 7.3 приводятся названия цифр от 1 до 9 на трех языках.

Таблица 7.3