当虚拟指定长度时,将字符串作为参数传递

时间:2011-01-24 08:45:19

标签: string fortran fortran90

如果我有这段代码

module test
contains
   subroutine xx(name)
      character(len=20), intent(in), optional :: name

      if (present(name)) then
         print *, name
      else
         print *, "foo"
      endif
   end subroutine
end module
program x
   use test

   call xx()
   call xx("foo2")
end program

它不会编译,因为“foo2”的长度不是20,编译器会抱怨

test.f90(17): error #7938: Character length argument mismatch.   ['foo2']
   call xx("foo2")
-----------^

如何在不修改子程序dummy len规范的情况下使这个东西工作?是否必须使用相同的长度声明一个中间变量并在调用时传递它?

3 个答案:

答案 0 :(得分:7)

标准语言很难理解。我读了@kemiisto引用的条款,要求长度(dummy arg) <= length(实际arg)。此处长度为(dummy arg) = 20length (actual arg) = 4,因此长度为(dummy arg) > length (actual arg),该条款不允许这样做。该子句讨论截断实际以匹配虚拟,如果需要,不用空格填充它。

如果用character(len = 20)替换character(len = *),代码将有效。因为您不想修改伪参数规范的长度,所以有问题吗?

答案 1 :(得分:2)

对我而言似乎符合标准的行为。

Fortran 2003,12.4.1.2与虚拟数据对象相关的实际参数

  

如果标量伪参数是类型的   默认字符,长度为len   伪论证应小于   或等于实际的长度   论点。虚拟参数变为   与最左边的len相关联   实际论证的字符。

然而,gfortran只是发出警告信息

  

警告:实际参数的字符长度短于虚拟参数'name'(4/20)(1)

在这方面,英特尔Fortran编译器似乎更符合标准。所以中间变量可能是唯一的选择。

或者实际上只是声明一个变量是选项,因为你的代码中没有变量。你有文字常数。无论如何,硬编码值不是一个好主意。 =)

答案 2 :(得分:1)

发生此错误的原因是允许您的方法将最多len=20个字符读/写到伪参数name。你的字符串文字小于这个数量,你的编译器会提醒你这个事实。即使声明为intent(in),您也可以读取超出实际参数长度并导致访问冲突等。

你应该坚持len=*使用伪参数,并在确定读/写安全字符数时使用lenlen_trim

或者,如果必须保留len=20,则应使用用于将值传递到该方法的临时变量。或者像"hello"//repeat(" ", 15)那样更加丑陋。