我是Fortran的新手,我需要编写一个代码,允许我读取包含数据数组(1876列x 3126行)的文本文件(.dat),其中包含不规则的空格/不规则分隔,并将其写入具有一致格式的新文件。简而言之,我只是希望数据的列彼此对齐。
,
<4 spaces> 0.2341 15.0769 <2 spaces> -10.0672 1.6278 <3 spaces> 66.9851 -14.7123 <3 spaces> -0.4468 -2.5673
上面的例子基本上是数据列的样子,每个值前面都有相应数量的空格。值的格式为'f10.4'
这是我试着写的代码。我能够编译代码并运行exe文件,然而,它无法从文本文件中读取并产生运行时错误:end of file.
program refgrid
implicit none
integer :: nrow, ncol
integer :: i, j
real, dimension(:,:), allocatable :: mat
print *, ' Input number of rows: '
read *, nrow
print *, 'Input number of columns: '
read *, ncol
allocate(mat(1:ncol,1:nrow))
open(UNIT=1, FILE='bathymetry2.dat', FORM='FORMATTED', STATUS='OLD', ACTION='READ')
do i=1, nrow
read(UNIT=1, FMT=*) mat
end do
close(UNIT=1)
open(UNIT=1, FILE='refgrid.dat', FORM='FORMATTED', STATUS='NEW', ACTION='WRITE')
do i=1, nrow
write(UNIT=1, FMT=101) mat
101 format(1826f10.4)
enddo
close(UNIT=1)
end program refgrid
我的问题:
我如何使用do循环从一行连续读取值?在"do"中使用f格式的重复功能时,我有点困惑循环。
我可以读/写数组"mat"作为一个整体数组吗?或者我如何分配读/写数据列表?我能赋值整个矩阵吗单个元素?
问题是,在你的do循环的每次迭代中,你试图在整个数组mat
中读取尽可能多的元素。您应该在每次迭代中只填充一列。或者,您可以使用一条read语句读取整个数组,而不需要任何循环。
至于写入,您需要重复该格式的次数与您有列的次数一样多。我建议动态地创建格式字符串,这样它就能自动适应用户输入的列数。请看下面的例子。您也可以省略写的do循环,因为Fortran将自动添加记录结束符号(换行符),当所有格式规范都被使用时,它将再次开始应用它们。
program refgrid
implicit none
integer :: nrow, ncol
real, allocatable :: mat(:,:)
character(20) :: form
print *, ' Input number of rows: '
read *, nrow
print *, 'Input number of columns: '
read *, ncol
allocate(mat(1:ncol, 1:nrow))
open(unit=1, file='bathymetry2.dat', status='OLD', action='READ')
read(1, *) mat
close(1)
write(form, "(A,I0,A)") "(", ncol, "F10.4)"
open(1, file='refgrid.dat', form='FORMATTED', status='NEW', action='WRITE')
write(1, form) mat
close(1)
end program refgrid
UPDATE:对于格式说明符的动态创建:您在字符串form
中写入三件事:字符串(A
),仅包含所需字符的整数(I0
)和另一个字符串(A
)。第一个字符串是(
,整数是ncol
,第二个字符串是F10.4)
。因此,假设ncol
的值为128
,则form
的值为字符串(128F10.4)
。这是一个包含有效格式说明符的字符串,因此您可以在write语句中使用它,而不是硬编码的格式说明符。