2012-03-23 2 views
3

В настоящее время в моем коде у меня есть 2D-массивМассив производного типа: выберите запись

integer, allocatable :: elements(:,:) 

и определить некоторые константы

integer, parameter :: TYP = 1 
integer, parameter :: WIDTH = 2 
integer, parameter :: HEIGHT = 3 
! ... 
integer, parameter :: NUM_ENTRIES = 10 

и выделить что-то вроде

allocate(elements(NUM_ENTRIES,10000)) 

так я может получить доступ к элементам, как

write(*,*) elements(WIDTH,100) ! gives the width of the 100th element 

Теперь я хотел бы иметь не только целое число, но и смесь типов для каждого элемента. Поэтому я определить производный тип

type Element 
    logical active 
    integer type 
    real width 
    ! etc 
end type 

и использовать массив элементов

type(Element), allocatable :: elements(:) 

с 2d версии массива я мог бы вызвать подпрограмму, говоря это, какую запись использовать. .

subroutine find_average(entry, avg) 
    integer, intent(in) :: entry 
    real, intent(out) :: avg 
    integer i, 
    real s 

    s = 0 
    do i = lbound(elements,1), ubound(elements,1) 
     if (elements(TYP,i) .gt. 0) s = s + elements(entry,i) 
    end do 
    avg = s/(ubound(elements,1)-lbound(elements,1)) 
end subroutine  

Так что я мог call find_average(HEIGHT) найти среднюю высоту или передать WIDTH, чтобы получить среднюю ширину. (И мои подпрограммы делают более сложные вещи, чем поиск средней высоты или ширины, это просто пример.)

Вопрос: Как использовать различные типы (как с производным типом), но и повторно использовать мои функции для работы с разными записями (как в подпрограмме примера)?

ответ

4

Для случая массива вместо передачи в массиве аргументов и индекса i вы можете передать один массив аргументов (i). При переключении в режим, имеющий производный тип, так же вы можете передать в variable_of_type% элемента, а не проходя весь variable_of_type и каким-то образом инструктирования процедуру, которая подэлемент предполагается работать. Если код должен отличаться для разных типов элементов (например, логического, целочисленного, реального), тогда вы можете написать конкретные процедуры для каждого, но затем вызвать с общим именем через общий блок интерфейса. Компилятор должен иметь возможность отличать процедуры общего интерфейса с некоторыми характеристиками аргументов, здесь их тип. Пример кода, в котором отличительная характеристика является рангом массива, см. how to write wrapper for 'allocate'

EDIT: пример кода. делает ли это то, что вы хотите?

module my_subs 

    implicit none 

    interface my_sum 
     module procedure sum_real, sum_int 
    end interface my_sum 

contains 

subroutine sum_real (array, tot) 
    real, dimension(:), intent (in) :: array 
    real, intent (out) :: tot 
    integer :: i 

    tot = 1.0 
    do i=1, size (array) 
     tot = tot * array (i) 
    end do 
end subroutine sum_real 

subroutine sum_int (array, tot) 
    integer, dimension(:), intent (in) :: array 
    integer, intent (out) :: tot 
    integer :: i 

    tot = 0 
    do i=1, size (array) 
     tot = tot + array (i) 
    end do 
end subroutine sum_int 

end module my_subs 


program test_dt 

use my_subs 

implicit none 

type my_type 
    integer weight 
    real length 
end type my_type 

type (my_type), dimension (:), allocatable :: people 
type (my_type) :: answer 

allocate (people (2)) 

people (1) % weight = 1 
people (1) % length = 1.0 
people (2) % weight = 2 
people (2) % length = 2.0 

call my_sum (people (:) % weight, answer % weight) 
write (*, *) answer % weight 

call my_sum (people (:) % length, answer % length) 
write (*, *) answer % length 

end program test_dt 
+0

'entry' всегда будет указывать на запись того же типа (скажем, всегда' real'), поэтому, к счастью, этой проблемы у меня не будет. Но первые два предложения мне не понятны. Для случая с массивом, вы имеете в виду, что я могу дать элементам среза (WIDTH, :) 'функции? Для случая производного типа я не хочу один элемент, мне нужны все элементы. Не могли бы вы добавить модифицированную версию функции моего примера, поэтому я понимаю, что вы имеете в виду? Спасибо –

+0

о редактировании: нет извините, это не то, что я хочу. –

+0

Он передает все элементы данного подпункта определенного пользователем типа. При необходимости Fortran может выбирать различные процедуры в зависимости от типа подэлемента. Как это отличается от того, что вы хотите сделать? –

Смежные вопросы