9

私が書いている純粋な手順にエラーチェックを取り入れようとしています。次のようなものが欲しいです:

pure real function func1(output_unit,a)
    implicit none
    integer :: a, output_unit

    if (a < 0) then
        write(output_unit,*) 'Error in function func1: argument must be a nonnegative integer. It is ', a
    else
    func1 = a/3

    endif
    return
end function func1

ただし、純粋な関数は外部ファイルへの IO ステートメントを持つことが許可されていないため、ユニット番号を関数に渡してみました。たとえばoutput_unit = 6、これがデフォルトの出力です。gfortran はこれを依然として違法と見なします。これを回避する方法はありますか?realエラーが発生したときに文字列を出力する関数を(ここでは組み込み型ではなく)派生型にすることは可能ですか?

4

2 に答える 2

3

この問題を抱えたのはあなたが最初ではありません。標準のこの欠陥は Fortran 2015 で修正される予定です。 「プロシージャ内のステートメントの出現に関する制限はerror stoppure削除する必要があります」 .

Fortran 2008 標準にはerror stop、いくつかの新しい並列計算機能のコンテキストにステートメントが含まれていました。エラーを通知し、実行可能な限りすぐにすべてのプロセスを停止します。現在、どちらのstopステートメントerror stoppureプロシージャでは許可されていません。これは明らかにスレッドセーフではないためです。実際には、内部エラーが発生した場合、これは不必要に制限的になります。

コンパイラによっては、実装を辛抱強く待つ必要がある場合があります。Intelがifortコンパイラに実装していることを知っています。( "F2015: PURE/ELEMENTAL 手順での STOP および ERROR STOP の制限解除" )

別のアプローチについては、この質問を見ることができますが、do concurrentあなたの場合、pure.

(正解終わり)

汚れた手がオプションである場合...

それまでの間、あなたは次のような残忍なことをすることができます

pure subroutine internal_error(error_msg)
    ! Try hard to produce a runtime error, regardless of compiler flags.
    ! This is useful in pure subprograms where you want to produce an error, 
    ! preferably with a traceback.
    ! 
    ! Though far from pretty, this solution contains all the ugliness in this 
    ! single subprogram.
    ! 
    ! TODO: replace with ERROR STOP when supported by compiler
    implicit none

    character(*), intent(in) :: error_msg

    integer, dimension(:), allocatable :: molested

    allocate(molested(2))
    allocate(molested(2))
    molested(3) = molested(4)
    molested(1) = -10
    molested(2) = sqrt(real(molested(1)))
    deallocate(molested)
    deallocate(molested)
    molested(3) = molested(-10)
end subroutine internal_error

誰かが尋ねたとしても、あなたはこれを私から得たのではありません。

于 2016-06-22T14:28:42.827 に答える
-1

私は自分で答えを見つけました。詳細はこちら. 「時代遅れ」と見なされるものを使用しますが、それでもトリックを行います。それは代替リターンと呼ばれます。関数では機能しないため、プロシージャをサブルーチンとして記述します。

pure real subroutine procA(arg1)
    implicit none
    integer :: arg1

    if (arg < 0) then
        return 1 ! exit the function and go to the first label supplied
                 ! when function was called. Also return 2, 3 etc.
    else
        procA = ... ! whatever it should do under normal circumstances
    endif
endsubroutine procA

.... 

! later on, procedure is called
num = procA(a, *220)

220 write(6,*) 'Error with func1: you've probably supplied a negative argument'

おそらくより良いのは、eriktousが提案したことです-おそらく論理値または整数としてステータスを返すプロシージャを取得し、プロシージャを呼び出すたびにプログラムにこの値をチェックさせます。すべてが順調なら、続けてください。それ以外の場合は、関連するエラー メッセージを出力します。

コメント歓迎。

于 2012-01-09T12:36:45.700 に答える