可选字符串参数的Fortran Fallback代码

时间:2014-08-19 18:54:51

标签: string fortran optional-parameters

所以我想将一个可选字符串传递给子例程,如果该字符串不存在则设置一个回退字符串。但是,我不想在编译时设置回退字符串的长度。所以我有两个想法来整理doStufFirst和doStuffSecond

所以我有这个:

MODULE stuff
    implicit none

    contains

subroutine dostuffFirst (string)
   implicit none
   character(len=*),intent(in),optional :: string
   character(len=min(8,len(string))) :: outString

   if(present(string)) THEN
    outString=string
   else
     outString="fallBack"
   endif

  call doStuff2(outString)

 end subroutine dostuffFirst


subroutine dostuffSecond (string)
    implicit none
    character(len=*),optional :: string
    character,dimension(:),allocatable :: outString
    integer :: i

   if(present(string)) THEN
    ALLOCATE(outString(len(string)))
        do i=1,len(string)
          outString(i)=string(i:i)
        end do
    else
        ALLOCATE(outString(8))
        outString(1:8)=(/"f","a","l","l","B","a","c","k"/)
    endif

    call doStuff2(outString)

end subroutine dostuffSecond


      subroutine doStuff2(str)
       implicit none
       character(len=*),intent(in) :: str

       write(*,*) str

      end subroutine doStuff2

end module stuff

PROGRAM prog
     use stuff
     implicit none


      call dostuffFirst("123")

      call dostuffSecond("123")

END program prog

但是doStuffFirst的问题是我不能在outString的声明中使用可选参数的len(string)。而dostuffSecond的问题是我现在已经成为一个排名第一的数组,但是doStuff2期待一个标量(并且之后更改所有内容以期望一个数组是不可行的)

有什么建议吗? 感谢

1 个答案:

答案 0 :(得分:2)

考虑dostuffFirst中的问题,尝试确定要传递给doStuff2的字符变量的长度,您可以在PRESENT本身执行doStuff2逻辑吗?

subroutine doStuff2(str)
  character(len=*), intent(in), optional :: str

  if (PRESENT(str)) then
    write(*,*) str
  else
    write(*,*) "fallback"
  end if
emd subroutine doStuff2

如果不止一次,我会承认后者会变得有点麻烦,但是你的dostuffFirst尝试确实可以使用包装器。一种方法是,如果你不需要一个接受输入字符串或后备字符串的变量,如下所示。

subroutine dostuffFirst (string)
   character(len=*),intent(in),optional :: string

   if(present(string)) THEN
     call doStuff2(string)
   else
     call doStuff2("fallBack")
   endif

 end subroutine dostuffFirst

当然,如果你有很多可能的字符串,这也很快就会变得非常尴尬(很多嵌套的if)。

subroutine dostuffFirst(string1, string2, string3)
  character(len=*), intent(in), optional :: string1, string2, string3

  if (PRESENT(string1)) then
    if (PRESENT(string2)) then
      if (PRESENT(string3)) then
        call doStuff2(string1, string2, string3)
      else
        call doStuff2(string1, string2, "fallback3")
  ! etc
end subroutine dostuffFirst

解决这些问题的传统方法是选择一个非常长的str_to_use s。

subroutine dostuffFirst(string1, string2, string3)
  character(len=*), intent(in), optional :: string1, string2, string3
  character(AS_LONG_AS_I_EVER_NEED) str_to_use1, str_to_use2, str_to_use3

  if (PRESENT(string1)) then
    str_to_use1 = string1
  else
    str_to_use1 = "fallback1"
  end if
  ! etc
  call doStuff2(str_to_use1, str_to_use2, str_to_use3)
end subroutine dostuffFirst

但是,如果您愿意转向更现代的编译器/编码标准,那么您可以使用延迟长度字符变量。

subroutine dostuffFirst(string1, string2, string3)
  character(len=*), intent(in), optional :: string1, string2, string3
! Deferred length working variables
  character(:), allocatable :: str_to_use1, str_to_use2, str_to_use3

  if (PRESENT(string1)) then
    str_to_use1 = string1
  else
    str_to_use1 = "fallback1"
  end if
  ! etc
  call doStuff2(str_to_use1, str_to_use2, str_to_use3)
end subroutine dostuffFirst

与前一种情况大致相同,但不必担心正确选择长度。