在 Fortran 中重新启动循环
Restart a loop in Fortran
我的算法如下所示:
10 WRITE (*,*) "Start"
DO I = 1, 10
WRITE (*,*) "Step"
IF(I .EQ. 5) then
go to 10
END IF
END DO
我想在 if 语句执行时重新启动循环。但是,我不想使用 go to,我试过这个:
10 WRITE (*,*) "Start"
DO I = 1, 10
WRITE (*,*) "Step"
IF(I .EQ. 5) then
I = 0; CYCLE
END IF
END DO
但后来我收到无法在循环内重新定义 I 变量的错误。所以我不确定如何处理这个问题。任何帮助将不胜感激
我可以建议解决此问题的方法:使用 while 循环或递归函数(在很大程度上取决于您的实际算法)。我附上了这两种情况的示例代码(请记住,使用带有保存限定符的变量并不是最好的主意,最好通过将变量作为参数传递给函数来实现 - 这里只是为了简单起见)
module functions
implicit none
integer :: restarted, save = 0
contains
recursive subroutine restart_loop
integer :: i
do i = 1, 10
print*, i
if ( i == 5 .and. restarted < 5 ) then
restarted = restarted + 1
call restart_loop
exit
end if
end do
end subroutine restart_loop
subroutine while_loop
integer :: i = 1
do while (i <= 10)
print*, i
if ( i == 5 .and. restarted < 5 ) then
i = 1
restarted = restarted + 1
end if
i = i + 1
end do
end subroutine while_loop
end module functions
program test_prog
use functions
implicit none
call while_loop
end program test_prog
表达这个问题的概念上简单的方法是:"I want to repeat a loop until it completes, where there is some abort condition"。
这个 "repeat until it completes" 是一个惯用的带有不确定迭代的 do 构造:
do
... ! Our actions; we exit this outer loop when we are satisfied
end do
[这也可以表述为 do-while 循环。]
使用内循环:
do
do i=1,10
... ! A conditional statement which aborts the inner loop
... ! And some actions
end do
! And once we're complete we exit the outer loop
end do
现在只需要处理 "abort inner" 和 "exit outer"。这里 cycle
和 exit
:
outer: do
print*, 'Start'
do i=1,10
print*, 'Step'
if (...) cycle outer ! Abort the inner loop
end do
exit outer ! The inner loop completed, so we're done
end do outer
外循环被标记,以便内循环中的cycle
语句可以引用它。如果没有该标签,cycle
将循环包含它的最内层循环。
这里可能有一处打字错误,但这在 "do while" 意义上有一些其他想法。
即可以轮询进来的东西。
... USE ISO... etc stuff.
REAL(KIND=C_FLOAT), DIMENSION(10) :: A
LOGICAL(KIND=C_BOOL) :: Question1 = .TRUE.
LOGICAL(KIND=C_BOOL) :: Question2 = .TRUE.
INTEGER(KIND=C_INT) :: Index = 0
INTEGER(KIND=C_INT) :: I = 5
WRITE(*,*)'Enter first index to skip:"
READ(*,*) I
Outer_Loop: DO WHILE (Question1) ! .eq. .TRUE.
Inner_Loop: DO WHILE (Question2) ! .EQV. .TRUE.
Index = Index + 1
IF(Index > UBOUND(A,1)) THEN
Question1 = .FALSE.
Question2 = .FALSE.
Exit
ENDIF
IF(Index == I) EXIT
!Whatever like A(INdex) = something....
ENDDO Inner_Loop
IF(Question1) THEN !We must have more to possibly read or do...
WRITE(*,*)'Do more? 1=yes, 0=No"
READ(*,*) I
IF(I == 1) THEN
WRITE(*,*)'Enter next index to skip:"
READ(*,*) I
Question2 = .TRUE.
!and one can do a reset of I=0 here, which then becomes I=1 the next time through the inner loop...
ELSE
Question1 = .FALSE.
Question2 = .FALSE.
EXIT
ENDIF
ELSE !Must have gotten here to exit at the end of array?
EXIT
ENDIF
ENDDO Outer_Loop
我的算法如下所示:
10 WRITE (*,*) "Start"
DO I = 1, 10
WRITE (*,*) "Step"
IF(I .EQ. 5) then
go to 10
END IF
END DO
我想在 if 语句执行时重新启动循环。但是,我不想使用 go to,我试过这个:
10 WRITE (*,*) "Start"
DO I = 1, 10
WRITE (*,*) "Step"
IF(I .EQ. 5) then
I = 0; CYCLE
END IF
END DO
但后来我收到无法在循环内重新定义 I 变量的错误。所以我不确定如何处理这个问题。任何帮助将不胜感激
我可以建议解决此问题的方法:使用 while 循环或递归函数(在很大程度上取决于您的实际算法)。我附上了这两种情况的示例代码(请记住,使用带有保存限定符的变量并不是最好的主意,最好通过将变量作为参数传递给函数来实现 - 这里只是为了简单起见)
module functions
implicit none
integer :: restarted, save = 0
contains
recursive subroutine restart_loop
integer :: i
do i = 1, 10
print*, i
if ( i == 5 .and. restarted < 5 ) then
restarted = restarted + 1
call restart_loop
exit
end if
end do
end subroutine restart_loop
subroutine while_loop
integer :: i = 1
do while (i <= 10)
print*, i
if ( i == 5 .and. restarted < 5 ) then
i = 1
restarted = restarted + 1
end if
i = i + 1
end do
end subroutine while_loop
end module functions
program test_prog
use functions
implicit none
call while_loop
end program test_prog
表达这个问题的概念上简单的方法是:"I want to repeat a loop until it completes, where there is some abort condition"。
这个 "repeat until it completes" 是一个惯用的带有不确定迭代的 do 构造:
do
... ! Our actions; we exit this outer loop when we are satisfied
end do
[这也可以表述为 do-while 循环。]
使用内循环:
do
do i=1,10
... ! A conditional statement which aborts the inner loop
... ! And some actions
end do
! And once we're complete we exit the outer loop
end do
现在只需要处理 "abort inner" 和 "exit outer"。这里 cycle
和 exit
:
outer: do
print*, 'Start'
do i=1,10
print*, 'Step'
if (...) cycle outer ! Abort the inner loop
end do
exit outer ! The inner loop completed, so we're done
end do outer
外循环被标记,以便内循环中的cycle
语句可以引用它。如果没有该标签,cycle
将循环包含它的最内层循环。
这里可能有一处打字错误,但这在 "do while" 意义上有一些其他想法。
即可以轮询进来的东西。
... USE ISO... etc stuff.
REAL(KIND=C_FLOAT), DIMENSION(10) :: A
LOGICAL(KIND=C_BOOL) :: Question1 = .TRUE.
LOGICAL(KIND=C_BOOL) :: Question2 = .TRUE.
INTEGER(KIND=C_INT) :: Index = 0
INTEGER(KIND=C_INT) :: I = 5
WRITE(*,*)'Enter first index to skip:"
READ(*,*) I
Outer_Loop: DO WHILE (Question1) ! .eq. .TRUE.
Inner_Loop: DO WHILE (Question2) ! .EQV. .TRUE.
Index = Index + 1
IF(Index > UBOUND(A,1)) THEN
Question1 = .FALSE.
Question2 = .FALSE.
Exit
ENDIF
IF(Index == I) EXIT
!Whatever like A(INdex) = something....
ENDDO Inner_Loop
IF(Question1) THEN !We must have more to possibly read or do...
WRITE(*,*)'Do more? 1=yes, 0=No"
READ(*,*) I
IF(I == 1) THEN
WRITE(*,*)'Enter next index to skip:"
READ(*,*) I
Question2 = .TRUE.
!and one can do a reset of I=0 here, which then becomes I=1 the next time through the inner loop...
ELSE
Question1 = .FALSE.
Question2 = .FALSE.
EXIT
ENDIF
ELSE !Must have gotten here to exit at the end of array?
EXIT
ENDIF
ENDDO Outer_Loop