Arrays e ES Formatada em Fortran

Arrays and Formatted I/O

This worksheet is also available in PDF format.

This worksheet makes use of several examples programs that are all available for download from this website.


By the end of this worksheet you will be able to:


Let us imagine that we want to find the average of 10 numbers. One (crude) method is shown in the next program.

    program av
    real :: x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,average
    read *, x1,x2,x3,x4,x5,x6,x7,x8,x9,x10
    average = (x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10)/10
    print *, 'the average is ',average
    print *, 'the numbers are:'
    print *, x1
    print *, x2
    print *, x3
    print *, x4
    print *, x5
    print *, x6
    print *, x7
    print *, x8
    print *, x9
    print *, x10
    end program av

This approach is messy, involves a lot of typing and is prone to error. Imagine if we had to deal with thousands of numbers!

The way around this is to use arrays. An array is a list that we can access through a subscript. To indicate to FORTRAN that we are using an array, we just specify its size when we declare it.

        real, dimension(100)  ::x
        x(1) = 3
        x(66) = 4

This snippet of code allocates 100 memory locations to the array x. To access an individual location, called an array element, we use asubscript – here we are assigning the number 4 to the 66th element of array x and 3 to the 1st element.

Now let’s return to program av at the start of this worksheet, we’ll re-write it using an array.

        program av2
        implicit none
        real ,dimension(10) :: x
        real                :: average,sum
        integer             :: i
        print *, 'enter 10 numbers'
        do i=1,10
        	read *, x(i)
        end do
        print *, 'the average is ',average
        print *, 'the numbers are'
        **print *,x**
        end program av2

Notice that if we type

        print*, x

the program will print out the entire contents of the array.

The additional benefit of this program is that with very few changes, we could make it deal with any number of items in our list. We can improve on this still further by making use theparameter data type:

      	program av3
        !just change the value of the parameter  to change the size of the !array
        implicit none
        **integer, parameter    ::** imax **= 10**
        real,dimension(imax)  :: x
        real                  ::  average,sum
        integer               :: i
        print *, 'enter’ ,**imax**, ’ numbers'
        do i=1,**imax**
        	read *, x(i)
        end do
        print *, 'the average is ',average
        print *, 'the numbers are'
        print *,x
        end program av3

Note this is an example of good programming. The code is easily maintainable – all we have to do to find an average of a list of numbers of anysize is just to change the size of the parameterimax. We can also allocate the size of the array at run time by dynamically allocating memory.

The following program demonstrates the use of arrays where we do not know the size of the array.

        program alloc
        implicit none
        **integer, allocatable,dimension(:):: vector** 
        !note syntax - dimension(:) 
        integer  :: elements,i
        print *,'enter the number of  elements in the vector'
        read *,elements    
        !allocates the correct amount  of memory 
        print *,' your vector is of  size ',elements,'. Now enter each element'
        do i=1,elements
             read *,vector(i)
        end do
        print *,'This is your vector'
        do i=1,elements
             print *,vector(i)
        end do            
        !tidies up the memory
        end program alloc

The program is called alloc.f95 and can be copied from the web page. Note in particular the bolded lines. The new way of declaring the array vector tells the compiler that it is allocatable – ie the size will be determined atrun time.

We shall look at this further in Section 7.

Exercise 5.1

Write a program that asks the user how many numbers they want to enter, call this valueimax. Allocate imaxelements to two arrays, aand b. Read in imax numbers to a and do the same to b. Print out the arrays a, b and print out the sum of a and b. Compare your attempt with sumalloc.f95.

Array magic

One of the benefits of arrays is that you can easily do operations on every element by using simple arithmetic operators.

        program ramagic
        implicit none
        real ,dimension(10)  :: a,b,c,d
        read(10,*) a
        print *, 'a= ',a
        print *, 'b= ',b
        print *, 'c= ',c
        print *, 'd= ',d
        end program  ramagic   
Exercise 5.2

Copy program ramagic.f95 and file data.txt to your own computer. Run the program and examine the output.

Exercise 5.3

Write a program that fills a 10 element array xwith values between 0 and .9 in steps of .1. Print the values of sin(x) and cos(x) using the properties of arrays to simplify your program. Compare your answer with ramagic2.f95.

Multi dimensional arrays

The arrays we have looked at so far have beenone dimensional, that is a single list of numbers that are accessed using a single subscript. In concept, 1 dimensional arrays work in a similar way to vectors. We can also use two dimensional arrays which conceptually are equivalent to matrices.

So, for example,

       integer,  dimension(5,5) :: a

sets up a storage space with 25 integer locations.

