Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Подбельский Фомин_Программирование на языке СИ_...doc
Скачиваний:
356
Добавлен:
10.08.2019
Размер:
53.81 Mб
Скачать

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

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

Функция lseek( ) изменяет текущую позицию в файле, связанном с дескриптором fd, на новую, определяемую смещением (второй параметр - offset) относительно выбранной точки отсчета (третий параметр - origin).

Точка отсчета задается одной из предопределенных констант, размещенных в заголовочном файле io.h (MS-DOS) или файле unistd.h (UNIX):

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

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

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

При удачном завершении функция lseek( ) возвращает новую текущую позицию чтения/записи, представляющую собой смещение от начала файла. Попытка переместиться за пределы файла считается ошибкой. Код ошибки заносится в глобальную переменную еrrnо, определенную в заголовочном файле errno.h.

Для определения текущей позиции в файле можно использовать функцию tell( ), прототип которой имеет следующий вид:

Приведем примеры использования функции lseek( ).

Пример 1.

Установка текущей позиции в файле на его начало:

Пример 2.

Установка текущей позиции для последующего добавления данных в файл (позиция в конце файла):

Пример 3.

Модификация записей в существующем файле

В качестве еще одного примера использования функции lseek( ) приведем фрагмент программы, производящей модификацию записей в существующем файле. Запись - это объект (последовательность байтов) в файле, являющаяся сложным структурным элементом в контексте программы, обрабатывающей эти записи. Логическая структура записи может быть любой: некоторой последовательностью байтов, строкой, структурой и т.д. В следующем фрагменте программы предполагается, что все записи имеют одинаковый размер (в байтах) и размещены в файле подряд.

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

Глава 8. Примеры разработки программ

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

8.1. Программа с объектами разных классов памяти Постановка задачи.

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

Пусть задан следующий способ получения равномерно распределенных псевдослучайных чисел (Gruenberger F., Babcock D. Computing with minicomputers. Los Angeles, 1973) :

aj=(xj+yj+zj+aj-1) mod 16384,

где xj = (2xj-1) mod 16381;

yj = (2yj-1) mod 16363;

zj =(2zj-1)mod 16349.

Для j > 0 и а0 =00 =z0=l.

В приведенных соотношениях mod - обозначение деления по модулю. В языке Си деление по модулю целых чисел реализуется с помощью операции '%'.

Получаемые значения aj распределены достаточно равномерно в диапазоне от 0 до 16383. Известно, что для получения величин, распределенных по нормальному закону из равномерно распределенных величин, можно использовать, например, такое приближенное соотношение :

гдеL = 1, 13,25,...

Используя приведенные соотношения, нужно получить заданное количество N псевдослучайных чисел Si, i = и оценить для полученной совокупности выборочное среднее (математическое ожидание) т и выборочную дисперсию V:

Введя или определив предельные значения элементов Smin, Smax в выборке {Si} из N элементов, сформировать гистограмму с заданным количеством К интервалов равной ширины.

Сравнить гистограмму, построенную для выборки псевдослучайных чисел, с кривой нормального (Гауссова) распределения, которая описывается уравнением:

где х - аргумент; V- дисперсия; т - математическое ожидание.

Гистограмма характеризуется следующими данными: Smin и Smax - предельные значения псевдослучайных чисел; N – общее количество помещаемых в гистограмму значений; К- количество равных интервалов разбиения оси абсцисс гистограммы; nj -количество значений Sj, относящихся к j-му интервалу, где

j =

Естественно соотношение :

На основании анализа гистограммы можно по-другому и с меньшей точностью оценить среднее значение тg и дисперсию Vg исходной последовательности псевдослучайных чисел {Si}. Для пояснения рассмотрим изображение гистограммы на рис.8.1. По оси абсцисс гистограммы - получаемые значения Si псевдослучайных чисел. По оси ординат - количество пj значений Si, относящихся к j-му интервалу (сгруппированных в нем). Количество интервалов К гистограммы фиксировано, интервалы имеют равную ширину:

Рис. 8.1. Гистограмма для псевдослучайных чисел

Среднее значение абсциссы j-гo интервала :

Cj представляет собой среднее значение данных (т.е. величин Si, отнесенных к j-му интервалу гистограммы. Для каждого j-го интервала количество значений Si равно nj, поэтому для оценки среднего значения mg выборки {Si} по данным гистограммы применимо соотношение :

Оценить выборочное значение дисперсии по данным гистограммы можно так :

Получаемое таким образом значение Vg оказывается немного больше оценки выборочной дисперсии К для всей выборки {Si}. Более точное значение оценки дисперсии dg получается с помощью поправки Шеппарда (равной h/12), т.е. :

Здесь h - ширина интервала гистограммы.