以下代码与 HighPerformanceMark 的答案基本相同(即,对逗号分隔的值使用列表导向的输入),但是当一行以逗号结尾时(例如,行下面的 3 和 4)。因此,我在每一行手动添加了一个逗号来处理这种情况:
program main
implicit none
integer, parameter :: nrow = 4, ncol = 9
character(100) :: csvinp( nrow ), time
integer :: dat( nrow, ncol ), irow, icol
csvinp( 1 ) = "2016:03:30:00:00,2,5,10,1,2,34,5,3,2"
csvinp( 2 ) = "2017:03:40:00:00,1,2,,4,,,,,9"
csvinp( 3 ) = "2018:03:50:00:00,,2,3,,,,7,,"
csvinp( 4 ) = "2019:03:60:00:00,,,,,,,,,"
do irow = 1, nrow
csvinp( irow ) = trim(csvinp( irow )) // "," !! add one more comma
enddo
dat(:,:) = 0 !! (#)
do irow = 1, nrow
read( csvinp( irow ), * ) time, dat( irow, : )
print *, "irow:", irow
print *, " time = ", trim( time )
print *, " columns = ", dat( irow, : )
enddo
print *
print *, "average of each column:"
do icol = 1, ncol
print *, "icol=", icol, "ave=", sum( dat( :, icol ) ) / real(nrow)
enddo
end
结果:
irow: 1
time = 2016:03:30:00:00
columns = 2 5 10 1 2 34 5 3 2
irow: 2
time = 2017:03:40:00:00
columns = 1 2 0 4 0 0 0 0 9
irow: 3
time = 2018:03:50:00:00
columns = 0 2 3 0 0 0 7 0 0
irow: 4
time = 2019:03:60:00:00
columns = 0 0 0 0 0 0 0 0 0
average of each column:
icol= 1 ave= 0.75
icol= 2 ave= 2.25
icol= 3 ave= 3.25
icol= 4 ave= 1.25
icol= 5 ave= 0.5
icol= 6 ave= 8.5
icol= 7 ave= 3.0
icol= 8 ave= 0.75
icol= 9 ave= 2.75
在这里,最初用一些所需值(例如 0)填充dat 似乎更好,因为如果字符串有空白列,dat 的相应元素不会被修改。比如我们把上面代码中的Line(#)改成dat = -100,我们得到
irow: 1
time = 2016:03:30:00:00
columns = 2 5 10 1 2 34 5 3 2
irow: 2
time = 2017:03:40:00:00
columns = 1 2 -100 4 -100 -100 -100 -100 9
irow: 3
time = 2018:03:50:00:00
columns = -100 2 3 -100 -100 -100 7 -100 -100
irow: 4
time = 2019:03:60:00:00
columns = -100 -100 -100 -100 -100 -100 -100 -100 -100
average of each column:
icol= 1 ave= -49.25
icol= 2 ave= -22.75
icol= 3 ave= -46.75
icol= 4 ave= -48.75
icol= 5 ave= -74.5
icol= 6 ave= -66.5
icol= 7 ave= -47.0
icol= 8 ave= -74.25
icol= 9 ave= -47.25
虽然我不确定这种行为是否符合标准,但在 gfortran-6、ifort-16 和 Oracle fortran 12.5 中是相同的。 (实际上,我希望编译器在有空白列时填充 0,但事实并非如此。)