http://ponce.sdsu.edu/fortran_book_10.html





CHAPTER 10 

 

ADDITIONAL FEATURES 

 

Chapters 1 through 6 dealt with the basic elements of the Fortran language. Chapters 7 through 9 covered the more advanced features such as DO loops, subcripted variables, and subprograms. This chapter contains a few additional features of the Fortran language which were not covered in previous chapters. These features include: 

  • Transfer of control in input/output 
  • Complex intrinsic functions, including complex arithmetic 
  • Character manipulation, including character substrings and character intrinsic functions. 
 
10.1 TRANSFER OF CONTROL IN INPUT/OUTPUT 

In Chapter 2 we learned how to work with the READ and WRITE statements by including two keyword specifiers in the control list (the logical unit and the format label). These were enclosed within parentheses and separated by a comma, as in

      READ(UNIT=5,FMT=100) A,B,C

In practice, this is usually shortened to: 

      READ(5,100) A,B,C 

An additional and often useful feature of the READ statement is the possibility to transfer control to an executable labeled statement if either of the following is encountered during runtime: 

  • an end-of-file condition, or 
  • an error condition. 

An example of a READ statement with keyword specifiers to accomplish transfer of control is:

      READ(UNIT=5,FMT=100,END=90,ERR=92) 

where END and ERR are the keyword specifiers for end-of-file condition and error condition, respectively.

The UNIT and FMT specifiers are optional if they appear in first and second place, respectively, on the control list. Thus, the previous statement may be reduced to 

      READ(5,100,END=90,ERR=92) 

The READ statement can include either the END or ERR specifiers, or both, in any order. The END= and ERR= are required. The WRITE statement can include only the ERR specifier. The statement labels to the right of the equal sign must be valid labels within the same program unit.

An end-of-file condition occurs when the execution of a READ statement runs out of records to read. When a READ statement with an end-of-file specifier encounters an end-of-file, control is transferred to the statement designated by the END specifier. If there is no END specifier, control is transferred to the statement designated by the ERR specifier. Is neither END nor ERR specifier appears, execution terminates with a runtime error.

For example, an end-of-file condition would occur if a READ statement within a DO loop is supposed to read 10 values, but only 9 values appear in the input file. As the 10th READ statement is executed, control searches for the 10th value and instead, it finds the end of the file. 

As you can see, the end-of-file feature is useful when the number of data records to be read is not fixed before hand. Such would be the case of an input file whose length varies with each application, and the calculations do not depend on the total number of values read. In this case, the READ can proceed with an end-of-file specifier, and control is transferred in an orderly manner when the entire input file has been read. 

An error condition occurs when an error is encountered during the execution of a READ or WRITE statement. In this case, control is transferred to the statement designated by the ERR specifier. If there is no ERR specifier, execution terminates with a runtime error.

The following example program illustrates the use of END and ERR specifiers. This example counts, reads, and writes several values of variable A, one at a time, in a GO TO-CONTINUE loop according to format 100. If an end-of-file condition is encountered during the execution of the READ statement (no more records are found in the input file), control is transferred to statement 90, an appropriate message is printed, and STOP 90 terminates execution. If an error is encountered during READ (for instance, the occurrence of an extraneous character such as @), control is transferred to statement 92, an appropriate message is printed, and STOP 92 terminates execution. If an error is encountered during WRITE (perhaps, a field overflow due to an insufficient format), control is transferred to statement 94, an appropriate message is printed, and STOP 94 terminates execution. 

Example Program: Transfer of Control in Input/Output 

C234567890 

      PROGRAM SPECIFIER 

   10 CONTINUE  

      N= N+1

      READ(5,100,END=90,ERR=92) A   

      WRITE(6,200,ERR=94) A 

      GO TO 10 

   90 WRITE(6,'(1X,A)')

     1'END-OF-FILE ENCOUNTERED DURING READ, STOP= '

      STOP 90 

   92 WRITE(6,'(1X,A)') 

     1'ERROR ENCOUNTERED DURING READ, STOP= ' 

      STOP 92 

   94 WRITE(6,'(1X,A)') 

     1'ERROR ENCOUNTERED DURING WRITE, STOP= ' 

      STOP 94 

  100 FORMAT(F10.0)

  200 FORMAT(1X,'NUMBER= ',I3,5X,'A= ',F6.2)

      END 

 

10.2 COMPLEX INTRINSIC FUNCTIONS

Complex Arithmetic 

In arithmetic, a complex number is written as 

a + bi 

where a is the real part, b is the imaginary part, and i = √ -1 = (-1)1/2.

In Fortran, a complex number is written as

(a,b

The modulus c of a complex number is its absolute value, that is, the hypotenuse of a right triangle of sides a and b :

c = (a2 + b2)1/2

The conjugate of a complex number (a + bi) is the complex number (a - bi). Conversely, the conjugate of complex number (a - bi) is (a + bi).

 The following intrinsic functions related to complex numbers are valid:

  •  CMPLX 
  • ABS 
  • CONJG 
  • REAL 
  • AIMAG 

CMPLX takes two integer or real values as arguments and converts them into the real and imaginary parts of a complex value. It has the form: 

      Z= CMPLX(A,B)

in which Z is a complex variable, A is an integer/real variable/constant assigned to the real part of Z, and B is an integer/real variable/constant assigned to the imaginary part of Z. When only one argument is given, this argument is taken as the real part, and a value of zero is taken as the imaginary part. 

The intrinsic function ABS can accept a real or complex number as an argument. If the argument is real, the function returns the absolute value of the argument. If the argument is complex, the function returns the modulus of the argument. 

      COMPLEX Y 

      DATA X,Y /-8.,(3.,4.)/ 

      C= ABS(X) 

      D= ABS(Y) 

In this example, C = |-8.| = 8., and D = (3 2 + 4 2) 1/2 = 5. 

The intrinsic function CONJG accepts a complex argument and returns its complex conjugate. The intrinsic function REAL accepts a complex argument and returns its real part.  The intrinsic function AIMAG accepts a complex argument and returns its imaginary part. 

The following example program illustrates the use of complex intrinsic functions. This example declares three complex variables X, Y, and Z, and initializes two real values A and B with a DATA statement (A= 3., B = 4.). Then it uses the intrinsic function CMPLX to define X and Y, ABS to calculate the modules of X and Y, CONJG to get the conjugate of X, and REAL and AIMAG to separate X into its real and imaginary components.

 Example Program: Use Of Complex Intrinsic Functions 

C234567890

      PROGRAM COMPLEX_INTR 

      COMPLEX X,Y,Z 

      DATA A,B /3.,4./ 

      X= CMPLX(A,B)   

      Y= CMPLX(6.,8.) 

      C= ABS(X) 

      D= ABS(Y) 

      Z= CONJG(X) 

      ALPHA= REAL(X)

      BETA= AIMAG(X) 

      WRITE(6,*) X,Y

      WRITE(6,*) C,D 

      WRITE(6,*) Z 

      WRITE(6,*) ALPHA,BETA 

      END 

The results (under unformatted write) are shown below. 

(3.0000,4.0000)      (6.0000,8.0000) 

5.0000           10.0000 

(3.0000,-4.0000) 

3.0000           4.0000

Operations with Complex Numbers

Operations with complex numbers include addition, subtraction, multiplication, division, and exponentiation.

In the addition of complex numbers, the real part of the sum is the sum of the real parts, and the imaginary part of the sum is the sum of the imaginary parts. Therefore: 

(a + bi) + (c + di) = (a + c) + (b + d) i 

Subtraction of complex numbers operates in the same way as addition: 

(a + bi) - (c + di) = (a - c) + (b - d) i 

Multiplication of complex numbers follows from the fact that i 2 = -1. Therefore: 

(a + bi) (c + di) = (ac - bd) + (ad + bc) i

Division of complex numbers is accomplished by multiplying both numerator and denominator by the conjugate of the denominator. This leads to: 

(a + bi) / (c + di) = [(ac + bd) - (ad - bc) i ] / (c2 + d2

Exponentiation of complex numbers to an integer power is accomplished in the same way as for real num bers. For instance:

                 (a + bi)3 = (a + bi) (a + bi) (a + bi

The following example program illustrates operations with complex numbers. This example defines three complex variables X, Y, and Z, and initializes the variables X and Y with a DATA statement. It proceeds to add, subtract, multiply, and divide these variables, each time writing out the result Z. Then it takes X to the power 2 and writes the result Z, and Y to the power 3, and writes the result Z.

 Example Program: Operations with Complex Variables 

C234567890 

      PROGRAM COMPLEX_OPERATIONS 

      COMPLEX X,Y,Z 

      DATA X,Y /(3.,4.),(1.,2.)/ 

      Z= X + Y 

      WRITE(6,*) 'Z= ',Z 

      Z= X - Y 

      WRITE(6,*) 'Z= ',Z 

      Z= X*Y

      WRITE(6,*) 'Z= ',Z 

      Z= X/Y 

      WRITE(6,*) 'Z= ',Z 

      Z= X**2 

      WRITE(6,*) 'Z= ',Z 

      Z= Y**3

      WRITE(6,*) 'Z= ',Z 

      END

The results (under unformatted write) are shown below. 

Z= (4.000000,6.000000)

Z= (2.000000,2.000000) 

Z= (-5.000000,10.00000) 

Z= (2.200000,-0.4000000)

Z= (-7.000000,24.00000)

Z= (-117.0000,44.00000) 

 

10.3 CHARACTER MANIPULATION

Character Substrings

A character substring is a segment of a character variable or character array element. It has the form: 

ABC(ileft:iright

where ABC is a character variable or array, and the integer arguments ileft and iright specify the leftmost and rightmost position of the substring of ABC, respectively. 

The following rules apply to character substrings: 

  • The value of ileft should be at least 1 and at most equal to iright. If omitted, the value of 1 is assumed. 

  • The value of iright should be at least equal to ileft and at most equal to the length of the character variable. If omitted, the value of length is assumed.

 Example 1

      CHARACTER*26 ALPHABET 

      DATA ALPHABET 

     1/'ABCDEFGHIJKLMNOPQRSTUVWXYZ'/ 

      WRITE(6,*) ALPHABET(9:14) 

This example declares a character variable of 26 characters named ALPHABET, and uses a DATA statement to assign it a string consisting of all 26 letters of the alphabet, Then, it writes in free format a substring consisting of the characters 9 to 14, which is the substring IJKLMN. 

Example 2 

      PARAMETER (NE=8,NC=10) 

      CHARACTER*(NC) NAME(NE) 

      DATA (NAME(J),J=1,4)/ 

     1'SMITH, JOE','PRICE, BOB', 

     2'LYONS, PAT','JONES, KIM'/

      DO 10 J=1,4  

      WRITE(6,100) NAME(J)(:5) 

   10 END DO 

  100 FORMAT(1X,A) 

This example declares a character array NAME of NE= 8 elements and NC= 10 characters per element, specified via the PARAMETER statement. Four elements of NAME are assigned using a DATA statement. The array of substrings containing characters 1 through 5 (the last names) are written following format 100. Since the left integer has been omitted, a value of 1 is assumed. 

 
Character Intrinsic Functions

The following character intrinsic functions are valid: 

  • LEN(C) 
  • INDEX(C1,C2) 
  • ICHAR(C) 
  • CHAR(I) 

The character intrinsic function LEN(C) returns the length of its character variable argument C, as in the following example. 

      CHARACTER*15 NAME,ADDRESS*20

      J= LEN(NAME) 

      K= LEN(ADDRESS) 

In this example, J = 15 (the length of character variable NAME), and K = 20 (the length of character variable ADDRESS). 

The character intrinsic function INDEX(C1,C2) searches for the value of a character substring C2 in the value of a specified character variable C1. Then:

  • If the value of C2 is found, the function gives the substring's starting position. 

  • If the value of C2 occurs more than once, the starting position of the leftmost occurrence is returned. 

  • If the value of C2 is not found, the function gives a value of zero (0). 

The following example illustrates the use of character intrinsic function INDEX(C1,C2). 

C234567890 

      CHARACTER*26 ALPHABET,INTEG*6 

      DATA ALPHABET /'ABCDEFGHIJKLMNOPQRSTUVWXYZ'/

      DATA INTEG /'IJKLMN'/ 

      L= INDEX(ALPHABET,INTEG) 

In this example, two character variables ALPHABET and INTEG are declared and assigned constant values ABCDEFGHIJKLMNOPQRSTUVWXYZ and IJKLMN. INTEG is seen to be a substring of ALPHABET, starting with character number 9. The intrinsic function INDEX returns the value L = 9.

The character intrinsic function ICHAR(C) takes the argument C, a character variable, and returns an integer equivalent in ASCII code. If C is longer than one character, only the first character is considered; the remainder is ignored. Table 10.1 shows ASCII code equivalences.

The following example illustrates the use of character intrinsic function ICHAR(C). 

      CHARACTER BLETTER

      DATA BLETTER /'B'/

      IEQUIVB= ICHAR(BLETTER) 

      WRITE(6,*) IEQUIVB 

This example declares a character variable BLETTER, of length one character. (Note that the declaration statement does not include a length. In this case, the length is assumed to be 1 by default; see Section 3.7). A DATA statement is used to assign a value of B to the character variable BLETTER. According to Table 10.1, the ASCII code equivalent of letter B is 66. Therefore: IEQUIVB = 66.

 

TABLE 10.1

ASCII CODE EQUIVALENCES 

 32

 33             ! 

34             " 

35            # 

36            $ 

37            % 

38            & 

39             ' 

40            ( 

41             ) 

42            * 

43            + 

44             , 

45            - 

46             . 

47             / 

48            0 

49            1 

50            2 

51            3 

52            4 

53            5 

54            6

55           7 

56            8 

57            9 

58             : 

59             ; 

60             <

61            = 

62             >

63             ?  

64             @ 

          65           A 

          66           B 

          67           C 

          68           D

          69           E 

          70           F 

          71           G 

          72           H 

          73            I 

          74            J 

          75           K 

          76           L

          77           M

          78           N 

          79           O 

          80            P

          81           Q 

          82            R 

          83            S 

          84            T

          85           U

          86           V 

          87           W

          88           X

          89           Y

          90           Z 

          91            [ 

          92            \ 

          93            ] 

          94            ^ 

          95            _ 

          96             ` 

 

         97             a 

         98             b 

         99             c 

        100            d

        101            e

        102            f 

        103            g 

        104            h 

        105            i 

        106            j

        107            k 

        108             l 

        109           m

        110            n 

        111            o 

        112            p 

        113            q 

        114            r 

        115            s

        116            t 

        117            u 

        118            v 

        119            w 

        120            x 

        121            y 

        122            z 

        123            { 

        124             | 

        125            } 

        126            ~

Note: Code 32 corresponds to a blank space. 

The character intrinsic function CHAR(I) perform the opposite task as intrinsic function ICHAR(C), that is, it takes the argument I, an integer value, and returns a character equivalent in ASCII code. The use of the CHAR(I) function is illustrated by the following example: 

      CHARACTER BLETTER 

      BLETTER= CHAR(66)

      WRITE(6,*) BLETTER 

According to Table 10.1, the value of character variable BLETTER is B. 

 
Lexical Comparison Intrinsic Functions

Fortran provides the lexical comparison intrinsic functions listed in Table 10.2. These functions take the form: 

func(c1,c2) 

where func is any of the functions listed in Table 10.2, and c1 and c2 are character constants, variables, or expressions. The lexical comparison functions are used for al phabetic sorting of character arrays, as shown below.

      CHARACTER*5 NAME(6),TEMP 

      IF(LGE(NAME(J),NAME(J+1))) THEN

      TEMP= NAME(J+1)

      NAME(J+1)= NAME(J) 

      NAME(J)= TEMP 

      ENDIF 

This example compares two consecutive names in a list, NAME(J) and NAME(J+1). If NAME(J) is greater than or equal to NAME(J+1) in alphabetic order (B is greater than A), they are sorted by accomplishing the following steps: 

  1. Storing NAME(J+1) in a temporary location TEMP, which now contains the value of NAME(J+1)

  2. Storing NAME(J) in the location where NAME(J+1) was.

  3. Storing TEMP, which has the same value as NAME(J+1), in the location of NAME(J).

This is the bubble sort of Section 8.7.

TABLE 10.2

LEXICAL COMPARISON INTRINSIC FUNCTIONS ______________________________________________________________

      Function                  Meaning                                                Equivalence 
______________________________________________________________

LLT(X,Y)               Lexical function less than                          (X.LT.Y) 

LLE(X,Y)              Lexical function less than or equal to       (X.LE.Y) 

LGT(X,Y)              Lexical function greater than                    (X.GT.Y) 

LGE(X,Y)             Lexical function greater than or equal to  (X.GE.Y)
______________________________________________________________ 

 Example Program: Lexical Comparison Functions 

C234567890 

      PROGRAM LEXISORT  

      PARAMETER (NC=5,NE=6) 

      CHARACTER*(NC) NAME(NE),TEMP 

      DATA NAME 

     1/'SMITH','PRICE','LYONS','JONES','MARKS','FIELD'/ 

      DO 10 K= 1,NE-1 

      DO 10 J= 1,NE-K

      IF(LGE(NAME(J),NAME(J+1))) THEN 

      TEMP= NAME(J+1)

      NAME(J+1)= NAME(J) 

      NAME(J)= TEMP 

      ENDIF 

   10 CONTINUE

      WRITE(6,'(1X,A)') NAME 

      END

This program sorts in alphabetical order a list of six last names. The output of this program is the sorted list: 

FIELD 

JONES

LYONS 

MARKS 

PRICE 

SMITH 

Note the following features of this program: 

  • The PARAMETER statement is used to set the character array size (NE= 6) and length (NC= 5). 

  • The array is initialized by using a DATA statement. 

  • Using the lexical comparison function LGE, an inner DO loop compares each element with the next, and proceeds to sort them if necessary. This loop varies from J = 1 to J = 6 - K. 

  • An outer loop varies from K = 1 to K = 5, each time decreasing the terminal parameter of the inner loop by 1. 

CHAPTER 10--PROBLEMS 

  1. Write a program that will read an input file containing an unspecified number of names, social security numbers, and grades for students in a class. The program will sort and print the names and grades alphabetically, and calculate and report the maximum, minimum, average, and median grade of the class. Test your program with the following data:

    WILSON, D. T.             565-45-2314         78 

    PEARCE, T. G.             552-89-7813         87 

    RUSSELL, K. S.            562-90-8745         76 

    GOMEZ, C. F.              554-32-8912         96

    BERGMAN, J. F.            586-34-7652         72 

    SIMMONS, K. D.            215-58-8999         85

    MORRISON, V. A.           550-86-8962         97 

    DAYTON, M. M.             564-13-4050         81 

    NELSON, J. D.             562-78-0002         75

    NGUYEN, K. T.             551-61-7987         76

  2. Write a program that will read the following set of characters, unscramble it and write the letters in alphabetical order, in row order, with trailing blank spaces (b). 

    QWERTYUIOP

    bASDFGHJKL 

    bbZXCVBNM

    The output should be:

    ABCDEFGHIJ 

    KLMNOPQRST 

    UVWXYZ 

  3. Write a program to solve the quadratic equation (ax2 + bx + c= 0) using complex arithmetic. Test your program with the following data sets:

                                          a                       b                        c
    ____________________________________________________________

    1)                                   1.                   -12.                     35. 

    2)                                   1.                   -12.                     36. 

    3)                                   1.                   -12.                     37. 
    ____________________________________________________________

  4. Write a program to decode a message written in an alphabetic code where each letter of the alphabet is replaced by the letter N places after it. After Z, the alphabet is repeated over. Make use of character substrings and the character intrinsic function INDEX(C1,C2). Test your program with N = 5, and the following message:   XJHWJY RJXXFLJ SZRGJW TSJ

  5. Write a program to encode a message where each letter of the alphabet is replaced by the letter N places after it. After Z, the alphabet is repeated over. Make use of character substrings and the character intrin sic function INDEX(C1,C2). Test your program with N = 7, and the following message:   SECRET MESSAGE NUMBER TWO

  6. Write a program to encode a message where the first letter of the alphabet (A) is replaced by the last (Z), the second (B) by the next to last (Y), and so on. Make use of character substrings and the character intrinsic function INDEX(C1,C2). Test your program with the following message:   SECRET MESSAGE NUMBER THREE

  7. Write a program to decode a message written in an alphabetic code where the first letter of the alphabet (A) is replaced by the last (Z), the second (B) by the next to last (Y), and so on. Make use of character sub strings and the character intrinsic function INDEX(C1,C2). Test your program with the following message:   HVXIVG NVHHZTV MFNYVI ULFI

  8. Write a program to generate the ASCII code equivalents of Table 10.1. Print in tabular form. 

  9. Write a program to accept a list of names of the form JONES, J. J., and convert to the form J. J. JONES. The number of names is not known beforehand. Test your program with the names of Problem 10.1. Print the list of converted names. 

  10. Write a program to accept a list of names of the form JOHN J. JONES and convert to the form JONES, JOHN J. The number of names is not known beforehand. Test your program with the data given below. Print the list of converted names.

    DWIGHT T. WILSON 

    THOMAS G. PEARCE 

    KENNETH S. RUSSELL 

    CHARLES F. GOMEZ 

    DONALD H. HUNT 

    JEFFREY F. BERGMAN 

    KYLE D. SIMMONS 

    VIRGINIA A. MORRISON 

    MICHAEL M. DAYTON 

    JOHN D. NELSON

    KENNETH T. CHANG 

  11. Write a function that accepts a real number hhmmss.tt, representing hours, minutes, seconds, and hundredths of a second, respectively, and returns a character value containing the corresponding hours, minutes, and seconds, including the fractional part. For example 073445.93 results in the character constant 7 hours, 34 minutes, 45.93 seconds . The function should test for out-of-range values such as 253255.66, 176523.45, or 094977.89, in which case it should issue an appropriate message and stop execution. Test your function with the examples given here. Print the answer in the calling program. [Hint: Use the CHARACTER*(*) FUNCTION statement. Separate input to the function into four integers, write these integers to an auxiliary file, backspace the record (see Section 11.3), read back the data as characters, and compose characters into function name]. 

  12. Write a program that will read a character string of 40 characters maximum length, disregard trailing blanks, and print the string in reverse order. Test your program with the following string: ABCDEFGHIJKLMNOPQRSTUVWXYZ 

  13. Write a function to determine the roman numeral representation of a given integer, for values in the range 1-99. Use the CHARACTER*(*) FUNCTION statement. Test your function with the following numbers: 7, 43, and 98. Print answer in the calling program. 

  14. Write a function to determine the roman numeral representation of a given integer, for values in the range 1-999. Use the CHARACTER*(*) FUNCTION statement. Test your function with the following numbers: 75, 433, and 988. Print answer in the calling program. 


       http://ponce.sdsu.edu/fortran_book_10.html 090311