01 (537404), страница 9
Текст из файла (страница 9)
запись A(k+1.3) при k = 3 идентична A(4);
запись A(B+2) при B = 3.62 идентична A(5).
В отличие от простой переменной, которая предназначена для хранения одной величины, массив позволяет хранить множество величин. Поэтому в программе обязательно должно быть оговорено их количество. Эту функцию выполняет оператор Dimension, который, как оператор описания, должен располагаться в начале программы – перед выполняемыми операторами. Он имеет вид
Dimension список ,
где список содержит имена массивов вместе с границами их индексов, за ключенными в скобках и разделенными запятыми. Имена массивов также разделяются запятыми.
Если значение границы индекса указано в форме целой положительной константы, то оно определяет наибольшее значение данного индекса. При этом наименьшее значение по умолчанию принимается равным единице. Допускается устанавливать значение нижней границы индекса отличное от единицы. В этом случае указываются обе границы индекса, разделенные символом ":". Например, оператор
Dimension A(3), B(-1:1)
описывает два вещественных массива с именами A и B, каждый из которых состоит из трех элементов. Разница между ними состоит в том, что элементы первого массива имеют имена A(1), A(2), A(3), а второго - B(-1), B(0) и B(1).
Оператор Dimension подразумевает, что тип массива определяется по первой букве его имени. Если требуется явное определение типа массива, то вместо оператора Dimension должны использоваться операторы описания типов Integer или Real. Например, операторы
Integer A(4)
Real Num(-2:2), L(0:2, 3)
описывают целый одномерный массив A из четырех элементов, одномерный вещественный массив Num из пяти элементов и двумерный вещественный массив L из девяти элементов.
Элементы массивов хранятся в памяти ЭВМ с последовательно возрастающими адресами. Так массив A(4) располагается в памяти следующим образом:
A(1) A(2) A(3) A(4) .
Многомерные массивы располагаются в памяти таким образом, что значения первого индекса возрастают быстрее значений второго, значения второго - быстрее значения третьего и так далее. Например, элементы двумерного вещественного массива L располагаются в следующем порядке
L(0,1) L(1,1) L(2,1) L(0,2) L(1,2) L(2,2) L(0,3) L(1,3) L(2,3)
Если массив L представить в виде матрицы
то такой порядок следования элементов в памяти ЭВМ соответствует размещению их по столбцам.
Ввод-вывод массивов осуществляется с помощью операторов Read и Write по тем же правилам, что и для простых переменных. Например, оператор
Read(*, *) A
считывает информацию в каждый элемент массива A, поэтому количество вводимых данных должно быть равно количеству его элементов, заданных при его описании. Так как константы будут вводиться последовательно, то их ввод надо осуществлять в соответствии с расположением элементов массива в памяти ЭВМ. Например, для двумерного массива - по столбцам.
В случае, когда требуется ввести не все элементы массива или изменить последовательность их ввода, необходимо использовать либо оператор цикла, либо специальную форму оператора Read с неявным циклом. Например, ввод двумерного массива L построчно, в традиционно принятом в математике виде, с помощью операторов цикла может быть организован следующим образом:
123456789...........................................................72 73.......80
Dimension L(0:2, 3)
Do i = 0, 2
Do j = 1, 3
Read(*, *) L(i, j)
EndDo
EndDo
....
Общая форма неявного цикла в операторах ввода-вывода имеет вид
(имя_массива(переменная)[,...], переменная = начало, конец [, шаг])
где переменная – переменная цикла (обязательно целого типа);
начало и конец – выражения целого типа, определяющие начальное и конечное значения переменной цикла, соответственно;
шаг – выражение целого типа, задающее шаг изменения значения переменной цикла. Шаг может отсутствовать, тогда он принимается равным 1.
Эта форма содержит все элементы оператора цикла, но есть и свои особенности:
-
в неявном цикле отсутствует ключевое слово Do;
-
тело цикла состоит из списка имен массивов, к элементам которых осуществляется последовательное обращение;
-
допускается использование вложенных неявных циклов по общим правилам организации циклов.
Тогда ввод двумерного массива L может быть организован в виде:
123456789............................................................72 73.......80
Dimension L(0:2, 3)
.......
Read(*, *) ((L(i, j), j = 1, 3), i = 0, 2)
.......
Операции вывода значений элементов массивов организуются с помощью оператора Write аналогичным образом.
Работа с массивами может быть проиллюстрирована следующим примером. Имеются результаты замеров проходного сечения 45-ти жиклеров. Определить среднее арифметическое значение результатов этих замеров. Эти значения r1, r2, ..., r45 удобно хранить в виде массива R(1), R(2), , ..., R(45). Тогда формула для вычисления среднего арифметического значений проходного сечения
может быть представлена в программе оператором Rcp = Rsum/45 , где Rsum есть результат накопления суммы значений элементов массива R. Предполагается, что результаты замеров записаны в файл с именем prog.dat в форме, представленной ниже
1 строка
2 строка
3 строка
4 строка
5 строка
6 строка
7 строка
8 строка
9 строка
123456789.123456789.123456789.1..80
Результаты замеров [мм]:
1.48 1.51 1.50 1.49 1.48 1.49
1.49 1.50 1.50 1.49 1.52 1.51
1.51 1.51 1.52 1.50 1.48 1.52
1.48 1.51 1.50 1.49 1.48 1.51
1.49 1.50 1.50 1.49 1.52 1.50
1.51 1.51 1.52 1.50 1.48 1.48
1.48 1.51 1.50 1.49 1.48 1.49
1.49 1.50 1.50
Результаты замеров [мм]:
1.48 1.51 1.50 1.49 1.48
1.49 1.49 1.50 1.50 1.49
1.52 1.51 1.51 1.51 1.52
1.50 1.48 1.52 1.48 1.51
1.50 1.49 1.48 1.51 1.49
1.50 1.50 1.49 1.52 1.50
1.51 1.51 1.52 1.50 1.48
1.48 1.48 1.51 1.50 1.49
1.48 1.49 1.49 1.50 1.50
Среднее значение Rср=1.498
Результат работы программы должен быть помещен в файл prog.res в виде
1 строка
2 строка
3 строка
4 строка
5 строка
6 строка
7 строка
8 строка
9 строка
10 строка
11 строка
123456789.123456789.123456789.1..80Программа решения этой задачи имеет вид:
123456789............................................................72 73.......80
Dimension R(45)
Open(1, File = 'prog.dat')
Open(2, File = 'prog.res')
Read(1, 1) (R(i), i = 1, 45)
1 Format(/(6F5.2))
Write(2, 2) (R(i), i = 1, 45)
2 Format(5X, 'Результаты замеров [мм]:'/(5F6.2))
Rsum = 0.0
Do i = 1, 45
Rsum = Rsum + R(i)
EndDo
Rcp = Rsum/45.
Write(2, 3) Rcp
3 Format(T3, 'Среднее значение Rcp = ', F5.3)
Close(1)
Close(2)
End
При решении ряда задач невозможно заранее прогнозировать размеры массивов, используемых для хранения информации. Вышеописанный способ использования массивов в программах требует указания в операторе Dimension его максимальных (фиксированных) размеров, а потому неэффективен. Фортран предоставляет возможность организовать динамическое изменение размера массива.
Динамическое изменение размера массива осуществляется с помощью операторов Allocate и DeAllocate. Массив с динамически изменяемыми границами описывается в начале программы перед выполняемыми операторами специальным образом с атрибутом Allocatable и указанием вместо максимальных значений индексов символа ":". Например:
123456789..............................................................72 73.......80
Dimension Data [Allocatable] (:,:)
Real Long [Allocatable] (:)
.................
Для выделения требуемого размера памяти ЭВМ под массивы с динамически изменяющимися размерами и установки верхней и нижней границ его индексов используется оператор Allocate. Общая форма оператора имеет вид:
Allocate (имя_массива([n:] k [, ...]) [, ...] [, Stat = err])
где n, k | – целые выражения, устанавливающие нижнюю и верхнюю границы индексов массива; |
err | – целая переменная, которая возвращает код ошибки при распределении памяти. |
В операторе Allocate можно определять несколько массивов, разделяя их через запятую. Параметр "Stat =" указывается один раз в конце оператора. Любая неудача размещения массивов вызовет ошибку выполнения, которая отмечается в параметре "Stat =", и переменная err принимает ненулевое значение.
Освобождение памяти, которое занимал динамически распределенный массив, осуществляется оператором DeAllocate, записываемым в виде:
DeAllocate(список [, Stat = err])
где список – список динамических массивов, организованных с помощью оператора Allocate, в котором имена массивов отделяются запятыми.
Параметр "Stat =" выполняет ту же функцию, что и в операторе Allocate, и должен быть последним. Переменная err принимает значение нуль, если освобождение памяти прошло успешно.
Использование динамически размещаемых массивов может быть проиллюстрировано на предыдущем примере, когда количество результатов замеров проходного сечения жиклеров заранее неизвестно. При создании такой программы необходимо ввести дополнительную целую переменную, значение которой будет определять количество проведенных замеров. В этом случае программа будет иметь вид
123456789..............................................................72 73.......80
Dimension R [Allocatable] (:)
Open(1, File = 'prog.dat')
Open(2, File = 'prog.res')
Write(*, 10)
10 Format(' Введите количество замеров N = '\)
Read(*, *) N
Allocate (R(N), Stat = Ierr)
If (Ierr.NE.0) Stop 'Нет памяти под массив R.'
Read(1, 1) (R(i), i = 1, N)
1 Format(/(6F6.2))
Write(2, 2) (R(i), i = 1, N)
2 Format(5X, 'Результаты замеров [мм]:'/(5F6.2))
Rsum = 0.0
Do i = 1, N
Rsum = Rsum + R(i)
EndDo
Rcp = Rsum/N
Write(2, 3) Rcp
3 Format(/T3, 'Среднее значение Rcp = ', F5.3)
Close(1)
Close(2)
DeAllocate(R)
Stop
End
З а д а н и е к л а б о р а т о р н о й р а б о т е
Составить программу решения следующих задач. Исходные данные вводить из файла prog_6.dat и результаты выводить в файл prog_6.res.
1. Вычислить суммы столбцов двумерного массива А размерностью 46. Результат представить в виде одномерного массива В.
2. Определить положительные четные значения в целочисленном двумерном массиве С (36 элементов) и записать сумму их индексов в одномерный массив D.
3. Вычислить отдельно суммы и произведения положительных и отрицательных элементов массива А (35 элементов) и записать результат в массив В из 4-х элементов.
4. Составить программу поиска максимальных элементов столбцов массива A (55 элементов). Результат записать в одномерный массив В.
5. Вычислить количество положительных элементов в целочисленном массиве М (34 элементов), значения которых не превышают 17, и записать их в одномерный массив В.
6. Определить четные отрицательные значения в целочисленном массиве N (53 элементов) и переписать их в одномерный массив D.
7. Определить количество отрицательных элементов, расположенных выше главной диагонали матрицы {aij} (i,j=1,5), значение которых больше -10 и записать их в одномерный массив С.
8. Определить три минимальных значения в массиве D (33 элементов) и записать их в одномерный массив F.
9. Преобразовать одномерный массив S из 15-ти элементов в двумерный – G (53 элементов) по столбцам.
10. Найти суммы значений элементов в столбцах верхнего треугольника матрицы {aij} (i,j=1,5) и записать их в одномерный массив Т.
11. Реорганизовать двумерный массив А (45 элементов) в одномерный массив D по строкам.
12. Сформировать одномерный массив X, значениями элементов которого являются минимальные значения элементов строк массива Н (55).
13. Найти три самых больших значения двумерного массива R (38 элементов) и записать суммы их индексов в одномерный массив P.
14. Составить программу вычисления суммы элементов строк матрицы {aij} (i,j=1,4), для которых выполняется условие 0,5 < aij < 2,5 и записать их в одномерный массив W.
15. Написать программу для определения количества четных положительных значений, расположенных выше побочной диагонали целочисленной матрицы {aij} (i,j=1,5), и записать их в одномерный массив В.
16. Определить количество отрицательных значений среди четных элементов строк массива F (36) и записать их в одномерный массив.
17. Заполнить по столбцам двумерный массив В (55 элементов) выше главной диагонали значениями из одномерного массива С, содержащего 10 элементов.