
- •Предисловие
- •1. Элементы языка
- •1.1. Свободная форма записи программы
- •1.2. Консоль-проект
- •1.2.1. Создание проекта в CVF
- •1.2.2. Создание проекта в FPS
- •1.2.3. Операции с проектом
- •1.2.4. Файлы с исходным текстом
- •1.3. Операторы
- •1.4. Объекты данных
- •1.5. Имена
- •1.6. Выражения и операции
- •1.7. Присваивание
- •1.8. Простой ввод/вывод
- •1.8.1. Некоторые правила ввода
- •1.8.2. Ввод из текстового файла
- •1.8.3. Вывод на принтер
- •1.9. Рекомендации по изучению Фортрана
- •1.10. Обработка программы
- •2. Элементы программирования
- •2.1. Алгоритм и программа
- •2.2. Базовые структуры алгоритмов
- •2.2.1. Блок операторов и конструкций
- •2.2.2. Ветвление
- •2.2.3. Цикл
- •2.2.3.1. Цикл "с параметром"
- •2.2.3.2. Циклы "пока" и "до"
- •2.2.4. Прерывание цикла. Объединение условий
- •2.3. Программирование "сверху вниз"
- •2.3.1. Использование функций
- •2.3.2. Использование подпрограмм
- •2.3.3. Использование модулей
- •2.4. Этапы проектирования программ
- •2.5. Правила записи исходного кода
- •3. Организация данных
- •3.1. Типы данных
- •3.2. Операторы объявления типов данных
- •3.2.1. Объявление данных целого типа
- •3.2.2. Объявление данных вещественного типа
- •3.2.3. Объявление данных комплексного типа
- •3.2.4. Объявление данных логического типа
- •3.3. Правила умолчания о типах данных
- •3.4. Изменение правил умолчания
- •3.5. Буквальные константы
- •3.5.1. Целые константы
- •3.5.2. Вещественные константы
- •3.5.3. Комплексные константы
- •3.5.4. Логические константы
- •3.5.5. Символьные константы
- •3.6. Задание именованных констант
- •3.7. Задание начальных значений переменных. Оператор DATA
- •3.8. Символьные данные
- •3.8.1. Объявление символьных данных
- •3.8.2. Применение звездочки для задания длины строки
- •3.8.3. Автоматические строки
- •3.8.4. Выделение подстроки
- •3.8.5. Символьные выражения. Операция конкатенации
- •3.8.6. Присваивание символьных данных
- •3.8.7. Символьные переменные как внутренние файлы
- •3.8.8. Встроенные функции обработки символьных данных
- •3.8.9. Выделение слов из строки текста
- •3.9. Производные типы данных
- •3.9.1. Объявление данных производного типа
- •3.9.2. Инициализация и присваивание записей
- •3.9.2.1. Конструктор производного типа
- •3.9.2.2. Присваивание значений компонентам записи
- •3.9.2.3. Задаваемые присваивания записей
- •3.9.3. Выражения производного типа
- •3.9.4. Запись как параметр процедуры
- •3.9.5. Запись как результат функции
- •3.9.6. Пример работы с данными производного типа
- •3.9.7. Структуры и записи
- •3.9.7.1. Объявление и присваивание значений
- •3.9.7.2. Создание объединений
- •3.9.8. Итоговые замечания
- •3.10. Целочисленные указатели
- •3.11. Ссылки и адресаты
- •3.11.1. Объявление ссылок и адресатов
- •3.11.2. Прикрепление ссылки к адресатам
- •3.11.3. Инициализация ссылки. Функция NULL
- •3.11.4. Явное открепление ссылки от адресата
- •3.11.5. Структуры со ссылками на себя
- •3.11.6. Ссылки как параметры процедур
- •3.11.7. Параметры с атрибутом TARGET
- •3.11.8. Ссылки как результат функции
- •4. Массивы
- •4.1. Объявление массива
- •4.2. Массивы нулевого размера
- •4.3. Одновременное объявление объектов разной формы
- •4.4. Элементы массива
- •4.5. Сечение массива
- •4.6. Присваивание массивов
- •4.7. Маскирование присваивания
- •4.7.1. Оператор и конструкция WHERE
- •4.7.2. Оператор и конструкция FORALL
- •4.8. Динамические массивы
- •4.8.1. Атрибуты POINTER и ALLOCATABLE
- •4.8.2. Операторы ALLOCATE и DEALLOCATE
- •4.8.3. Автоматические массивы
- •4.9. Массивы - формальные параметры процедур
- •4.9.1. Массивы заданной формы
- •4.9.2. Массивы, перенимающие форму
- •4.9.3. Массивы, перенимающие размер
- •4.10. Использование массивов
- •4.11. Массив как результат функции
- •4.12. Встроенные функции для массивов
- •4.12.1. Вычисления в массиве
- •4.12.2. Умножение векторов и матриц
- •4.12.3. Справочные функции для массивов
- •4.12.3.1. Статус размещаемого массива
- •4.12.3.2. Граница, форма и размер массива
- •4.12.4. Функции преобразования массивов
- •4.12.4.1. Элементная функция MERGE слияния массивов
- •4.12.4.2. Упаковка и распаковка массивов
- •4.12.4.3. Переформирование массива
- •4.12.4.4. Построение массива из копий исходного массива
- •4.12.4.5. Функции сдвига массива
- •4.12.4.6. Транспонирование матрицы
- •4.13. Ввод/вывод массива под управлением списка
- •4.13.1. Ввод/вывод одномерного массива
- •4.13.2. Ввод/вывод двумерного массива
- •5. Выражения, операции и присваивание
- •5.1. Арифметические выражения
- •5.1.1. Выполнение арифметических операций
- •5.1.2. Целочисленное деление
- •5.1.3. Ранг и типы арифметических операндов
- •5.1.4. Ошибки округления
- •5.2. Выражения отношения и логические выражения
- •5.3. Задаваемые операции
- •5.4. Приоритет выполнения операций
- •5.5. Константные выражения
- •5.6. Описательные выражения
- •5.7. Присваивание
- •6. Встроенные процедуры
- •6.1. Виды встроенных процедур
- •6.2. Обращение с ключевыми словами
- •6.3. Родовые и специфические имена
- •6.4. Возвращаемое функцией значение
- •6.5. Элементные функции преобразования типов данных
- •6.6. Элементные числовые функции
- •6.7. Вычисление максимума и минимума
- •6.8. Математические элементные функции
- •6.8.1. Экспоненциальная, логарифмическая функции и квадратный корень
- •6.8.2. Тригонометрические функции
- •6.9. Функции для массивов
- •6.10. Справочные функции для любых типов
- •6.11. Числовые справочные и преобразовывающие функции
- •6.11.1. Модели данных целого и вещественного типа
- •6.11.2. Числовые справочные функции
- •6.12. Элементные функции получения данных о компонентах представления вещественных чисел
- •6.13. Преобразования для параметра разновидности
- •6.14. Процедуры для работы с битами
- •6.14.1. Справочная функция BIT_SIZE
- •6.14.2. Элементные функции для работы с битами
- •6.14.3. Элементная подпрограмма MVBITS
- •6.14.4. Пример использования битовых функций
- •6.15. Символьные функции
- •6.16. Процедуры для работы с памятью
- •6.17. Проверка состояния "конец файла"
- •6.18. Неэлементные подпрограммы даты и времени
- •6.19. Случайные числа
- •6.20. Встроенная подпрограмма CPU_TIME
- •7. Управляющие операторы и конструкции
- •7.1. Оператор GOTO безусловного перехода
- •7.2. Оператор и конструкции IF
- •7.2.1. Условный логический оператор IF
- •7.2.2. Конструкция IF THEN END IF
- •7.2.3. Конструкция IF THEN ELSE END IF
- •7.2.4. Конструкция IF THEN ELSE IF
- •7.3. Конструкция SELECT CASE
- •7.4. DO-циклы. Операторы EXIT и CYCLE
- •7.5. Возможные замены циклов
- •7.6. Оператор STOP
- •7.7. Оператор PAUSE
- •8. Программные единицы
- •8.1. Общие понятия
- •8.2. Использование программных единиц в проекте
- •8.3. Работа с проектом в среде DS
- •8.4. Главная программа
- •8.5. Внешние процедуры
- •8.6. Внутренние процедуры
- •8.7. Модули
- •8.8. Оператор USE
- •8.9. Атрибуты PUBLIC и PRIVATE
- •8.10. Операторы заголовка процедур
- •8.10.1. Общие характеристики операторов заголовка процедур
- •8.10.2. Результирующая переменная функции
- •8.11. Параметры процедур
- •8.11.1. Соответствие фактических и формальных параметров
- •8.11.2. Вид связи параметра
- •8.11.3. Явные и неявные интерфейсы
- •8.11.4. Ключевые и необязательные параметры
- •8.11.5. Ограничения на фактические параметры
- •8.11.6. Запрещенные побочные эффекты
- •8.12. Перегрузка и родовые интерфейсы
- •8.12.1. Перегрузка процедур
- •8.12.2. Перегрузка операций и присваивания
- •8.12.3. Общий вид оператора INTERFACE
- •8.13. Ассоциирование имен
- •8.14. Область видимости имен
- •8.15. Область видимости меток
- •8.16. Ассоциирование памяти
- •8.16.1. Типы ассоциируемой памяти
- •8.16.2. Оператор COMMON
- •8.16.3. Программная единица BLOCK DATA
- •8.17. Рекурсивные процедуры
- •8.18. Формальные процедуры
- •8.18.1. Атрибут EXTERNAL
- •8.18.2. Атрибут INTRINSIC
- •8.19. Оператор RETURN выхода из процедуры
- •8.20. Оператор ENTRY дополнительного входа в процедуру
- •8.21. Атрибут AUTOMATIC
- •8.22. Атрибут SAVE
- •8.23. Атрибут STATIC
- •8.24. Атрибут VOLATILE
- •8.25. Чистые процедуры
- •8.26. Элементные процедуры
- •8.27. Операторные функции
- •8.28. Строка INCLUDE
- •8.29. Порядок операторов и директив
- •9. Форматный ввод/вывод
- •9.1. Преобразование данных. Оператор FORMAT
- •9.2. Программирование спецификации формата
- •9.3. Выражения в дескрипторах преобразований
- •9.4. Задание формата в операторах ввода/вывода
- •9.5. Списки ввода/вывода
- •9.5.1. Элементы списков ввода/вывода
- •9.5.2. Циклические списки ввода/вывода
- •9.5.3. Пример организации вывода
- •9.6. Согласование списка ввода/вывода и спецификации формата. Коэффициент повторения. Реверсия формата
- •9.7. Дескрипторы данных
- •9.8. Дескрипторы управления
- •9.9. Управляемый списком ввод/вывод
- •9.9.1. Управляемый именованным списком ввод/вывод
- •9.9.1.1. Объявление именованного списка
- •9.9.1.2. NAMELIST-вывод
- •9.9.1.3. NAMELIST-ввод
- •9.9.2. Управляемый неименованным списком ввод/вывод
- •9.9.2.1. Управляемый неименованным списком ввод
- •9.9.2.2. Управляемый неименованным списком вывод
- •10. Файлы Фортрана
- •10.1. Внешние и внутренние файлы
- •10.2. Позиция файла
- •10.3. Устройство ввода/вывода
- •10.4. Внутренние файлы
- •10.5. Внешние файлы
- •10.6. Записи
- •10.6.1. Типы записей
- •10.6.2. Записи фиксированной длины
- •10.6.3. Записи переменной длины
- •10.6.4. Сегментированные записи
- •10.6.5. Потоки
- •10.6.6. CR-потоки
- •10.6.7. LF-потоки
- •10.7. Передача данных с продвижением и без
- •10.8. Позиция файла перед передачей данных
- •10.9. Позиция файла после передачи данных
- •10.10. Двоичные последовательные файлы
- •10.11. Неформатные последовательные файлы
- •10.12. Текстовые последовательные файлы
- •10.13. Файлы, подсоединенные для прямого доступа
- •10.14. Удаление записей из файла с прямым доступом
- •10.15. Выбор типа файла
- •11. Операции над внешними файлами
- •11.1. Оператор BACKSPACE
- •11.2. Оператор REWIND
- •11.3. Оператор ENDFILE
- •11.4. Оператор OPEN
- •11.5. Оператор CLOSE
- •11.6. Оператор READ
- •11.7. Оператор ACCEPT
- •11.8. Оператор FIND
- •11.9. Оператор DELETE
- •11.10. Оператор UNLOCK
- •11.11. Оператор WRITE
- •11.12. Оператор PRINT
- •11.13. Оператор REWRITE
- •11.14. Оператор INQUIRE
- •11.15. Функция EOF
- •11.16. Организация быстрого ввода/вывода
- •12.1. Некоторые сведения об объектах ActiveX
- •12.2. Для чего нужен конструктор модулей
- •12.3. Интерфейсы процедур управления Автоматизацией
- •12.4. Идентификация объекта
- •12.5. Примеры работы с данными Автоматизации
- •12.5.1. OLE-массивы
- •12.5.2. BSTR-строки
- •12.5.3. Варианты
- •12.6. Другие источники информации
- •12.7. Как воспользоваться объектом ActiveX
- •12.8. Применение конструктора модулей
- •12.9. Пример вызова процедур, сгенерированных конструктором модулей
- •Приложение 1. Вывод русского текста в DOS-окно
- •Приложение 2. Нерекомендуемые, устаревшие и исключенные свойства Фортрана
- •П.-2.1. Нерекомендуемые свойства Фортрана
- •П.-2.1.1. Фиксированная форма записи исходного кода
- •П.-2.1.2. Оператор EQUIVALENCE
- •П.-2.1.3. Оператор ENTRY
- •П.-2.1.4. Вычисляемый GOTO
- •П.-2.1.5. Положение оператора DATA
- •П.-2.2. Устаревшие свойства Фортрана, определенные стандартом 1990 г.
- •П.-2.2.1. Арифметический IF
- •П.-2.2.2. Оператор ASSIGN присваивания меток
- •П.-2.2.3. Назначаемый GOTO
- •П.-2.2.4. Варианты DO-цикла
- •П.-2.2.5. Переход на END IF
- •П.-2.2.6. Альтернативный возврат
- •П.-2.2.7. Дескриптор формата H
- •П.-2.3. Устаревшие свойства Фортрана, определенные стандартом 1995 г.
- •П.-2.4. Исключенные свойства Фортрана
- •Приложение 3. Дополнительные процедуры
- •П.-3.1. Запуск программ
- •П.-3.2. Управление программой
- •П.-3.3. Работа с системой, дисками и директориями
- •П.-3.4. Управление файлами
- •П.-3.5. Генерация случайных чисел
- •П.-3.6. Управление датой и временем
- •П.-3.7. Ввод с клавиатуры и генерация звука
- •П.-3.8. Обработка ошибок
- •П.-3.9. Аргументы в командной строке
- •П.-3.10. Сортировка и поиск в массиве
- •П.-3.11. Управление операциями с плавающей точкой
- •Литература
- •Предметный указатель
- •Оглавление

10. Файлы Фортрана
Замечание. Файлы, подсоединенные для прямого доступа, мы будем, для сокращения, также называть прямыми файлами, а для последовательного доступа - последовательными.
Впоследовательных файлах существующие записи могут только читаться, но не могут редактироваться. Без потери информации новые записи добавляются только после последней записи файла. Попытка вывести запись до этой записи приведет к отсечению последующих записей
-их замене на добавляемую. Для изменения записи последовательного файла возможен такой путь: прочитать все записи файла в массив; изменить
внем нужную запись; перейти на начало файла и записать массив в файл.
Впрямых файлах доступ к записи выполняется по номеру записи, задавая который можно читать, добавлять, замещать или удалять запись. В этом и состоит основное отличие между последовательными и прямыми файлами. При включении спецификатора REC в операторы передачи данных и управления файлами прямой файл позиционируется вслед за указанной этим спецификатором записью.
Для внешних файлов справедливо:
•для обеспечения доступа файл должен быть открыт (подсоединен к устройству В/В);
•при открытии файла по умолчанию он позиционируется на первую запись файла или на "конец файла", если в файле нет ни одной записи;
•последней записью файла является специальная запись "конец файла".
10.6. Записи
10.6.1. Типы записей
Запись - |
это последовательность значений (в случае неформатных |
и двоичных |
файлов) или последовательность символов (в случае |
форматных файлов). Поле записи - часть записи, содержащая данные, которые могут быть использованы оператором ввода. Тип записи определяет способ хранения полей в пределах записи. Тип записи не сохраняется как атрибут файла. Однако применение с файлом типа записи, отличного от используемого при создании файла, может привести в некоторых случаях к непредсказуемым результатам.
Запись является текущей, если файл установлен внутри записи, в противном случае текущей записи нет.
Если опущена опция компилятора /fpscomp:ioformat, в CVF доступны следующие 6 типов записей:
1)фиксированной длины. Такие записи возможны в файлах и с последовательной и со связанной организацией;
2)переменной длины; возможны только в файлах с последовательной организацией;
331

