在 Fortran 中解析随机 "String + Integers"

Parse random "String + Integers" in Fortran

假设我要解析以下字符串:

"Compute the sum of (integer) and (integer)" 在 Fortran 90 中,我不知道其中的整数有多大。可以是3,也可以是30万。

据我所知,FORMAT 语句没有为在 运行 时推断整数大小留出空间。为小至 3 的数字选择一个太大的尺寸,比如 i5,然后程序崩溃。

我最好怎么做?

如果编译时知道整数在字符串中的位置(例如第 5 个和第 7 个字),我们可以直接使用列表定向读取来获取整数:

character(256) :: line, words( 50 )
integer :: i1, i2

line = "Compute the sum of 3 and 30000, then we get..."

read( line, * ) words( 1 : 7 )   !! get the first seven words from a line
read( words( 5 ), * ) i1         !! convert the 5th and 7th words to integer
read( words( 7 ), * ) i2         !! so that i1 = 3, i2 = 30000

但是如果不知道整数的位置(例如,当从用户输入中获得时),事情可能会更复杂......我为此编写了一些子程序,所以如果它看起来有用,请尝试一下:)

module strmod
contains

subroutine split ( line, words, nw )
    implicit none
    character(*), intent(in)  :: line
    character(*), intent(out) :: words(:)
    integer,      intent(out) :: nw
    character(len(words)) :: buf( size(words) )
    integer :: k, ios

    nw = 0 ; words(:) = ""

    do k = 1, size(words)
        read( line, *, iostat=ios ) buf( 1 : k )
        if ( ios /= 0 ) exit
        nw = k
        words( 1 : nw ) = buf( 1 : nw )
    enddo

endsubroutine

subroutine words_to_ints ( words, ints, ni )
    implicit none
    character(*), intent(in)  :: words(:)
    integer,      intent(out) :: ints(:)
    integer,      intent(out) :: ni
    integer :: k, val, ios

    ni = 0 ; ints(:) = 0

    do k = 1, size(words)
        read( words( k ), *, iostat=ios ) val
        if ( ios /= 0 ) cycle
        ni = ni + 1
        if ( ni > size(ints) ) stop "size(ints) too small"
        ints( ni ) = val
    enddo

endsubroutine

endmodule

program main
    use strmod
    implicit none
    character(80) :: line, words( 50 )  !! works also with size 5 or 7 etc
    integer :: ints( 50 ), nw, ni, k

    line = "Compute the sum of 3 and 30000, then we get 300003 (no!!)"
            !... Note: spaces and commas serve as delimiters. Better to avoid "/".

    call split ( line, words, nw )
    call words_to_ints ( words, ints, ni )

    print *, "Word counts:", nw
    do k = 1, nw
        print *, trim( words( k ) )
    enddo

    print *, "Int counts:", ni
    print *, ints( 1 : ni )
end

结果:

Word counts:          12
Compute
the
sum
of
3
and
30000
then
we
get
300003
(no!!)
Int counts:           3
       3       30000      300003