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