2017-02-03 9 views
3

У меня есть алгоритм, который выглядит следующим образом:Перезапустите петлю в Fortran

10 WRITE (*,*) "Start" 
DO I = 1, 10 
WRITE (*,*) "Step" 
IF(I .EQ. 5) then 
    go to 10 
END IF 
END DO 

Я хочу, чтобы перезапустить цикл, когда что если оператор выполняет. Тем не менее, я не хочу, чтобы использовать идти, я попытался это:

10 WRITE (*,*) "Start" 
DO I = 1, 10 
WRITE (*,*) "Step" 
IF(I .EQ. 5) then 
    I = 0; CYCLE 
END IF 
END DO 

Но тогда я получаю сообщение об ошибке, что я не могу переопределить переменную I, внутри цикла. Поэтому я не уверен, как подойти к этому. Любая помощь была бы очень благодарна

+2

Похоже, вы пытаетесь узнать, что это здорово. Ответ, который вы приняли, - это * не * лучший способ решить вашу проблему. – Ross

ответ

-2

Я могу предложить способы решения этой проблемы: использовать цикл 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 
+0

Как вы помещаете подпрограмму внутри основной программы? Я всегда получаю ошибки, когда я это делаю (Unclassifiable statement at (1)). Подпрограммы работают только для меня, когда они находятся за пределами основной программы, или до конечного оператора:/ – efefef

+0

@efefef вы этого не делаете, это невозможно в Fortran. Как вы можете видеть здесь, я определяю модуль, содержащий подпрограммы - по-моему, это лучше, чем просто определение подпрограммы, поскольку оно обеспечивает определенную (ограниченную) функциональность пространства имен. Обратите внимание на строку «use functions» - это то, как вы импортируете модуль для использования. – Chaosit

+1

@efefef Я настоятельно рекомендую вам ознакомиться с некоторыми из fortran [documentation] (http://stackoverflow.com/documentation/fortran/topics) здесь. Помещение подпрограмм в модули - это очень хорошая идея. Также см. [Эту страницу документа] (http://stackoverflow.com/documentation/fortran/2203/program-units-and-file-layout/7202/internal-subprograms#t=201702031606390419663) о том, как включить подпрограмму внутри программный блок. –

9

Концептуально простой способ сформулировать эту проблему: «Я хочу повторить цикл до тех пор, пока он не завершится, когда есть какое-то условие прерывания».

Это «повтор, пока он не закончит» является идиоматически сделай построить с неопределенными итераций:

do 
    ... ! Our actions; we exit this outer loop when we are satisfied 
end do 

[Это также может быть выражено как делать-пока петля.]

С внутреннего цикла:

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 

Теперь это всего лишь вопрос обработки «прерывания внутреннего» и «выхода наружу». Здесь 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 будет циклически содержать самую внутреннюю петлю.

-1

Вероятно, здесь есть опечатка, но у этого есть некоторые другие идеи в смысле «делать пока».

т.е. один опрашивать что-то поступать.

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

 Смежные вопросы

  • Нет связанных вопросов^_^