[英]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 文件包含由一個(或多個)指定分隔符(通常是逗號)分隔的字符字段時,您可能需要專門的閱讀器來分解它們。 建議:
下面的代碼大量使用了自動分配(這給了我關於 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.