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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24071722/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 02:18:16  来源:igfitidea点击:

Converting a string to an integer in Fortran 90

stringintegerfortrancharacterfortran90

提问by user3504976

I know that IACHAR(s)returns the code for the ASCII character in the first character position of the string s, but I need to convert the entire string to an integer. I also have a few number of strings (around 30 strings, each consists of at most 20 characters). Is there any way to convert each one of them to a unique integer in Fortran 90?

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

回答by Alexander Vogt

You can reada string into an integer variable:

您可以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

回答by Kevin Ng

You can use the read() method as suggested, or you could use faiNumber for Fortran(faiNumber-Fortran) that was written by me at https://github.com/kevinhng86/faiNumber-Fortran. faiNumber-Fortran operated about 10x faster than read()(tested with gfortran8 with build version legacy, f95, f2003, and f2018).

您可以按照建议使用 read() 方法,也可以将 faiNumber 用于 Fortran(faiNumber-Fortran),这是我在https://github.com/kevinhng86/faiNumber-Fortran 上编写的。faiNumber-Fortran 的运行速度比 read() 快约 10 倍(使用 gfortran8 测试,构建版本为旧版、f95、f2003 和 f2018)。

Also, if you use faiNumber-Fortran, you are guarded against invalid string such as "1 abc", "125 7895", and so on. Those formats are parsable by the read() procedure(tested with gfortran8 with build version legacy, f95, f2003, and f2018). Where faiNumber will notify you that the input string is invalid.

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

For version one you get two versions, one to use with pure procedures, of which slightly slower than the version that can only be used by impure procedures.

对于版本一,您会得到两个版本,一个用于纯程序,其中比只能由非纯程序使用的版本稍慢。

FaiNumber-Fortran also let you choose where to start and end in your string. This below is a small example of what you can do. There is a lot more than the example. Nonetheless, I documented the code very thoroughly(I hope). The example is for the version that built as an all pure procedures library.

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(345)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