2016-08-05 5 views
2

名前リストを使用して派生型にネストされた割り当て可能な配列を作成するのに問題があります。最小の例を以下に示します。どのようにして、派生型内の割り付け可能な配列をネストされていないかのように動作させるようにプログラムを変更できますか? fooで名前リストを使用して派生型に割り当て可能な配列を書き込む方法は?

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 
/

fooで含まれ、プログラムがコンパイルに失敗します。

>> 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

として、エラーメッセージには、ユーザー定義の派生型I/O(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

ありがとう、イアン。ネームリストが派生型内の割り付け可能な変数から直接書き込むことを言語が許可しない特別な理由はありますか? – lenzinho

+1

割り当て可能なコンポーネントの割り当てステータス(またはポインタコンポーネントのセマンティクスと関連付けステータス)が明示的に書式化されていません。おそらくコンポーネントが常に割り当てられます。割り当てられていない条件を表す必要はありません。おそらく下限は常に1などです。多型コンポーネントと遅延長さパラメータを持つコンポーネントを考えると、さらに複雑になります。 – IanH

+0

ありがとう、Ian。 1つの最終的な質問:i10を書いた後、なぜ(unit、 "(i10)"、iostat = iostat、iomsg = iomsg)は改行を生成しないのですか? UDDTIO内でどのようにラインブレークを達成できますか? – lenzinho

関連する問題