在 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"。这里 cycleexit:

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