It is very easy to make a program repeat a sequence of instructions an indefinite number of times. However the example we are about to give is an example of very bad programming practice which should never be emulated! it is provided here simple to illustrate how easy concept is to implement.
Any instruction or sequnce of instructions will be repeated indefinitely if it is preceded and terminated respectively by the two instructions shown below:
do ! instructions to be repeated here end do
Here is a very simple program which illustrates this. It is a very bad program, because as written it will never stop running!
If you are going to compile and run it, first make sure you know how to do an `emergency stop' on your computer system. This is usually achieved by pressing simulataneously the letter `c' key and the key marked `Control' or `Cntrl'.
The principle should however be clear from this example....
To be useful, the repetition clearly needs to be under rather better control! A useful way of achieving this is to count the nunber of repetitions and stop after a predetermined number. the means of doing this is described next.
do times = 1, 10 print *, 'ZAP!!' end doThe only difference between this and the previous example (so far) is in the first line. The interpretation of this can be consider to be as follows:
Like any other variable, times must be declared at the beginning of the program, before it is used. However, because times will have values which are always whole numbers or integers, the form of the declaration is different from those seen so far:
integer :: timesHere is the complete, and much improved, program:
program zap ! This is a better program !!! integer :: times do times = 1, 10 print *, 'ZAP!!' end do end programCopy it from this link.
The counter variable has other uses than just stopping this program loop. Its value is 1 the first time round, 2 the second and so on.
Try changing the instruction in the loop to:
print *, 'ZAP times ..', timesand confirm this.
There are a number of other uses for integer variables, but a major one is controlling loops like this. The number of times the loop is to be repeated, and, associated with it, the starting and finishing values of the counter variable, must be specified before the do instruction is encountered, but may in fact be general integer expressions.
Note that in this example the numbers `1' and `10' were written without decimal points, whereas these were required for numbers in the general expressions encountered previously. This is because these starting and finishing values must be whole numbers. The following would also be allowed, try them, printing out the counter value on each loop:
The following sections provide programs to illustrate the use of repetition loops and an number of other programming techniques. You are encouraged to copy and modify these as described.
Modify it to calculate and print the squares of numbers from 1 to 15 by altering only a single character in the program.
Square roots can also be calculated by raising numbers to the power 0.5, or in Fortran writing ** 0.5 Check that this gives the same answers, and modify the program to tabulate cube roots.
integer :: i real :: x ..... do i = 1, 12 x = i * 0.25 print *, x, sqrt(x) end do ...There is a more general way of doing this described later.
x = x + 3If you are in any doubt about what will happen, complete the following program segment by adding the necessary adiitional instructions, and run it.
..... x = 4 print *, 'x was', x x = x + 3 print *, 'x now is', x .....There are many circumstance where it is convenient or necessary to use this kind of `recursive' instruction. One such is illustrated in the example below. Complete this program and use it to compute some factorials. Check to see that it gives the correct answers! 5! is 120, 10! is 3628800. What happens when you try to calculate 100! which is about 10158?
n! = 1 . 2 . 3 .... (n-1) . n
Consider the following program segment:
... integer :: fact, n, i n = 5 fact = 1 do i=2,n fact = fact * n end do ...
Recall that this quantity is equal to ½(n+1)n.
real :: Tprop, Tbut, T, dT integer :: i, n .... n=10 ! number of points ... dT = (Tbut - Tprop) / (n-1) ! divide range by number of INTERVALS ! .. this gives size of interval T = Tprop ! Start here do i=1, n print *, T ! the current temperature T = T + dT ! next temperature ... end do ...Exercise: Write a program to tabulate the vapour pressures of propabe and butane at 12 equispaced temperature points between their respective 1atm boiling points.
Consider the following sequence of instructions:
.... if ( a >=0.0 ) then print *, 'a is zero or positive' else print *, 'a is negative' end if ...Their implication should be fairly obvious. If the variable a has a value greater than or equal to zero, then the instruction:
print *, 'a is zero or positive'is carried out and the appropriate message printed. On the other hand if this is not the case (`else') then the instruction:
print *, 'a is negative'is obeyed.
The program would then proceed with any instructions following end if.
The above is an example of the most general form of the conditional or `if' construction used for decision making in computer programs. The lines between then and else and between else and end if may contain any sequence of legal `executable' instructions. (This excludes `formal' instructions like real :: or end program.)
As an example of using this for of the `if' construction, here is a program to solve a quadratic equation using the quadratic formula. The program tests to se if the equation has real roots before procedding with the solution.
Two other forms of the `if' construction are useful. Sometimes it is only required to carry out a series of instructions if a condition is satisfied. This is achieved by the following. Note that the symbols /= are the Fortran version of the `not equals' sign.
if (a /=0.0 ) then print *, 'a is not zero so can be a divisor' x = 1 / a end ifNotice that in this case nothing happens if the condition is not satisfied, i.e. if a is equal to zero. In this case the value of x is not set by any instruction shown in this program segment.
Finally if only a single instruction is to depend on the outcome of the condition then it may be shortened to:
if (a /= 0.0 ) x = 1 / a
`<' and `>' have their obvious forms, <= stands for `less than or equal to' and hence the obvious interpretation of >=.
'Not equal to as above is /=.
Confusingly `equal to' must be written with two equals signs, i.e. as ==.
program random ! generate some random numbers real :: x real, external :: rand integer :: i do i= 1, 10 x = rand(0) print *, x end do end program(Note the special form of declaration: real, external :: rand which says that rand, a function to generate random real numbers in the range 0.0 to 1.0, is to be found outside, i.e. `external' to the program. This is one of a number of useful function which exist in special libraries.)
Copy the program from here and modify it (a) to print only random number greater than 0.5, and (b) to count and subsequently print out the number of such numbers.
We have already encountered an example of a `procedure call' in the print instruction. we can (loosely) define a procedure call as an instruction which `causes something to happen' other than, or in addition to, simply assigning a value to a variable.
Procedure calls have two main characteristics. Firstly the procedur invoked by the call has a name, e.g. print. Secondly there are usually one or more arguments which specify with what the procedure is to perform whatever it is meant to do.
The name of the procedure is fixed, but the programmer chooses the arguments. Thus:
print *, 'Hello'has as argument the character string 'Hello' and so that is what gets printed.
print *, whateverhas the variable whatever as argument, so its value gets displayed.
print is a rather special procedure which is built into the language. There are some others like it which you will encounter later. Another type of procedure is the subroutine procedure or simply a subroutine. These are not built into the language but are available in special libraries or can be defined by the programmer.
At this point we will introduce one example of a subroutine procedure which is available in a standard library, and another user defined subroutine which will be supplied to you. Writing your own subroutines will be covered later.
A subroutine procedure call which activates the procedure consists of the word call followed by the name of the procedure and then a list of its arguments (if any) in brackets.
system takes a single argument, the name of the Unix command as a character string in quotes, e.g. 'ls'
The following complete program will cause a listing of your files to be printed on the screen when the compiled program is run:
program list_files
call system ('ls')
end program
A version of this program
can be copied from
here. You can try changing
`ls' to `ls -l' and see what happens.
The above versions of the program are the minimum size and complexity required to access this subroutine. If you learn more about the Fortran 90 language you will discover that a stricter and more pedantic form is available. for completeness we have supplied a `long' version of the program here. (You will need this version if you are using the downloaded Lahey Fortran on a PC.)
To make use of this subroutine you must do two things. Firstly, as i the previous example, you must write a program to `call' the subroutine. A typical call migh look like tis:
call atomic ('K', Kno, Kwt)
Here the string 'K' determines that it is the
properties of potasium which are required. Kno
is a variable which you the programmer must have declared
as an integer in your program. The subroutine
call will set this to the atomic number of potasium.
Kwt must have been declared as a real
variable and will contain the corresponding atomic weight.
Note that these can be any appropriately declared variables and can
thus have any names that you want to give them.
To use use this subroutine you also need to let your program know about it. The simplest way to to this is to copy the whole subroutine from the link and put it in the same file as the program you are writing which will use the subroutine. the layout of the file will then be as shown below.
program atom_stuff
! My own program, declarations etc. go here..
real :: Kwt, ...
....
call atomic ('K', Kno, Kwt)
print *, 'Properties of Potasium..', ...
...
end program atom_stuff
! What follows is just copied..
subroutine atomic (element, number, value)
! look up atomic no. and weight of some common elements
... etc
...
end subroutine atomic
It is not necessary that you understand how atomic
actually works, but it is useful to note the existance of
variables which will hold character strings. a declararation
such as:
character *(2) :: elementdeclares a variable called element for storing not numbers but letters, up to a maximum length of two characters.
This section has been left until last because we do not particularly want to encourage you to write `interactive' programs until you are reasonably experienced in writing self contained programs.
All the programs shown to you so far have been `self contained' in that all the information required for the program to work is contained within the program.
All your handin examples should normally be written in this way. A major advantage of such a program is that it's operation can be checked by reference only to a printout of the program. A disadvantage is that every time we want to change a parameter then the the program file must be edited and recompiled.
This disadvantage become obvious with somthing like the simple vapour pressure calculation discussed earlier. A sample program for this is here. we will now discuss how to make this program more `user friendly' and `interactive'.
When ever the computer encounters an instruction like the following:
read *, xit does two things.
First it stops and waits for the user to type something on the keyboard. Secondly it interprets whatever has been typed in the context of what kind of variable x has been declared to be, and if it can, assigns whatever has been typed in to x. This should be clear from the following complete program which you might like to copy and try:
program readin real :: x print *, 'Type in a valid real number:' read *, x print *, 'The number you typed was ', x end programYou can copy the program from here. If you are trying it out, see what happens if you type either an integer or something that isn't a valid number.
Note that the variable which appears in the read instruction must be a variable which is not declared as a parameter.
It is possible in principle to have more than one variable in the list following read *, but this is not a good idea when numbers are being read from the keyboard. (They can come from elsewhere, as will be discussed later.) Also you should always print out a message to remind the user what to type in.
This is a circumstance in which it is sometimes permissable to use a do without a counter variable. However, a neater approach makes use of the instruction described in the next section.
exitwhich can only appear inside a do .. end do loop causes a immediate termination of the loop. The program carries on at the instruction following end do.
The do may be either with or without a counter variable. In the latter case the count is overridden and the loop stops at whatever is its current value.
The exit instruction is normally always the subject of a condition, e.g.:
if (TK <= 0.0) exit