Fortran中获取变长字符串列表的更好方式

3

经过深入研究,我已经想出了一种在Fortran中实现可变长度字符串列表的自制方案。这实际上是一个自定义类型的数组,它只有一个成员属性,即可变长度字符串。语法有些麻烦,我想知道是否有更好的方法,但我一直没有找到。

这是我的代码:

! scratch.f90
module string_list

  type t_string
     character(len=:), allocatable :: s
  end type

end module

program main
  use string_list

  implicit none

  integer i
  type(t_string), allocatable :: list(:)

  allocate(list(2))
  list(1)%s = "hi my name is"
  list(2)%s = "slim shady"

  do i=1,2
     print *, len(list(i)%s)
  end do

end program


编译使用 gfortran 命令,例如: gfortran scratch.f90 -o scratch

然后:

> ./scratch
13
10

3
我认为你的方法是Fortran中显而易见且默认的方法。如果我们了解更多关于你使用情况的信息,或许可以建议一种更好(在某种意义上)的方法。至于语法的繁琐程度,我只能说"嗯"。 - High Performance Mark
我的用途是逐行读取配置文件。由于我解析和处理它们的方式,需要将文件数据存储在可按行号索引的结构中。到目前为止,这种方法对于这样做非常有效。考虑到旧版Fortran的限制,我应该感激这种方法甚至是可能的。 - Vince W.
2
搜索“Fortran中的可变长度字符串,ISO/IEC 1539-2:1994(E)”。抱歉进行了编辑。您可以在此处找到实现:http://www.astro.wisc.edu/~townsend/resource/download/code/iso_varying_string_1.2.f90 - evets
如果您告诉我们您希望语法是什么样子,这可能会帮助我们建议一些您认为不那么“繁琐”的东西。 - Ian Bush
1
我认为更简便的方式是使用list(1) = ...而不是list(1)%s = ...。也许在整个事情的大局中这并不是很重要,但我有一种直觉感觉应该有更好的方法,可能是因为拥有一个只有一个成员的结构体感觉像是不必要的复杂性。显然,在缺乏对这种数据结构的内置支持的情况下,这种复杂性是有用的,也许我正在展示我对我所认为的“应该”可用的偏见,因为我主要在支持此类结构的语言中工作。 - Vince W.
1个回答

6

正如评论所建议的那样,你的方法可能是一个不错的起点。为了使语法更加简单,你可以创建一些类型绑定的运算符和过程,例如:

module string_list
    implicit none 
    type str
        character(:), allocatable :: s
    contains
        procedure :: assa, get, length
        generic :: assignment(=) => assa
        generic :: operator(-) => get
        generic :: l => length
    end type
contains
    subroutine assa(st,str1)
        class(str), intent(out) :: st
        character(*), intent(in) :: str1
        st%s = str1
    end
    function get(st1) result(str1)
        class(str), intent(in) :: st1
        character(:), allocatable :: str1
        str1 = st1%s
    end
    function length(st1) result(nn)
        class(str), intent(in) :: st1
        integer :: nn
        nn = len(st1%s)
    end
end 

program test
    use string_list, only: str
    implicit none
    type(str), dimension(:), allocatable :: stra
    allocate(stra(2))
    stra(1) = "hello "
    stra(2) = "fortran"
    print*, -stra(1)
    print*, -stra(1)//-stra(2)
    print*, stra(1)%l(), stra(2)%l()
    print*, len(-stra(1)), len(-stra(2))
end

结果是

 hello 
 hello fortran
           6           7
           6           7

这可能不是最聪明的设计,我只是出于兴趣尝试了一下。在这里,我重载了-一元运算符以提取实际字符串,并使用=进行赋值,以避免使用%s语法,并添加了一个更方便的长度函数。


1
那很酷。我要稍微玩一下它。 - Vince W.
2
你还可以再进一步,定义一些派生类型 i/o过程,如果你愿意的话。 - High Performance Mark
1
恭喜你,你重新发明了轮子。请参阅Fortran中的可变长度字符字符串,ISO/IEC 1539-2:1994(E)。 - evets
如果这个程序被真正使用,就需要对未分配的组件进行某种处理。 - francescalus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接