Как увеличить размер массива на лету в Fortran?
моя программа работает через 3D-массив, помечая "кластеры", которые он находит, а затем выполняет некоторые проверки, чтобы увидеть, имеют ли какие-либо соседние кластеры метку выше текущего кластера. Есть второй массив, который содержит "правильную" метку кластера. Если он обнаруживает, что N-й смежный кластер помечен правильно, этот элемент присваивается 0, в противном случае присваивается ему правильная метка (например, если n-й сайт имеет метку 2, а соседний помечен 3, 3-й элемент labelArray
имеет значение 2). У меня есть веская причина сделать это, честно!
все, что я хочу, это иметь возможность назначить N-й элемент labelArray
на лету. Я смотрел на выделяемые массивы и объявлял вещи как labelArray(*)
но я действительно не понимаю их, несмотря на поиск в интернете и StackOverflow.
Так что любая помощь в этом будет потрясающей.
3 ответов
вот вопрос переполнения стека с некоторыми примерами кода, показывающими несколько способов использования выделяемых массивов Fortran:Как получить массив priorly-unkown в качестве вывода функции в Fortran: объявление, выделение, тестирование на наличие уже выделенного, использование нового move_alloc и выделение при назначении. Не показано явное освобождение, так как примеры используют move_alloc и автоматическое освобождение при выходе из процедуры.
P. S. Если вы хотите повторно добавить один элемент, вы должны подумать о своем подходе к структуре данных. Добавление одного элемента за раз путем увеличения массива не является эффективным подходом. Чтобы вырастить массив из N элементов до N+1 в Fortran, скорее всего, придется создать новый массив и скопировать все существующие элементы. Более подходящей структурой данных может быть связанный список. Связанный список можно создать в Fortran, создав пользовательский тип и используя указатели. Вы связываете членов вместе, указывая от одного к другому. Накладные расходы на добавление другого члена незначительны. Недостатком является то, что проще всего получить доступ к членам списка по порядку. У вас нет простой возможности массива, используя индексы, получить доступ к членам в любом порядке.
информация о связанных списках в Fortran, которые я нашел в интернете:http://www-uxsup.csx.cam.ac.uk/courses/Fortran/paper_12.pdf и http://www.iag.uni-stuttgart.de/IAG/institut/abteilungen/numerik/images/4/4c/Pointer_Introduction.pdf
если вы объявляете массив allocatable, вы используете deffered shape в форме real,
allocatable :: labelArray(:,:)
или
real,dimension(:,:),allocatable :: labelArray
с числом двойных двоеточий, означающим ранг (количество ваших индексов) вашего массива.
если массив нераспределен, вы используете
allocate(labelarray(shapeyouwant))
С правильным количеством индексов. Например allocate(labelarray(2:3,-1:5))
для массива с индексами 2 до 3 в demension 1 и -1 до 5 в размерности 2.
для изменения размера вы должны сначала освободить массив, используя
deallocate(labelArray)
чтобы перераспределить выделенный массив в новую форму, вам сначала нужно выделить новый массив с новой формой, скопировать существующий массив в новый массив и переместить ссылку старого массива в новый массив с помощью move_alloc()
.
call allocate(tmp(size_old+n_enlarge))
tmp(1:size_old) = array(1:size_old)
call move_alloc(tmp, array)
старый массив освобождается автоматически при перемещении ссылки на новый массив move_alloc()
.
Fortran 95 освобождает массивы автоматически, если они выпадают из области видимости (например, конец их подпрограммы).
Fortran 2008 имеет приятную особенность автоматического распределения по назначению. Если ты скажешь array1=array2
и array1 не выделяется, он автоматически выделяется для правильной формы.
поздний комментарий... проверьте численные рецепты для Fortran 90. Они реализовали хорошую функцию перераспределения, которая была совместима с Fortran 90. В этом случае массивы должны быть атрибутивными указателями, а не присваиваемыми.
функция получает старый массив и нужный размер и возвращает указатель на новый массив с измененным размером.
Если это вообще возможно, используйте Fortran 95 или 2003. Если 2003 год невозможен, то 95-хороший компромисс. Он обеспечивает лучший синтаксис указателя.