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:
Storing NAME(J+1) in a temporary location TEMP,
which now contains the value of NAME(J+1).
Storing NAME(J) in the location where NAME(J+1)
was.
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
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
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
bbZXCVBNMb
The output should be:
ABCDEFGHIJ
KLMNOPQRST
UVWXYZ
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.
____________________________________________________________
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
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.
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
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
Write a program to generate the ASCII code equivalents of Table 10.1.
Print in tabular form.
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.
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
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].
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
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.
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.
|