简体   繁体   English

在Fortran中重新启动循环

[英]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 : 这里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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM