【发布时间】:2020-03-17 04:09:00
【问题描述】:
在 Fortran 中,是否有任何方法可以声明“可分配数组的数组”,而不需要将可分配数组包装成派生类型?
我的主要用例是允许调用具有可变长度字符串数组的函数,即我正在寻找与文字匹配的类型签名
["Hello", &
"World.", &
"How are you?"]
动机
在 Fortran 中,字符串本机表示为固定大小的字符数组,右侧用空格填充。字符串数组通常表示为(等长)字符数组的数组,我假设这是为了使它们表现得像字符矩阵。
然而,这也意味着做类似的事情
CALL mySubroutine(["Hello","World.","How are you?"])
将导致编译器错误,如
Error: Different CHARACTER lengths (5/4) in array constructor at (1)
通常建议的解决方法(参见例如Return an array of strings of different length in Fortran)是使用派生类型的数组,例如
TYPE string
CHARACTER(LEN=:), ALLOCATABLE :: chars
END type string
! ...
CALL myStringSubroutine([string("Hello"), &
string("World."), &
string("How are you?")])
但是,由于没有此类标准化的 string 类型,我更经常看到 API 使用本机支持的“解决方法”,例如使用固定大小的字符串,并在使用时对其进行修剪。在这种情况下,调用看起来像
CALL myFixedSubroutine(["Hello ", &
"World. ", &
"How are you?"])
虽然原则上这没有问题,但如果其中一个字符串比其他字符串长得多,它可能会变得笨拙且效率低下。它还对版本控制有影响,现在将 "... you?" 更改为 "... you??" 意味着必须更改其他行的填充,从而产生虚假差异。
(在 cmets 中,给出了至少自动化空白填充的建议。)
【问题讨论】:
-
Fortran 中没有本机列表类型。只有 Fortran 数组。数组不是列表。互联网上提供了派生列表类型的实现,甚至在这里也经常出现。
-
另请注意,数组构造函数
[character(135):: 'Hello', 'World.', 'How are you?']解决了您的一些问题。 -
@VladimirF 可能没有原生列表类型,但当不需要可变长度时,通常可以以相同的方式使用数组。我正在寻找的基本上归结为使用“数组数组”而不是“2 级数组”。虽然后者显然更适合矩阵性能,但前者通常更适合围绕计算的基础架构代码。
-
@kdb arrays of arrays 在这里也被多次处理。还有使用几乎相同的包装器的指针数组。只需将指针组件与字符组件切换即可。它真的是一样的,非常简单。 stackoverflow.com/questions/8900336/arrays-of-pointers 我看到你称其为解决方法,但通常情况下,这确实是要去做的事情。如果您已经知道,不确定问题是什么。
-
@VladimirF 包装器编写起来很简单,但它们使代码更难阅读,所以我试图找到一个不需要它们的解决方案。对于指针,虽然
TYPE(string)用于此类变量参数的性能会更高,但它在任何其他地方都会变得不那么有用,因为指针最终可能指向已释放的内存。我正在寻找改进静态检查能力的方法,所以使用POINTER将是一个倒退。