将一组显式字符串传递给Fortran子例程

将一组显式字符串传递给Fortran子例程,fortran,fortran95,Fortran,Fortran95,我试图编写一个小型实用程序例程,它可以将菜单项列表作为字符串(理想情况下,在子例程调用中明确定义),将这些字符串作为编号选项显示,并要求用户选择一个。验证的责任留给调用例程。我的第一次尝试是使用以与数组初始化语句相同的方式定义的字符串的显式数组,但失败了,因此我尝试了使用连续行发送带有“marker”字符的单个显式字符串的方法 以下内容似乎在Cygwin下的gfortran 4.7.3中起作用: PROGRAM menutest IMPLICIT NONE INTEGER :: n CALL m

我试图编写一个小型实用程序例程,它可以将菜单项列表作为字符串(理想情况下,在子例程调用中明确定义),将这些字符串作为编号选项显示,并要求用户选择一个。验证的责任留给调用例程。我的第一次尝试是使用以与数组初始化语句相同的方式定义的字符串的显式数组,但失败了,因此我尝试了使用连续行发送带有“marker”字符的单个显式字符串的方法

以下内容似乎在Cygwin下的gfortran 4.7.3中起作用:

PROGRAM menutest
IMPLICIT NONE
INTEGER :: n
CALL menu(n, 'This is option 1$&
              Option Two$&
              Option number three$' )
WRITE(*,*) 'You chose option ' ,n
END PROGRAM menutest

SUBROUTINE menu(n, entrylist)
IMPLICIT NONE
INTEGER :: n, i, nitems,pos1,pos2
CHARACTER (LEN=*) :: entrylist
!
pos1 = 1
pos2 = 1
i=1
! Loop over entries
DO
  entrylist = entrylist(pos1:)
  pos2 = INDEX(entrylist,'$')
  IF (pos2 == 0) THEN
     EXIT
  END IF
  WRITE (*,'(A,I2,A,A)') '(',i,') ',entrylist(:pos2-1)
  i = i+1
  pos1 = pos2+1
END DO
WRITE(*,*) 'Choose an option from the menu'
READ(*,*) n
END SUBROUTINE menu
不幸的是,使用LinuxGfortran4.5.x时失败了。我需要一个能够在尽可能多的编译器上,在尽可能多的平台上,在尽可能多的F95编译器上可靠工作的解决方案。我希望能够在我的程序中多次调用它,使用不同长度的列表和不同长度的字符串


有谁有更好的解决方案吗?

您当然可以发送字符串数组:

CALL menu(n, [character(20) :: 'This is option 1', &
                               'Option Two', &
                               'Option number three'] )
write(*,*) 'You chose option ' ,n

contains
  subroutine menu(n, entrylist)
    CHARACTER(len=*),intent(in) :: entrylist(:)
    integer, intent(out) :: n
    integer i
    do i=1,size(entrylist)
      write(*,*) trim(entrylist(i))
    end do
    read(*,*) n
  end subroutine

end
这种形式的数组构造函数是Fortran 2003。如果必须避免,则通过元素的正常分配来构建数组

strings(1) = 'This is option 1'
strings(2) = 'Option Two'
strings(3) = 'Option number three'
call menu(n, strings)

注意,子例程需要一个显式接口,因此在这个简短的示例中它是一个内部过程。您通常希望它位于全尺寸程序的模块中。

简单的修复方法是,不要修改作为文本传递的字符串:

!  entrylist = entrylist(pos1:)  <-- get rid of this offending line
   pos2 = pos1-1+INDEX(entrylist(pos1:),'$')
   IF (pos2 == pos1-1) THEN

      ...

   WRITE (*,'(A,I2,A,A)') '(',i,') ',entrylist(pos1:pos2-1)

!entrylist=entrylist(pos1:)这里的错误是您正在修改作为文本传递的字符串。您可以通过从不重新分配而是跟踪开始/结束位置和写入来解决此问题。。entrylist(ipos1:ipos2)…也违反了字符上下文中的自由形式行连续规则(在这种情况下,连续行必须以符号开头)。@IanH很好。福威格夫特兰觉得很好。省略连续行上的前导空格。显然,是否包含这些空格存在歧义。