0% found this document useful (0 votes)
8 views61 pages

Com221 Fortran Lang

Download as docx, pdf, or txt
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 61

FORTRAN[221] |1

Fortran – Overview
FORTRAN (FORmula TRANslation) is a third-generation ( 3GL ) programming language that
was designed for use by engineers, mathematicians, and other users and creators of scientific
algorithms. It has a very succinct and spartan syntax. Today, the C language has largely
displaced FORTRAN.

History

One of the oldest programming languages, the FORTRAN was developed by a team of
programmers at IBM led by John Backus, and was first published in 1957. The name FORTRAN
is an acronym for FORmula TRANslation, because it was designed to allow easy translation of
math formulas into code.

Often referred to as a scientific language, FORTRAN was the first high-level language, using the
first compiler ever developed. Prior to the development of FORTRAN computer programmers
were required to program in machine/assembly code, which was an extremely difficult and time
consuming task, not to mention the dreadful chore of debugging the code. The objective during
it's design was to create a programming language that would be: simple to learn, suitable for a
wide variety of applications, machine independent, and would allow complex mathematical
expressions to be stated similarly to regular algebraic notation.

The American Standards Association (now known as the American National Standards
Association) had released its first Standard for a Programming Language in 1966. This first
standardized version has come to be known as FORTRAN '66 (aka.. FORTRAN IV).

Despite this standardization, a few years later, various new dialects began to surface again,
requiring the Standards Association review the language again. This version is known as
FORTRAN '77. This version was released in 1978 (it was called '77 because the Association
began it's review in 1977), with several new features. Some of the more notable properties
were; new error handling methods, and mechanisms for managing large-scale programs. The
latest version; Fortran '90 (released in 1990, using the new capitalization scheme) added even
more new features, such as support for: recursion, pointers, and for programmer-defined data
types.

Significant Language Features

Some of the more significant features of the language are as listed below:

 Simple to learn - when FORTRAN was design one of the objectives was to write a
language that was easy to learn and understand.
 Machine Independent - allows for easy transportation of a program from one machine
to another.
 More natural ways to express mathematical functions - FORTRAN permits even
severely complex mathematical functions to be expressed similarly to regular algebraic
notation.
 Problem orientated language
 Remains close to and exploits the available hardware
FORTRAN[221] |2

 Efficient execution - there is only an approximate 20% decrease in efficiency as


compared to assembly/machine code.
 Ability to control storage allocation -programmers were able to easily control the
allocation of storage (although this is considered to be a dangerous practice today, it was
quite important some time ago due to limited memory.
 More freedom in code layout - unlike assembly/machine language, code does not need
to be laid out in rigidly defined columns, (though it still must remain within the
parameters of the FORTRAN source code form).

Areas of Application

FORTRAN is useful for a wide variety of applications, some of the more outstanding ones are as
follows:

 Number crunching - due to the more natural (like it's true algebraic form) way of
expressing complex mathematical functions and it's quick execution time, FORTRAN is
easy and efficient at processing mathematical equations.
 Scientific, mathematical, statistical, and engineering type procedures - due to it's
rapid number-crunching ability FORTRAN is a good choice for these type of applications.

Fortran - Basic Syntax


A Fortran program is made of a collection of program units like a main program, modules, and
external subprograms or procedures.

Each program contains one main program and may or may not contain other program units.
The syntax of the main program is as follows:

program program_name
implicit none
! type declaration statements
! executable statements
end program program_name

A Simple Program in Fortran


Let’s write a program that adds two numbers and prints the result:

Program addNumbers .
! This simple program adds two numbers
implicit none
! Type declarations
real :: a, b, result
! Executable statements
a = 12.0
b = 15.0
result = a + b
print *, 'The total is’ ,result
FORTRAN[221] |3

end program addNumbers

When you compile and execute the above program, it produces the following result:

The total is 27.0000000

Please note that:

 All Fortran programs start with the keyword program and end with the keyword end
program, followed by the name of the program.

 The implicit none statement allows the compiler to check that all your variable types
are declared properly. You must always use implicit none at the start of every program.

 Comments in Fortran are started with the exclamation mark (!), as all characters after
this (except in a character string) are ignored by the compiler.

 The print * command displays data on the screen.

 Indentation of code lines is a good practice for keeping a program readable.

 Fortran allows both uppercase and lowercase letters. Fortran is case-insensitive, except
for string literals.

Basics
The basic character set of Fortran contains:

 the letters A ... Z and a ... z


 the digits 0 ... 9
 the underscore (_) character
 the special characters = : + blank - * / ( ) [ ] , . $ ' ! " % & ; <> ?
Tokens are made of characters in the basic character set. A token could be a keyword, an
identifier, a constant, a string literal, or a symbol.

Program statements are made of tokens.

Identifier
An identifier is a name used to identify a variable, procedure, or any other user-defined item. A
name in Fortran must follow the following rules:

 It cannot be longer than 31 characters.

 It must be composed of alphanumeric characters (all the letters of the alphabet, and the
digits 0 to 9) and underscores (_).

 First character of a name must be a letter.

 Names are case-insensitive

Keywords
FORTRAN[221] |4

Keywords are special words, reserved for the language. These reserved words cannot be used
as identifiers or names.

The following table, lists the Fortran keywords:

The non-I/O keywords

allocatable allocate assign assignment block data

call Case character common complex

contains continue cycle data deallocate

default Do double precision else else if

elsewhere end block data end do end function end if

end interface end module end program end select end subroutine

end type end where entry equivalence exit

external function go to if implicit

in inout integer intent interface

intrinsic kind len logical module

namelist nullify only operator optional

out parameter pause pointer private

program public real recursive result

return save select case stop subroutine

target then type type() use

Where While

The I/O related keywords

backspace close endfile format inquire

open print read rewind Write

Fortran - Data Types


Fortran provides five intrinsic data types, however, you can derive your own data types as well.
The five intrinsic types are:
FORTRAN[221] |5

 Integer type
 Real type
 Complex type
 Logical type
 Character type

Integer Type
The integer types can hold only integer values. The following example extracts the largest value
that can be held in a usual four byte integer:

program testingInt
implicit none
integer :: largeval
print *, huge(largeval)
end program testingInt
When you compile and execute the above program it produces the following result:
2147483647

Note that the huge() function gives the largest number that can be held by the specific integer
data type. You can also specify the number of bytes using the kind specifier. The following
example demonstrates this:

program testingInt
implicit none
!two byte integer
integer(kind=2) :: shortval
!four byte integer
integer(kind=4) :: longval
!eight byte integer
integer(kind=8) :: verylongval
!sixteen byte integer
integer(kind=16) :: veryverylongval
!default integer
integer :: defval
print *, huge(shortval)
print *, huge(longval)
print *, huge(verylongval)
print *, huge(veryverylongval)
print *, huge(defval)
end program testingInt

When you compile and execute the above program, it produces the following result:
32767
2147483647
9223372036854775807
170141183460469231731687303715884105727
2147483647

Real Type
It stores the floating point numbers, such as 2.0, 3.1415, -100.876, etc.

Traditionally there are two different real types, the default real type and double
precision type. However, Fortran 90/95 provides more control over the precision of real and
integer data types through the kind specifier, which we will study in the chapter on Numbers.

The following example shows the use of real data type:


FORTRAN[221] |6

program division
implicit none
! Define real variables
real :: p, q, realRes
! Define integer variables
integer :: i, j, intRes
! Assigning values
p = 2.0
q = 3.0
i = 2
j = 3
! floating point division
realRes = p/q
intRes = i/j

print *, realRes
print *, intRes
end program division
When you compile and execute the above program it produces the following result:
0.666666687
0
Complex Type
This is used for storing complex numbers. A complex number has two parts, the real part and
the imaginary part. Two consecutive numeric storage units store these two parts.

For example, the complex number (3.0, -5.0) is equal to 3.0 – 5.0i

We will discuss Complex types in more detail, in the Numbers chapter.

Logical Type
There are only two logical values: .true. and .false.

Character Type
The character type stores characters and strings. The length of the string can be specified by
len specifier. If no length is specified, it is 1.

For example, character (len=40) :: name


name = “Zara Ali”
The expression, name(1:4) would give the substring “Zara”.
Implicit Typing
Older versions of Fortran allowed a feature called implicit typing, i.e., you do not have to
declare the variables before use. If a variable is not declared, then the first letter of its name will
determine its type.

Variable names starting with i, j, k, l, m, or n, are considered to be for integer variable and
others are real variables. However, you must declare all the variables as it is good programming
practice. For that you start your program with the statement:
implicit none
This statement turns off implicit typing.
FORTRAN[221] |7

Fortran – Variables
A variable is nothing but a name given to a storage area that our programs can manipulate.
Each variable should have a specific type, which determines the size and layout of the variable's
memory; the range of values that can be stored within that memory; and the set of operations
that can be applied to the variable.

The name of a variable can be composed of letters, digits, and the underscore character. A name
in Fortran must follow the following rules:

 It cannot be longer than 31 characters.


 It must be composed of alphanumeric characters (all the letters of the alphabet, and the
digits 0 to 9) and underscores (_).
 First character of a name must be a letter.
 Names are case-insensitive.
Based on the basic types explained in previous chapter, following are the variable types:
Type Description

Integer It can hold only integer values.

Real It stores the floating point numbers.

Complex It is used for storing complex numbers.

Logical It stores logical Boolean values.

Character It stores characters or strings.

Variable Declaration
Variables are declared at the beginning of a program (or subprogram) in a type declaration
statement.

Syntax for variable declaration is as follows:

type-specifier :: variable_name

For example,

integer :: total
real :: average
complex :: cx
logical :: done
character(len=80) :: message ! a string of 80 characters
Later you can assign values to these variables, like,
total = 20000
average = 1666.67
done = .true.
message = “A big Hello from Softecks”
cx = (3.0, 5.0) ! cx = 3.0 + 5.0i
You can also use the intrinsic function cmplx, to assign values to a complex variable:
cx = cmplx (1.0/2.0, -7.0) ! cx = 0.5 – 7.0i
FORTRAN[221] |8

cx = cmplx (x, y) ! cx = x + yi
Example
The following example demonstrates variable declaration, assignment and display on screen:

program variableTesting
implicit none

! declaring variables
integer :: total
real :: average
complex :: cx
logical :: done
character(len=80) :: message ! a string of 80 characters

!assigning values
total = 20000
average = 1666.67
done = .true.
message = "A big Hello from Softecks"
cx = (3.0, 5.0) ! cx = 3.0 + 5.0i

Print *, total
Print *, average
Print *, cx
Print *, done
Print *, message
end program variableTesting

When the above code is compiled and executed, it produces the following result:
20000
1666.67004
(3.00000000, 5.00000000 )
T
A big Hello from Softecks

Fortran – Constants
The constants refer to the fixed values that the program cannot alter during its execution. These
fixed values are also called literals.
Constants can be of any of the basic data types like an integer constant, a floating constant, a
character constant, a complex constant, or a string literal. There are only two logical
constants : .true. and .false.

The constants are treated just like regular variables, except that their values cannot be
modified after their definition.

Named Constants and Literals


There are two types of constants:

 Literal constants
 Named constants
A literal constant have a value, but no name.
FORTRAN[221] |9

For example, following are the literal constants:

Type Example

Integer constants 0 1 -1 300 123456789

Real constants 0.0 1.0 -1.0 123.456 7.1E+10 -52.715E-30

Complex constants (0.0, 0.0) (-123.456E+30, 987.654E-29)

Logical constants .true. .false.

Character constants "PQR" "a" "123'abc$%#@!"

" a quote "" "

'PQR' 'a' '123"abc$%#@!'

' an apostrophe '' '

A named constant has a value as well as a name.

Named constants should be declared at the beginning of a program or procedure, just like a
variable type declaration, indicating its name and type. Named constants are declared with the
parameter attribute. For example,

real, parameter :: pi = 3.1415927

Example

The following program calculates the displacement due to vertical motion under gravity.

program gravitationalDisp

! this program calculates vertical motion under gravity

implicit none

! gravitational acceleration

real, parameter :: g = 9.81

! variable declaration

real :: s ! displacement

real :: t ! time

real :: u ! initial speed

! assigning values
F O R T R A N [ 2 2 1 ] | 10

t = 5.0

u = 50

! displacement

s = u * t - g * (t**2) / 2

! output

print *, "Time = ", t

print *, 'Displacement = ',s

end program gravitationalDisp

When the above code is compiled and executed, it produces the following result:

Time = 5.00000000

Displacement = 127.374992

Fortran – Operators

An operator is a symbol that tells the compiler to perform specific mathematical or logical
manipulations. Fortran provides the following types of operators:

 Arithmetic Operators
 Relational Operators
 Logical Operators
Let us look at all these types of operators one by one.

Arithmetic Operators
Following table shows all the arithmetic operators supported by Fortran. Assume
variable A holds 5 and variable B holds 3 then:

Operato Description Example


r

+ Addition Operator, adds two operands. A + B will give 8

- Subtraction Operator, subtracts second operand from the A - B will give 2


first.

* Multiplication Operator, multiplies both operands. A * B will give 15


F O R T R A N [ 2 2 1 ] | 11

/ Division Operator, divides numerator by de-numerator. A / B will give 1

** Exponentiation Operator, raises one operand to the power A ** B will give 125
of the other.

Relational Operators
Following table shows all the relational operators supported by Fortran. Assume
variable A holds 10 and variable B holds 20, then:

Operato Equivalent Description Example


r

== .eq. Checks if the values of two operands are equal or (A == B) is


not, if yes then condition becomes true. not true.

/= .ne. Checks if the values of two operands are equal or (A != B) is


not, if values are not equal then condition becomes true.
true.

> .gt. Checks if the value of left operand is greater than (A > B) is
the value of right operand, if yes then condition not true.
becomes true.

< .lt. Checks if the value of left operand is less than the (A < B) is
value of right operand, if yes then condition true.
becomes true.

>= .ge. Checks if the value of left operand is greater than or (A >= B) is
equal to the value of right operand, if yes then not true.
condition becomes true.

<= .le. Checks if the value of left operand is less than or (A <= B) is
equal to the value of right operand, if yes then true.
condition becomes true.

Operators Precedence in Fortran


Operator precedence determines the grouping of terms in an expression. This affects how an
expression is evaluated. Certain operators have higher precedence than others; for example,
F O R T R A N [ 2 2 1 ] | 12

the multiplication operator has higher precedence than the addition operator.

For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher
precedence than +, so it first gets multiplied with 3*2 and then adds into 7.

Here, operators with the highest precedence appear at the top of the table, those with the
lowest appear at the bottom. Within an expression, higher precedence operators will be
evaluated first.

Category Operator Associativity

Logical NOT and negative sign .not. (-) Left to right

Exponentiation ** Left to right

Multiplicative */ Left to right

Additive +- Left to right

Relational <<= >>= Left to right

Equality == != Left to right

Logical AND .and. Left to right

Logical OR .or. Left to right

Assignment = Right to left

Fortran – Decisions

Decision making structures require that the programmer specify one or more conditions to be
evaluated or tested by the program, along with a statement or statements to be executed, if the
condition is determined to be true, and optionally, other statements to be executed if the
condition is determined to be false.
F O R T R A N [ 2 2 1 ] | 13

Following is the general form of a typical decision making structure found in most of the
programming languages:

Fortran provides the following types of decision making constructs.

Statement Description

If… then construct An if… then… end if statement consists of a logical


expression followed by one or more statements.

If… then...else construct An if… then statement can be followed by an optional else
statement, which executes when the logical expression is
false.

nested if construct You can use one if or else if statement inside


another if or else if statement(s).

select case construct A select case statement allows a variable to be tested for
equality against a list of values.

nested select case construct You can use one select case statement inside
another select case statement(s).

Fortran - if...else if...else Statement


An if statement construct can have one or more optional else-if constructs. When
the if condition fails, the immediately followed else-if is executed. When the else-if also fails,
its successor else-if statement (if any) is executed, and so on.

The optional else is placed at the end and it is executed when none of the above conditions hold
true.

 All else statements (else-if and else) are optional.


 else-if can be used one or more times
 else must always be placed at the end of construct and should appear only once.
Syntax:
The syntax of an if...else if...else statement is:

[name:]

if (logical expression 1) then

! block 1

else if (logical expression 2) then


F O R T R A N [ 2 2 1 ] | 14

! block 2

else if (logical expression 3) then

! block 3

else

! block 4

end if [name]

Example

program ifElseIfElseProg

implicit none

! local variable declaration

integer :: a = 100

! check the logical condition using if statement

if( a == 10 ) then

! if condition is true then print the following

print*, "Value of a is 10"

else if( a == 20 ) then

! if else if condition is true

print*, "Value of a is 20"

else if( a == 30 ) then

! if else if condition is true

print*, "Value of a is 30"

else

! if none of the conditions is true

print*, "None of the values is matching"

end if
F O R T R A N [ 2 2 1 ] | 15

print*, "exact value of a is ", a

end program ifElseIfElseProg

When the above code is compiled and executed, it produces the following result:

None of the values is matching

exact value of a is 100

Fortran – Loops

There may be a situation, when you need to execute a block of code several number of times. In
general, statements are executed sequentially : The first statement in a function is executed
first, followed by the second, and so on.

Programming languages provide various control structures that allow for more complicated
execution paths.

A loop statement allows us to execute a statement or group of statements multiple times and
following is the general form of a loop statement in most of the programming languages:

Fortran provides the following types of loop constructs to handle looping requirements

Loop Type Description

do loop This construct enables a statement, or a series of statements, to be carried


out iteratively, while a given condition is true.

do while loop Repeats a statement or group of statements while a given condition is true. It
tests the condition before executing the loop body.

nested loops You can use one or more loop construct inside any other loop construct.

Loop Control Statements


Loop control statements change execution from its normal sequence. When execution leaves a
scope, all automatic objects that were created in that scope are destroyed.

Fortran supports the following control statements.

Control Statement Description

exit If the exit statement is executed, the loop is exited, and the execution
F O R T R A N [ 2 2 1 ] | 16

of the program continues at the first executable statement after the


end do statement.

cycle If a cycle statement is executed, the program continues at the start of


the next iteration.

stop If you wish execution of your program to stop, you can insert a stop
statement

Fortran – Numbers

Numbers in Fortran are represented by three intrinsic data types:

 Integer type
 Real type
 Complex type
Integer Type
The integer types can hold only integer values. The following example extracts the largest value
that could be hold in a usual four byte integer:

program testingInt

implicit none

integer :: largeval

print *, huge(largeval)

end program testingInt

When you compile and execute the above program it produces the following result:

2147483647

Please note that the huge() function gives the largest number that can be held by the specific
integer data type. You can also specify the number of bytes using the kind specifier. The
following example demonstrates this:

program testingInt

implicit none

!two byte integer

integer(kind=2) :: shortval

!four byte integer

integer(kind=4) :: longval
F O R T R A N [ 2 2 1 ] | 17

!eight byte integer

integer(kind=8) :: verylongval

!sixteen byte integer

integer(kind=16) :: veryverylongval

!default integer

integer :: defval

print *, huge(shortval)

print *, huge(longval)

print *, huge(verylongval)

print *, huge(veryverylongval)

print *, huge(defval)

end program testingInt

When you compile and execute the above program it produces the following result:

32767

2147483647

9223372036854775807

170141183460469231731687303715884105727

2147483647

Real Type
It stores the floating point numbers, such as 2.0, 3.1415, -100.876, etc.

Traditionally there were two different real types : the default real type and double
precision type.

However, Fortran 90/95 provides more control over the precision of real and integer data
types through the kind specifier, which we will study shortly.

The following example shows the use of real data type:

program division

implicit none

! Define real variables

real :: p, q, realRes

! Define integer variables

integer :: i, j, intRes

! Assigning values
F O R T R A N [ 2 2 1 ] | 18

p = 2.0

q = 3.0

i=2

j=3

! floating point division

realRes = p/q

intRes = i/j

print *, realRes

print *, intRes

end program division

When you compile and execute the above program it produces the following result:

0.666666687

Complex Type
This is used for storing complex numbers. A complex number has two parts : the real part and
the imaginary part. Two consecutive numeric storage units store these two parts.

For example, the complex number (3.0, -5.0) is equal to 3.0 – 5.0i

The generic function cmplx() creates a complex number. It produces a result who’s real and
imaginary parts are single precision, irrespective of the type of the input arguments.

program createComplex

implicit none

integer :: i = 10

real :: x = 5.17

print *, cmplx(i, x)

end program createComplex

When you compile and execute the above program it produces the following result:

(10.0000000, 5.17000008)

The following program demonstrates complex number arithmetic:

program ComplexArithmatic

implicit none

complex, parameter :: i = (0, 1) ! sqrt(-1)


F O R T R A N [ 2 2 1 ] | 19

complex :: x, y, z

x = (7, 8);

y = (5, -7)

write(*,*) i * x * y

z=x+y

print *, "z = x + y = ", z

z=x-y

print *, "z = x - y = ", z

z=x*y

print *, "z = x * y = ", z

z=x/y

print *, "z = x / y = ", z

end program ComplexArithmatic

When you compile and execute the above program it produces the following result:

(9.00000000, 91.0000000)

z = x + y = (12.0000000, 1.00000000)

z = x - y = (2.00000000, 15.0000000)

z = x * y = (91.0000000, -9.00000000)

z = x / y = (-0.283783793, 1.20270276)

The Range, Precision and Size of Numbers


The range on integer numbers, the precision and the size of floating point numbers depends on
the number of bits allocated to the specific data type.

The following table displays the number of bits and range for integers:

Number of bits Maximum value Reason

64 9,223,372,036,854,774,807 (2**63)–1

32 2,147,483,647 (2**31)–1

The following table displays the number of bits, smallest and largest value, and the precision
for real numbers.

Number of bits Largest value Smallest value Precision


F O R T R A N [ 2 2 1 ] | 20

64 0.8E+308 0.5E–308 15–18

32 1.7E+38 0.3E–38 6-9

The following examples demonstrate this:

program rangePrecision

implicit none

real:: x, y, z

x = 1.5e+40

y = 3.73e+40

z=x*y

print *, z

end program rangePrecision

When you compile and execute the above program it produces the following result:

x = 1.5e+40

Error : Real cos its kind at (1)

main.f95:5.12:

y = 3.73e+40

Error : Real constant overflows its kind at (1)

Now let us use a smaller number:

program rangePrecision

implicit none

real:: x, y, z

x = 1.5e+20

y = 3.73e+20

z=x*y

print *, z

z = x/y

print *, z

end program rangePrecision


F O R T R A N [ 2 2 1 ] | 21

When you compile and execute the above program it produces the following result:

Infinity

0.402144760

Now let’s watch underflow:

program rangePrecision

implicit none

real:: x, y, z

x = 1.5e-30

y = 3.73e-60

z=x*y

print *, z

z = x/y

print *, z

end program rangePrecision

When you compile and execute the above program it produces the following result:

y = 3.73e-60

Warning : Real constant underflows its kind at (1)

Executing the program....

$demo

0.00000000E+00

Infinity

The Kind Specifier


In scientific programming, one often needs to know the range and precision of data of the
hardware platform on which the work is being done.

The intrinsic function kind() allows you to query the details of the hardware’s data
representations before running a program.

program kindCheck

implicit none

integer :: i

real :: r
F O R T R A N [ 2 2 1 ] | 22

complex :: cp

print *,' Integer ', kind(i)

print *,' Real ', kind(r)

print *,' Complex ', kind(cp)

end program kindCheck

When you compile and execute the above program it produces the following result:

Integer 4

Real 4

Complex 4

You can also check the kind of all data types:

program checkKind

implicit none

integer :: i

real :: r

character*1 :: c

logical :: lg

complex :: cp

print *,' Integer ', kind(i)

print *,' Real ', kind(r)

print *,' Complex ', kind(cp)

print *,' Character ', kind(c)

print *,' Logical ', kind(lg)

end program checkKind

When you compile and execute the above program it produces the following result:

Integer 4

Real 4

Complex 4

Character 1

Logical 4

Fortran – Characters
F O R T R A N [ 2 2 1 ] | 23

The Fortran language can treat characters as single character or contiguous strings.

Characters could be any symbol taken from the basic character set, i.e., from the letters, the
decimal digits, the underscore, and 21 special characters.

A character constant is a fixed valued character string.

The intrinsic data type character stores characters and strings. The length of the string can be
specified by len specifier. If no length is specified, it is 1. You can refer individual characters
within a string referring by position; the left most character is at position 1.

Character Declaration
Declaring a character type data is same as other variables:

type-specifier :: variable_name

For example,

character :: reply, sex

you can assign a value like,

reply = ‘N’

sex = ‘F’

The following example demonstrates declaration and use of character data type:

program hello

implicit none

character(len=15) :: surname, firstname

character(len=6) :: title

character(len=25)::greetings

title = 'Mr. '

firstname = 'Rowan '

surname = 'Atkinson'

greetings = 'A big hello from Mr. Bean'

print *, 'Here is ', title, firstname, surname

print *, greetings

end program hello

When you compile and execute the above program it produces the following result:

Here is Mr. Rowan Atkinson

A big hello from Mr. Bean

Concatenation of Characters
F O R T R A N [ 2 2 1 ] | 24

The concatenation operator //, concatenates characters.

The following example demonstrates this:

program hello

implicit none

character(len=15) :: surname, firstname

character(len=6) :: title

character(len=40):: name

character(len=25)::greetings

title = 'Mr. '

firstname = 'Rowan '

surname = 'Atkinson'

name = title//firstname//surname

greetings = 'A big hello from Mr. Bean'

print *, 'Here is ', name

print *, greetings

end program hello

When you compile and execute the above program it produces the following result:

Here is Mr.Rowan Atkinson

A big hello from Mr.Bean

Some Character Functions


The following table shows some commonly used character functions along with the
description:

Function Description

len(string) It returns the length of a character string

index(string,sustring It finds the location of a substring in another string, returns 0 if not


) found.

achar(int) It converts an integer into a character

iachar(c) It converts a character into an integer


F O R T R A N [ 2 2 1 ] | 25

trim(string) It returns the string with the trailing blanks removed.

scan(string, chars) It searches the "string" from left to right (unless back=.true.) for the
first occurrence of any character contained in "chars". It returns an
integer giving the position of that character, or zero if none of the
characters in "chars" have been found.

verify(string, chars) It scans the "string" from left to right (unless back=.true.) for the first
occurrence of any character not contained in "chars". It returns an
integer giving the position of that character, or zero if only the
characters in "chars" have been found

adjustl(string) It left justifies characters contained in the "string"

adjustr(string) It right justifies characters contained in the "string"

len_trim(string) It returns an integer equal to the length of "string" (len(string))


minus the number of trailing blanks

repeat(string,ncopy) It returns a string with length equal to "ncopy" times the length of
"string", and containing "ncopy" concatenated copies of "string"

Example 1

This example shows the use of the index function:

program testingChars

implicit none

character (80) :: text

integer :: i

text = 'The intrinsic data type character stores characters and strings.'

i=index(text,'character')

if (i /= 0) then

print *, ' The word character found at position ',i

print *, ' in text: ', text

end if

end program testingChars

When you compile and execute the above program it produces the following result:
F O R T R A N [ 2 2 1 ] | 26

The word character found at position 25

in text : The intrinsic data type character stores characters and strings.

Example 2

This example demonstrates the use of the trim function:

program hello

implicit none

character(len=15) :: surname, firstname

character(len=6) :: title

character(len=25)::greetings

title = 'Mr.'

firstname = 'Rowan'

surname = 'Atkinson'

print *, 'Here is', title, firstname, surname

print *, 'Here is', trim(title),' ',trim(firstname),' ', trim(surname)

end program hello

When you compile and execute the above program it produces the following result:

Here is Mr. Rowan Atkinson

Here is Mr. Rowan Atkinson

Example 3

This example demonstrates the use of achar function

program testingChars

implicit none

character:: ch

integer:: i

do i=65, 90

ch = achar(i)

print*, i, ' ', ch

end do

end program testingChars

When you compile and execute the above program it produces the following result:

65 A

66 B
F O R T R A N [ 2 2 1 ] | 27

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

Checking Lexical Order of Characters


The following functions determine the lexical sequence of characters:

Function Description

lle(char, char) Compares whether the first character is lexically less than or equal to the
second

lge(char, char) Compares whether the first character is lexically greater than or equal to
the second
F O R T R A N [ 2 2 1 ] | 28

lgt(char, char) Compares whether the first character is lexically greater than the second

llt(char, char) Compares whether the first character is lexically less than the second

Example 4

The following function demonstrates the use:

program testingChars

implicit none

character:: a, b, c

a = 'A'

b = 'a'

c = 'B'

if(lgt(a,b)) then

print *, 'A is lexically greater than a'

else

print *, 'a is lexically greater than A'

end if

if(lgt(a,c)) then

print *, 'A is lexically greater than B'

else

print *, 'B is lexically greater than A'

end if

if(llt(a,b)) then

print *, 'A is lexically less than a'

end if

if(llt(a,c)) then

print *, 'A is lexically less than B'

end if

end program testingChars

When you compile and execute the above program it produces the following result:

a is lexically greater than A

B is lexically greater than A


F O R T R A N [ 2 2 1 ] | 29

A is lexically less than a

A is lexically less than B

Fortran – Strings

The Fortran language can treat characters as single character or contiguous strings.

A character string may be only one character in length, or it could even be of zero length. In
Fortran, character constants are given between a pair of double or single quotes.

The intrinsic data type character stores characters and strings. The length of the string can be
specified by len specifier. If no length is specified, it is 1. You can refer individual characters
within a string referring by position; the left most character is at position 1.

String Declaration
Declaring a string is same as other variables:

type-specifier :: variable_name

For example,

Character(len=20) :: firstname, surname

you can assign a value like,

character (len=40) :: name

name = “Zara Ali”

The following example demonstrates declaration and use of character data type:

program hello

implicit none

character(len=15) :: surname, firstname

character(len=6) :: title

character(len=25)::greetings

title = 'Mr.'

firstname = 'Rowan'

surname = 'Atkinson'

greetings = 'A big hello from Mr. Beans'

print *, 'Here is', title, firstname, surname

print *, greetings
F O R T R A N [ 2 2 1 ] | 30

end program hello

When you compile and execute the above program it produces the following result:

Here is Mr. Rowan Atkinson

A big hello from Mr. Bean

String Concatenation
The concatenation operator //, concatenates strings.

The following example demonstrates this:

program hello

implicit none

character(len=15) :: surname, firstname

character(len=6) :: title

character(len=40):: name

character(len=25)::greetings

title = 'Mr.'

firstname = 'Rowan'

surname = 'Atkinson'

name = title//firstname//surname

greetings = 'A big hello from Mr. Beans'

print *, 'Here is', name

print *, greetings

end program hello

When you compile and execute the above program it produces the following result:

Here is Mr. Rowan Atkinson

A big hello from Mr. Bean

Extracting Substrings
In Fortran, you can extract a substring from a string by indexing the string, giving the start and
the end index of the substring in a pair of brackets. This is called extent specifier.

The following example shows how to extract the substring ‘world’ from the string ‘hello
world’:

program subString

character(len=11)::hello

hello = "Hello World"


F O R T R A N [ 2 2 1 ] | 31

print*, hello(7:11)

end program subString

When you compile and execute the above program it produces the following result:

World

Example

The following example uses the date_and_time function to give the date and time string. We
use extent specifiers to extract the year, date, month, hour, minutes and second information
separately.

program datetime

implicit none

character(len = 8) :: dateinfo ! ccyymmdd

character(len = 4) :: year, month*2, day*2

character(len = 10) :: timeinfo ! hhmmss.sss

character(len = 2) :: hour, minute, second*6

call date_and_time(dateinfo, timeinfo)

! let’s break dateinfo into year, month and day.

! dateinfo has a form of ccyymmdd, where cc = century, yy = year

! mm = month and dd = day

year = dateinfo(1:4)

month = dateinfo(5:6)

day = dateinfo(7:8)

print*, 'Date String:', dateinfo

print*, 'Year:', year

print *,'Month:', month

print *,'Day:', day

! let’s break timeinfo into hour, minute and second.


F O R T R A N [ 2 2 1 ] | 32

! timeinfo has a form of hhmmss.sss, where h = hour, m = minute

! and s = second

hour = timeinfo(1:2)

minute = timeinfo(3:4)

second = timeinfo(5:10)

print*, 'Time String:', timeinfo

print*, 'Hour:', hour

print*, 'Minute:', minute

print*, 'Second:', second

end program datetime

When you compile and execute the above program, it gives the detailed date and time
information:

Date String: 20140803

Year: 2014

Month: 08

Day: 03

Time String: 075835.466

Hour: 07

Minute: 58

Second: 35.466

Trimming Strings
The trim function takes a string, and returns the input string after removing all trailing blanks.

Example

program trimString

implicit none

character (len=*), parameter :: fname="Susanne", sname="Rizwan"

character (len=20) :: fullname

fullname=fname//" "//sname !concatenating the strings

print*,fullname,", the beautiful dancer from the east!"

print*,trim(fullname),", the beautiful dancer from the east!"

end program trimString


F O R T R A N [ 2 2 1 ] | 33

When you compile and execute the above program it produces the following result:

Susanne Rizwan , the beautiful dancer from the east!

Susanne Rizwan, the beautiful dancer from the east!

Left and Right Adjustment of Strings


The function adjustl takes a string and returns it by removing the leading blanks and
appending them as trailing blanks.

The function adjustr takes a string and returns it by removing the trailing blanks and
appending them as leading blanks.

Example

program hello

implicit none

character(len=15) :: surname, firstname

character(len=6) :: title

character(len=40):: name

character(len=25):: greetings

title = 'Mr. '

firstname = 'Rowan'

surname = 'Atkinson'

greetings = 'A big hello from Mr. Beans'

name = adjustl(title)//adjustl(firstname)//adjustl(surname)

print *, 'Here is', name

print *, greetings

name = adjustr(title)//adjustr(firstname)//adjustr(surname)

print *, 'Here is', name

print *, greetings

name = trim(title)//trim(firstname)//trim(surname)

print *, 'Here is', name

print *, greetings

end program hello

When you compile and execute the above program it produces the following result:

Here is Mr. Rowan Atkinson


F O R T R A N [ 2 2 1 ] | 34

A big hello from Mr. Bean

Here is Mr. Rowan Atkinson

A big hello from Mr. Bean

Here is Mr.RowanAtkinson

A big hello from Mr. Bean

Searching for a Substring in a String


The index function takes two strings and checks if the second string is a substring of the first
string. If the second argument is a substring of the first argument, then it returns an integer
which is the starting index of the second string in the first string, else it returns zero.

Example

program hello

implicit none

character(len=30) :: myString

character(len=10) :: testString

myString = 'This is a test'

testString = 'test'

if(index(myString, testString) == 0)then

print *, 'test is not found'

else

print *, 'test is found at index: ', index(myString, testString)

end if

end program hello

When you compile and execute the above program it produces the following result:

test is found at index: 11

Fortran – Arrays

Arrays can store a fixed-size sequential collection of elements of the same type. An array is used
to store a collection of data, but it is often more useful to think of an array as a collection of
variables of the same type.
F O R T R A N [ 2 2 1 ] | 35

All arrays consist of contiguous memory locations. The lowest address corresponds to the first
element and the highest address to the last element.

Numbers(1) Numbers(2) Numbers(3) Numbers(4)

Arrays can be one- dimensional (like vectors), two-dimensional (like matrices) and Fortran
allows you to create up to 7-dimensional arrays.

Declaring Arrays
Arrays are declared with the dimension attribute.

For example, to declare a one-dimensional array named number, of real numbers containing 5
elements, you write,

real, dimension(5) :: numbers

The individual elements of arrays are referenced by specifying their subscripts. The first
element of an array has a subscript of one. The array numbers contains five real variables –
numbers(1), numbers(2), numbers(3), numbers(4), and numbers(5).

To create a 5 x 5 two-dimensional array of integers named matrix, you write:

integer, dimension (5,5) :: matrix

You can also declare an array with some explicit lower bound, for example:

real, dimension(2:6) :: numbers

integer, dimension (-3:2,0:4) :: matrix

Assigning Values
You can either assign values to individual members, like,

numbers(1) = 2.0

or, you can use a loop,

do i=1,5

numbers(i) = i * 2.0

end do

One dimensional array elements can be directly assigned values using a short hand symbol,
called array constructor, like,

numbers = (/1.5, 3.2,4.5,0.9,7.2 /)

please note that there are no spaces allowed between the brackets ‘( ‘and the back slash
‘/’

Example
F O R T R A N [ 2 2 1 ] | 36

The following example demonstrates the concepts discussed above.

program arrayProg

real :: numbers(5) !one dimensional integer array

integer :: matrix(3,3), i , j !two dimensional real array

!assigning some values to the array numbers

do i=1,5

numbers(i) = i * 2.0

end do

!display the values

do i = 1, 5

Print *, numbers(i)

end do

!assigning some values to the array matrix

do i=1,3

do j = 1, 3

matrix(i, j) = i+j

end do

end do

!display the values

do i=1,3

do j = 1, 3

Print *, matrix(i,j)

end do

end do

!short hand assignment

numbers = (/1.5, 3.2,4.5,0.9,7.2 /)

!display the values

do i = 1, 5

Print *, numbers(i)

end do

end program arrayProg

When the above code is compiled and executed, it produces the following result:
F O R T R A N [ 2 2 1 ] | 37

2.00000000

4.00000000

6.00000000

8.00000000

10.0000000

1.50000000

3.20000005

4.50000000

0.899999976

7.19999981

Some Array Related Terms


The following table gives some array related terms:

Term Meaning

Rank It is the number of dimensions an array has. For example, for the array named
matrix, rank is 2, and for the array named numbers, rank is 1.

Exten It is the number of elements along a dimension. For example, the array numbers has
t extent 5 and the array named matrix has extent 3 in both dimensions.

Shape The shape of an array is a one-dimensional integer array, containing the number of
elements (the extent) in each dimension. For example, for the array matrix, shape is
(3, 3) and the array numbers it is (5).

Size It is the number of elements an array contains. For the array matrix, it is 9, and for
F O R T R A N [ 2 2 1 ] | 38

the array numbers, it is 5.

Passing Arrays to Procedures


You can pass an array to a procedure as an argument. The following example demonstrates the
concept:

program arrayToProcedure

implicit none

integer, dimension (5) :: myArray

integer :: i

call fillArray (myArray)

call printArray(myArray)

end program arrayToProcedure

subroutine fillArray (a)

implicit none

integer, dimension (5), intent (out) :: a

! local variables

integer :: i

do i = 1, 5

a(i) = i

end do

end subroutine fillArray

subroutine printArray(a)

integer, dimension (5) :: a

integer::i

do i = 1, 5

Print *, a(i)

end do

end subroutine printArray

When the above code is compiled and executed, it produces the following result:

2
F O R T R A N [ 2 2 1 ] | 39

In the above example, the subroutine fillArray and printArray can only be called with arrays
with dimension 5. However, to write subroutines that can be used for arrays of any size, you
can rewrite it using the following technique:

program arrayToProcedure

implicit none

integer, dimension (10) :: myArray

integer :: i

interface

subroutine fillArray (a)

integer, dimension(:), intent (out) :: a

integer :: i

end subroutine fillArray

subroutine printArray (a)

integer, dimension(:) :: a

integer :: i

end subroutine printArray

end interface

call fillArray (myArray)

call printArray(myArray)

end program arrayToProcedure

subroutine fillArray (a)

implicit none

integer,dimension (:), intent (out) :: a

! local variables

integer :: i, arraySize

arraySize = size(a)

do i = 1, arraySize

a(i) = i
F O R T R A N [ 2 2 1 ] | 40

end do

end subroutine fillArray

subroutine printArray(a)

implicit none

integer,dimension (:) :: a

integer::i, arraySize

arraySize = size(a)

do i = 1, arraySize

Print *, a(i)

end do

end subroutine printArray

Please note that the program is using the size function to get the size of the array.

When the above code is compiled and executed, it produces the following result:

10

Array Sections
So far we have referred to the whole array, Fortran provides an easy way to refer several
elements, or a section of an array, using a single statement.

To access an array section, you need to provide the lower and the upper bound of the section,
as well as a stride (increment), for all the dimensions. This notation is called a subscript
triplet:

array ([lower]:[upper][:stride], ...)

When no lower and upper bounds are mentioned, it defaults to the extents you declared, and
stride value defaults to 1.
F O R T R A N [ 2 2 1 ] | 41

The following example demonstrates the concept:

program arraySubsection

real, dimension(10) :: a, b

integer:: i, asize, bsize

a(1:7) = 5.0 ! a(1) to a(7) assigned 5.0

a(8:) = 0.0 ! rest are 0.0

b(2:10:2) = 3.9

b(1:9:2) = 2.5

!display

asize = size(a)

bsize = size(b)

do i = 1, asize

Print *, a(i)

end do

do i = 1, bsize

Print *, b(i)

end do

end program arraySubsection

When the above code is compiled and executed, it produces the following result:

5.00000000

5.00000000

5.00000000

5.00000000

5.00000000

5.00000000

5.00000000

0.00000000E+00

0.00000000E+00

0.00000000E+00

2.50000000

3.90000010

2.50000000
F O R T R A N [ 2 2 1 ] | 42

3.90000010

2.50000000

3.90000010

2.50000000

3.90000010

2.50000000

3.90000010

Array Intrinsic Functions


Fortran 90/95 provides several intrinsic procedures. They can be divided into 7 categories.

 Vector and matrix multiplication

 Reduction

 Inquiry

 Construction

 Reshape

 Manipulation

 Location

Fortran - Basic Input Output

We have so far seen that we can read data from keyboard using the read * statement, and
display output to the screen using the print* statement, respectively. This form of input-output
is free format I/O, and it is called list-directed input-output.

The free format simple I/O has the form:

read(*,*) item1, item2, item3...

print *, item1, item2, item3

write(*,*) item1, item2, item3...

However the formatted I/O gives you more flexibility over data transfer.

Formatted Input Output


Formatted input output has the syntax as follows:

read fmt, variable_list


F O R T R A N [ 2 2 1 ] | 43

print fmt, variable_list

write fmt, variable_list

Where,

 fmt is the format specification

 variable-list is a list of the variables to be read from keyboard or written on screen

Format specification defines the way in which formatted data is displayed. It consists of a
string, containing a list of edit descriptors in parentheses.

An edit descriptor specifies the exact format, for example, width, digits after decimal point
etc., in which characters and numbers are displayed.

For example:

Print "(f6.3)", pi

The following table describes the descriptors:

Descriptor Description Example

I This is used for integer output. This takes the form print "(3i5)", i, j, k
‘rIw.m’ where the meanings of r, w and m are
given in the table below. Integer values are right
justified in their fields. If the field width is not
large enough to accommodate an integer then the
field is filled with asterisks.

F This is used for real number output. This takes the print "(f12.3)",pi
form ‘rFw.d’ where the meanings of r, w and d are
given in the table below. Real values are right
justified in their fields. If the field width is not
large enough to accommodate the real number
then the field is filled with asterisks.

E This is used for real output in exponential print "(e10.3)",123456.0


notation. The ‘E’ descriptor statement takes the gives ‘0.123e+06’
form ‘rEw.d’ where the meanings of r, w and d
are given in the table below. Real values are right
justified in their fields. If the field width is not
large enough to accommodate the real number
then the field is filled with asterisks.

Please note that, to print out a real number with


three decimal places a field width of at least ten is
needed. One for the sign of the mantissa, two for
F O R T R A N [ 2 2 1 ] | 44

the zero, four for the mantissa and two for the
exponent itself. In general, w ≥ d + 7.

ES This is used for real output (scientific notation). print "(es10.3)",123456.0


This takes the form ‘rESw.d’ where the meanings gives ‘1.235e+05’
of r, w and d are given in the table below. The ‘E’
descriptor described above differs slightly from
the traditional well known ‘scientific notation’.
Scientific notation has the mantissa in the range
1.0 to 10.0 unlike the E descriptor which has the
mantissa in the range 0.1 to 1.0. Real values are
right justified in their fields. If the field width is
not large enough to accommodate the real number
then the field is filled with asterisks. Here also, the
width field must satisfy the expression w ≥ d + 7

A This is used for character output. This takes the print "(a10)", str
form ‘rAw’ where the meanings of r and w are
given in the table below. Character types are right
justified in their fields. If the field width is not
large enough to accommodate the character string
then the field is filled with the first ‘w’ characters
of the string.

X This is used for space output. This takes the form print "(5x, a10)", str
‘nX’ where ‘n’ is the number of desired spaces.

/ Slash descriptor – used to insert blank lines. This print "(/,5x, a10)", str
takes the form ‘/’ and forces the next data output
to be on a new line.

Following symbols are used with the format descriptors:

Symbol Description

c Column number

d Number of digits to right of the decimal place for real input or output

m Minimum number of digits to be displayed

n Number of spaces to skip

r Repeat count – the number of times to use a descriptor or group of descriptors


F O R T R A N [ 2 2 1 ] | 45

w Field width – the number of characters to use for the input or output

Example 1

program printPi

pi = 3.141592653589793238

Print "(f6.3)", pi

Print "(f10.7)", pi

Print "(f20.15)", pi

Print "(e16.4)", pi/100

end program printPi

When the above code is compiled and executed, it produces the following result:

3.142

3.1415927

3.141592741012573

0.3142E-01

Example 2

program printName

implicit none

character (len=15) :: first_name

print *,' Enter your first name.'

print *,' Up to 20 characters, please'

read *,first_name

print "(1x,a)",first_name

end program printName

When the above code is compiled and executed, it produces the following result: (assume the
user enters the name Zara)

Enter your first name.

Up to 20 characters, please

Zara

Example 3

program formattedPrint
F O R T R A N [ 2 2 1 ] | 46

implicit none

real :: c = 1.2786456e-9, d = 0.1234567e3

integer :: n = 300789, k = 45, i = 2

character (len=15) :: str="Tutorials Point"

print "(i6)", k

print "(i6.3)", k

print "(3i10)", n, k, i

print "(i10,i3,i5)", n, k, i

print "(a15)",str

print "(f12.3)", d

print "(e12.4)", c

print '(/,3x,"n = ",i6, 3x, "d = ",f7.4)', n, d

end program formattedPrint

When the above code is compiled and executed, it produces the following result:

45

045

300789 45 2

300789 45 2

Tutorials Point

123.457

0.1279E-08

n = 300789 d = *******

The Format Statement


The format statement allows you to mix and match character, integer and real output in one
statement. The following example demonstrates this:

program productDetails

implicit none

character (len=15) :: name

integer :: id

real :: weight

name = 'Ardupilot'
F O R T R A N [ 2 2 1 ] | 47

id = 1

weight = 0.08

print *,' The product details are'

print 100

100 format (7x,'Name:', 7x, 'Id:', 1x, 'Weight:')

print 200, name, id, weight

200 format(1x, a, 2x, i3, 2x, f5.2)

end program productDetails

When the above code is compiled and executed, it produces the following result:

The product details are

Name: Id: Weight:

Ardupilot 1 0.08

Fortran - File Input Output

Fortran allows you to read data from, and write data into files.

In the last chapter, you have seen how to read data from, and write data to the terminal. In this
chapter you will study file input and output functionalities provided by Fortran.

You can read and write to one or more files. The OPEN, WRITE, READ and CLOSE statements
allow you to achieve this.

Opening and Closing Files


Before using a file you must open the file. The open command is used to open files for reading
or writing. The simplest form of the command is:

open (unit = number, file = "name").

However, the open statement may have a general form:

open (list-of-specifiers)

The following table describes the most commonly used specifiers:

Specifier Description

[UNIT=] u The unit number u could be any number in the range 9-99 and it indicates
the file, you may choose any number but every open file in the program
must have a unique number
F O R T R A N [ 2 2 1 ] | 48

IOSTAT= ios It is the I/O status identifier and should be an integer variable. If the open
statement is successful then the ios value returned is zero else a non-zero
value.

ERR = err It is a label to which the control jumps in case of any error.

FILE = fname File name, a character string.

STATUS = sta It shows the prior status of the file. A character string and can have one of
the three values NEW, OLD or SCRATCH. A scratch file is created and
deleted when closed or the program ends.

ACCESS = acc It is the file access mode. Can have either of the two values, SEQUENTIAL
or DIRECT. The default is SEQUENTIAL.

FORM= frm It gives the formatting status of the file. Can have either of the two values
FORMATTED or UNFORMATTED. The default is UNFORMATTED

RECL = rl It specifies the length of each record in a direct access file.

After the file has been opened, it is accessed by read and write statements. Once done, it should
be closed using the close statement.

The close statement has the following syntax:

close ([UNIT=]u[,IOSTAT=ios,ERR=err,STATUS=sta])

Please note that the parameters in brackets are optional.

Example

This example demonstrates opening a new file for writing some data into the file.

program outputdata

implicit none

real, dimension(100) :: x, y

real, dimension(100) :: p, q

integer :: i

! data

do i=1,100

x(i) = i * 0.1
F O R T R A N [ 2 2 1 ] | 49

y(i) = sin(x(i)) * (1-cos(x(i)/3.0))

end do

! output data into a file

open(1, file='data1.dat', status='new')

do i=1,100

write(1,*) x(i), y(i)

end do

close(1)

end program outputdata

When the above code is compiled and executed, it creates the file data1.dat and writes the x and
y array values into it. And then closes the file.

Reading from and Writing into the File

The read and write statements respectively are used for reading from and writing into a file
respectively.

They have the following syntax:

read ([UNIT=]u, [FMT=]fmt, IOSTAT=ios, ERR=err, END=s)

write([UNIT=]u, [FMT=]fmt, IOSTAT=ios, ERR=err, END=s)

Most of the specifiers have already been discussed in the above table.

The END=s specifier is a statement label where the program jumps, when it reaches end-of-file.

Example

This example demonstrates reading from and writing into a file.

In this program we read from the file, we created in the last example, data1.dat, and display it
on screen.

program outputdata

implicit none

real, dimension(100) :: x, y

real, dimension(100) :: p, q

integer :: i

! data

do i=1,100

x(i) = i * 0.1

y(i) = sin(x(i)) * (1-cos(x(i)/3.0))


F O R T R A N [ 2 2 1 ] | 50

end do

! output data into a file

open(1, file='data1.dat', status='new')

do i=1,100

write(1,*) x(i), y(i)

end do

close(1)

! opening the file for reading

open (2, file='data1.dat', status='old')

do i=1,100

read(2,*) p(i), q(i)

end do

close(2)

do i=1,100

write(*,*) p(i), q(i)

end do

end program outputdata

When the above code is compiled and executed, it produces the following result:

0.100000001 5.54589933E-05

0.200000003 4.41325130E-04

0.300000012 1.47636665E-03

0.400000006 3.45637114E-03

0.500000000 6.64328877E-03

0.600000024 1.12552457E-02

0.699999988 1.74576249E-02

0.800000012 2.53552198E-02

0.900000036 3.49861123E-02

1.00000000 4.63171229E-02

1.10000002 5.92407547E-02

1.20000005 7.35742599E-02

1.30000007 8.90605897E-02
F O R T R A N [ 2 2 1 ] | 51

1.39999998 0.105371222

1.50000000 0.122110792

1.60000002 0.138823599

1.70000005 0.155002072

1.80000007 0.170096487

1.89999998 0.183526158

2.00000000 0.194692180

2.10000014 0.202990443

2.20000005 0.207826138

2.29999995 0.208628103

2.40000010 0.204863414

2.50000000 0.196052119

2.60000014 0.181780845

2.70000005 0.161716297

2.79999995 0.135617107

2.90000010 0.103344671

3.00000000 6.48725405E-02

3.10000014 2.02930309E-02

3.20000005 -3.01767997E-02

3.29999995 -8.61928314E-02

3.40000010 -0.147283033

3.50000000 -0.212848678

3.60000014 -0.282169819

3.70000005 -0.354410470

3.79999995 -0.428629100

3.90000010 -0.503789663

4.00000000 -0.578774154

4.09999990 -0.652400017

4.20000029 -0.723436713

4.30000019 -0.790623367

4.40000010 -0.852691114

4.50000000 -0.908382416

4.59999990 -0.956472993
F O R T R A N [ 2 2 1 ] | 52

4.70000029 -0.995793998

4.80000019 -1.02525222

4.90000010 -1.04385209

5.00000000 -1.05071592

5.09999990 -1.04510069

5.20000029 -1.02641726

5.30000019 -0.994243503

5.40000010 -0.948338211

5.50000000 -0.888650239

5.59999990 -0.815326691

5.70000029 -0.728716135

5.80000019 -0.629372001

5.90000010 -0.518047631

6.00000000 -0.395693362

6.09999990 -0.263447165

6.20000029 -0.122622721

6.30000019 2.53026206E-02

6.40000010 0.178709000

6.50000000 0.335851669

6.59999990 0.494883657

6.70000029 0.653881252

6.80000019 0.810866773

6.90000010 0.963840425

7.00000000 1.11080539

7.09999990 1.24979746

7.20000029 1.37891412

7.30000019 1.49633956

7.40000010 1.60037732

7.50000000 1.68947268

7.59999990 1.76223695

7.70000029 1.81747139

7.80000019 1.85418403

7.90000010 1.87160957
F O R T R A N [ 2 2 1 ] | 53

8.00000000 1.86922085

8.10000038 1.84674001

8.19999981 1.80414569

8.30000019 1.74167395

8.40000057 1.65982044

8.50000000 1.55933595

8.60000038 1.44121361

8.69999981 1.30668485

8.80000019 1.15719533

8.90000057 0.994394958

9.00000000 0.820112705

9.10000038 0.636327863

9.19999981 0.445154816

9.30000019 0.248800844

9.40000057 4.95488606E-02

9.50000000 -0.150278628

9.60000038 -0.348357052

9.69999981 -0.542378068

9.80000019 -0.730095863

9.90000057 -0.909344316

10.0000000 -1.07807255

Fortran – Procedures

A procedure is a group of statements that perform a well-defined task and can be invoked
from your program. Information (or data) is passed to the calling program, to the procedure as
arguments.

There are two types of procedures:

 Functions
 Subroutines
Function
A function is a procedure that returns a single quantity. A function should not modify its
arguments.
F O R T R A N [ 2 2 1 ] | 54

The returned quantity is known as function value, and it is denoted by the function name.

Syntax:

Syntax for a function is as follows:

function name(arg1, arg2, ....)

[declarations, including those for the arguments]

[executable statements]

end function [name]

The following example demonstrates a function named area_of_circle. It calculates the area of a
circle with radius r.

program calling_func

real :: a

a = area_of_circle(2.0)

Print *, "The area of a circle with radius 2.0 is"

Print *, a

end program calling_func

function area_of_circle (r)

! this function computes the area of a circle with radius r

implicit none

! function result

real :: area_of_circle

! dummy arguments

real :: r

! local variables

real :: pi

pi = 4 * atan (1.0)

area_of_circle = pi * r**2

end function area_of_circle

When you compile and execute the above program, it produces the following result:

The area of a circle with radius 2.0 is

12.5663710

Please note that:


F O R T R A N [ 2 2 1 ] | 55

 You must specify implicit none in both the main program as well as the procedure.

 The argument r in the called function is called dummy argument.

The result Option

If you want the returned value to be stored in some other name than the function name, you
can use the result option.

You can specify the return variable name as:

function name(arg1, arg2, ....) result (return_var_name)

[declarations, including those for the arguments]

[executable statements]

end function [name]

Subroutine
A subroutine does not return a value, however it can modify its arguments.

Syntax

subroutine name(arg1, arg2, ....)

[declarations, including those for the arguments]

[executable statements]

end subroutine [name]

Calling a Subroutine

You need to invoke a subroutine using the call statement.

The following example demonstrates the definition and use of a subroutine swap, that changes
the values of its arguments.

program calling_func

implicit none

real :: a, b

a = 2.0

b = 3.0

Print *, "Before calling swap"

Print *, "a = ", a

Print *, "b = ", b

call swap(a, b)

Print *, "After calling swap"


F O R T R A N [ 2 2 1 ] | 56

Print *, "a = ", a

Print *, "b = ", b

end program calling_func

subroutine swap(x, y)

implicit none

real :: x, y, temp

temp = x

x=y

y = temp

end subroutine swap

When you compile and execute the above program, it produces the following result:

Before calling swap

a = 2.00000000

b = 3.00000000

After calling swap

a = 3.00000000

b = 2.00000000

Specifying the Intent of the Arguments


The intent attribute allows you to specify the intention with which arguments are used in the
procedure. The following table provides the values of the intent attribute:

Value Used as Explanation

in intent(in) Used as input values, not changed in the function

out intent(out) Used as output value, they are overwritten

inout intent(inout) Arguments are both used and overwritten

The following example demonstrates the concept:

program calling_func

implicit none

real :: x, y, z, disc
F O R T R A N [ 2 2 1 ] | 57

x= 1.0

y = 5.0

z = 2.0

call intent_example(x, y, z, disc)

Print *, "The value of the discriminant is"

Print *, disc

end program calling_func

subroutine intent_example (a, b, c, d)

implicit none

! dummy arguments

real, intent (in) :: a

real, intent (in) :: b

real, intent (in) :: c

real, intent (out) :: d

d = b*b - 4.0*a*c

end subroutine intent_example

When you compile and execute the above program, it produces the following result:

The value of the discriminant is

17.0000000

Recursive Procedures
Recursion occurs when a programming languages allows you to call a function inside the same
function. It is called recursive call of the function.

When a procedure calls itself, directly or indirectly, is called a recursive procedure. You should
declare this type of procedures by preceding the word recursive before its declaration.

When a function is used recursively, the result option has to be used.

Following is an example, which calculates factorial for a given number using a recursive
procedure:

program calling_func

implicit none

integer :: i, f

i = 15

Print *, "The value of factorial 15 is"


F O R T R A N [ 2 2 1 ] | 58

f = myfactorial(15)

Print *, f

end program calling_func

recursive function myfactorial (n) result (fac)

! computes the factorial of n (n!)

implicit none

! function result

integer :: fac

! dummy arguments

integer, intent (in) :: n

select case (n)

case (0:1)

fac = 1

case default

fac = n * myfactorial (n-1)

end select

end function myfactorial

Internal Procedures
When a procedure is contained within a program, it is called the internal procedure of the
program. The syntax for containing an internal procedure is as follows:

program program_name

implicit none

! type declaration statements

! executable statements

...

contains

! internal procedures

...

end program program_name

The following example demonstrates the concept:

program mainprog

implicit none
F O R T R A N [ 2 2 1 ] | 59

real :: a, b

a = 2.0

b = 3.0

Print *, "Before calling swap"

Print *, "a = ", a

Print *, "b = ", b

call swap(a, b)

Print *, "After calling swap"

Print *, "a = ", a

Print *, "b = ", b

contains

subroutine swap(x, y)

real :: x, y, temp

temp = x

x=y

y = temp

end subroutine swap

end program mainprog

When you compile and execute the above program, it produces the following result:

Before calling swap

a = 2.00000000

b = 3.00000000

After calling swap

a = 3.00000000

b = 2.00000000

Subroutines and Functions

Re-using code – the subroutine


Examine the following program

program output

implicit none
F O R T R A N [ 2 2 1 ] | 60

real,dimension(3) :: a,b,c

character :: answer*1

!initialise arrays

a = 1.5

b = 2.5

c = 3.5

write(*,1) 'a',a

print *, 'type y to continue or any other key to finish'

read *, answer

if (answer /= 'y') stop

write(*,1) 'b',b

print *, 'type y to continue or any other key to finish'

read *, answer

if (answer /= 'y') stop

write(*,1) 'c',c

print *, 'type y to continue or any other key to finish'

read *, answer

if (answer /= 'y') stop

write(*,1) 'a*b*c',a * b * c

1 format(a,3f8.3)

end program output

The program sets up some arrays and then outputs them. At three stages in the program
(bolded), it asks whether it should continue; it stops if the answer is not 'y'. Notice that the
three bolded parts of the code are identical.

Simple enough – but look at the amount of code! Most of it is the same – wouldn't it be nice to
re-use the code and cut down on the typing? The answer is to use subroutines.

program output1

implicit none

real,dimension(3) :: a,b,c

!initialise arrays

a = 1.5

b = 2.5
F O R T R A N [ 2 2 1 ] | 61

c = 3.5

write(*,1) 'a',a

call prompt()

write(*,1) 'b',b

call prompt()

write(*,1) 'c',c

call prompt()

write(*,1) 'a*b*c',a * b * c

1 format(a,3f8.3)

end program output1

!++++++++++++++++++++++++++++++++++++++++++++++

subroutine prompt()

!prompts for a keypress

implicit none

character answer*1

print *, 'type y to continue or any other key to finish'

read *, answer

if (answer /= 'y') stop

end subroutine prompt

Examine the code, each time we use type

call prompt()

the program jumps to the line

subroutine prompt()

then executes each line of the code it finds in the subroutine until it reaches the line

end subroutine prompt

and then returns to the main program and carries on where it left off.

The program is much easier to understand now. All the code for prompting is in one place. If we
ever need to change the code which prompts the user to continue, we will only ever need to
change it once. This makes the program more maintainable.

You might also like