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

时间:2013-10-31 08:08:14

标签: fortran fortran95

我正在尝试编写一个小的实用程序例程,它可以将菜单条目列表作为字符串(理想情况下,在子例程调用中明确定义),将这些字符串显示为编号选项,并要求用户选择一个。验证的责任留给调用例程。我的第一次尝试,使用以与数组初始化语句相同的方式定义的显式字符串数组,失败了,所以我尝试使用连续行发送带有'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

不幸的是,这使用Linux gfortran 4.5.x失败了。我需要一个能够在尽可能多的编译器上尽可能多地使用F95编译器的解决方案,以及尽可能多的平台。我希望能够在我的程序中多次调用它,使用不同长度的字符串列表。

有没有人有更好的解决方案?

2 个答案:

答案 0 :(得分:2)

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

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)

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

答案 1 :(得分:0)

简单修复,不要修改以文字形式传递的字符串:

!  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)

用gfortran 4.x进行测试