web-dev-qa-db-ja.com

Fortran90で文字列を整数に変換する

IACHAR(s)が文字列sの最初の文字位置にあるASCII文字のコードを返すことは知っていますが、文字列全体を整数に変換する必要があります。また、文字列の数が数個あります(約30文字列、それぞれが最大20文字で構成されます)。Fortran90で各文字列を一意の整数に変換する方法はありますか?

9
user3504976

文字列を整数変数にreadすることができます。

module str2int_mod
contains 

  elemental subroutine str2int(str,int,stat)
    implicit none
    ! Arguments
    character(len=*),intent(in) :: str
    integer,intent(out)         :: int
    integer,intent(out)         :: stat

    read(str,*,iostat=stat)  int
  end subroutine str2int

end module

program test
  use str2int_mod
  character(len=20) :: str(3)
  integer           :: int(3), stat(3)

  str(1) = '123' ! Valid integer
  str(2) = '-1'  ! Also valid
  str(3) = 'one' ! invalid

  call str2int(str,int,stat)

  do i=1,3
    if ( stat(i) == 0 ) then
      print *,i,int(i)
    else
      print *,'Conversion of string ',i,' failed!'
    endif
  enddo
end program
15
Alexander Vogt

提案されているようにread()メソッドを使用するか、 https://github.com/kevinhng86/faiNumber-Fortran で私が作成したFortran(faiNumber-Fortran)のfaiNumberを使用できます。 faiNumber-Fortranはread()よりも約10倍高速に動作しました(ビルドバージョンlegacy、f95、f2003、およびf2018を備えたgfortran8でテスト済み)。

また、faiNumber-Fortranを使用すると、「1 abc」、「1257895」などの無効な文字列から保護されます。これらの形式は、read()プロシージャ(ビルドバージョンlegacy、f95、f2003、およびf2018を使用したgfortran8でテスト済み)によって解析可能です。ここで、faiNumberは、入力文字列が無効であることを通知します。

バージョン1の場合、2つのバージョンがあります。1つは純粋なプロシージャで使用するためのもので、そのうちの1つは、不純なプロシージャでのみ使用できるバージョンよりもわずかに低速です。

FaiNumber-Fortranでは、文字列の開始位置と終了位置を選択することもできます。以下は、あなたができることの小さな例です。例以外にもたくさんあります。それにもかかわらず、私はコードを非常に徹底的に文書化しました(私は願っています)。この例は、すべて純粋なプロシージャライブラリとしてビルドされたバージョン用です。

program example
    ! For 64/128, use fnDecimalUtil64/fnDecimalUtil128.
    ! To use procedures of 64/128, The right module have to be called.
    use fnDecimalUtil   
    implicit none
    ! For 64/128, integer kind are k_int64/k_int128.
    integer(k_int32)  ::  resultValue, startpos, endpos
    ! Where there is an error code return, it will always be an int32 value.
    integer(k_int32)  ::  errorInt
    logical           ::  errorLogical

    ! For 64/128, call decToInt64/decToInt128.
    call decToInt32("123", resultValue, errorLogical)
    if ( errorLogical .eqv. .FALSE. ) then
        print *, resultValue
    else 
        print *, "There was an error during parsing."
    end if

    startpos = 13
    endpos = 17
    call decToInt32(" This here($12345)can be parse with start and end", &
                     resultValue, errorLogical, startpos, endpos)

    if ( errorLogical .eqv. .FALSE. ) then
        print *, resultValue
    else 
        print *, "There was an error during parsing."
    end if

    ! This procedure below is where you need to know what was wrong
    ! during parsing the input string.
    !
    ! This may run slower if the strings are long. The TrueError procedure
    ! has exactly the same feature as the normal one, they are just 
    ! different by how errors are handled.
    !
    ! Empty string will be checked first then error 5.
    !
    ! If error 5 is encountered, nothing else will be check. For error
    ! 5, startpos will be checked first before endpos.
    !
    ! For 64/128, call decToInt64TrueError/decToInt128TrueError
    startpos = 12
    call decToInt32TrueError("  line 24: 1278421", resultValue, errorInt, startpos) ! startpos can be used without endpos,

    if ( errorInt == 0 ) then
        print *, resultValue
    else if ( errorInt == 1 ) then
        print *, "The input string was empty."
    else if ( errorInt == 2 ) then
        print *, "The input string contained an invalid decimal integer."
    else if ( errorInt == 3 ) then
        print *, "The input string contained a value that is smaller than the minimum value of the data type."
    else if ( errorInt == 4 ) then
        print *, "The input string contained a value that is larger than the maximum value of the data type."
    else if ( errorInt == 5 ) then
        print *, "It was either startpos > length, endpos < startpos, or endpos < 1."
    end if
end program example
0
Kevin Ng