3

メニュー エントリのリストを文字列 (理想的には、サブルーチン呼び出しで明示的に定義) として取得し、これらの文字列を番号付きオプションとして提示し、ユーザーにいずれかを選択するよう求める小さなユーティリティ ルーチンを作成しようとしています。検証の責任は、呼び出しルーチンに任されています。配列初期化ステートメントと同じ方法で定義された文字列の明示的な配列を使用した最初の試みは失敗したため、継続行を使用して、「マーカー」文字を含む単一の明示的な文字列を送信するアプローチを試みました。

以下は、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 コンパイラで確実に動作するソリューションが必要です。異なる長さの文字列の異なる長さのリストを使用して、プログラムで何度も呼び出すことができるようにしたいと考えています。

誰かがより良い解決策を持っていますか?

4

2 に答える 2

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)

サブルーチンは明示的なインターフェースを必要とするため、この短い例では内部手続きであることに注意してください。通常、本格的なプログラムのモジュールに必要です。

于 2013-10-31T08:37:07.747 に答える
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 でテスト済み

于 2013-10-31T14:18:13.307 に答える