О. В. Бартеньев. Современный ФОРТРАН
3)сегментированные; возможны только в файлах с последовательной организацией, открытых для неформатного последовательного доступа. Сегментированные файлы являются прерогативой CVF и не могут быть использованы другими платформами;
4)потоки без разделителей между записями; возможны только в файлах с последовательной организацией;
5)CR-потоки; используют CR (CHAR(13), carriage return) в качестве разделителя между записями; употребляются в файлах с последовательной организацией;
6)LF-потоки; используют CR и LF (CHAR(10), line feed) в качестве разделителей между записями; применяются в файлах с последовательной организацией.
10.6.2. Записи фиксированной длины
Записи фиксированной длины имеют приведенную на рис. 10.1 структуру.
Данные записи
< |
-------------------- Длина записи (RECL = recl) ---------------------- |
> |
|
Рис. 10.1. Структура записи фиксированной длины |
|
Записи фиксированной длины имеют связанные файлы и файлы с последовательной организацией, открытые для прямого доступа. Длина записи задается в операторе OPEN спецификатором RECL.
Пример:
type point |
|
|
real x, y |
|
|
end type point |
|
|
integer i |
|
|
type(point) :: pt1 = point(1.0, 1.0), pt2 = point(2.0, 2.0), pt3 = point(3.0, 3.0) |
|
|
open(1, file = 'a.txt', organization = 'sequential', access = 'direct', |
& |
|
form = 'formatted', recordtype = 'fixed', recl = 20) |
|
|
write(1, '(2f10.3)', rec = 1) pt1 |
! Заносим в файл 3 записи |
|
write(1, '(2f10.3)', rec = 2) pt2 |
! Спецификатор RECORDTYPE = 'FIXED' |
|
write(1, '(2f10.3)', rec = 3) pt3 |
! может быть опущен |
|
end |
|
|
Результат (состав файла a.txt):
1.000 1.000 2.000 2.000 3.000 3.000
Замечание. Пример справедлив только для CVF, поскольку в операторе OPEN FPS спецификатор ORGANIZATION появляться не может.
332

