Обратная связь
|
Размещение массива в памяти компьютера Говоря о размещении массива в памяти, следует прояснить:
- какой объем памяти требуется;
- в каком порядке элементы массива хранятся в памяти;
- когда массив размещают в памяти.
Какой объем памяти требуется?
Объем памяти, занимаемый массивом, определяется просто из-за того, что все элементы однотипны и занимают одинаковый объем памяти. <объем_памяти> = <память на один элемент>*size(array) Размер массива ограничивает лишь объем памяти компьютера.
В каком порядке элементы массива хранятся в памяти?
В большинстве случаев программист об этом может не задумываться. Однако, в ряде случаев при передаче массива целиком подразумевается именно этот порядок:
- при подготовке данных для ввода;
- при написании форматов вывода;
- при задании начальных значений для элементов массива.
Порядок хранения стандартизован в Фортране: для одномерного массива – по возрастанию индекса, для матрицы – по столбцам, для многомерного массива – самый быстрый первый индекс, медленнее второй, наконец, последний – самый медленный, каждый из индексов пробегает все значения по возрастанию.
Пример. В каком порядке надо готовить данные?
Всего в трехмерном массиве P(1:2,1:2,1:2) 8 элементов. Его элементы располагаются в памяти, как указано выше, и порядок чтения разъясняется вторым оператором read. Именно в этом порядке и надо готовить данные. Так как read бесформатный, можно, не нарушая порядка следования, либо все числа перечислить в одной строке через пробел или запятую, либо – каждое число – в отдельной строке.
dimension P(1:2,1:2,1:2)
read(1,*) P ! читать весь массив – понимают как
read(1,*) P(1,1,1),P(2,1,1),P(1,2,1),P(2,2,1),P(1,1,2),P(2,1,2),P(1,2,2),P(2,2,2)
Предупреждение. Размещение массива в памяти стандартно и никак не зависит от порядка ввода.
Когда массив размещают в памяти?
Форма статического массива, (предыдущий пример), известна при компиляции – shape(P)=(/2,2,2/); массив размещается в памяти при запуске программы. Форма динамического массива не определена при компиляции, например,
Real,allocatable,Dimension(:,:) :: Matrix, Matr1, Matr2, X(:)
Известно лишь количество измерений массивов: два для Matrix и один для X. Запустив программу, сначала определяют протяженности, а затем динамически размещают массивы в памяти оператором
allocate( X(1:N),Matrix(1:M,1:N),&
Matr1(1:N ,1:M), Matr2(1:N,1:N) )
Освобождают память оператором
deallocate( X, Matrix, Matr1, Matr2 )
Массив как аргумент процедуры должен быть размещен в памяти до входа в процедуру; в нее передается его адрес, независимо от способа написания размерности:
Real,intent,Dimension(1:N)::Mas - в виде переменной N;
Real,intent(in),Dimension(1:10)::Mas - в виде константы 10;
Real,intent(in),Dimension(:)::Mas – без указания размерности;
Real,intent(in),Dimension(*)::Mas-массив, перенимает форму;
Dimension(1:N,1:M) – в виде массива с перераспределением памяти между строками и столбцами, например, 3*4=4*3=2*6=6*2=12.
В любом случае количество элементов можно узнать с помощью функции size(array), а для матрицы число строк – size(Matrix,dim=1), число столбцов – size(Matrix, dim=2).
Пример (массивы X, Y, P, Q конформны):
real,dimension(1:11):: X,Y ! массивы X,Y по 11 элементов
real,dimension(-5:5)::P,Q ! P,Q – по 11 элементов с номерами 5,..0,..5
Y=sin(X+0.5)/4 + 2.1; p= Y/2; Q=P-1
Секции массивов и неявный цикл в списках ввода/вывода
Требуя гибкой организации, ввод/вывод массивов часто подразумевает строчную форму написания цикла в списке ввода/вывода. Неявный Do – это конструкция вида read(..) (v, i=iн,iк,is); write (..) (v, i=iн,iк,is) , где v -список переменных, выражений, элементов массива, зависящих от i. Скобки как бы заменяют do .. enddo , ограничивая область действия цикла по переменной i. Возможно вложение циклов. Поскольку речь идет об индексах, то i, iн, iк, is– целые величины. Триплетом называют тройку целых величин iн, iк, is , записанных в отличие от цикла через двоеточие iн:iк:is. Как можно заметить из примеров, приведенных ниже в Табл.32, триплеты можно употреблять вместо индексов, как в M(i,1:3:2). Известно также, что шаг is=1, если он опущен M(i,1:3). В отличие от цикла в триплете можно опускать не только шаг, но и iн – M(i,:3), и iк – M(i,1:) и оба – M(i,::2), и даже все три элемента триплета вместе – M(i,:). Поэтому, например, M(i,:) и M(i,1:3) эквивалентны. Опущенные iн-начало и iк-конец выбираются из описания массива. Понятно, что M(:,:) писать не стоит, потому что это эквивалентно M. Секция массива – это тоже массив, который можно применять почти везде, где применяют массивы. Как массив секция имеет свою форму.
Часто наряду с секциямииспользуют неявный цикл Do, когда требуется изменить стандартный порядок ввода/вывода. И ту, и другую конструкцию применяют, в частности, для ввода-вывода.
Таблица 32.
Ввод-вывод на матрице Integer,dimension(1:3,1:4)::M
Задание
| Неявный Do
| Используя секции
| Ввод 1-ой строки
| read(*,*) (M(1,j), j=1,4)
| read(*,*) M(1,1:4)
| Вывод по строкам
| read(1,*)((M(i,j),j=1,4),i=1,3)
| read(1,*) (M(i,:),i=1,3)
| Вывод матрицы по строкам
| write(*,7) ( i, M(i,:),i=1,3 )
7format(1x,'№',i1,':',4i3)
| То же, но длиннее, с номерами
| write(*,7) (i, M(i,1:4),i=1,3)
| Ввод 2-го столбца
| read(*,*)(M(i,2),i=1,3)
| read(*,*) M(:,2)
| Ввод диагонали матрицы
| read(*,*) (M(i,i),i=1,3)
В данных - диагональ матрицы
|
|
Программы, модули и механизмы обмена данными
Простейшая задача - главная программа. Сложную задачу разбивают на подзадачи, и реализуют в виде программ и модулей. Главная программа вызывает процедуры, те в свою очередь другие процедуры, и т.д. Объекты, обрабатываемые многими программами, помещают в централизованное хранилище – модуль. Программы и модули, объединяют термином программная единица (ПЕ)- конструкции четырех видов в Табл. 33, 34.
Таблица 33. Виды программных единиц
Программные единицы
| Программы – носители данных для внутренних процедур
| Модуль– носитель данных для тех, кто его использует, и для модульных процедур
| Главная программа
| Процедуры
| Подпрограмма
| Функция
| ProgramP use M описания действия Contains внутренние процедуры импортируют описания внешнего носителя end ProgramP
| Subroutine S(аргменты) use M описания действия Contains внутренние процедуры, с импортом описаний внешней программы-носителя EndSubroutine S
| FunctionF(аргументы)use M описания, включая F действия, включая F=выражение Contains внутренние процедуры импортируют описания внешнего носителя End FunctionF
| ModuleM use другой_модуль описания действия containsмодульная процедура contains внутренние процедуры end мод. процедуры.. модульные процедуры End ModuleM
| Программы состоят из описаний объектов и действий над ними, модули – только из централизованных описаний объектов и процедур доступа к ним из других программ и модулей. Процедуры вызывают, чтобы выполнить предусмотренные действия, среди которых также могут быть новые вызовы процедур. Помимо возникающих цепочек вызовов программ в сложной задаче строятся цепочки использования модулей. Циклы в цепочке вызовов программ (рекурсия, то есть вызов самое себя) допустимы, а циклы в цепочке использований модулей (тавтология) недопустимы.
Таблица 34.
Программная единица может быть .. внешней, внутренней, модульной
П р о г р а м м ы
| Модуль как хранилище данных (только внешний)
| Главная программа
| Процедуры
| Подпрограмма
| Функция
| ProgramP
| SubroutineS(аргументы)
| FunctionF(аргументы)
| ModuleM
| Program может быть только внешней
| Subroutineможет бытьвнешней, внутренней, модульной
| Functionможет быть внешней,внутренней, модульной
| Mодульные процедуры с внутренними процедурами
| Объект модуля доступен по имени в ПЕ, где модуль использовали
|
|
|