Restart a loop in Fortran

落花浮王杯 提交于 2021-01-27 13:42:55

问题


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. 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. So I'm not sure how to approach this. Any help would be much appreciated


回答1:


I can suggest to ways of solving this issue: either use a while loop or a recursive function (highly depends on your actual algorithm). 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



回答2:


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
  ...  ! Our actions; we exit this outer loop when we are satisfied
end do

[This could also be phrased as a do-while loop.]

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:

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. Without that label the cycle will cycle the innermost loop containing it.




回答3:


Likely a typo here somewhere, but this has some other ideas in a "do while" sense.

i.e. 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


来源:https://stackoverflow.com/questions/42026668/restart-a-loop-in-fortran

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!