Fortran 77中的字符串数组

7

我有一个关于Fortran 77的问题,但一直没有找到解决方案。

我正在尝试存储一个字符串数组,定义如下:

character matname(255)*255

这是一个长度为255的字符串数组,共有255个字符串。

之后,我从文件中读取了一系列名称,并将数组的内容设置为如下:

matname(matcount) = mname

编辑: 实际上,mname 的值是硬编码为 mname = 'AIR',类型为 character*255,它是函数 matadd() 的参数,该函数执行前一行。但这仅用于测试,在将来它将从文件中读取。

稍后我想用以下方式打印它:

write(*,*) matname(matidx)

但是它似乎打印了所有的255个字符,它打印了我分配的字符串和很多垃圾。

  • 那么我的问题是,如何知道存储的字符串长度?
  • 我应该有另一个数组来存储所有的长度吗?
  • 如何知道读取的字符串长度?

谢谢。

4个回答

5
您可以使用此函数来获取长度(不包括末尾空格)。
integer function strlen(st)
      integer       i
      character     st*(*)
      i = len(st)
      do while (st(i:i) .eq. ' ')
        i = i - 1
      enddo
      strlen = i
      return
      end

从这里获取:http://www.ibiblio.org/pub/languages/fortran/ch2-13.html

附注:当你说matname(matidx)时,它会获取整个字符串(256)个字符...因此,这是您的字符串加上空格或垃圾。


谢谢你,我也想投票给你,但我还没有足够的声望。 - Siu

4
Timotei发布的函数只会在您感兴趣的字符串部分只包含空格时给出字符串的长度。如果您在程序中分配变量,则应该为真,因为FORTRAN应该将变量初始化为空,对于字符来说就是一个空格。
但是,如果您从文件中读取数据,则可能会在行末捕获其他控制字符(特别是回车符和/或换行符,\r和/或\n取决于您的操作系统)。您还应该在函数中将它们剔除以获取正确的字符串长度。否则,您可能会得到一些有趣的打印语句,因为这些字符也会被打印出来。
以下是我修改后的函数版本,可检查末尾除空格以外的备用空格字符。
  function strlen(st)
  integer           i,strlen
  character         st*(*)
  i = len(st)
  do while ((st(i:i).eq.' ').or.(st(i:i).eq.'\r').or.
 +  (st(i:i).eq.'\n').or.(st(i:i).eq.'\t'))
    i = i - 1
  enddo
  strlen = i
  return
  end

如果“垃圾”部分中还有其他字符,这种方法仍然无法完全解决问题。
假设该方法对您的数据有效,您可以将写入语句更改为以下内容:
write(*,*) matname(matidx)(1:strlen(matname(matidx)))

它会仅打印出实际字符串。

至于是否应该使用另一个数组来存储字符串的长度,这取决于你。strlen()函数是O(n),而在表中查找长度是O(1)。如果您经常计算这些静态字符串的长度,那么在读入时计算一次长度,将它们存储在数组中并在需要时查找它们可能会提高性能。然而,如果您没有注意到明显的减速,我就不会担心它。


我不得不修改接收字符串作为参数的函数的类型定义为:character mname*(*)。以前,该变量的结尾是随机垃圾,现在它被填充了空格。感谢您的解释,非常清晰明了。我也不知道*符号的含义。 - Siu

1
根据您使用的编译器,您可以使用trim()内置函数从字符串中删除任何前导/尾随空格,然后像通常一样进行处理。
character(len=25) :: my_string
my_string = 'AIR'
write (*,*) ':', trim(my_string), ':'

应该打印:AIR:

编辑: 更好的是,似乎有一个len_trim()函数,它返回修剪后字符串的长度。


0

英特尔和康柏克视觉Fortran具有内在函数LEN_TRIM(STRING),该函数返回没有尾随空格的长度。

如果您想抑制前导空格,请使用“调整左侧”即ADJUSTF(STRING)

在这些FORTRAN中,我还注意到一个有用的功能:如果您将一个字符串作为参数传递给函数或子例程,并且在子例程内部将其声明为CHARACTER*(*), 则在子例程中使用LEN(STRING)函数将返回传入的实际字符串长度,而不是在调用程序中声明的字符串长度。

例如: CHARACTER*1000 STRING

        .
        .

  CALL SUBNAM(STRING(1:72)

  SUBROUTINE SYBNAM(STRING)
  CHARACTER*(*) STRING
  LEN(STRING) will be 72, not 1000

使用字符串的结构和长度有时是有意义的。 - Holmz

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