在Fortran 90中将字符串转换为整数

问题描述 投票:9回答:2

我知道IACHAR(s)在字符串s的第一个字符位置返回ASCII字符的代码,但我需要将整个字符串转换为整数。我也有一些字符串(大约30个字符串,每个字符串最多包含20个字符)。有没有办法将它们中的每一个转换为Fortran 90中的唯一整数?

string integer fortran character fortran90
2个回答
14
投票

你可以将一个字符串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

0
投票

你可以按照建议使用read()方法,或者你可以使用我在https://github.com/kevinhng86/faiNumber-Fortran写的fanNumber for Fortran(faiNumber-Fortran)。 faiNumber-Fortran的运行速度比read()快10倍(使用gfortran8进行测试,内置版本为legacy,f95,f2003和f2018)。

此外,如果您使用faiNumber-Fortran,您将受到防范,例如“1 abc”,“125 7895”等无效字符串。这些格式可通过read()过程进行解析(使用带有构建版本legacy,f95,f2003和f2018的gfortran8进行测试)。 faiNumber将通知您输入字符串无效。

对于版本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
© www.soinside.com 2019 - 2024. All rights reserved.