
- •Предисловие
- •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. Управление операциями с плавающей точкой
- •Литература
- •Предметный указатель
- •Оглавление

4. Массивы
При объявлении массива помимо задающих динамические массивы атрибутов ALLOCATABLE и POINTER и атрибута задания формы массива DIMENSION могут быть использованы атрибуты INTENT, OPTIONAL, PARAMETER, PRIVATE, PUBLIC, SAVE и TARGET.
4.2. Массивы нулевого размера
Массив, как, впрочем, и строка, может иметь нулевой размер. Всегда, когда нижняя граница превосходит соответствующую верхнюю границу, массив имеет размер 0. Например:
real b2(0, 15), d(5, 20, 1:-1) |
|
|
|
print *, size(b2), size(d) |
! |
0 |
0 |
Массивы нулевого размера всегда считаются определенными и при использовании подчиняются обычным правилам.
4.3. Одновременное объявление объектов разной формы
При необходимости можно одним оператором объявлять объекты разной формы. Так, оператор
real, dimension(10) :: a, b, b2(15), d(5, 20)
объявляет массивы a и b формы (10), массив b2 формы (15) и массив d формы (5, 20). То есть приоритетом при использовании атрибута DIMENSION обладает явное описание формы массива.
Оператор
integer na, nb, a(10), d(5, 20)
объявляет скаляры na и nb и массивы a и d разной формы.
4.4. Элементы массива
В этом разделе мы обобщим понятие элемента массива. Массив может содержать элементы встроенных и производных типов данных:
type order |
! Описание заказа |
integer ordnum, cus_id |
|
character(15) |
item(10) |
end type
! Примеры массивов символьного и производного типа
character(20) st(10) /10*'T-strings'/ |
! st - массив строк |
type(order) cord, orders(100) |
! orders - массив заказов |
Приведенные описания определяют массивы st, orders, cord%item и orders(k)%item (k - целое и 0 ≤ k ≤ 100). Элементы массивов являются скалярами.
Примеры элементов массивов:
st(7), orders(15), cord%item(7), orders(10)%item(8)
113

О. В. Бартеньев. Современный ФОРТРАН
Из символьного массива можно извлечь еще один объект данных - подстроку, например:
print *, st(7)(1:6) ! T-stri
или
character(15) itord
orders = order( 2000, 455, (/ ('Item', k = 1, 10) /) )
itord = orders(10)%item(8) |
|
print *, itord(3:4) |
! em |
Однако содержащаяся в символьном массиве подстрока по соглашению не рассматривается как элемент массива.
В общем случае элемент массива - это скаляр вида
частный указатель [%частный указатель...]
где частный указатель есть
частное имя [(список индексов)]
Если частный указатель является именем массива, то он обязан иметь список индексов, например orders(10)%item(8). Число индексов в каждом списке индексов должно равняться рангу массива или массива - компонента производного типа. Каждый индекс должен быть целым скалярным выражением, значение которого лежит в пределах соответствующих границ массива или массива-компонента.
4.5. Сечение массива
Получить доступ можно не только к отдельному элементу массива, но и к некоторому подмножеству его элементов. Такое подмножество элементов массива называется сечением массива. Сечение массива может быть получено в результате применения индексного триплета или векторного индекса, которые при задании сечения подставляются вместо одного из индексов массива.
Индексный триплет имеет вид:
[нижняя граница] : [верхняя граница] [:шаг]
Каждый из параметров триплета является целочисленным выражением. Шаг изменения индексов может быть и положительным и отрицательным, но не может равняться нулю. Все параметры триплета являются необязательными.
Индексный триплет задает последовательность индексов, в которой первый элемент равен его нижней границе, а каждый последующий больше (меньше) предыдущего на величину шага. В последовательности находятся все задаваемые таким правилом значения индекса, лежащие между границами триплета. Если же нижняя граница больше верхней и шаг
114

