Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在fortran中读取具有未知边界的行中的整数序列_Fortran_Line - Fatal编程技术网

在fortran中读取具有未知边界的行中的整数序列

在fortran中读取具有未知边界的行中的整数序列,fortran,line,Fortran,Line,我想在FORTRAN中读取一行中具有未知边界的整数序列。我的问题与之前的帖子类似 但是,我想读取一行中未知整数的序列,并将其保存在单独的数组中。整数的连续行应该保存到其他数组中 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

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

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

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数组中)。我有数百行这样的代码,因此我需要根据最大长度进行分类,并对它们进行计数


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

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包含问题中的整行,加上以下几行

# 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)
中的值复制到所需的数组来保存每行的结果

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

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

但是,不建议使用这种直接方法,因为当read语句遇到“end”或“err”条件时,
VAL(1:n)
将变得未定义。尽管ifort和gfortran似乎在
VAL(1:n)
中保留数据,即使在满足该条件的情况下(因此即使使用直接方法,它们也可以工作),但对于其他编译器,也不能保证相同的行为。相反,缓冲区方法通过在
vals(1:n)
前一步保存数据来避免这种风险,因此不使用未定义的数据。这就是为什么在上面的代码中使用缓冲区方法,尽管它长了一条语句。

类似的东西可能满足您的要求

  INTEGER :: ix, rdstat
  INTEGER, DIMENSION(6) :: nums
  CHARACTER(len=128) :: aline
  ...
  OPEN(21,file='data.txt')

  DO ix = 1,10
     READ(21,'(a)',iostat=rdstat) aline
     IF (rdstat/=0) catch_errors()

     nums = -99 ! a guard
     READ(aline,*,iostat=rdstat) nums
     IF (rdstat/=0) catch_errors()
     ! do something with nums
  END DO

  CLOSE(21)
我还没有完全测试过这一点,也没有为您编写
catch\u errors
——实际上,您可能不太想这样做。第一个版本可能太脆弱了,但它是否合适在很大程度上取决于输入文件的一致性(或其他)

该策略是将每一行读入一个字符变量(一行足够整行的长度),然后使用内部的、列表定向的读取从字符变量的开头读取6个整数。这充分利用了列表定向输入的内置功能,即在输入流中用空格分隔值来查找整数。这种方法也适用于逗号分隔的整数列表。内部只读查找6个整数,然后在找不到更多整数或只有无法解释为整数的内容(如字符串
#comment
)时捕获错误

  • 我假设最大行长度为128个字符,您可能需要调整它
  • 我已经指定了程序将读取的行数的固定上限。您可能需要更改该选项,或者更改为
    do/while
    循环
  • 正如您的问题所指定的,程序要求一行中的整数不超过6个
  • 在每行读取时,数组
    nums
    在每个元素处填充
    -99
    ;这是一个“警卫”。如果您的输入文件中可能出现
    -99
    ,您可能需要对此进行更改
  • 一旦拥有了
    nums
    中的数字,如何处理它们完全取决于您自己

您好,我试图用gfortran将您的代码编译为.f90文件,它导致
读取测试.f90:10.8:val(1:n)=buf(1:n)1错误:在(1
@AlphaF20处的不可分类语句非常感谢!我相信
val
vals
的一个打字错误(现在在上述代码中已更正)。我还将
buf
的大小从10000更改为100(因为gfortran发出了关于大型本地阵列的警告)。