The next program creates a 2 dimensional array with 2 rows and 3 columns. It fills all locations in column 1 with 1, columns 2 with 2, column 3 with 3 and so on.

       program twodra
       implicit none
       integer,dimension(2,3)      ::  a
       integer                     ::row,col,count
       count = 0
       !creates an array with 3 cols and 2 rows
       !sets col 1 to 1, col2 to 2 and so on
       do row=1,2
          do col =1,3
           end do
       end do
       do row=1,2
          do col =1,3
             print  *,a(row,col)
          end do
       end do
       end program twodra                   

FORTRAN actually allows the use of arrays of up to 7 dimensions, a feature which is rarely needed. To specify a extended precision 3 dimensional array b with subscripts ranging from 1 to 10, 1 to 20 and 1 to 30 we would write:

        real  (kind=ikind),dimension(10,20,30) :: b  
Exercise 5.4

Using a 4*4 array create an identity matrix, that is, a matrix of the form:

    1  0  0  0
    0  1  0  0
    0  0  1  0
    0  0  0  1

and output it. Wouldn’t it be nice if we could actually output the matrix elements in rows and columns? At the end of this section we shall see exactly how to do this.

Formatting your output

You may now be wondering if there is any way to have better control over what your output looks like. So far we have been using the default output option – that’s what the *’s are for in the write and print statements:

          write(10,*) x,y,z
          print  *, 'program finished'
Exercise 5.5

Copy format.f95, and run it

        program format
        implicit none
        !demonstrates use of the format statement
        integer, parameter ::  ikind=selected_real_kind(p=15)
        real , dimension(4)               :: x
        integer, dimension(4)             :: nums
        integer                             :: i
        real(kind=ikind),dimension(4)      :: computed
        !fill up the arrays with something
        do i = 1,4
           nums(i)           = i * 10
           computed(i)       =  cos(0.1*i)
           x(i)              = computed(i)
        end do
        print *,'nums -  integer'
        **write(*,1) nums**
        **1     format(2i10)**
        print *, 'x - real'
        **      write(*,2) x**
        **2     format(f6.2)**
        print *, 'computed -  double precision'
        **      write(*,3)  computed**
        **3     format(f20.7)** 
        end program format

You can see that the write and formatstatements come in pairs.

 **write(output device,label) variable(s)**
 **label  format(specification)**

We are using in this example a * as the output device – in other words, the screen.

The format statement can actually go anywhere in the program, but by convention we usually place them just after the associated write or all together at the end of the program. It’s just a matter of taste.

The tricky part here is the specification. There are different specifications for integer, real, and character variables.

Integer Specification

General form : nim

Floating point Specification

General form : nfm.d

If the total width for output (m) is too small, FORTRAN will just output *’s.

Rule m >= width of the integer part plus
1 (space for decimal point) plus
1 (space for sign – if negative)

Essentially, make m nice and wide and you won’t have any trouble!

Exponential Specification

General form nEm.d

        real :: a,b
        a = sqrt(5.0)
        b = -sqrt(a)
        write(*,10) a,b
        10  **format(2E14.5)**


    0.22361E+01  -0.14953E+01

Character Specification

General form nAm

        program chars
        implicit none
        character ::a*10,b*10
        write(*,10) a,b
        10    format(2a10)
        end program chars
Exercise 5.6

Using the format specifications in format.f95 as a guide, produce a table of

    x        ex         


0 less than or equal to x less than or equal to 1


for values of x in increments of 0.1. Write your output to a file called myoutput. Ensure that your output lines up neatly in columns. An example program is neatoutput.f95 is available on the website.

Implied Do Loop to write arrays

So far, the method we have used for input and output of arrays is:

        integer :: col,row
        real :: ra(10,10)
        **!using do loop**
        do row = 1,10
           do col = 1,10
             read *,      ra(row,col)
             write(*,*)   ra(row,col)
           end do
        end do

The trouble with this method is that the rows and columns are not preserved on output. An alternative, and neater method is to use an implied do loop in the write statement.

        real :: ra(10,10)
        integer :: row,col
        !use implied do
        do row = 1,10
           do col = 1,10
             read *,        ra(row,col)
           end do
        end do
        do row=1,10
           **write(*,10)  (ra(row,col),col=1,10)**
        end do
        10  format(10f5.1)             

Exercise 5.7

In Exercise 5.4 you wrote a program to produce and identity matrix. Apply what you know about formatting now to make a neatly formatted matrix onscreen. There is an example identity1.f95 available on the website.


  3. Eli Bendersky’s website – Memory layout of multi-dimensional arrays
Avatar de zrhans

Posted by

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logo do

Você está comentando utilizando sua conta Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.

Site criado com

%d blogueiros gostam disto: