Branching Control Structures

Control structures alter the normal sequential flow of a statement execution. IF statements allow a program to follow different paths depending on predefined criteria.

Logical IF

IF (logical-expression) statement

Any executable statement may appear in the statement except DO, IF, any part of a block IF statement or END.

If the logical-expression evaluates to .TRUE., then the statement is executed and control passes on to the next executable statement in the program. However, if the logical-expression evaluates to .FALSE., then the statement is ignored and as before, control passes on to the next executable statement in the program.

Example

      Y = 0.0
      IF (X .NE. 0.0) Y = 1.0/X
      WRITE(*,*)X,Y

The variable Y is assigned the value 0.0. Then a logical IF statement is encountered. If X is nonzero (supposedly X has been assigned a value somewhere earlier in the program), then Y is assigned the value of 1.0/X and both values are written out to the default output device. However, if X is zero, then the logical expression X .NE. 0.0 is false. In this instance, the statement Y = 1.0/X is skipped and control passes immediately to the WRITE statement following.

Block IF

The block IF statement is a more general version of the simple logical IF and can take several forms, depending on the complexity of the decisions and/or branching.

IF-THEN-END IF

IF (logical-expression) THEN
   statement1
   statement2statementn
END IF

This is the simplest form of the block IF. Instead of a single executable statement, the word THEN follows the logical-expression. Then one or more executable statements are listed in the order they should be executed (this is the 'statement block' which gives the block IF its name) and the block IF statement concludes with an END IF statement.

Example

      Y = 0.0
      Z = -1.0
      IF (X .NE. 0.0) THEN
         Y = 1.0/X
         Z = X**2
      END IF
      WRITE(*,*)X,Y,Z

Here the variable Y is assigned the value 0.0 and the variable Z is assigned the value -1.0. Then a block IF statement is encountered. If X is nonzero then Y is assigned the value of 1.0/X and Z is assigned the value X**2. Then all three values are written out to the default output device. However, if X is zero, then the logical expression X .NE. 0.0 is false. In this instance, the statements inside the block are skipped and control passes immediately to the WRITE statement following the END IF statement.

IF-THEN-ELSE-END IF

IF (logical-expression) THEN
   statement-block1
ELSE
   statement-block2
END IF

This slightly more complicated case allows for one statement block to be executed if the logical-expression evaluates to .TRUE. and an alternative statement block to be executed if the logical-expression is .FALSE.

Example

Suppose CREDIT and DEBIT have been declared to be INTEGER variables and TRNSCT (short for 'transaction') has been declared to be a REAL variable.

      IF (TRNSCT .GE. 0.0) THEN
         CREDIT = CREDIT + 1
      ELSE
         DEBIT  = DEBIT + 1
      END IF

Assuming that these variables have been given values earlier in the program, this IF statement tests to see if TRNSCT is non-negative. If it is, the logical expression evaluates to .TRUE. and the variable CREDIT is incremented by 1. Otherwise, the variable DEBIT is incremented by 1. Only one of the blocks is executed, depending on the value of the logical-expression. Once one of the blocks has been executed, control transfers to the end of the block IF and the statements following.

Note how this structure differs from the previous one. In the IF-THEN-END IF, it is possible for no action to take place. However, with an IF-THEN-ELSE-END IF structure, one of the blocks must be executed.

IF-THEN-ELSE IF-THEN-ELSE-END IF

IF (logical-expression1) THEN
   statement-block1
ELSE IF (logical-expression2) THEN
   statement-block2
ELSE IF (logical-expression3) THEN
   statement-block3
…
ELSE
   statement-blockn
END IF

This is the most general case, allowing for multiple decisions with an optional default. Any number of ELSE IF-THEN blocks may be used and the final ELSE block is optional. If it exists, then it will be executed if none of the preceding logical expressions evaluate to .TRUE. However, if there is no ELSE block, then it is entirely possible that none of the blocks in the block IF statement will be executed. Note that if an ELSE block is to be included in a block IF statement, it must be the final block.

Example

The Gregorian reform of the Julian calendar during the sixteenth century gave us the rule we use today to determine leap years. Years evenly divisible by 4 are leap years but the only centurial years (years ending with 00) that are leap years are those evenly divisible by 400.

      IF (MOD(YEAR,400) .EQ. 0) THEN
         WRITE(*,*)YEAR,' is a leap year'
      ELSE IF (MOD(YEAR,100) .EQ. 0) THEN
         WRITE(*,*)YEAR,' is NOT a leap year'
      ELSE IF (MOD(YEAR,4) .EQ. 0) THEN
         WRITE(*,*)YEAR,' is a leap year'
      ELSE
         WRITE(*,*)YEAR,' is NOT a leap year'
      END IF

This block IF statement is one way of testing to see if an INTEGER variable called YEAR is a leap year or not. (Note that this is a very inefficient algorithm for calculating leap years!) The MOD function returns the value argument1 modulo argument2. The first logical expression, (MOD(YEAR,400) .EQ. 0 returns .TRUE. if the year is evenly divisible by 400. If it is, then the year followed by the message is a leap year is written to the standard output device. If not, the second logical expression is evaluated. This one tests to see if YEAR is evenly divisible by 100. This takes care of the other three centurial year cases. The third logical expression looks for years that are evenly divisible by 4. If none of the logical expressions evaluate to .TRUE., then the ELSE block is executed, leaving us with no leap year.

General Considerations

Any executable statement may appear in the statement block except END. In particular, another complete block IF or a complete DO loop may appear within the statement block. Control may pass out of the block (for instance, with a GO TO statement) but it is illegal to transfer into the middle of a block. After a block of statements has been executed, control is passed to the next executable statement following the END IF statement (unless, of course, control was passed out of the block in some manner).

If a block IF statement contains many branches, then the order in which the ELSE IF blocks occur may affect efficiency. Place the blocks which are most likely to be executed near the top of the block IF. Remember: the optional ELSE block must always occur last.

In each of the examples, the statement blocks are indented slightly from the left. This is not a requirement but makes the structure of the program much more immediately obvious, particularly when there is deep nesting of control structures.

Nesting

Nesting refers to the inclusion of a complete control structure within another control structure. For instance, it is possible to place a block IF statement within another block IF. The two block IF statements do not overlap; rather, one contains the other.

Example

Consider this program fragment where the variables A, B and C have already been assigned values.

      IF (A .NE. 0.0) THEN
         DISC = B**2 - 4.0*A*C
         IF (DISC .GT. 0.0) THEN
            WRITE(*,*)'The roots are real and distinct'
         ELSE IF (DISC .LT. 0.0) THEN
            WRITE(*,*)'The roots are complex conjugates'
         ELSE
            WRITE(*,*)'The roots are real and identical'
         END IF
      ELSE
         WRITE(*,*)'The equation is linear, not quadratic'
      END IF

If A is non-zero, then the first statement block is executed. The value for the variable DISC is calculated and then another complete block IF statement is encountered. The string The roots are real and distinct is written out if DISC is positive. If DISC is exactly zero, then The roots are real and identical is written out. However, if DISC is neither positive nor zero (that is, if DISC is negative), then The roots are complex conjugates is written out. This inner or nested block IF statement then concludes within in the first statement block of the outer block IF.

If, however, A is zero, then the second statement block is executed; namely, the string The equation is linear, not quadratic is written out. The outer block IF statement then concludes.

The careful use of indentation makes nested constructs easier to see although it has no effect on the running of the program.

It is also possible to nest different types of control structures. For instance, you can nest a DO loop within a statement block of a block IF statement. Conversely, a DO loop can contain a block IF. The only consideration is that one structure must be fully contained within the other. Overlap is not allowed.

Arithmetic IF

IF (arithmetic-expression) label-1, label0, label1

This form of IF statement is obscure and its use is strongly discouraged.

It is equivalent to this block IF statement:

IF (arithmetic-expression .LT. 0) THEN
   GO TO label-1
ELSE IF (arithmetic-expression .EQ. 0) THEN
   GO TO label0
ELSE
   GO TO label1
END IF