Fortran 中的字符串

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

在 Java 中,任何从

Object
派生的类都有一个漂亮的函数:

public String toString()

它本身的功能不是很神奇,但是 Java 解释器使用它的方式使它非常有用。而且,当然,这不是生死攸关的事情,而是一件非常好的事情,让有些懒惰的编码人员的生活更轻松。据我所知,Fortran(或许多其他语言)中不存在任何类似的东西。

我错了吗?这样的东西存在吗?或者,在 Fortran 传说中是否隐藏着类似的东西?

对于那些不熟悉 Java 的人:简单(但有点不准确)说,如果在任何需要 String 的地方使用了一个对象变量(没有引用它的任何成员),Java 解释器会查找

toString()变量类的 
方法,通过层次结构默认向上(一直到
Object
)。因此,每个对象都有一些可用的
toString()

在 Fortran 中将一个

toString()
函数实现到一个类(或类型)中并不是很麻烦。好吧,这有点取决于类型的复杂性,以及用户希望函数返回什么。

写起来会方便得多:

    write(*,*) somevariable

代替

    write(*,*) somevariable%toString()

与课程作业类似

    character (len = *) :: str
    str = somevariable

代替

    str = somevariable%toString()

当然,这与类型转换有关。隐式类型转换,如果我没记错的话。

希望就此展开长时间的讨论,因为除了我已经写的内容,我没有什么可以贡献的了。

fortran tostring fortran2003 fortran2008
2个回答
0
投票

在 Fortran 中,变量从内部格式到字符串的转换是通过“Internal WRITE”完成的。例如:

character(100) :: str
write (str,*) somevariable

在派生类型变量的情况下,如果组件都是内部类型(或其他具有内部类型的派生类型),则组件将按顺序输出。如果您有任何指针或可分配组件,或者如果您对格式有特殊要求,您将声明一个“用户定义的派生类型 I/O 过程”来执行此操作,然后在 I/O 操作期间根据需要自动调用它.

你可能已经注意到,上面我声明变量

str
具有特定的长度,因为今天你需要这样做。将于今年晚些时候发布的 Fortran 2023 允许您将
str
声明为延迟长度可分配变量,内部写入将(重新)分配它到必要的长度。当然,您需要等待编译器实现该功能。


0
投票

Fortran 没有“如果在预期 X 类型之一的地方给出 Y 类型的对象,则将其转换为 X 类型之一”的强烈概念。这涵盖了不同类型的数字对象(例如 Y 双精度、X 实数)以及派生类型和字符串。

您会在过程引用中的参数不匹配等情况下看到这一点。

在某些情况下我们确实有类型转换,比如在

x+y
中这两个对象是不同类型的。

所以,像

somevariable
这样的引用总是1对该对象的引用,而不是它的任何一个(或多个)组件或类型绑定过程/绑定名称。

在类似的地方

call dosomething(somevariable)

其中

dosomething
需要一个字符,但
somevariable
不是一个字符,永远不会为您执行隐式转换。

但是,在您感兴趣的两种情况下,可以说

somevariable
作为派生类型是预期的,但是会发生其他事情而不是立即处理该类型。

  1. 对于数据传输,可以使用定义的输入/输出
  2. 对于角色的赋值,可以使用定义的赋值

例如(具体解释见其他问答),我们可以定义一个类型

t
,它有一个通用的
write(formatted)
和一个
assignment(=)
的接口,它有一个字符左侧和
type(t)
右侧边:

module mod
  type t
     integer :: i=0
   contains
     procedure :: write
     generic :: write(formatted) => write
  end type t

  interface assignment(=)
     module procedure assign
  end interface assignment(=)
  
contains

  subroutine write(dtv, unit, iotype, v_list, iostat, iomsg)
    class(t), intent(in) :: dtv
    integer, intent(in) :: unit
    character(*), intent(in) :: iotype
    integer, intent(in) :: v_list(:)
    integer, intent(out) :: iostat
    character(*), intent(inout) :: iomsg
  
    write (unit, "(A)", iostat=iostat, iomsg=iomsg) "Object says hello"
  end subroutine write

  subroutine assign(lhs, rhs)
    character(:), allocatable, intent(out) :: lhs
    class(t), intent(in) :: rhs

    lhs = "From assignment"
  end subroutine assign

end module mod

可以使用

dt
编辑描述符(或使用列表定向输出)调用定义的输出过程,并且像往常一样定义赋值:

  use mod, only : t, assignment(=)
  character(:), allocatable :: str

  print '(dt)', t()

  str = t()
  print '(A)', str
end

1 当这些组件都可以访问时,对派生类型对象的引用可以扩展到它的组件顺序在对象的内部数据传输中。

© www.soinside.com 2019 - 2024. All rights reserved.