无法编译 returns 部分字符串的函数

Unable to compile function which returns parts of a string

我想在我的代码中使用以下函数。我希望它采用给定的字符串,删除所有前导零和 return 没有前导零的字符串。例如我给它 '00023' 它应该 return '23___'_ 是 space) 我的代码中有这个功能:

function cut_zeros(string)
implicit none
    character(5) :: cut_zeros, string
    integer:: string_limit, i

    string_limit = 5

    do i= 1, string_limit
        if (string(i)/='0') then
            cut_zeros = string(i : string_limit)
            exit
        endif
    enddo

end function cut_zeros

真不知道编译器出了什么问题。它提供了以下信息:

   cut_zeros = string(i : string_limit)
                        1
Error: Syntax error in argument list at (1)

我还有一个问题?是否可以使函数假定长度?这样我就可以将任意长度的字符串传递给它?据我了解这是不可能的,因为函数的return值不能假设长度,对吗?

该错误消息实际上具有误导性。错误发生在上面一行:要比较第i个字符,需要使用string(i:i)。如果将该行更改为

if (string(i:i)/='0') then

代码按预期运行。

对于你问题的第二部分,你可以使用假设长度的字符串!您可以简单地将 return 值的长度设置为输入字符串的长度:

function cut_zeros(string)
implicit none
    character(*) :: string
    character(len=len(string)) :: cut_zeros
    integer:: string_limit, i

    string_limit = len(string)

    do i= 1, string_limit
        if (string(i:i)/='0') then
            cut_zeros = string(i : string_limit)
            exit
        endif
    enddo
end function cut_zeros

这里选择了return字符串的长度,如果没有去掉零,它仍然有一个有效的长度。请注意,您将需要一个接口来处理假定长度的虚拟参数。

要将输出字符串裁剪到所需的确切长度,您需要可分配的字符串,但并非所有编译器都完全支持:

function cut_zeros(string)
implicit none
    character(*) :: string
    character(len=:),allocatable :: cut_zeros
    integer:: string_limit, i

    string_limit = len(string)

    do i= 1, string_limit
        if (string(i:i)/='0') then
            allocate( character(len=string_limit-i+1) :: cut_zeros )
            cut_zeros = string(i : string_limit)
            exit
        endif
    enddo
end function cut_zeros

子字符串引用的语法需要分隔冒号,即您需要 string(i:i)。如果你没有那个冒号,编译器认为该语法是一个函数引用(它知道它不是一个数组引用,因为你没有将 string 声明为一个数组)。

您不需要假定的长度函数。这样的事情存在,但它们是不合时宜的,最好被遗忘。您可能想要的是一个自动长度函数,其中函数结果的长度取决于输入。

FUNCTION cut_zeros(string)
  CHARACTER(*), INTENT(IN) :: string
  ! The length of the function result is the same as the length 
  ! of the argument.
  CHARACTER(LEN(string)) :: cut_zeros

具有自动结果的函数在引用它的任何范围内都需要一个显式接口。最好将它放在一个模块中,然后使用该模块。

或者您可以使用 Fortran 的现有功能

  CHARACTER(6) :: src = '002305'
  CHARACTER(LEN(src)) :: dest
  ...
  dest = src(SCAN(src,'123456789'):)
  ! now dest is '2305__'

这仅在第一个非 0 字符是另一个数字时有效,如果您有其他字符需要担心将第二个参数中使用的集合扩展到 SCAN