在Fortran中读取未知界限中的一行整数 [英] Reading a sequence of integer in a line with unknown bound in fortran

查看:137
本文介绍了在Fortran中读取未知界限中的一行整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在FORTRAN中读取一行具有未知边界的整数序列。我的问题类似于以前的帖子,





但是,我想读取一系列未知数一行中的整数并将其保存在单独的数组中。并且连续的整数行应该保存到其他数组中

 我的文件看起来像这样
5 7 8 9 10 (1)(6)阵列
93 102 92#c(1)(3)
105 107 110 145 147 112#f(2)(6)
(1)(5)
43 47 48 51(b)(1)(2)
12 54 55#c(2)(3)
15 17 21 23 45 62#d(1)(4)

因此,我有一个最大长度为6的整数序列(存储在f数组中),最小长度为2(存储在b数组中)。我有这样的数百行,这样我需要根据最大长度进行分类并计数。

可能有很多方法可以做到这一点,下面是一个这样的例子。在这里,split()对列表中的所有值进行列表定向输入的多次尝试,直到遇到非数字字符或行尾。



<$ p $
隐式无
字符(*),intent(in):: line
real * 8 :: vals($) *),buf(10000)
integer :: n
$ b $ = 1
do
read(line,*,end = 100,err = 100)buf( 1:n)!! (请参阅附录中为什么使用buf)
val(1:n)= buf(1:n)
n = n + 1
enddo
100
n = n - 1
结束

程序主
隐含无
字符(200)::行
实数* 8 :: vals(10000)
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包含问题中的所有行,并加上以下行:

 #附加数据
1,2,3,4,5#逗号分隔整数
1.23e2 -4.56e2,777#整数/浮点混合大小写

它给出s

 注释行
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
评论栏
1 2 3 4 5
123 -456 777

所以可以通过复制值来保存每行的结果在vals(1:n)中添加到所需的数组中。

[附录(感谢@francescalus)]
在上面的代码中,数据被读取一次进入buf(1:n),然后复制到val(1:n)。有人可能会认为将数据读入val(1:n)会更直接,因此

  read(line ,*,end = 100,err = 100)val(1:n)

然而,不推荐使用此方法,因为当读取语句遇到结束或错误条件时,val(1:n)变得不确定。虽然ifort和gfortran似乎仍然保留val(1:n)中的数据,即使满足该条件(因此即使采用直接方法也能工作),但其他编译器无法保证相同的行为。相比之下,缓冲方法通过将数据先前保存到val(1:n)来避免此风险,以便未使用未定义的数据。这就是为什么在上面的代码中使用缓冲方法的原因,尽管它是一个更长的声明。


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,

Reading a file of lists of integers in Fortran

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)

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.

Reading a file of lists of integers in Fortran

解决方案

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( 10000 )
    integer :: n

    n = 1
    do
        read( line, *, end=100, err=100 ) buf( 1 : n )   !! (See Appendix for why buf is used here)
        val( 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( 10000 )
    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

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

it gives

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

So one can save the result for each line by copying the values in vals(1:n) to a desired array.

[ Appendix (thanks to @francescalus) ] In the above code, the data are read once into buf(1:n) and then copied to val(1:n). One might think that it would be more direct to read in the data into val(1:n) such that

read( line, *, end=100, err=100 ) val( 1 : n )

However, this direct approach is not recommended because val(1:n) becomes undefined when the read statement hits the "end" or "err" condition. Although ifort and gfortran seem to retain the data in val(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 val(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中读取未知界限中的一行整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