簡體   English   中英

如何在 fortran 90 中讀取“:”(冒號)作為字符?

[英]How to read ":" (colon) as a character in fortran 90?

我正在嘗試閱讀帶有 Fortran 90 的 csv 文件,但我收到了此錯誤消息。

forrtl: severe (59): list-directed I/O syntax error, unit 21, file /data3/khee/data/AWS/ASCII/STATION/2021/csvfile/test.csv
Image              PC                Routine            Line        Source             
a.out              000000000043B9EE  Unknown               Unknown  Unknown
a.out              0000000000412AB0  Unknown               Unknown  Unknown
a.out              00000000004036D3  Unknown               Unknown  Unknown
a.out              00000000004034DE  Unknown               Unknown  Unknown
libc-2.17.so       000000333901F84D  __libc_start_main     Unknown  Unknown
a.out              00000000004033E9  Unknown               Unknown  Unknown

我很快意識到輸入文件的“冒號”(:)會導致這個問題。 問題是我的 Fortran 代碼無法將“冒號”讀取為字符。 但我無法編輯輸入文件。

我該如何解決?

這是我的 Fortran 代碼和輸入文件的示例短語。

program read_data

  implicit none

  integer :: HSID, DSID
  real :: HLAT, HLON, HALT, DTEMP, DWDEG, DWSPD, DPRCP, DSPRS, DMSLP, DHMD, DSR, DSRH
  character(len=16) :: DATE

  open(21,file='/data3/khee/data/AWS/ASCII/STATION/2021/csvfile/test.csv',form='formatted',access='sequential',status='old')

10  read(21,*,end=90) DSID, DATE, DTEMP, DWDEG, DWSPD, DPRCP, DSPRS, DMSLP, DHMD, DSR, DSRH
           write(*,*) DSID, DATE, DTEMP, DWDEG, DWSPD, DPRCP, DSPRS, DMSLP, DHMD, DSR, DSRH
           
go to 10
90 continue

  write(*,*) "EOF"
  stop
  
end program read_data

848,2021-01-01 00:00,-4.1,9.1,2,0,,,,0,0

謝謝你!

當 CSV 文件包含由一個(或多個)指定分隔符(通常是逗號)分隔的字符字段時,您可能需要專門的閱讀器來分解它們。 建議:

  • 一次讀一行(如@Yosukesabai);
  • 將該行拆分為分隔符處的字段並將它們放入一個數組中。 一旦你有一個字符串數組,你可以隨意轉換它們。

下面的代碼大量使用了自動分配(這給了我關於 memory 泄漏的 eebie-jeebies),並且由於字符可能具有不同的長度,因此將它們包裝在“字符串”派生類型中(抱歉:C++ 的陰影。)。 它停在空行(可能不是您想要的)或文件末尾。

所有的“背景資料”都在一個模塊中完成。

!==========================================================

module ModString
   use iso_fortran_env
   implicit none

   type String
      character(len=:), allocatable :: data
   end type String

contains
   function readLine( unit )
      character(len=:), allocatable :: readLine
      integer, intent(in) :: unit
      character(len=1000) buffer
      integer stat

      read( unit, "(a)", iostat=stat ) buffer
      if ( stat /= 0 ) then
         readline = ""
      else
         readLine = trim( buffer )
      end if

   end function readLine

   !----------------------------------------------

   function splitString( line, separators )
      type(String), allocatable :: splitString(:)
      character(len=*), intent(in) :: line
      character(len=*), intent(in) :: separators

      integer numFields
      integer L
      integer i, p, q

      L = len( line )
      numFields = 1          ! should end with 1 more than number of separators
      do i = 1, len( line )
         if ( line(i:i) == separators ) numFields = NumFields + 1
      end do

      allocate( splitString( numFields ) )
      p = 1
      do i = 1, numFields - 1
         q = p - 1 + scan( line(p:L), separators )
         splitString(i)%data = line(p:q-1)
         p = q + 1
      end do
      splitString(numFields)%data = line(p:L)

   end function splitString

end module ModString

!==========================================================

program main
   use iso_fortran_env
   use ModString
   implicit none
   character(len=:), allocatable :: line
   type(String), allocatable :: fields(:)
   integer i

   open( 10, file="in" )

   do
      ! Read a single line
      line = readLine( 10 )
      if ( len( line ) == 0 ) exit
      write( *, * ) line

      ! Split line into fields at each comma
      fields = splitString( line, ',' )
      do i = 1, size( fields )
         write( *, "( 1x, 'Field ', i2, ': ', a )" ) i, fields(i)%data
      end do

      write( *, * )
   end do

   close( 10 )

end program main
          
!==========================================================

對於輸入
848,2020-01-01 00:00,-4.1,9.1,2,0,,,,0,0
000,2021-09-15 18:30,-4.1,9.1,2,0,A,B,C,1,
547,2022-01-01 00:00,-4.1,9.1,2,0,,,,0,5

它給出了 output
848,2020-01-01 00:00,-4.1,9.1,2,0,,,,0,0
字段 1:848
場2:2020-01-01 00:00
字段 3:-4.1
字段 4:9.1
字段 5:2
字段 6:0
字段 7:
字段 8:
字段 9:
字段 10:0
字段 11:0

000,2021-09-15 18:30,-4.1,9.1,2,0,A,B,C,1,
字段 1:000
場二:2021-09-15 18:30
字段 3:-4.1
字段 4:9.1
字段 5:2
字段 6:0
字段 7:A
字段 8:B
字段 9:C
字段 10:1
字段 11:

547,2022-01-01 00:00,-4.1,9.1,2,0,,,,0,5
字段 1:547
場2:2022-01-01 00:00
字段 3:-4.1
字段 4:9.1
字段 5:2
字段 6:0
字段 7:
字段 8:
字段 9:
字段 10:0
第 11 場:5

這就是我會做的......

或者,實際上,我會在 python 或其他好用的東西中編寫一個預處理器,並格式化 fortran 滿意的內容,並讓 fortran 代碼處理干凈的輸入。

program read_data

  implicit none

  integer :: HSID, DSID
  real :: HLAT, HLON, HALT, DTEMP, DWDEG, DWSPD, DPRCP, DSPRS, DMSLP, DHMD, DSR, DSRH
  character(len=16) :: DATE
  
  character(len=9999):: buf
  integer :: cnt, i

  open(21,file='test.csv',form='formatted',access='sequential',status='old')
  !read(11,*)

  10 read(21,'(a)',end=90) buf
  ! find first two commas
  cnt=0
  do i=1,9999
    if (buf(i:i)==',') cnt=cnt+1
    if (cnt==2)exit
  enddo


  read(buf(1:i),*) DSID, DATE
  read(buf(i+1:9999),*) DTEMP, DWDEG, DWSPD, DPRCP, DSPRS, DMSLP, DHMD, DSR, DSRH
  write(*,*) DSID, DATE, DTEMP, DWDEG, DWSPD, DPRCP, DSPRS, DMSLP, DHMD, DSR, DSRH

  go to 10
  90 continue

  write(*,*) "EOF"
  stop

end program read_data

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM