2016-08-05 4 views
2

У меня возникли проблемы с записью распределяемого массива, вложенного в производный тип, с помощью namelists. Ниже приведен минимальный пример. Как я могу изменить программу, чтобы иметь распределяемый массив внутри производного типа, как если бы он не был вложен?Как написать распределяемый массив в производном типе с помощью namelists?

program test 

    implicit none 

    type struct_foo 
     integer, allocatable :: nested_bar(:) 
    end type struct_foo 

    integer, allocatable :: bar(:) 
    type(struct_foo) :: foo 
    ! namelist/list/foo, bar 
    namelist/list/bar 

    allocate(bar(5)) 
    bar = [1:5] 

    allocate(foo%nested_bar(5)) 
    foo%nested_bar=[1:5] 

    write(*,list) 

end program test 

С обув закомментирован списке имен, он прекрасно работает, производя вывод:

&LIST 
BAR  =   1,   2,   3,   4,   5 
/

С обув включен, программа не компилировать:

>> ifort -traceback test_1.f90 -o test && ./test 
test_1.f90(20): error #5498: Allocatable or pointer derived-type fields require a user-defined I/O procedure. 
    write(*,list) 
--------^ 
compilation aborted for test_1.f90 (code 1) 
+0

Можете ли вы рассказать нам, какой компилятор вы используете? – chw21

+0

ifort (IFORT) 15.0.3 20150408 – lenzinho

ответ

3

As в сообщении об ошибке указано, что вам необходимо предоставить определенную пользователем процедуру ввода-вывода производного типа (UDDTIO). Это необходимо для ввода/вывода любого объекта с выделенным или указательным компонентом.

Как объект производного типа, отформатированный в файле, полностью находится под контролем процедуры UDDTIO.

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

module foo_mod 
    implicit none 

    type struct_foo 
    integer, allocatable :: nested_bar(:) 
    contains 
    procedure, private :: write_formatted 
    generic :: write(formatted) => write_formatted 
    end type struct_foo 
contains 
    subroutine write_formatted(dtv, unit, iotype, v_list, iostat, iomsg) 
    class(struct_foo), intent(in) :: dtv 
    integer, intent(in) :: unit 
    character(*), intent(in) :: iotype 
    integer, intent(in) :: v_list(:) 
    integer, intent(out) :: iostat 
    character(*), intent(inout) :: iomsg 

    integer :: i 

    if (allocated(dtv%nested_bar)) then 
     write (unit, "(l1,i10,i10)", iostat=iostat, iomsg=iomsg) & 
      .true., & 
      lbound(dtv%nested_bar, 1), & 
      ubound(dtv%nested_bar, 1) 
     if (iostat /= 0) return 
     do i = 1, size(dtv%nested_bar) 
     write (unit, "(i10)", iostat=iostat, iomsg=iomsg) & 
      dtv%nested_bar(i) 
     if (iostat /= 0) return 
     end do 
     write (unit, "(/)", iostat=iostat, iomsg=iomsg) 
    else 
     write (unit, "(l1,/)", iostat=iostat, iomsg=iomsg) .false. 
    end if 
    end subroutine write_formatted 
end module foo_mod 

program test 
    use foo_mod 

    implicit none 

    integer, allocatable :: bar(:) 
    type(struct_foo) :: foo 
    namelist/list/foo, bar 

    allocate(bar(5)) 
    bar = [1:5] 

    allocate(foo%nested_bar(5)) 
    foo%nested_bar=[1:5] 

    write (*,list) 
end program test 

Использование UDDTIO, очевидно, требует компилятора, который реализует эту функцию языка Fortran 2003.

+0

Спасибо, Ян. Есть ли конкретная причина, по которой язык не позволяет намелисту писать напрямую из allocatable в производном типе? – lenzinho

+1

Нет очевидного форматированного представления статуса распределения выделяемого компонента (или семантики и статуса ассоциации компонента-указателя). Возможно, компонент всегда будет выделен - в этом случае нет необходимости представлять нераспределенное условие, возможно, нижняя граница всегда будет одной и т. Д. Это становится еще более сложным, если вы рассматриваете полиморфные компоненты и компоненты с параметрами отложенной длины. – IanH

+0

Еще раз спасибо, Ян. Один последний вопрос: почему не писать (unit, "(i10)", iostat = iostat, iomsg = iomsg) вызывают разрыв строки после записи i10? Как можно добиться разрыва линии в UDDTIO? – lenzinho