FORTRAN is often viewed as an outdated and archaic language, but it is just as capable of doing any job that other compiled languages can. It’s thoroughly up to date, with the previous stable standard being released in 2018 (5779), and the previous in 2010 (5771). Modern FORTRAN – which is now just spelt Fortran, although I prefer the former – supports generics and modularisation, object-oriented programming, concurrent programming, and is even interoperable with C. This post will walk you through the basic structure of a FORTRAN program. It’s designed for people who already know a little about programming, but haven’t worked with FORTRAN in the past.
There’s no reason not to use FORTRAN, provided you enjoy working with the language and you can use it within your environment. At the end of the day, the tools used are unimportant; only the ability of the final product to meet requirements matters. That being said, I wouldn’t recommend using FORTRAN if the rest of your company only understands Objective-C. That probably won’t go down well with your boss.
This post and any future posts regarding FORTRAN will not deal with language elements that are specific to fixed-form FORTRAN. If you’re working with legacy code or compilers, a lot of this may not apply to you. I will be following the convention of writing all keywords in capitals, though this is completely optional.
The initial program template
All FORTRAN programs start with the following basic template:
PROGRAM program_name IMPLICIT none ! code goes here END PROGRAM program_name
Every FORTRAN program starts with the keyword
PROGRAM followed by the name of the program and ends with
END PROGRAM followed by the name of the program.
PROGRAM is optional, but it is almost always included as it informs the compiler where the main routine of the program begins.
Most modern FORTRAN programs follow this with
IMPLICIT none. This tells the compiler that no implicit types are used by this program. This is because, if this is not set, FORTRAN will attempt to define any variables with the names
i, j, k, l, m and
n as integers, and all other variables as real. It is included in almost all code to prevent issues with mistaken type declarations. This statement comes straight after
PROGRAM. Only the
USE keyword may be placed before it, but we will come to that later.
! character indicates a comment. Everything after the
! on that line is ignored by the compiler, except when it is used in a character string.
The rest of the code for the program follows these statements. FORTRAN programs do have a specific order, though. You can’t write anything in any order and expect it to work – just as
main() must be at the end of a C file.
Specification, Execution and Subprogram
The specification, or declaration, section is placed immediately after the implicit statement. This part of the program specifies the data types of variables that will be used by the main program. For instance, if our program were to use an integer referenced as
the_integer and a character string referenced as
the_character, our program would now look like this.
PROGRAM program_name IMPLICIT none ! Start of the specification part ! The integer variable INTEGER :: the_integer ! The character variable CHARACTER :: the_character ! End of the specification part ! The rest of the code goes here END PROGRAM program_name
As you can see in the code above, we now have two variables initialised. You should note that FORTRAN does not have a separate data type for strings. The character type covers both single characters and strings of characters. You do need to define how long the string will be, however, or the compiler will truncate it to a single character. Alternatively, you can include a wildcard, but this comes with its own drawbacks that I won’t be covering here.
INTEGER :: the_integer CHARACTER (LEN=6) :: the_character
After the specification section of the program, we have the execution section. This section handles the main program logic that will be executed when the program is run. Using what we have thus far, we can quickly demonstrate how this part of the program might look.
PROGRAM program_name IMPLICIT none ! Start of the specification part ! The integer variable INTEGER :: the_integer ! The character variable CHARACTER (LEN=6) :: the_character ! End of the specification part ! Start of the execution part ! Putting the variables to use the_character = "World!" the_integer = 1 the_integer = 1 + the_integer ! Printing to the command line PRINT *, "Hello ", the_character PRINT *, the_integer ! End of the execution part END PROGRAM program_name
Now we have a functioning, albeit short, FORTRAN program. But what about subprograms? To begin to understand subprograms, we have to separate subprograms into two different subtypes: functions and subroutines.
Functions are designed to emulate mathematical functions. They work just like functions in C languages, although functions are typically used if there is a single value that must be returned. Functions cannot return more than one value. The following is an example function that prompts for two integers, then adds two integers together.
INTEGER FUNCTION Addition(a, b) IMPLICIT none INTEGER :: a, b Addition = a + b END FUNCTION Addition
This function can then be called from the main program code. It will execute, then return the value of
Addition. Note that the name of the function is used as the return statement, rather than using a keyword such as
return as is the case in C.
Unlike functions, subroutines are designed to be used when a return value is not required, or when more than one return value is required. Functions can serve the former purpose, but this is generally not how they are used. They are visually similar to functions, as you will see below.
SUBROUTINE Subtraction(a, b, c) IMPLICIT none INTEGER, INTENT(IN) :: a, b INTEGER, INTENT(OUT) :: c c = a - b END SUBROUTINE Subtraction
There are a few key differences, however. Firstly, there is no type assigned to the subroutine. This is because subroutines do not have to return a value, nor do they have to return only a single value. Secondly, the variables that are going to be returned by the subroutine are included in the formal argument.
Finally, we have to declare what the purpose of our variables is, as you can see with
INTENT(OUT). When the intent of a variable is
IN, that means the value of this variable is determined by the input of the subroutine’s formal argument. When the intent is
OUT, then the value will be determined within the subroutine, then returned to the part of the program that called the subroutine. Both of these can be combined with the intent
Using functions and subroutines
Now that we know how functions and subroutines are written, we can see how they are implemented in programs.
PROGRAM program_name IMPLICIT none ! Start of the specification part ! The integer variable INTEGER :: the_integer, the_output ! The character variable CHARACTER (LEN=6) :: the_character ! End of the specification part ! Start of the execution part ! Putting the variables to use the_character = "World!" the_integer = 1 the_integer = 1 + the_integer PRINT *, "Hello ", the_character PRINT *, the_integer ! Calling the function Addition(a, b) PRINT *, Addition(the_integer, the_integer) ! Calling the subroutine Subtraction(a, b, c) CALL Subtraction(the_integer, the_integer, the_output) PRINT *, the_output ! End of the execution part ! Start of the subprogram part CONTAINS INTEGER FUNCTION Addition(a, b) IMPLICIT none INTEGER :: a, b Addition = a + b END FUNCTION Addition SUBROUTINE Subtraction(a, b, c) IMPLICIT none INTEGER, INTENT(IN) :: a, b INTEGER, INTENT(OUT) :: c c = a - b END SUBROUTINE Subtraction ! End of the subprogram part END PROGRAM program_name
To separate out functions and subroutines from the main program, we use the keyword
CONTAINS. This lets the compiler know that the code included after this is not a part of the main program, and thus should be executed when called, rather than procedurally.Now that the subprograms are included in the entirety of our code thus far, we can see some differences between the two. Right off the bat, we can see that a new integer has been declared in the main program. This integer,
the_output, is defined by the output of the subroutine. Unlike functions, subroutines must have their output assigned to variables declared by the main program.
We can also see that functions and subroutines are called in a different manner. Functions can be called from within code as they can in C, but subroutines must be called with the
CALL keyword. This is because the compiler cannot predetermine how the output of a subroutine will be used if an output is provided. Functions will return a single output that it can interpret, however.
There’s just one more element of FORTRAN programs that we haven’t covered, and that is modules. As these separate out program code into multiple files and introduce a whole new array of issues that encroach upon object-oriented development, I will cover these in a different post.
Concluding The Basic Structure of a FORTRAN Program
If you’ve gotten this far, congratulations. You’ve successfully learned more about FORTRAN than the majority of today’s programmers will ever know.
This post will, hopefully, give you everything you need to know to begin reading FORTRAN programs. You might not understand what the code does, but you’ll be able to pick out the structure of the program and translate that into the concepts of a language that you are more familiar with.
If you have any suggestions for how this article can be improved, requests for future articles, or queries about all of the nonsense you’ve just read, leave a comment below, or mention me in the Rauchland Discord server or via Twitter.
If you enjoy my blog or find it useful, please consider becoming a patron on Patreon to help me keep my site live and create more content!