Chapter 4 functions
(4.1) subroutine
program main implicit none call hello() end program main subroutine hello() implicit none write(*,*) "Hello!" return end subroutine hello
The difference between the subroutine and the main program is that the program code of the main program will be executed automatically at the beginning of the program, while the subroutine will not be executed automatically. It needs to be called by others to execute, which is the reason why it is called "sub". In fact, the status of the main program and subroutine is similar. The main program is called "main" because it is the execution entrance of the whole program.
The main program does not have to be placed at the beginning of the program code. It can be arranged at any position of the program. You can write the subroutine first and then the main program. The last command of a subroutine is usually return, indicating that the program wants to return to the place where it was called. The return command can also be omitted. The subroutine will return automatically after executing all its code. Return can also be used anywhere in the subroutine to end the subroutine in advance.
In addition to calling the main program, subroutines can also call each other. Subroutines can also call themselves. This operation is called "recursion". The subroutine has its own variable declaration independently, that is, the variables declared in the main program and subroutine are irrelevant to each other. In addition to independent variables, subroutines also independently have their own lines of code.
(4.2) user defined function
The operation of user-defined function is basically the same as that of subroutine. It also needs to be called to execute. It can also declare variables independently. Parameter transfer is also address transfer.
However, it must be declared before calling the custom function, and a value will be returned after the custom function is executed. Therefore, subroutines and custom functions are collectively referred to as "functions", because they are a program that needs to be called to execute.
program main implicit none real :: a = 1,b = 2 real,external :: add !statement add It's a function, not a variable write(*,*) add(a,b) end program main !The first way to write function add(a,b) implicit none real :: a,b,add !here add Is the declared return value type add = a + b return end function add !The second way to write real function add(a,b) implicit none real :: a,b add = a + b return end function add !The third way to write real function add(a,b) result(ret) implicit none real :: a,b ret = a + b return end function add
(4.3) parameters of function
When Fortran passes parameters, it is address passing, which means that the parameters passed during call and the parameters received in subroutines will use the same memory address to record data, and changing the formal parameters will affect the value of the actual parameters. Some languages, such as C, use value passing. At this time, changing the formal parameter cannot affect the value of the argument.
program main implicit none integer :: a = 1,b = 2 call swap(a,b) !Can achieve the purpose of exchange end program main subroutine swap(a,b) integer a,b,temp temp = a; a = b; b = temp; end subroutine swap
call showReal(1.0) !When passing parameters to a function, the type should be correct. Remember to add a decimal point when using floating-point numbers
call func(2) !When using constants as arguments subroutine func(num) !Ensure that the subroutine cannot change the contents of this parameter implicit none integer :: num num = num + 1 !An error occurs when the value of the incoming parameter is changed return end subroutine add
!Displays an element based on the address of the passed array element subroutine showOne(arr) implicit none integer :: arr(1) !Note that a single element array is defined here, not directly arr,Because the parameters passed are array parameters write(*,"(I3)") arr return end subroutine showOne !Three elements are displayed based on the address of the passed array element subroutine showThree(arr) implicit none integer :: arr(3) write(*,"( 3(I3) )") arr return end subroutine showThree !Based on the address of the passed array element, 2 is displayed*2 Elements subroutine showTwoByTwo(arr) implicit none integer :: arr(2,2) integer :: i,j write(*,"( 2(I3,I3,/) )") ((arr(i,j),j = 1,2),i = 1,2) end subroutine showTwoByTwo program main implicit none integer :: arr(5) = (/1,2,3,4,5/) call showOne(arr) !□□1,The passed parameter is the array name, which means that the address of the first element of the array is passed call showThree(arr) !□□1□□2□□3 call showThree(arr(2)) !□□2□□3□□4,Pass the address of the second element call showTwoByTwo(arr) !□□1□□3 !□□2□□4 end program main
When an array is declared in the main function, it must use constants to assign its size. However, in the function, if the array is a parameter received by the function, you can use variables to assign its size, or even do not assign its size. Because the memory space of the array has been configured in the declaration of the main program, new memory will not be configured in the declaration of the function.
subroutine useArray1(arr,size) implicit none integer :: size integer :: arr(size) write(*,*) arr return end subroutine useArray1 subroutine useArray2(arr) implicit none integer :: arr(*) integer :: i write(*,*) (arr(i),i=1,5) !The output must indicate which dimension to output. Here is a one-dimensional array, so it must indicate that the output is the first dimension of the first dimension~5 Elements return end subroutine useArray2 program main implicit none integer :: size = 5 integer :: arr(5) = (/1,2,3,4,5/) call useArray1(arr,size) call useArray2(arr) end program main
For multi-dimensional arrays, only the last dimension can not be assigned a size, and other dimensions must be assigned a size. The array size assigned in the function is only used to facilitate inspection. Although there are so many strange rules here, you should form a good habit of passing all the actual declared sizes of arrays.
The variables in the function will be allocated memory when the function is called, and will die after the call. Add a save in the variable declaration statement of the function to save these variables, and you can permanently remember the values given in the last function call during program execution.
!Custom functions are passed as arguments program main implicit none real,external :: func !statement func Is a custom function real,intrinsic :: sin !statement sin Is a library function call funcSub(func) !Custom functions are passed as arguments call funcSub(sin) !Library functions are passed as arguments end program main real function func(num) result(ret) implicit none real :: num ret = num * 2 return end function func subroutine funcSub(f) implicit none real,external :: f !statement f Is a function write(*,*) f(1.0) return end subroutine funcSub
!Subroutines are passed as parameters program main implicit none external ssub !statement ssub Is the subroutine name call sub(ssub) !Subroutines are passed as parameters end program main subroutine ssub() implicit none write(*,*) "Hello!" return end subroutine ssub subroutine sub(ssub) implicit none external ssub !statement ssub Is a subroutine call ssub() return end subroutine sub
common is a method of using global variables in Fortran77. It can connect variables under different scopes.
program main implicit none integer :: a,b common a,b a = 1 b = 2 call showCommon() !output□□□□□□□□□□□1□□□□□□□□□□□2 end program main subroutine showCommon() implicit none integer :: num1,num2 common num1,num2 write(*,*) num1,num2 return end subroutine showCommon
When global variables are used, they are corresponding according to their relative position relationship when they are declared, rather than using variable names. Therefore, num1 declared in this subroutine corresponds to a of the main program, and num2 corresponds to b; Because a and num1 are the first variables in common, and b and num2 are the second variables in common. In addition, the declaration of global variables cannot be written in the form of integer, common:: A, b.
!Suppose a global variable is declared in the main program integer a,b,c,d,e,f common a,b,c,d,e,f !Corresponding in subroutine integer num1,num2,num3,num4,num5,num6 common num1,num2,num3,num4,num5,num6
If you want to use the sixth global variable, namely f and num6, you must declare that the first five variables are padded in front before you can get the sixth variable for use. This kind of trouble is even more surprising when there are many global variables. One way to reduce this trouble is to classify variables and put them in independent common intervals:
program main implicit none integer :: a,b,c,d,e,f common /group1/ a common /group2/ b common /group3/ c common /group4/ d common /group5/ e common /group6/ f f = 1 call showCommon6() !output□□□□□□□□□□□1 end program main subroutine showCommon6() implicit none integer :: num6 common /group6/ num6 write(*,*) num6 return end subroutine showCommon6
The common variable cannot be directly assigned by using the data statement in the subroutine or main program. It should be assigned by using the data statement in the block data program module.
program main implicit none integer :: a,b common a,b integer :: c,d common /group1/ c,d integer :: e,f common /group2/ e,f write(*,"( 6(I3) )") a,b,c,d,e,f end program main block data a2f implicit none integer a,b common a,b data a,b /1,2/ integer c,d common /group1/ c,d data c,d /3,4/ integer e,f common /group2/ e,f data e,f /5,6/ end block data a2f
The block data program is also very similar to the subroutine. It is also an independent program module and has its own variable declaration, but it can execute itself without being called by others. In fact, this program will take effect before the main program is executed, but its function is only to set the initial value of global variables, and there can be no other execution commands. It should also be pointed out that global variables cannot be declared as constants, so parameter cannot appear in block data.
(4.4) recursive function
In addition to being called by others, functions can also be called by themselves, which is called recursion. Each time a recursive function is called, the local variables declared in the function will use different addresses. A classic case is to calculate factorial by recursion:
program main implicit none integer :: n = 5 integer,external :: myFactorial write(*,*) myFactorial(n) end program main recursive integer function myFactorial(n) result(ans) !Recursive functions must use result To change his name implicit none integer,intent(in) :: n !read-only if(n < 0) then stop else if(n <= 1) then ans = 1 return end if ans = n * myFactorial(n-1) !Call yourself to calculate(n-1)! return end function myFactorial
(4.5) internal function
Fortran 90 can also use the contains statement to make a "attribution" of functions, defining that some functions can only be called in some specific functions. At this time, the functions do not need to be declared in the main program.
program main or subroutine sub or function func ... contains ... subroutine localSub ... end subroutine localSub ... function localFunc ... end function localFunc ... end program main or subroutine sub or function func
The contains statement isolates the internal routine from its program unit. A program unit can only contain one contains statement.
The scope of implicit none is the whole program unit. There is no need to write this statement in the internal function.
(4.6) module
module Module name ... contains ... subroutine Routine name ... end subroutine Routine name ... function Function name ... end function Function name ... end [ module [Module name] ]
Modules are usually used to encapsulate the parts of the program with related functions. use module module module name must be placed before implicit none. Module should be written in front of the main program. Different modules can call each other. A module has two access rights: private (which can only be used inside the module) and public (which can be used by the program unit using the module).
(4.7) intent attribute
integer,intent(in) :: a !appoint a Can only be passed in(read-only) integer,intent(out) :: a !appoint a The value should be reset in the function integer,intent(inout) :: a !It's not written intent Is the same effect
In fact, the intent attribute without specifying parameters will not affect the program execution results. It is only used to avoid errors when writing the program. It is set as a read-only variable. If its value is changed in the function, an error will occur in the compilation process, and it is set as a variable to be output. If a number is not reset in the function, a warning message will appear in the compilation process.
(4.8) interface block
Interface is a program module used to describe the parameter type and return value type of the function to be called. The interface block must be used in the following cases:
(1) When the return value of the function is an array.
(2) When the number of function parameters called is uncertain.
(3) When a parameter is passed by specifying the location where it is passed in.
(4) When the return value of the function is a pointer.
(5) When inputting index function.
program main implicit none interface function random10(a,b) result(arr) !The function returns an array, so the interface block is used implicit none real :: a,b,temp,i real :: arr(10) end function random10 end interface real :: a(10) call random_seed() !This random number seed must be called before calling the random number function a = random10(1.0,10.0) write(*,"(10F6.2)") a end program main !Returned by 10 ranges in(a,b)An array of random numbers function random10(a,b) result(arr) implicit none real :: a,b,temp,i real :: arr(10) do i = 1,10 call random_number(temp) !Generate 0~1 Between random numbers, using temp receive arr(i) = a + (b - a) * temp !produce a~b Random number between end do return end function random10
If another subroutine also calls the function random10, the interface block of the function random10 needs to be written clearly in this subroutine. At this time, you can use module to reduce this trouble:
module random10Module implicit none contains function random10(a,b) result(arr) implicit none real :: a,b,temp,i real :: arr(10) do i = 1,10 call random_number(temp) arr(i) = a + (b - a) * temp end do return end function random10 end module random10Module program main use random10Module implicit none real :: a(10) call random_seed() a = random10(1.0,10.0) write(*,"(10F6.2)") a end program main
(4.9) optional attribute
program main implicit none interface subroutine sub(a,b) !The number of function parameters called is uncertain, so the interface block is used implicit none integer :: a integer,optional :: b end subroutine sub end interface call sub(1) call sub(2,3) end program main subroutine sub(a,b) implicit none integer :: a integer,optional :: b if(present(b)) then write(*,*) a,b else write(*,*) a end if return end subroutine sub
In Fortran 90, parameters can not be passed in the order of parameters, but can be directly substituted into the variable name in the subroutine to call "specify parameter position".
program main implicit none interface real function func(x,a,b,c) result(ans) !Specify the parameter location to pass the parameter, so use the interface block implicit none real :: x real,optional :: a,b,c real :: realA,realB,realC end function func end interface write(*,*) func(2.0,c = 1.0) write(*,*) func(2.0,a = 2.0,b = 1.0) end program main real function func(x,a,b,c) result(ans) implicit none real :: x real,optional :: a,b,c real :: realA,realB,realC if(present(a)) then realA = a else realA = 0.0 end if if(present(b)) then realB = b else realB = 0.0 end if if(present(c)) then realC = c else realC = 0.0 end if ans = realA * x ** 2 + realB * x + realC return end function func
(4.10) entry statement
Entry is used to create a new entry in the function. When calling this entry, the program code before the entry point will be skipped to execute the function.
program main implicit none call sub() !Hello World! call midSub() !World! end program main subroutine sub() implicit none write(*,*) "Hello!" entry midSub() !Another entrance write(*,*) "World!" return end subroutine sub
(4.11) return statement
program main implicit none integer :: a write(*,*) "Please enter any number:" read(*,*) a call judgeNumber(a,*100,*200,*300) !Three rebate points are specified 100 write(*,*) "Negative." stop 200 write(*,*) "Zero." stop 300 write(*,*) "Positive." end program main subroutine judgeNumber(num,*,*,*) implicit none integer :: num if(num < 0) then return 1 !Return to the first rebate point else if(num == 0) then return 2 !Return to the second rebate point else return 3 !Return to the third rebate point end if end subroutine judgeNumber
ginseng Test Endowment material come source Reference sources Reference sources
- Engineering analysis program design Chen Bin, Zhou qulan Xi'an Jiaotong University Press
- FORTRAN 95 programming Peng Guolun China Electric Power Press
- Fortran programming (Fourth Edition) Stephen J.Chapman. China Electric Power Press
Bo
passenger
create
do
:
A
i
d
e
n
L
e
e
Blog creation: Aiden\ Lee
Blog creation: Aiden Lee
Special statement: the article is for learning reference only. Please indicate the source for reprint. Embezzlement is strictly prohibited!