4. Массивы
положителен или нижняя граница меньше верхней и шаг отрицателен, то последовательность является пустой.
Пример:
real a(1:10) |
|
a(3:7:2) = 3.0 |
! Триплет задает сечение массива с элементами |
|
! a(3), a(5), a(7), которые получат значение 3.0 |
a(7:3:-2) = 3.0 |
! Элементы a(7), a(5), a(3) получат значение 3.0 |
При отсутствии нижней (верхней) границы триплета ее значение принимается равным значению нижней (верхней) границы соответствующего экстента массива. Так, a(1:5:2) и a(:5:2) задают одно и то же сечение массива a, состоящее из элементов a(1), a(3), a(5). Сечение из элементов a(2), a(5), a(8) может быть задано так: a(2:10:3) или a(2::3).
Пример:
real a(10), r /4.5/ |
! Элементы a(2), a(5), a(8) получат значение 4.0 |
a(2::3) = 4.0 |
|
a(7:9) = 5.0 |
! Элементы a(7), a(8), a(9) получат значение 5.0 |
a(:) = 3.0 |
! Все элементы массива получат значение 3.0 |
a(::3) = 3.0 |
! Сечение из элементов a(1), a(4), a(7), a(10) |
a(::int(r / 2)) = 3.0 |
! Параметр триплекса - целочисленное выражение |
print *, size(a(4:3)) |
! 0 (сечение нулевого размера) |
|
! Функция SIZE возвращает размер массива |
Нижняя граница триплета не может быть меньше нижней границы соответствующего экстента массива. Так, ошибочно задание сечения a(-2:5:3) в массиве a(1:10). Верхняя граница триплета должна быть такой, чтобы последний элемент задаваемой триплетом последовательности не превышал верхней границы соответствующего экстента массива. Например, в массиве a(1:10) допустимо сечение a(3:12:5). Верхняя граница триплета всегда должна присутствовать при использовании триплета в последней размерности перенимающего размер массива (разд. 4.9.3).
В случае многомерного массива сечение может быть задано посредством подстановки индексного триплета (впрочем, так же, как и векторного индекса) вместо одного или нескольких индексов, например:
real a(8, 3, 5) a(1:4:2, 2:3, 4) = 4.0
В заданном сечении в первом измерении индекс может принимать значения 1 и 3, во втором - 2 и 3, а в третьем - только 4. Таким образом, сечение обеспечивает доступ к элементам a(1, 2, 4), a(1, 3, 4), a(2, 2, 4) и a(2, 3, 4). Поскольку в третьем измерении сечения индекс фиксирован, то сечение является двумерным массивом с формой (2, 2).
115

О. В. Бартеньев. Современный ФОРТРАН
Частными случаями сечений двумерного массива являются его строки и столбцы, например:
integer a(5, 8) |
|
a(3, :) = 3 |
! Сечение - третья строка матрицы |
a(:, 4) = 7 |
! Сечение - четвертый столбец матрицы |
Пример. В какой строке матрицы чаще встречается заданное число k.
integer, parameter :: m = 3, n = 5 integer :: a(m, n), b(m), i, k = 2, km(1)
a = reshape((/ |
1, |
2, |
2, |
4, |
3, |
& |
|
2, |
4, |
2, |
8, |
2, |
& |
|
-2, |
2, |
6, |
2, |
2 |
/), shape = (/m, n/), order = (/2, 1/)) |
do i = 1, m
b(i) = count(a(i, :) == k) end do
km = maxloc(b)
print *, 'Строки в которых k = ', k, ' входит наибольшее число раз' do i = 1, m
if(b(i) == b(km(1))) print *, 'Строка ', i end do
end
Замечание. Массив b можно сформировать, не применяя цикла:
b = count(a == k, 2) |
! Функция COUNT рассмотрена в разд. 4.12.1. |
Векторный индекс является одномерным целочисленным массивом, содержащим значения индексов, попадающих в сечение исходного массива, например:
real a(20), b(10, 10) |
! vi, vj - целочисленные массивы; |
integer :: vi(3), vj(2) |
|
vi= (/1, 5, 7/) |
! используются как векторные индексы |
vj= (/2, 7/) |
! для задания сечений массивов a и b |
a(vi) = 3.0 |
! a(1), a(5), a(7) получат значение 3.0 |
b(2, vj) = 4.0 |
! b(2, 2), b(2, 7) - значение 4.0 |
b(vi, vj) = 5.0 |
! b(1, 2), b(1, 7), b(5, 2), b(5, 7), |
|
! b(7, 2) и b(7, 2) - значение 5.0 |
Векторный индекс в отличие от индексного триплета позволяет извлечь в сечение произвольное подмножество элементов массива. Значения индексов должны находиться в пределах границ соответствующей размерности исходного массива. Значения индексов в векторном индексе могут располагаться в произвольном порядке и могут повторяться. Например:
real a(10, 8) /80 * 3.0/, b(5) b = a(3, (/5, 3, 2, 7, 2/))
116