10. Файлы Фортрана
10.6.3. Записи переменной длины
Такие записи могут содержать произвольное число байт (не превышающее максимально возможное значение). Их структура отображена на рис. 10.2.
|
|
Данные записи |
|
|
|
|
|
|
|
4 |
<-------------------------- |
Длина записи --------------------------- |
> |
4 |
Рис. 10.2. Структура записи переменной длины
Записи переменной длины могут существовать только в файлах с последовательной организацией. Каждая запись обрамляется 4-байтовыми полями, содержащими длину записи и выполняющими контрольные функции. Хранимая в этих полях величина возвращается при использовании оператора READ с дескриптором управления Q (разд. 9.8). Прочитанное значение можно затем употребить для определения размера списка В/В.
В CVF файлы с записями переменной длины обычно не используются как текстовые файлы, для которых, как правило, задается спецификатор
RECORDTYPE = 'STREAM_LF'.
Пример:
integer recl
open(2, file = 'a.txt', recordtype = 'variable', form = 'unformatted') ! Заносим в файл 3 записи
write(2) 123, 555 |
! Длина записи 8 |
байт |
write(2) 'Next record' |
! Длина записи 11 байт |
|
write(2) 1.4e-6 |
! Длина записи 4 |
байта |
close(2) |
|
|
!Закрыли файл, чтобы открыть его для форматного доступа
!и прочитать длину второй записи
open(2, file = 'a.txt', recordtype = 'variable', form = 'formatted')
! Спецификатор FORM = 'FORMATTED' может быть опущен
read(2, '(a)') |
! Переход на начало второй записи |
read(2, '(Q)') recl |
! Читаем число байт в записи 2 |
print *, recl |
! 11 |
end |
|
10.6.4. Сегментированные записи
Сегментированные записи состоят из одной или более переменной длины неформатных записей в последовательно организованном дисковом файле. В FPS таких записей нет; в CVF по умолчанию неформатные данные записываются в файлы с последовательной организацией, открытые для последовательного доступа, в виде сегментированных записей. Они полезны при работе с длинными записями, в случаях, когда нет возможности (из-за ограничений по размеру виртуальной памяти) или желания формировать одну длинную запись. Тогда она разбивается на
333

