2017-12-26 48 views
2

Fortran 코드에서 파생 형식에 대한 사용자 정의 I/O 프로 시저를 구현하고 싶습니다. 그러나 해당 절차 내의 write 문은 두 개의 순차적 인 write 문 사이에 줄 바꿈을 생성 할 수 없습니다. 파생 된 유형 및 절차는 다음과 같이 정의됩니다.Write 문은 파생 형식에 대해 사용자 정의 형식화 된 I/O 프로 시저 내에서 새 줄을 생성 할 수 없습니다.

모듈 :

module station_module 
    implicit none 

    character(8), parameter :: FmtFloat = '(5E15.7)' 

    type :: station 
     integer, private :: ns = 0 
     real, public, allocatable :: xloc(:), yloc(:), zloc(:) 
    contains 
     procedure, public :: import_station 
     procedure, public :: export_station 
     procedure, private :: read_station 
     generic, public :: read (formatted) => read_station 
     procedure, private :: write_station 
     generic, public :: write (formatted) => write_station 
     final :: destruct_station 
    end type station 

    interface station 
     module procedure new_station 
    end interface station 

contains 

    function new_station(n) result(t) 
     implicit none 
     integer, intent(in) :: n 
     type(station) :: t 

     if (n > 0) then 
      allocate (t%zloc(n)) 
      allocate (t%yloc(n)) 
      allocate (t%xloc(n)) 
      t%ns = n 
     end if 
    end function new_station 

    subroutine read_station(dtv, unit, iotype, vlist, iostat, iomsg) 
     implicit none 
     class(station), intent(inout) :: dtv 
     integer, intent(in) :: unit 
     character(*), intent(in) :: iotype 
     integer, intent(in) :: vlist(:) 
     integer, intent(out) :: iostat 
     character(*), intent(inout) :: iomsg 

     call dtv%import_station(unit) 

     iostat = 0 
    end subroutine read_station 

    subroutine import_station(this, unit) 
     implicit none 
     class(station), intent(inout) :: this 
     integer, intent(in) :: unit 
     character(256) :: header, footer 
     integer ns 

     read (unit, '(A)') header !> Header 
     read (unit, *) ns 
     if (ns > 0) then 
      if (allocated(this%zloc)) then 
       deallocate (this%zloc) 
      end if 
      allocate (this%zloc(ns)) 
      read (unit, *) this%zloc 

      if (allocated(this%yloc)) then 
       deallocate (this%yloc) 
      end if 
      allocate (this%yloc(ns)) 
      read (unit, *) this%yloc 

      if (allocated(this%xloc)) then 
       deallocate (this%xloc) 
      end if 
      allocate (this%xloc(ns)) 
      read (unit, *) this%xloc 

      this%ns = ns 
     end if 
     read (unit, '(A)') footer !> Footer 
    end subroutine import_station 

    subroutine export_station(this, unit) 
     implicit none 
     class(station), intent(in) :: this 
     integer, intent(in) :: unit 

     write (unit, '(A)') ">STATION INFO" 
     write (unit, '(I6)') this%ns 
     write (unit, *) "Z:" 
     write (unit, FmtFloat) this%zloc 
     write (unit, *) "Y:" 
     write (unit, FmtFloat) this%yloc 
     write (unit, *) "X:" 
     write (unit, FmtFloat) this%xloc 
     write (unit, '(A)') ">END STATION" 
    end subroutine export_station 

    subroutine write_station(dtv, unit, iotype, vlist, iostat, iomsg) 
     implicit none 
     class(station), intent(in) :: dtv 
     integer, intent(in) :: unit 
     character(*), intent(in) :: iotype 
     integer, intent(in) :: vlist(:) 
     integer, intent(out) :: iostat 
     character(*), intent(inout) :: iomsg 

     call dtv%export_station(unit) 

     iostat = 0 
    end subroutine write_station 

    subroutine destruct_station(this) 
     implicit none 
     type(station), intent(inout) :: this 

     if (allocated(this%xloc)) then 
      deallocate (this%xloc) 
     end if 
     if (allocated(this%yloc)) then 
      deallocate (this%yloc) 
     end if 
     if (allocated(this%zloc)) then 
      deallocate (this%zloc) 
     end if 
     this%ns = 0 
    end subroutine destruct_station 

end module station_module 

우리는 사용자 정의 형식의 쓰기 문이 그냥 두 가지 방법으로 같은 결과를 기대하는 export_station라는 이름의 일반 서브 루틴을 호출 볼 수 있습니다.

>STATION INFO  4Z: 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 
Y: 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00X: 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00>END STATION 
>STATION INFO 
    4 
Z: 
    0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 
Y: 
    0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 
X: 
    0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 
>END STATION 

정규 서브 루틴 export_station 내가 무엇을 기대 생성합니다

program Test 
    use station_module 
    implicit none 
    type(station) :: pt, pt1, pt2 

    pt = station(4) 

    write(*, *) pt 

    call pt%export_station(6) 

end program Test 

출력 :

여기 내 테스트 프로그램입니다. 두 개의 write 문 사이에 새로운 행이 생성되지만 write 파생 유형의 명령문은 그렇지 않습니다.

답변

2

출력 문장에는 상위와 하위의 두 가지 클래스가 있습니다. 첫 번째 경우의 부모 출력 문은 write (*,*) pt입니다.

처음이 것이 부모 인 경우 export_station에서 write_station을 호출하면 하위 출력 문인 쓰기 문이 발생합니다. export_station이 사용자에 의해 직접 호출되면 write 문은 그 자체가 부모 출력 문입니다.

자식 데이터 전송 문과 부모 데이터 전송 문 간의 중요한 차이점 중 하나는 부모 문이 데이터 전송 전후에 파일의 위치를 ​​지정한다는 것입니다. 즉, write (unit,*) "Z:"이 완료되면 전송 명령문이 부모 인 경우에만 기록 된 레코드 다음에 파일이 배치됩니다.

따라서 새 줄을 볼 수 있습니다. 이것은 기록 된 레코드 뒤에 단순히 놓는 것입니다.

완료시 파일을 배치하지 않는 하위 데이터 전송 명령문은 새 행을 적용하지 않습니다.


현재 테스트 머신에 액세스 할 수 없으므로이 부분은 추측입니다. 자식 전송 문에 대한 출력의 일부로 new_line('')에서 반환 된 새 줄 문자를 명시 적으로 작성할 수 있습니다. advance='no'은 하위 명령문에서 무시 될 것이므로 두 경우 모두 사용할 수 있습니다. 현재 존재하는 분할 레코드 방식에 의존하기보다는 새로운 행이 기록되는 위치를 명시 적으로 제어합니다.

+0

인텔 포럼에서도이 질문을 받았습니다. 나는 사용자 정의 파생 형 I/O가 모두 발전하지 않고 변경할 수 없다. 줄 바꿈을 원할 경우 명시 적으로 작성해야한다 (예 :/형식을 사용).) " –

+0

답장이 될만한 더 간결한 성명서, 여기 @stvelionel. – francescalus

+0

당신의 대답은 정확했기 때문에 발가락을 밟고 싶지 않았지만 괜찮 으면. .. done! –

3

또한 인텔 포럼에서이 질문을 받았습니다. 나는 사용자 정의 파생 형 I/O가 모두 발전하지 않고 변경할 수 없다. 예를 들어/format을 사용하여 개행을 명시 적으로 작성해야하는 경우 "