Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Глава 3_3.doc
Скачиваний:
33
Добавлен:
13.03.2016
Размер:
158.72 Кб
Скачать

Файлы прямого доступа

Файлы прямого доступа могут быть форматными, двоичными, неформатными. Все записи в файле прямого доступа имеют одинаковую длину. Длина записи задается параметром RECL= в операторе открытия файла. Для открытия форматного файла прямого доступа в программе записывается оператор следующей структуры:

OPEN(N, FILE=fname, ACCESS=`DIRECT`, FORM=`FORMATTED`, RECL=recl)

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

OPEN(N, FILE=fname, ACCESS=`DIRECT`, FORM=`BINARY`, RECL=recl)

Здесь recl – целое число, задающее длину записи.

По умолчанию файл прямого доступа имеет опцию FORM=`UNFORMATTED`.

В файле прямого доступа можно перейти на начало любой записи с номером r с помощью оператора read, в котором задан параметр REC=r-1. При этом список ввода может отсутствовать. В неформатном или двоичном файле оператор имеет вид

READ(N, [rec=r-1]) [список_ввода]

В форматном файле:

READ(N, frm, [rec=r-1]) [список_ввода]

Если список ввода отсутствует, то просто происходит установка ФУ на соответствующую запись. Если отсутствует параметр rec=, то читается текущая запись. Аналогично записывается оператор WRITE для двоичного или неформатного файла:

WRITE(N, [rec=r-1]) список_вывода

Для форматного файла:

WRITE(N, frm, [rec=r-1]) список_вывода

Пример. Имеется неформатный файл прямого доступа numbers.dat, содержащий 100 вещественных чисел типа real(8). Нужно занулить в файле все числа с четными номерами (2-е, 4-е и т.д.), а все числа с нечетными номерами переписать в форматный файл последовательного доступа massiv.txt.

Real(8):: nul=0

OPEN(1,FILE=`numbers.dat`,ACCESS=`DIRECT`, & FORM=`UNFORMATTED`, RECL=8)

Open(2, FILE=`massiv.txt`)

Do i=2,100,2

Write(1, rec=i-1) nul

Enddo

Rewind 1

Do i=1,99,2

Read(1, rec=i-1) nul

Write(2,*)nul

enddo

Упражнения

  1. Дан форматный последовательный файл с вещественными числами. Определить количество нулевых значений в файле.

  2. Даны два форматных последовательных файла, содержащие массивы целых чисел. Определить, являются ли они тождественными.

  3. Дан двоичный файл последовательного доступа, содержащий элементы квадратной матрицы N*N, расположенные по строкам (вещественные числа типа REAL(8)). Заполнить двумерный массив числами из файла.

  4. В текстовом файле последовательного доступа хранится текст книги. Размер строки – 80 символов, размер страницы – 50 строк. Определить номера страниц, на которых имеется слово FORTRAN.

  5. В текстовом файле прямого доступа хранится текст книги. Размер строки – 80 символов, размер страницы – 50 строк. Везде, где содержится слово fortran, записанное строчными буквами, нужно заменить его на слово FORTRAN, записанное прописными буквами.

3.14. Производные типы данных

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

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

Такая структура называется одноуровневым деревом. В Фортране эта информация может храниться в одной переменной производного типа. Задать тип и описать соответствующую переменную можно следующим образом:

Type Exam !имя типа

character(50)name !1-е поле

integer(1) mark1 !2-е поле

integer(1) mark2 !3-е поле

integer(1) mark3 !4-е поле

End type Exam

Type (Exam) Student ! Переменная производного типа

Общий формат оператора объявления производного типа:

TYPE имя_типа

компоненты (поля) структуры

END TYPE

Общий формат объявления переменной производного типа:

TYPE (имя_типа) имя_переменной

К каждому элементу переменной производного типа можно обратиться, используя составное имя, которое имеет следующую структуру:

имя_переменной%имя_поля

Например, student%name; student%mark2 и т.п. Если, например, требуется полю "mark1" присвоить значение "3", то это делается так:

Student%mark1 = 3.

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

Type Sveden

character(50)name

integer(2) nomer

integer(1) kurs

character(6) grup

end type Sveden

Type Exam

Type(Sveden)rekviz !Поле типа Exam является структурой

integer(1) mark1 !Тип этой структуры должен

integer(1) mark2 !быть описан выше

integer(1) mark3

End type Exam

Type (Exam) Student ! Переменная производного типа

Теперь, чтобы присвоить студенту определенную фамилию и инициалы, надо написать в программе:

Student%rekviz%FIO=`Иванов Н.Н.`

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

Type(exam) group(30).

Конструктор структуры

Конструктор структуры – это константа описанного производного типа. Ее формат следующий:

Имя_типа(список_значений_полей).

Например:

еxam(`Иванов Н.Н.`,3,4,5).

Конструктор можно использовать при инициализации структуры.

Type(exam)::student = еxam(`Иванов Н.Н.`,3,4,5).

Конструктор можно использовать в операторе присваивания:

Student= еxam(`Иванов Н.Н.`,3,4,5).

С помощью конструктора можно инициализировать целый массив производного типа:

Group=exam(`None`,0,0,0).

Или присвоить значения отдельному элементу массива:

Group(5)=exam(`Ильин А.Б.`,4,5,5).

Пример 1. Ввести с клавиатуры сведения об оценках 30 студентов группы. Получить на экране список из Ф.И.О. и суммы набранных баллов каждым студентом.

Type exam

Character(20) name

Integer mark(3) !оценки организованы в массив

End type exam

Type(exam)group(30) !объявлен массив производного типа

Print(`Вводите данные`)

Do i=1,30

Print *, I,`-й студент:`

Read *, group(i) !При вводе поля следует отделять

!пробелами

Enddo

Print *, `Суммы баллов`

Do i=1,30

Write(*,`(1X,A20,I4`) group(i)%name, group(i)%mark(1) + &

Group(i)%mark(2) + group(i)%mark(3)

Enddo

end

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

Пример 2. Дан текстовый файл с результатами экзаменов, сданных студентами. Число студентов может быть любым. Создать текстовый файл, содержащий фамилии студентов и суммы набранных баллов.

Type exam

Character(20) name

Integer mark(3) !оценки организованы в массив

End type exam

Type(exam)stud !объявлена переменная производного типа

Open(1, file=`examen.txt`)

Open(2, file=`result.txt`)

Write(2,*) `Results of examination`

Do while(.not.EOF(1))

Read (1,*) stud

Write(2,`(1X,A20,I4)`) stud%name, stud%mark(1)+ &

stud%mark(2) + stud%mark(3)

Enddo

Close(2)

end

Пример 3. Сведения о результатах экзаменов хранятся в текстовом файле exam.txt прямого доступа. В запись номер 20 нужно внести изменение: поменять оценку по второму экзамену на 5 (студент пересдал экзамен).

Type exam

Character(20) name

Integer mark(3)

End type exam

Type(exam)stud !объявлена переменная производного типа

Open(1, file=`examen.txt`, access=`direct`, recl=26)

Read(1,10, rec=19)stud !читается 20-я запись

Stud%mark(2)=5 !присваивается новое значение поля

Backspase 1 !возврат на 1-ю запись

Write(1, 10) stud !перезапись

10 FORMAT(A20, 3I2)

end

Напомним, что в файле прямого доступа все записи имеют одинаковую длину. В данном примере длина равна 26 байт: 20 байт – фамилия, и по 2 байта на каждую оценку.