2015-08-07 2 views
1

Я пишу программу в Fortran 95 (для компиляции с помощью gfortran), содержащую подпрограмму, выполняющую определенное вычисление. Как было предложено в «Fortran 95/2003 для ученых &« Инженеры »от SJ Chapman, я пытаюсь остановить подпрограмму при возникновении ошибки и« бросить »[1] флаг ошибки, который является« catch »ed [1 ] вызывающей программой, которая предпримет все необходимые действия. В идеале, я собираюсь что-то вроде:Как остановить подпрограмму и поднять флаг?

! Pseudo-code 
PROGRAM my_prog 
    integer :: error_flag 
    CALL my_subr (<input_args>, <output_args>, error_flag) 
    ! Also error_flag is an output: 0 -> everything OK, 1 -> error 
    IF (error_flag /= 0) THEN 
     WRITE (*,*) 'Error during execution of "my_subr"' 
    ELSE 
     ... do something ... 
    END IF 
END PROGRAM my_prog 

Как я могу остановить подпрограмму и корректно обрабатывать ошибки?

Ниже приведен пример: «деление» subroutine принимает целочисленное входное значение и итеративно делит его на значение, которое является входным значением, уменьшенным на количество шагов-1. Когда такое значение достигает нуля, флаг должен быть поднят, и подпрограмма должна выйти без выполнения деления на ноль.

SUBROUTINE division (inval, outval, error_flag) 
    IMPLICIT NONE 

    INTEGER, INTENT(IN) :: inval 
    REAL, INTENT(OUT) :: outval 
    INTEGER, INTENT(OUT) :: error_flag ! 0 -> OK, 1 -> error 

    INTEGER :: i 
    REAL :: x 

    error_flag = 0 
    x = REAL(inval) 
    DO i = 0, 10 
    IF (inval-i == 0) error_flag = 1 
    ! How can I gracefully exit now? 
    x = x/REAL(inval-i) 
    END DO 

END SUBROUTINE division 

PROGRAM my_prog 
    IMPLICIT NONE 
    REAL :: outval 
    INTEGER :: error_flag 
    CALL division (8, outval, error_flag) 
    IF (error_flag == 1) THEN 
    WRITE (*,*) 'Division by zero' 
    ELSE 
    WRITE (*,*) 'Output value:', outval 
    END IF 
END PROGRAM my_prog 

Примечания:

[1] Я заимствование (в, вероятно, несоответствующим образом) жаргон C++ 's.

+1

В вашем примере используется флаг ошибки. Чем больше вы этого не сделаете? У вас была проблема с этим? Fortran ближе к C в этом отношении (C использует возвращаемые значения очень похожим образом). –

+1

Внутри подпрограммы вы должны использовать ту же логику, что и ваша вызывающая программа, - оберните потенциально неприятный код внутри какой-либо логики, чтобы перейти к концу процедуры без дополнительной суматохи при возникновении ошибки. –

+0

@VladimirF: Проблема не в вышеупомянутом псевдокоде, а в 'подпрограмме': допустим, у меня есть цикл, и я сталкиваюсь с делением на ноль. Я хотел бы поднять флаг _ before_ деление выполняется, _not_ выполнить деление и сразу же «выйти» подпрограмму. Как я могу это сделать? –

ответ

1

Видя ваш пример, кажется, что вы просто отсутствует return заявление:

error_flag = 0 
    x = REAL(inval) 
    DO i = 0, 10 
    IF (inval-i == 0) then 
         error_flag = 1 
         return 
    END IF 

    x = x/REAL(inval-i) 
    END DO 
+1

Нет, все в порядке. Зачем? У вас также может быть больше инструкций 'exit', которые советуют глупо. По крайней мере, если применять слепо. –

1

Одним из возможных вариантов было бы изменить

DO i = 0, 10 
    IF (inval-i == 0) error_flag = 1 
    ! How can I gracefully exit now? 
    x = x/REAL(inval-i) 
    END DO 

в

DO i = 0, 10 
    IF (inval-i == 0) THEN 
     error_flag = 1 
     EXIT 
    END IF 
    ! Now you have gracefully exited 
    x = x/REAL(inval-i) 
    END DO 
    ! Code to tidy up if the error flag was set 

Здесь EXIT заявление выходит из цикла - ответ Владимира показывает вам как использовать RETURN для более быстрого выхода из подпрограммы. Какой бы подход вы ни выбрали, не забудьте назначить outval перед тем, как покинуть подпрограмму.

Смежные вопросы