Fortran from the ground up

Loops: do and do while

The counted do loop, the do while loop for when the end is a condition rather than a number, and the two statements that change the shape of a loop from inside: exit and cycle.

Part 4 of 12

Beginner14 min readBack to Courses

A loop with a known count

do i = 1, 10 runs its body ten times, with i taking the values 1 through 10. The third number, if you give one, is the step: do i = 2, 10, 2 takes 2, 4, 6, 8, 10, and a negative step counts down. The body ends at end do.

The loop variable is an ordinary integer that happens to be managed by the loop. Assigning to it inside the body is legal and almost always a mistake — the next iteration overwrites the value, so the loop count no longer means what it says. Declare it with the other integers, as implicit none requires.

After a counted loop finishes normally, the loop variable holds the first value past the limit — 11 for do i = 1, 10. That is a defined value, not a leftover, and a program that prints i after the loop is printing that number. Do not rely on it as a count; use a separate counter when the number of passes matters.

A loop with a condition

When the number of passes is not known in advance, do while (condition) repeats as long as the condition is true. The condition is tested before the body, so a loop whose condition is false from the start runs zero times — usually what you want, and worth remembering when a loop seems to do nothing.

Something inside the body has to change the condition, or the loop never ends. That is the one real requirement, and the usual bug is a counter that is updated on only some paths through the body.

exit can also be written inside a do while or an infinite do, which is how a loop that waits for input is written. A do with no control clause repeats forever, so every path through its body must eventually reach an exit or the program hangs.

exit, cycle and named loops

exit leaves the loop immediately, which is how a search stops once it has found what it wanted. cycle abandons the current pass and goes on with the next one, which turns "only the odd values" into a single test at the top of the body.

Both affect the innermost loop only. When there are two loops and you need to leave the outer one, put a name on it: outer: do i = 1, n ... end do outer, then exit outer from anywhere inside. Named loops cost one word and save a flag.

The do variable does not have to be an integer in modern Fortran, but an integer is the familiar case and the one the examples use. A real loop variable accumulates rounding error, so a loop that counts passes should count in integers even when the values it computes are real.

Three loops, one idea

total = 0
do i = 1, 10
  total = total + i
end do

do i = 10, 1, -1
  print *, 'counting down: ', i
end do

left = 3
do while (left > 0)
  print *, 'liftoff in ', left
  left = left - 1
end do

The count is fixed before the first pass

When a counted do begins, Fortran evaluates the start, the limit and the step once, works out how many passes that means, and then runs them. Changing the limit variable inside the body does not extend the loop, and the loop variable is set by the loop itself on each pass. That is why do i = 1, n is safe even when n was computed from values the body changes: the count was decided at the start.

The step decides the direction. do i = 10, 1 with the default step of 1 runs zero times, because the start is already past the limit; counting down needs do i = 10, 1, -1. A step of zero is rejected, and when the loop variable is an integer the step has to be an integer too.

Three loop mistakes cost real time: a do while whose condition never changes, which runs until the server stops it; exit used when cycle was meant, which ends the whole loop on the first match; and an inner loop that reuses the outer loop’s variable, so the outer count is destroyed. The first two are one word apart, and the third is why loop variables deserve names like row and col.

Try these next

  • Print every third number from 3 to 30 with do i = 3, 30, 3.
  • Halve a number with do while until it reaches 1, printing each value.
  • Write two nested loops and use exit outer to leave both when the product passes 20.

Sum, skip, count down

Run it and count the lines of output. Then make the first loop sum only the even numbers (hint: cycle), and make the countdown start at 5.

Output
Click "Run" to execute your code

Stop when you find it, count down by two

Run it and follow the two loops. Then change target to 50, predict the square before you run, and add a countdown from 5 with a step of -2.

Output
Click "Run" to execute your code

When a loop surprises you, print the loop variable and the value the condition depends on at the top of the body. In Fortran that is one print statement, and it answers "why did this run once" faster than reading the code again.

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

How many times does the body of do i = 1, 10 run?