【问题标题】:Parse random "String + Integers" in Fortran在 Fortran 中解析随机“字符串 + 整数”
【发布时间】:2015-10-31 00:00:54
【问题描述】:

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

“计算 (integer) 和 (integer) 之和”在 Fortran 90 中,我无法确定整数的大小。可以是 3,也可以是 300,000。

据我所知,FORMAT 语句不会为在运行时推断整数的大小留出空间。选择一个太大的尺寸,比如 i5,但是对于小到 3 的数字,程序就会崩溃。

我最好怎么做?

【问题讨论】:

    标签: fortran fortran90 fortran95


    【解决方案1】:

    如果在编译时知道字符串中整数的位置(例如第 5 个和第 7 个单词),我们可以使用 list-directed read 直接获取整数:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-23
      • 2022-06-10
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 2014-04-08
      相关资源
      最近更新 更多