Вычисление суммы целых чисел от 1 до N в вариантах с предусловием и постусловием представлено в примерах 3.72 и 3.73. Прекращение работы цикла осуществляется оператором EXIT.
Пример 3.72. Вычисление суммы целых чиселв цикле с предусловием program SUMN4
integer :: SUM = 0, I=0 !Инициализация суммы и переменной цикла read*, N
do
if (I == N) exit I=I+1
SUM = SUM + I end do
print *, “SUM=”, SUM end
Пример 3.73. Вычисление суммы целых чиселв цикле с постусловием program SUMN5
integer :: SUM = 0, I=0 !Инициализация суммы и переменной цикла read*, N
do
I=I+1
SUM = SUM + I if (I == N) exit
end do
print *, “SUM=”, SUM end
Действие оператора CYCLE можно наблюдать (пример 3.74) при селекции (отборе) и выводе на экран только четных чисел из диапазона от единицы до N. Если на очередной итерации переменная цикла I будет иметь нечетное значение, то оператор CYCLE сразу передает управление на END DO, минуя оператор PRINT и тем самым игнорируя печать нечетных чисел.
Пример 3.74. Печать четных чисел в диапазоне от 1 до N
Program EVENPRINT read*, N
do I = 1, N
if (I / 2 * 2 /= I) cycle print *, I
end do end
181
Обзор циклических конструкций Фортрана и их возможностей будет не полным без упоминания о работе с массивами – это одно из наиболее частых применений циклов. В качестве иллюстраций рассмотрим поиск максимального элемента в одномерном массиве (пример 3.75) и транспонирование двумерной квадратной матрицы размером с экстентами равными N (пример 3.76).
Пример 3.75. Поиск максимального элемента в одномерном массиве program ARRMAX
integer, parameter :: N = 5
integer, parameter, dimension(N):: ARR = (/ 1, 4, 5, 2, 3/)
MX = ARR(N – 1) ! Разгонное значение для максимального элемента do I = 1, N
if( ARR(I) > ARR(MX)) MX = ARR(I) end do
print*, NUMAX end
На роль максимального элемента в одномерном массиве (см. пример 3.75) сначала назначается любой элемент массива, например предпоследний (с номером N – 1). Затем назначенное максимальное значение MX поочередно сравнивается со всеми остальными элементами массива в цикле, перебирающем номера элементов. Если на очередной итерации цикла найдется элемент массива больший MX, то в переменную MX запишется новый максимум. Таким образом, по завершении цикла в переменной MX зафиксируется значение максимального элемента массива.
Транспонирование квадратной матрицы (N строк и N столбцов) заключается в том, чтобы поменять местами строки и столбцы матрицы – первая строка должна стать первым столбцом, вторая строка – вторым столбцом – и так вплоть до последней строки. Для хранения такой матрицы потребуется массив ранга два (двумерный массив) с экстентами (протяженностями по каждому измерению), равными N. Исходная и транспонированная матрицы хранятся в разных массивах: M – исходная матрица, T – транспонированная матрица (см. пример 3.76). Матрица M инициализируется специализированным конструктором одномерных массивов (см. пример 3.23), переформатированным функцией RESHAPE (см. пример 3.28). Для работы с двумерными матрицами, в частности для их транспонирования, обычно используется конструкция из двух вло-
182
женных циклов: внешний цикл осуществляет последовательный перебор строк, а внутренний – перебор столбцов. Сама процедура транспонирования заключается в перекрестном изменении номеров строк и номеров столбцов, т.е. индекс I, являющийся номером строки в матрице M, становится номером столбца в матрице T, и наоборот. Последующие циклы используются для вывода на экран исходной и транспонированной матрицы.
В примере 3.76 применена конструкция из двух вложенных циклов. В общем случае в Фортране допускается произвольная вложенность циклов, при этом пересечение циклов недопустимо.
Пример 3.76. Транспонирование квадратной матрицы program TSPMATR
integer , parameter ::N=2
integer, dimension(N, N) :: M=RESHAPE( (/( I, I = 1, N*N)/), (/N, N/) ), T do I = 1, N
do J = 1, N
T (J, I) = M (I, J) end do
end do
print*, “Матрица М” do I = 1, N
print*, (M(I, J), J = 1, N) end do
print*, “Матрица Т” do I = 1, N
print*, (T(I, J), J = 1, N) end do
end
3.5.4. Оператор GO TO
Большинство критиков Фортрана внушают своим слушателям, что программы на этом языке состоят сплошь из операторов с метками и безусловных переходов GO TO между ними. Читатель, ознакомленный с предыдущим материалом, может по достоинству оценить подобных «специалистов» с их представлениями о Фортране, соответствующими 60-м годам прошлого столетия. При программировании на современных языках высокого уровня (с высоким уровнем абстракции данных) скачкообразные переходы между
183
блоками программы используются крайне редко, можно сказать только в экстренных случаях, но все-таки они необходимы.
В Фортране 90/95 оператор GO TO или (GOTO) имеет вид:
GO TO метка
где метка – метка оператора, соответствующая правилам записи программы в свободном формате (см. п. 3.1.4, примеры 3.13 и 3.14).
Один из немногих случаев, в которых необходим GO TO, – это выход из внутреннего цикла в конструкции из нескольких вложенных циклов. Например, при обнаружении искомого элемента в многомерном массиве CUBE следует прекратить поиск, что означает выход из структуры вложенных циклов (пример 3.77).
Пример 3.77. Поиск элемента в трехмерном массиве program FINDELM
integer , parameter ::N=3
integer, dimension(N, N, N):: CUBE=RESHAPE((/( I, I = 1, N*N*N)/), (/N, N, N/)) read*, ELM !Введите целое число от 1 до 27
do I = 1, N
do J = 1, N
do K = 1, N
if (CUBE(I, J, K) .eq. ELM) goto 10 enddo
enddo enddo
10 continue print*, I, J, K end
Оператор EXIT позволяет выйти только из внутреннего цикла в предшествующий цикл, поэтому в данном случае логично воспользоваться оператором GO TO.
3.6.ВВОД/ВЫВОД ДАННЫХ
3.6.1.Простейшие операции ввода/вывода
Любая работающая программа преобразует исходные данные в конечный результат. Исходные данные считываются из файлов,
184
ассоциированных с внешними устройствами, а затем обрабатываются и записываются в другие внешние файлы. В Фортране каждое устройство и файл, с которым взаимодействует программа, в смысле ввода/вывода имеет идентификационный номер. Например, номер стандартного устройства ввода – клавиатуры, обычно «5», а номер стандартного устройства вывода – экрана монитора, обычно «6». Для устройства ввода/вывода по умолчанию в качестве номера используется «*» – символ «звездочка». Обычно устройствами ввода/вывода по умолчанию являются экран и клавиатура, хотя в зависимости от настроек вычислительной системы такими устройствами может оказаться все, что угодно – от пылесоса до крылатой ракеты, если они управляются данным компьютером.
Для ввода данных в Фортране предусмотрен оператор READ, а для вывода – оператор WRITE. Для вывода данных на стандартное устройство чаще используется оператор PRINT, поскольку формат его записи предполагает, что устройство вывода предопределено.
Входные и выходные данные всегда имеют определенный вид или формат представления. Для правильного восприятия информации, как человеком, так и компьютером, имеет значение, представлены ли целые переменные со значениями «один», «два» и «три» на экран в виде «123» или «1^^2^^3» (через пробелы). Поскольку при написании программы внимание разработчика чаще всего сосредоточено на правильной реализации вычислительного алгоритма, то для ввода/вывода данных предусмотрен формат по умолчанию, обозначаемый «*» (звездочкой).
Таким образом, умолчание в отношении ввода/вывода данных, подразумевает соглашение относительно стандартного устройства и формата ввода и вывода данных – именно этот вариант ввода/вывода используется в большинстве примеров программ данного учебного пособия. Соответствующие операторы Фортрана приведены в табл. 3.8.
Таблица 3.8. Варианты операторов ввода/вывода под управлением списка
Оператор |
|
Действие |
READ (*,*) список ввода |
|
Ввод с клавиатуры |
READ *, список ввода |
|
Ввод с клавиатуры |
WRITE (*,*) список вывода |
|
Вывод на экран |
PRINT *, список вывода |
|
Вывод на экран |
|
185 |
|