Fortran 2008 - класс хранения с распределяемыми свойствами с использованием двоичного потока [дубликат]

Я попробовал следующее:

nullIdx <- as.array(which(is.na(masterData$RequiredColumn)))
masterData$RequiredColumn[nullIdx] = masterData$RequiredColumn[nullIdx-1]

nullIdx получает номер idx, где когда-либо masterData $ RequiredColumn имеет значение Null / NA. В следующей строке мы заменим его соответствующим значением Idx-1, то есть последним хорошим значением перед каждым значением NULL / NA

2
задан francescalus 19 December 2015 в 20:06
поделиться

1 ответ

Если Fortran90 + означает, что вы довольны Fortran 2003, тогда есть опция определяемого пользователем производного типа IO. Это позволяет обернуть дополнительную учетную запись, необходимую для размещения в записи. Я поставлю пример кода внизу.

Если вы не хотите использовать эту функцию, возможно, потому, что у вас нет компилятора, который ее поддерживает (я тестировал с ifort 14 ), то вы можете легко имитировать бухгалтерский учет.

Важнейшая часть - это просто отправлять и считывать размеры и выделять переменные перед чтением.

Код:

module types

   type core
      integer, dimension(8) :: indx
   end type core 

   type sample
      integer :: a
      real*8, dimension(:), allocatable :: b
      type(core), dimension(:), allocatable :: c
    contains
      procedure write_sample
      procedure read_sample
      generic :: write(unformatted) => write_sample
      generic :: read(unformatted) => read_sample
   end type sample

   contains

     ! Unformatted writing for the sample derived type
     subroutine write_sample(dtv, unit, iostat, iomsg)
       class(sample), intent(in) :: dtv
       integer, intent(in) :: unit
       integer, intent(out) :: iostat
       character(*), intent(inout) :: iomsg

       integer i

       ! Write a record giving sizes for the allocation
       write(unit, iostat=iostat, iomsg=iomsg) SIZE(dtv%b), SIZE(dtv%c)
       write(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, &
                                               (dtv%c(i)%indx, i=1,SIZE(dtv%c))

     end subroutine write_sample

     ! Unformatted reading for the sample derived type
     subroutine read_sample(dtv, unit, iostat, iomsg)
       class(sample), intent(inout) :: dtv
       integer, intent(in) :: unit
       integer, intent(out) :: iostat
       character(*), intent(inout) :: iomsg

       integer i
       integer sizeb, sizec

       ! We first have a record telling us the sizes of components
       read(unit, iostat=iostat, iomsg=iomsg) sizeb, sizec
       ! So we do the allocation
       allocate(dtv%b(sizeb), dtv%c(sizec))
       ! And then finally the reading.
       read(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, &
                                             (dtv%c(i)%indx, i=1,SIZE(dtv%c))

     end subroutine read_sample

end module types

program save_it
   use types

   implicit none

   integer i, unit_in, unit_out

   ! here it comes
   type(sample) :: save
   type(sample) :: save_test

   ! Define some values - using ifort don't forget to set the compile flag
   save%a = 14
   save%b = [(i*1., i=1, 10)]
   save%c = [core([(i, i=1,8)]), core([(i, i=11, 18)])]

   ! Write out the derived type
   open(newunit=unit_out, file='serial', form='unformatted', &
        status='replace', action='write')
   write(unit_out) save
   close(unit_out)

   ! Read in the derived type to a new one
   open(newunit=unit_in, file='serial', form='unformatted', &
        status='old', action='read')
   read(unit_in) save_test
   close(unit_in)

   ! Test, if we want to be certain

end program save_it

Конечно, предстоит сделать много работы, чтобы сделать его надежным.

2
ответ дан francescalus 19 August 2018 в 03:00
поделиться
  • 1
    очень проницательный фрагмент кода и отличные идеи! спасибо – argasm 27 March 2014 в 21:09
  • 2
    Обратите внимание, что дочерние операторы ввода / вывода всегда рассматриваются как непереходные - как процедуры write_sample, так и read_sample только записывают и считывают свои данные в одиночной записи, созданной родительскими инструкциями записи и чтения в основной программе. – IanH 27 March 2014 в 22:26
  • 3
    @IanH Это хороший момент, спасибо. Возможно, в комментариях к моим процедурам я должен сказать «кусок». а не «запись»? Или есть еще менее загруженный / более правильный термин? – francescalus 27 March 2014 в 22:50
  • 4
    @francescalus, какой компилятор вы используете? Это не работает с gfortran 6.3.0 (последняя доступная версия, о которой я знаю для MinGW). Я получаю: generic :: write(unformatted) => write_sample, Error: Expected '=>' at (1). Если я удалю, (unformatted), я получу: write(unit_out) save, Error: Data transfer element at (1) cannot have ALLOCATABLE components unless it is processed by a defined input/output procedure. – Jeff Irwin 29 July 2018 в 16:12
  • 5
    @JeffIrwin, я использовал ifort (14, если мой комментарий в ответе верен, а не проверен позже). Насколько я понимаю, вам понадобится gfortran 7+ для поддержки определенных операций ввода-вывода. – francescalus 29 July 2018 в 23:11
Другие вопросы по тегам:

Похожие вопросы: