如何停止子程序并举旗?
How to stop a subroutine and raise a flag?
我正在用 Fortran 95 编写一个程序(用 gfortran 编译),其中包含一个执行特定计算的子例程。正如 S. J. Chapman 在 "Fortran 95/2003 for Scientists & Engineers" 中所建议的那样,我试图在遇到错误时停止子例程并且 "throw"[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
"division" 接受一个整数输入值,并迭代地将它除以一个值,该值是输入值减去 steps-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++ 的行话。
看到您的示例,您似乎只是缺少 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
一种可能是改变
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
语句退出循环——Vladimir 的回答向您展示了如何使用 RETURN
更快速地退出子例程。无论您选择哪种方法,都不要忘记在离开子例程之前分配给 outval
。
我正在用 Fortran 95 编写一个程序(用 gfortran 编译),其中包含一个执行特定计算的子例程。正如 S. J. Chapman 在 "Fortran 95/2003 for Scientists & Engineers" 中所建议的那样,我试图在遇到错误时停止子例程并且 "throw"[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
"division" 接受一个整数输入值,并迭代地将它除以一个值,该值是输入值减去 steps-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++ 的行话。
看到您的示例,您似乎只是缺少 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
一种可能是改变
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
语句退出循环——Vladimir 的回答向您展示了如何使用 RETURN
更快速地退出子例程。无论您选择哪种方法,都不要忘记在离开子例程之前分配给 outval
。