Reading a sequence of integer in a line with unknown bound in fortran

前端 未结 2 1044
走了就别回头了
走了就别回头了 2021-01-22 20:41

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 in

2条回答
  •  终归单人心
    2021-01-22 21:00

    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.

提交回复
热议问题