2017-12-26 16 views
2

Ich möchte die benutzerdefinierten E/A-Prozeduren für die abgeleiteten Typen in meinem Fortran-Code implementieren. write Anweisungen innerhalb dieser Prozeduren können jedoch keine neuen Zeilen zwischen zwei sequentiellen write-Anweisungen erzeugen. Der abgeleitete Typ und die abgeleiteten Prozeduren sind wie folgt definiert.Write-Anweisung kann keine neuen Zeilen innerhalb benutzerdefinierter formatierter E/A-Prozeduren für abgeleiteten Typ erzeugen

Das Modul:

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 

Wir können sehen, dass die benutzerdefinierte formatierte Schreib Anweisung rufen Sie einfach ein regelmäßiges Unterprogramm namens export_station, durch denen ich das gleiche Ergebnis in beiden Richtungen zu erwarten.

Hier ist mein Testprogramm:

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 

Der Ausgang:

>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 

Die regelmäßige Unterprogramm export_station produziert, was ich erwarte. Neue Zeilen werden zwischen zwei write-Anweisungen erstellt, während write Anweisung des abgeleiteten Typs nicht.

Antwort

2

Hier gibt es zwei Klassen von Ausgabeanweisungen: ein Eltern- und ein Kindelement. Die übergeordnete Ausgabeanweisung im ersten Fall lautet write (*,*) pt.

Wenn dies zuerst das übergeordnete Element ist, führt der Aufruf von export_station über write_station zu den Schreibanweisungen, die untergeordnete Ausgabeanweisungen sind. Wenn export_station direkt vom Benutzer aufgerufen wird, sind diese Schreibanweisungen selbst übergeordnete Ausgabeanweisungen.

Ein wesentlicher Unterschied zwischen einer untergeordneten Datenübernahmeanweisung und einer übergeordneten Datenübernahmeanweisung besteht darin, dass eine übergeordnete Anweisung die Datei vor und nach der Datenübertragung positioniert. Das heißt, wenn die write (unit,*) "Z:" abgeschlossen ist, wird die Datei nach dem gerade geschriebenen Datensatz positioniert, nur wenn die Übertragungsanweisung ein Elternteil ist.

So sehen Sie die neuen Zeilen: Dies ist einfach nach der schriftlichen Aufzeichnung.

Eine untergeordnete Datenübernahmeanweisung, die die Datei nach Abschluss nicht positioniert, wirkt sich nicht auf eine neue Zeile aus.


Ich habe im Moment keinen Zugang zu einer Testmaschine, daher ist dieser Teil spekulativ. Sie können ein neues Zeilenzeichen, das von new_line('') zurückgegeben wird, als Teil Ihrer Ausgabe für die unterordnete Übertragungsanweisung explizit schreiben. Da advance='no' in einer untergeordneten Anweisung ignoriert wird, könnten Sie dies für beide Fälle verwenden und explizit steuern, wo neue Zeilen geschrieben werden, anstatt sich auf den Split-Record-Ansatz zu verlassen, wie er derzeit existiert.

+0

Dies wurde auch auf dem Intel-Forum gefragt. Ich antwortete dort. "Benutzerdefinierte I/O vom abgeleiteten Typ sind alle nicht fortschreitend (und Sie können dies nicht ändern). Wenn Sie Zeilenumbrüche haben wollen, müssen Sie sie explizit schreiben (zum Beispiel mit einem/-Format).„) –

+0

Eine knappe Aussage, die wohl wert ist eine Antwort mehr als ein Kommentar hier, @stevelionel. – francescalus

+0

Ihre Antwort richtig war, so wollte ich nicht auf die Zehen treten, aber wenn Sie mit ihm in Ordnung sind. .. getan! –

3

Dies wurde auch auf dem Intel-Forum gefragt. Ich antwortete dort. "Benutzerdefinierte I/O vom abgeleiteten Typ sind alle nicht fortschreitend (und Sie können dies nicht ändern). Wenn Sie Zeilenumbrüche möchten, müssen Sie sie explizit schreiben (z. B. mit einem/-Format)."

Verwandte Themen