问题描述
我想在 FORTRAN 中读取具有未知界限的行中的整数序列.我的问题与之前的帖子类似,
I would like to read a sequence of integer in a line with unknown bound in FORTRAN. My question is similar to the following previous post,
但是我想在一行中读取一系列未知数的整数并将其保存在单独的数组中.连续的整数行应该保存到其他数组中
however I want to read a sequence of unknown numbers of integer in a line and save it in separate arrays. And successive lines of integer should be saved to some other array
My file looks like this
5 7 8 9 10 13 # should be stored f(1)(6) arrays
93 102 92 # c(1)(3)
105 107 110 145 147 112 # f(2)(6)
97 98 # b(1)(2)
12 54 55 # c(2)(3)
15 17 21 23 45 # e(1)(5)
43 47 48 51 62 # d(1)(4)
因此,我有一个最大长度为 6(存储在 f 数组中)和最小长度为 2(存储在 b 数组中)的整数序列.我有数百行这样的行,因此我需要根据最大长度进行分类并计数.
Thus I have a sequence of integers with maximum length of 6 (to be stored in f array) and minimum length of 2(to be stored in b array). I have hundreds of lines like this, such that I need to classify according to the maximum length and count on them.
推荐答案
可能有很多方法可以做到这一点,下面是一个这样的例子.在这里,split() 对行中所有值的列表导向输入进行多次尝试,直到遇到非数字字符或行尾.
There are probably many ways to do this, and the following is one such example. Here, the split() makes multiple trials for list-directed input for all values in the line, until non-numeric characters or the end of line is encountered.
subroutine split( line, vals, n )
implicit none
character(*), intent(in) :: line
real*8 :: vals(*), buf( 100 ) !! currently up to 100 items (for test)
integer :: n
n = 1
do
read( line, *, end=100, err=100 ) buf( 1 : n ) !! (See Appendix for why buf is used here)
vals( 1:n ) = buf( 1:n )
n = n + 1
enddo
100 continue
n = n - 1
end
program main
implicit none
character(200) :: line
real*8 :: vals( 100 )
integer :: n
open( 10, file="test.dat", status="old" )
do
read( 10, "(a)", end=500 ) line
call split( line, vals, n )
if ( n == 0 ) then
print *, "comment line"
else
print *, nint( vals( 1 : n ) )
endif
enddo
500 continue
close( 10 )
end
如果 test.dat 包含问题中的整行,加上以下行
If test.dat contains the whole lines in the Question, plus the following lines
# additional data
1,2,3 , 4 , 5 # comma-separated integers
1.23e2 -4.56e2 , 777 # integer/floating-point mixed case
它给了
comment line
5 7 8 9 10 13
93 102 92
105 107 110 145 147 112
97 98
12 54 55
15 17 21 23 45
43 47 48 51 62
comment line
1 2 3 4 5
123 -456 777
因此可以通过将 vals(1:n)
中的值复制到所需的数组来保存每一行的结果.
So one can save the result for each line by copying the values in vals(1:n)
to a desired array.
[ 附录(感谢@francescalus)]在上面的代码中,数据被一次读入buf(1:n)
,然后复制到vals(1:n)
.有人可能认为将数据读入 vals(1:n)
这样会更直接
[ Appendix (thanks to @francescalus) ]In the above code, the data are read once into buf(1:n)
and then copied to vals(1:n)
. One might think that it would be more direct to read in the data into vals(1:n)
such that
read( line, *, end=100, err=100 ) vals( 1 : n )
但是,不建议使用这种直接方法,因为当读取语句到达end"时,vals(1:n)
变得未定义.或错误"状况.尽管 ifort 和 gfortran 似乎保留了 vals(1:n)
中的数据,即使满足该条件(因此即使使用直接方法它们也可以工作),但不能保证其他编译器具有相同的行为.相比之下,缓冲区方法通过将前一步的数据保存到 vals(1:n)
来避免这种风险,因此未使用未定义的数据.这就是为什么在上面的代码中使用缓冲区方法的原因,尽管它是一个语句.
However, this direct approach is not recommended because vals(1:n)
becomes undefined when the read statement hits the "end" or "err" condition. Although ifort and gfortran seem to retain the data in vals(1:n)
even when that condition is met (and so they work even with the direct approach), the same behavior cannot be guaranteed for other compilers. In contrast, the buffer approach avoids this risk by saving the data one step before to vals(1:n)
, so that undefined data are not used. This is why the buffer approach is used in the above code despite it is one statement longer.
这篇关于在fortran中读取具有未知界限的行中的整数序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!