[英]Restart a loop in Fortran
I have an algorithm that looks like this: 我有一个看起来像这样的算法:
10 WRITE (*,*) "Start"
DO I = 1, 10
WRITE (*,*) "Step"
IF(I .EQ. 5) then
go to 10
END IF
END DO
I want to restart the loop, when that if statement executes. 当if语句执行时,我想重新启动循环。 However, I don't want to have to use a go to, I tried this:
但是,我不想使用去,我试过这个:
10 WRITE (*,*) "Start"
DO I = 1, 10
WRITE (*,*) "Step"
IF(I .EQ. 5) then
I = 0; CYCLE
END IF
END DO
But then I get the error that I can't redefine the I variable, inside a loop. 但后来我得到的错误是我无法在循环内重新定义I变量。 So I'm not sure how to approach this.
所以我不确定如何处理这个问题。 Any help would be much appreciated
任何帮助将非常感激
A conceptually simple way to phrase this problem is: "I want to repeat a loop until it completes, where there is some abort condition". 一个概念上简单的方法来表达这个问题是:“我想重复一个循环,直到它完成,哪里有一些中止条件”。
This "repeat until it completes" is idiomatically a do construct with indeterminate iterations: 这个“重复直到它完成”是惯用的具有不确定迭代的do构造:
do
... ! Our actions; we exit this outer loop when we are satisfied
end do
[This could also be phrased as a do-while loop.] [这也可以用作do-while循环。]
With the inner loop: 内循环:
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
Now it's just a matter of handling "abort inner" and "exit outer". 现在只需要处理“中止内部”和“退出外部”。 Here
cycle
and exit
: 这里
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
The outer loop is labelled so that the cycle
statement in the inner loop can reference it. 标记外部循环,以便内部循环中的
cycle
语句可以引用它。 Without that label the cycle
will cycle the innermost loop containing it. 没有该标签,
cycle
将循环包含它的最内层循环。
Likely a typo here somewhere, but this has some other ideas in a "do while" sense. 在某处可能是一个错字,但这有一些其他想法在“做同时”的意义上。
ie One could poll something coming in. 即可以调查一些事情。
... 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
I can suggest to ways of solving this issue: either use a while loop or a recursive function (highly depends on your actual algorithm). 我可以建议解决这个问题的方法:使用while循环或递归函数(高度取决于您的实际算法)。 I am attaching a sample code for both cases (keep in mind that having variables with save qualifier is not the best idea, it's much better to do that with by passing variables as arguments to function - here it is used just for simplicity)
我为这两种情况附加了一个示例代码(请记住,使用保存限定符的变量不是最好的想法,通过将变量作为参数传递给函数来做更好的事情 - 这里仅用于简单)
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.