О. В. Бартеньев. Современный ФОРТРАН
сегменты, которые и образуют результирующую запись. Каждый сегмент является физической записью, а результирующая запись рассматривается как единая логическая. Последняя (в случае дискового файла) может превышать максимально допустимый размер записи (2.14*109 байт), но каждый сегмент не должен быть больше этого размера.
Для доступа к сегментированному файлу задаются спецификаторы
FORM = 'UNFORMATTED' и RECORDTYPE = 'SEGMENTED'. Если они не заданы и открывается ранее созданный сегментированный файл, то работа с ним может сопровождаться ошибками. Структура сегментированной записи представлена на рис. 10.3.
|
|
|
Данные сегмента |
|
|
|
|
|
|
2 |
2 |
< |
------------------------- Длина сегмента ------------------------- |
> |
|
|
|
|
|
Рис. 10.3. Структура сегментированной записи
Контрольная информация, предваряющая запись, содержит 4 байта. Первые два содержат длину сегмента, два последующих - идентификатор сегмента, принимающий значения:
•1 в случае первого сегмента;
•2 в случае последнего;
•3 при наличии одного сегмента;
•0 для всех промежуточных (между первым и последним) сегментов.
Если длина сегмента - нечетное число, то пользовательские данные будут увеличены на 1 байт, содержащий пробел.
10.6.5. Потоки
Поток не группируется в записи и не содержит контрольной информации. Файлы-потоки применяются с CARRIAGECONTROL = 'NONE' и содержат символьные или двоичные данные. Передаваемая порция данных и позиция файла определяются размером списка В/В. Структура потока дана на рис. 10.4.
Данные потока |
EOF |
|
|
Рис. 10.4. Поток
10.6.6. CR-потоки
Записи CR-потока имеют переменную длину и завершаются символом возврата каретки, который автоматически проставляется при добавлении записи в файл-поток и удаляется при ее чтении. Именно этот символ и позволяет определить длину текущей записи. Поскольку CR-потоки завершаются символом CHAR(13), в вводимых записях этот символ должен отсутствовать. Структура записи CR-потока изображена на рис. 10.5.
334