4. Массивы
В массив b попадут значения элементов сечения массива a: a(3, 5), a(3, 3), a(3, 2), a(3, 7) и вновь a(3, 5).
Сечения с повторяющимися значениями индексов не могут появляться в правой части оператора присваивания и в списке ввода оператора READ. Например, присваивание
real a(10)
a(/5, 3, 2, 7, 2/) = (/1.2 , 1.3, 1.4, 1.5, -1.6/)
недопустимо, поскольку 1.4 и -1.6 не могут одновременно храниться в a(2). Размер сечения равен нулю, если векторный индекс имеет нулевой
размер.
Сечение массива с векторным индексом не может быть внутренним файлом, адресатом ссылки. Если сечение массива с векторным индексом является фактическим параметром процедуры, то оно рассматривается как выражение и соответствующий формальный параметр должен иметь вид связи INTENT(IN). При использовании заданного векторным индексом сечения в качестве фактического параметра в процедуре создается копия этого сечения, которую и адресует соответствующий формальный параметр.
Сечение массива (заданное индексным триплетом или векторным индексом) сохраняет большинство свойств массива и может быть, в частности, использовано в качестве параметра встроенных функций для массивов, элементных и справочных функций и пользовательских процедур.
Пример. Найти сумму положительных элементов главной диагонали квадратной матрицы.
integer, parameter :: n = 10 |
|
|
integer :: a(n, n) /100 * 3.0/, i |
|
|
integer :: b(n * n) |
|
|
integer :: v(n) = (/ (i + n * (i - 1), i = 1, n) /) |
|
|
a(9, 9) = -1 |
! v - векторный индекс, содержащий |
|
b=reshape(a, shape = (/100/)) |
! номера элементов главной диагонали |
|
|
! массива a; b(v) - сечение массива b |
|
print *, sum(b(v), mask=b(v)>0) |
! |
27 |
Использование сечений позволяет более эффективно решать задачи, для которых раньше применялись DO-циклы (разд. 7.5).
Пример. Поменять порядок следования элементов массива. integer :: i, a(10) = (/ (i, i = 1, 10) /)
a = a(10:1:-1) |
|
print '(10i3)', a |
! 10 9 8 7 6 5 4 3 2 1 |
Сечение, помимо рассмотренных случаев, может быть взято у массивов производных типов, а также содержать массивы - компоненты структур и подстроки символьных массивов. Общий вид сечения массива:
117

О. В. Бартеньев. Современный ФОРТРАН
частный указатель [%частный указатель ...] ... [(диапазон подстроки)]
где частный указатель есть
частное имя [(список индексов сечения)]
Число индексов сечения в каждом списке должно равняться рангу массива или массива - компонента структуры. Каждый индекс сечения
должен быть либо индексом, либо индексным триплетом, либо векторным индексом, например:
real a(8, 5, 5)
a(4, 1:4:2, (/2, 5/)) = 4.0 ! 4 - индекс; 1:4:2 - индексный триплет; ! (/2, 5/)) - векторный индекс
Частный указатель ненулевого ранга определяет ранг и форму сечения. Размер сечения равен нулю, если хотя бы один из экстентов частного указателя равен нулю.
Диапазон подстроки может присутствовать, только если последний частный указатель относится к символьному типу и является скаляром или имеет список индексов сечения.
Пример сечения, состоящего из подстрок массива: character(len = 20) st(10) /10*'Test String'/
print *, st((/1, 3, 10/))(5:8) |
! Str Str Str |
print *, st(2:6:2)(5:8) |
! Str Str Str |
Сечение массива, имя которого заканчивается именем компонента структуры, также является компонентом структуры.
Пример сечений, содержащих массивы - компоненты структур:
type order |
! Описание заказа: |
integer(4) ordnum, cus_id |
! номер заказа, код покупателя |
character(15) item(10) |
! список вещей заказа |
end type |
! ords - массив заказов |
type(order) cord, ords(100) |
|
cord%item(2:6) = 'dress' |
|
ords(5:7:2)%item(7) = 'tie' |
|
ords(9)%item((/1, 8, 9/)) = 'blazer' |
|
ords(9)%item((/8, 9/))(8:9) = '20' |
! dress tie |
print *, cord%item(3), ords(5)%item(7) |
|
print *, ords(9)%item(1), ords(9)%item(8) |
! blazer blazer 20 |
Образуемое из массивов - компонентов структур сечение не может содержать более одного нескалярного объекта. Так, попытка создать сечение вида
ords(5:7:2)%item((/ 1, 8, 9 /)) = 'none'
вызовет ошибку компиляции.
Частное имя справа от частного указателя не должно иметь атрибут POINTER. Так, нельзя задать сечение list(1:15:2)%ival в таком примере:
118