第五章    数 组
This presentation is the property of its rightful owner.
Sponsored Links
1 / 37

第五章 数 组 PowerPoint PPT Presentation


  • 40 Views
  • Uploaded on
  • Presentation posted in: General

第五章 数 组. Fortran 90 数组的特点: *** 可以逐个元素对数组进行操作,也可以对数组整体、数组段直接进行操作; *** Fortran 90 提供了针对数组操作的构造块和函数; *** Fortran 90 提供了动态数组,以有效利用内存; *** Fortran 90 数组具有隐式循环和数组赋值的功能。. 第一节 数组声明. 数组声明实例 REAL , DIMENSION(15) ::X !下界缺省值为 1

Download Presentation

第五章 数 组

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


5938258

第五章 数 组

Fortran 90数组的特点:

*** 可以逐个元素对数组进行操作,也可以对数组整体、数组段直接进行操作;

*** Fortran 90提供了针对数组操作的构造块和函数;

*** Fortran 90提供了动态数组,以有效利用内存;

*** Fortran 90 数组具有隐式循环和数组赋值的功能。


5938258

第一节 数组声明

数组声明实例

  • REAL,DIMENSION(15) ::X !下界缺省值为1

  • REAL,DIMENSION(1:5,1:3) ::Y

  • REAL,DIMENSION(-4:0,1:3) ::Z

    (1)维(rank) —代表下标个数。X为一维数组,Y和Z为二维数组。

    (2)界(bounds) — X下界1、上界15,Y下界1和1,上界5和3,Z下界-4和1、上界0和3。

    (3)度(extent) —维上的元素个数。X度为15,Y和Z度为5和3。

    (4)大小(size) —总的元素个数,或特定维上的元素个数。X、Y和Z的大小为15。

    (5)形状(shape) —由维和度决定。X的形状为(/15/),Y和Z形状为(/5,3/)。

    (6)一致的(conformable) —形状相同的数组是一致的或兼容的,一致的数组才能相互赋值,这里Y和Z 形状相同。


5938258

数组声明的一般形式:

  • TYPE,DIMENSION( [dl:],du[[dl:] du]…) ::Arr

  • TYPE [::] Arr( [dl:], du[[dl:] du]…)

    TYPE代表数据类型,dl 和du 分别为维的下界和上界,Arr 为数组变量。

    下列都是合法的数组声明:

  • INTEGER, PARAMETER ::lda=5

  • REAL,DIMENSION(100) ::R

  • REAL,DIMENSION(1:10,1:10) ::S

  • REAL ::T(10,10)

  • REAL,DIMENSION(-10: -1) ::X

  • INTEGER,PARAMETER ::lda=5

  • REAL,DIMENSION(0:lda-1) ::Y

  • REAL,DIMENSION(1+lda*lda,10) ::Z

    表明:

    (1)上、下界可以任意规定;

    (2)缺省下界为1;

    (3)可省略 DIMENSION 属性,如 T ;

    (4)数组大小可以为0;

    (5) Fortran 77数组声明分2步:先数组类型,再数组维数及大小。


5938258

例 5-1 一维数组的使用,从保存有学生学号、姓名和成绩三列数据的文件中读取全部数据,并在屏幕上显示

PROGRAM Main

IMPLICIT NONE

INTEGER,PARAMETER :: MAX = 100 ! 最大行数

CHARACTER(20) NO(MAX),NAME(MAX) ! 学号、姓名

REAL MARK(MAX) ! 成绩

INTEGER IO,I,N ! N 代表实际行数

OPEN (1,FILE = ‘DATA.TXT’)

READ(1,*,IOSTAT = IO) (NO(I),NAME(I),MARK(I),I=1,MAX)

IF(IO<0)THEN ! 遭遇文件尾

N=I-1

ELSE

N=MAX

END IF

PRINT*,N

WRITE(*,‘(2A,F4.1)’) (NO(I),NAME(I),MARK(I),I=1,N)

CLOSE(1)

END PROGRAM


5938258

例5-2 二维数组的使用,从保存有学生学号、姓名和成绩三列数据的文件中读取全部数据,并在屏幕上显示

  • PROGRAM Main

  • IMPLICIT NONE

  • INTEGER,PARAMETER :: MAX = 100 !最大行数

  • CHARACTER(20) Stud(MAX,3)

    !学号、姓名、成绩,共3列

  • INTEGER IO,I,J,N

  • OPEN (1,FILE = ‘DATA.TXT’)

  • READ(1,*,IOSTAT = IO) ((Stud(I,J),J=1,3),I=1,MAX)

  • IF(IO<0)THEN

  • N=I-1

  • ELSE

  • N=MAX

  • END IF

  • PRINT*,N

  • PRINT*,((Stud(I,J),J=1,3),I=1,N)

  • CLOSE(1)

  • END PROGRAM


5938258

第二节 数组存储

1. 自由存储

  • 不规定数组在内存中如何存储,便于编写可移植的程序,编译器可以自由地实现存储优化。例如:在分布式计算环境中,一个大的数组可以被存储到100 个处理器中,每个存储数组中的部分元素。在 High Performance Fortran 中,自由存储被广泛应用。

    2. 列主存储

  • 先存储第一列,然后是第二列、第三列,直到最后一列,称为列主存储。例如:向另一个语言编写的例程传递数组、数组构造、数组输入/输出、系统提供的一些数组函数(TRANSFER,RESHAPE,PACK,UNPACK和MERGE)时,需要明确给出数组的存储方式 —列主存储。


5938258

第三节 数组操作

1. 数组赋初值

(1) 使用 DATA 的一般形式为:

  • INTEGER A(5)

  • DATA A/1, 2, 3, 4, 5/! A(1), A(2), A(3), A(4), A(5)的值分别为1, 2, 3, 4, 5

    (2) 使用乘号(*)

  • DATA A /5 *3/! A(1), A(2), A(3), A(4), A(5)的值都为3

    乘号“*” 表示数据的重复, 重复的次数写在前面。

    (3) 使用隐式循环

  • DATA (A(I), I=2,4) /2, 3, 4/ !A(2),A(3),A(4)的值分别为2,3,4

    隐式循环可用来设置数组的初值,也可以认为是 DO 循环的简略形式,在隐式循环中,同样可以设置循环变量的增量(或步长)。例如:

  • DATA (A(I), I=1, 5, 2) /1, 3, 5/ !A(1),A(3),A(5)的值分别为1,3,5


5938258

隐式循环也可以嵌套使用,例如:

  • INTEGER B(2,2),I,J

  • DATA ((B(I,J),J=1,2 ) /1,2,3,4/

    (4) 省略 DATA

    Fortran 90可以省略 DATA 关键字,直接给数组设置初值。例如:

  • INTEGER :: A(5)=(/1,2,3,4,5/)

    省略 DATA ,仍可使用隐式循环,所赋初值的个数要与数组元素的个数相等。

  • INTEGER I

  • INTEGER ::A(5)=(/1,(2,I=2,4),5/)

    !A(2),A(3),A(4)的值为2,A(1)和A(5)的值分别为1,5

    隐式循环可以给数组赋初值,也可以用来输出数组。例如:

  • PRINT *,((B(I,J),I=1,2),J=1,2)


5938258

2. 数组整体操作

Fortran 90 可以对数组进行整体操作,操作简化,举例说明如下:

  • A=5

    其中,A是任意维数及大小的数组,该语句将数组A 所有元素的值设为5。

  • A=(/1,2,3/)

    其中,A(1)=1,A(2)=2,A(3)=3,所提供的数据个数必须跟数组 A 的大小一样。

  • A=B

    其中,A 和 B 是形状完全相同的数组,数组 A 相应位置元素的值设置成同数组 B。

  • A=B+C

  • A=B-C

  • A=B*C

  • A=B/C

    其中,A、B 和 C 是3个形状完全相同的数组,数组 B 和 C 相应位置元素的值相加、相减、相乘和相除,得到的结果再赋给数组 A 对应元素。

  • A=Sin(B)

    其中,数组 A 的每一个元素为数组 B 相应元素的 Sin 值,数组 B 须是实型。

  • A=B>C

    其中,A、B 和 C 是3个形状完全相同的数组,不过 A 为逻辑型数组,B 和 C 为同类型的数值型数组。


5938258

3. 数组段操作

Fortran 90除针对整个数组进行操作外,还能对数组段进行操作。

数组段的下标三元组形式为:

  • [<bound1>] : [<bound2>] :[<stride>]

    数组段起始于下标 bound1 ,终止于下标 bound2,步长为 stride。例如:

  • A(:) !整个数组;

  • A(m:n:k) !A(m)~A(n),步长为k

  • A(m:) !A(m)~A(上界),步长1;

  • A(:n) !A(下界)~A(n),步长1;

  • A(::2) !A(下界)~A(上界),步长2;

  • A(m:m) !一个元素的数组段

    数组段的操作语法类似于隐式循环,如:

  • A(3:5) =5

    其中,将A(3)、A(4)、A(5)的值设置为5,其他值不变。


5938258

  • A(3:) =5

    其中,将A(3)以后所有元素的值设为5,其他值不变。

  • A(3:5) = (/3,4,5/)

    其中,将A(3) 、A(4)、 A(5) 的值分别设为 3、4、5,其他值不变。

  • A(1:3) = B(4:6)

    其中,设置A(1) = B(4)、 A(2) = B(5)、 A(3) = B(6)。

  • A(1:10) = A(10:1:-1)

    其中,A(1:10)翻转,即将A(1)设为A(10),A(2)设为A(9),依次类推。

  • A(:) = B(:,2)

    其中,假设 A 和 B 分别声明为 INTEGER A(5)、 INTEGER B(5,2),这里将二维数组B第2列的 5 个元素的值赋给一维数组 A 的5个元素,注意必须保持元素个数的一致。


5938258

4. 数组输出

数组元素、数组整体和数组段都可以表控输出(PRINT*),对3×3矩阵假设有下列输出语句:

  • PRINT*,‘Array element =’,a(3,2)

  • PRINT*,‘Array section =’,a(:,1)

  • PRINT*,‘Sub – array =’,a(:2,:2)

  • PRINT*,‘Whole Array =’,a

  • PRINT*,‘Array Transp“d =’,TRANSPOSE(a)

    输出结果为:

  • Array element = 6

  • Array section = 1 2 3

  • Sub – array =1 2 4 5

  • Whole Array =1 2 3 4 5 6 7 8 9

  • Array Transosed =1 4 7 2 5 8 3 6 9


5938258

5. WHERE构造

关于WHERE的说明:WHERE用来取出部分数组内容进行操作,WHERE的操作是按照逻辑判断,使用满足条件的部分数组元素。

关于WHERE的实例:使用 WHERE 构造计算应上交的所得税,每年收入3万元以下,所得税为10%;收入为3万元到5万元之间,所得税为12%;收入5万元以上,所得税为15%

例5-3 WHERE 构造的使用

  • PROGRAM Main

  • IMPLICIT NONE

  • REAL :: income(10)=(/25000,30000,50000,40000,&

    35000,60000,27000,45000,20000,70000/)

  • REAL :: tax(10) = 0

  • INTEGER I

  • CALL Proc_Where;PRINT*,tax

  • CALL Proc_IF;PRINT*,tax

  • CONTAINS


5938258

  • SUBROUTINE Proc_Where ! Where构造

  • WHERE(income<30000.0)

  • tax = income*0.1

  • ELSEWHERE(income<50000.0)

  • tax = income*0.12

  • ELSEWHERE

  • tax = income*0.15

  • END WHERE

  • END SUBROUTINE

  • SUBROUTINE Proc_IF ! IF构造

  • DO I = 1,10

  • IF(income(I)<30000.0)THEN

  • tax(I)=income(I)*0.1

  • ELSE IF(income(I)<50000.0)THEN

  • tax(I)=income(I)*0.12

  • ELSE

  • tax(I)=income(I)*0.15

  • END IF

  • END DO

  • END SUBROUTINE

  • END PROGRAM


5938258

WHERE 构造的程序代码比较精简,其语法格式为:

  • WHERE(logical-expr1)

  • block1

  • ELSEWHERE(logical-expr2)

  • block2

  • ELSEWHERE(logical-expr3)

  • block3

  • ELSEWHERE

  • blockE

  • END WHERE

    如果只有一条执行语句,那么可以将这条执行语句写在 WHERE后面,并省略 END WHERE,例如:

  • WHERE(income>50000) income = 50000

    此时,WHERE 构造转化为 WHERE语句,WHERE语句和 IF 语句在构造形式上是相同的,但省去了循环语句,结构精简。

  • WHERE(logical-expr) 执行语句


5938258

WHERE 构造也可以被命名,例如:

  • name:WHERE(income>50000)

  • income = 50000

  • END WHERE name

    WHERE 构造也可以嵌套使用,例如:

  • WHERE(income<50000.0)

  • WHERE(income<30000.0)

  • tax = income*0.1

  • ELSEWHERE

  • tax = income*0.12

  • END WHERE

  • ELSEWHERE

  • tax = income*0.15

  • END WHERE


5938258

6. FORALL 构造

FORALL构造,通过隐式循环来使用数组,功能强大,属于 Fortran 95 新添功能,举例说明如下:例 5-4 FORALL 构造的使用

  • PROGRAM Main

  • IMPLICIT NONE

  • INTEGERI,J,A(5,5)

  • CALL Proc_1

  • WRITE(*,‘(5I)’)((A(I,J),J=1,5),I=1,5)

  • CALL Proc_2

  • WRITE(*,‘(5I)’)((A(I,J),J=1,5),I=1,5)

  • CONTAINS

  • SUBROUTINE Proc_1

  • FORALL(I=1:5,J=1:5)

  • A(I,J)=I*J

  • END FORALL

  • END SUBROUTINE

  • !Proc_1采用FORALL来实现;Proc_2采用DO循环来实现

  • SUBROUTINE Proc_2

  • DO I = 1,5

  • DO J = 1,5

  • A(I,J) = I*J

  • END DO

  • END SUBROUTINE

  • END PROGRAM


5938258

例5-5 FORALL 语句的使用

  • PROGRAM Main

  • IMPLICIT NONE

  • INTEGER I,J

  • INTEGER,PARAMETER :: N=5

  • INTEGER A(N,N)

  • CALL Proc_1

  • WRITE(*,‘(5I)’)((A(I,J),J=1,N),I=1,N)

  • CALL Proc_2

  • WRITE(*,‘(5I)’)((A(I,J),J=1,N),I=1,N)

  • CONTAINS

  • SUBROUTINE Proc_1

  • FORALL(I=1:N,J=1:N,I<J)A(I,J)=1 !上三角

  • FORALL(I=1:N,J=1:N,I==J)A(I,J)=2 !对角线

  • FORALL(I=1:N,J=1:N,I>J)A(I,J)=3 !下三角

  • END SUBROUTINE

    !内部例程Proc_1采用FORALL来实现


5938258

  • SUBROUTINE Proc_2

  • DO I = 1,N

  • DO J =1,N

  • IF(I<J) A(I,J)=1 !上三角

  • IF(I==J) A(I,J)=2 !对角线

  • IF(I>J) A(I,J)=3 !下三角

  • END DO

  • END DO

  • END SUBROUTINE

  • END PROGRAM

    !内部例程Proc_2采用DO循环结合IF语句来实现

    FORALL 语句的一般形式为:

  • FORALL(循环表达式1,[循环表达式2]…,[条件判别式]) 执行语句

    FORALL 构造的一般形式为:

  • [name:] FORALL (循环表达式1, [循环表达式2]…,[条件判别式])

  • FORALL 语句块

  • END FORALL [name]


5938258

关于FORALL的说明如下:

(1)循环表达式,相当于 DO 循环中的表达式1、表达式2和表达式3,循环表达式的数量和数组维数相对应;

(2)条件判别式,逻辑表达式,若省略该项(缺省),则条件为真,条件判断式可使用循环表达式中的循环变量;

(3)FORALL 语句块,要被赋值的变量须是数组元素或数组段,且须引用出现在循环表达式中的所有循环变量(或数组下标),赋值表达式不能是字符表达式;

(4)Name规定FORALL 构造的名字;

(5)FORALL 可以嵌套,可以在 FORALL 构造中使用 WHERE,但 WHERE构造中不能使用 FORALL ,FORALL 的嵌套及 FORALL中使用 WHERE的例子详见课本68页的程序代码段。


5938258

7. 矢量下标

数组段中的元素次序未必是线性的,例如:

  • INTEGER,DIMENSION(5) :: V=(/1,4,8,12,10/)

  • INTEGER,DIMENSION(3) :: W=(/1,2,2/)

  • A(V) = 3.5

    A(V) 标识一个非规则数组段:A(1) 、A(4) 、A(8) 、A(12) 和A(10),将 3.5 赋给上列5个元素。

  • C(1:3,1) = A(W)

    将数组段C(1:3,1) 设为A(1) 、A(2) 、A(2),即将A(1) 、A(2) 、A(2) 的值赋给数组段C(1:3,1) 。

    对矢量下标的说明:

    (1)矢量下标可用在赋值操作符(=)的任何一边,为保持并行计算环境下数组操作的完整性,赋值操作符左边的数组下标必须是唯一的,那么对A(W)赋值是非法的,因为A(W)放在“=”左边,A(2)被赋值2次。

    (2)矢量下标的效率非常的低,不应轻易使用。


5938258

8. 数组标准函数

Fortran 90 提供了许多针对数组操作的标准函数,假设有下列数组声明:

REAL,DIMENSION(-10:10,23,14:28) ::A

说明如下:

(1) LBOUND(SOURCE[,DIM]) —返回指定维的数组下界,如:

  • LBOUND(A) = (/-10,1,14/) (数组)

  • LBOUND(A,1) = -10 (标量)

    (2) UBOUND(SOURCE[,DIM]) —返回指定维的数组上界,如:

  • LBOUND(A) = (/10,23,28/) (数组)

  • LBOUND(A,1) = 10 (标量)

    (3) SHAPE(SOURCE) —返回数组形状,如:

  • SHAPE(A) = (/21,23,15/) (数组)

  • SHAPE((/4/)) = (/1/) (数组)

    (4) SIZE(SOURCE[,DIM]) —返回数组(或指定维)的元素个数,如:

  • SIZE(A,1) = 21

  • SIZE(A) = 7245


5938258

(5) RESHAPE(SOURCE,SHAPE) —改变数组形状,如:

  • B = RESHAPE((/1,2,3,4/),(/2,2/)) ! INTEGER :: B(2,2)

    将一维数组A(4)改成二维数组B(2,2), 存放顺序为B(1,1),B(2,1),B(1,2),B(2,2)

    (6) ALL(X) —相当于逻辑“与”操作,当逻辑数组 X 中的所有元素为真时,该函数返回真;否则,返回假。

    (7) ANY(X) —相当于逻辑“或”操作,当逻辑数组 X 中的任何元素为真时,该函数返回真;否则,返回假。

    (8) SUM(X) —返回数值型数组所有元素的和,如下列代码段所示:

  • INTEGER,DIMENSION(5,5)::A

  • REAL X(3),Y(3)

  • IF(ANY(A>0)) A=1

  • IF(ANY(A == 0)) A=-1

  • Dot = SUM(X*Y)


5938258

第四节 数组参数

作为例程参数使用的数组有固定形状、假定大小和假定形状数组3种形式,不管是哪一种形式的数组参数,其传递均采取引用方式传递。

1. 固定形状数组

固定形状数组,其维具有明确的上、下界,其形状规定采取如下形式:

  • ([dl:] du[,[dl:] du]…)

    其中:dl 和 du 分别代表下、上界,若下界省略,其缺省值为1,维的上、下界取整数。

    说明:

    假设至少有一维的界由非常量表达式表示,这样的数组称为大小可调数组,其实际大小待例程调用时方能确定。非常量表达式中的变量,要么是虚参,要么是公用区中的变量。

    实例:例5-6。


5938258

例5-6 固定形状数组,数组可调大小

  • PROGRAM MAIN

  • IMPLICIT NONE

  • REAL,DIMENSION(3,2)::A1=(/1.0,2.0,3.0,4.0,5.0,6.0/)

  • PRINT*,THE_SUM(A1,3,2)

  • CONTAINS

  • FUNCTION THE_SUM(A,M,N)

  • INTEGER M,N,I,J

  • REAL A(M,N),THE_SUM,SUMX ! A为可调大小数组

  • SUMX=0.0

  • DO J=1,N

  • DO I=1,M

  • SUMX=SUMX+A(I,J)

  • END DO

  • END DO

  • THE_SUM=SUMX

  • END FUNCTION

  • END PROGRAM

    *** 函数THE_SUM 中的虚参数组A为可调大小数组,运行时,可调大小数组A的大小由与虚参M和N对应的实参决定。


5938258

2. 假定形状数组

假定形状数组,不明确规定维的上界,其形状规定形式为:

  • ([dl]:[,[dl]:]…)

    下界 dl 若省略,缺省值为1。

    例5-7 假定形状数组参数的使用

  • PROGRAM Main

  • IMPLICIT NONE

  • REAL,DIMENSION(3:5,2:3)::A1=(/1.0,2.0,3.0,4.0,5.0,6.0/)

  • PRINT*,THE_SUM(A1)

  • CONTAINS

  • FUNCTION THE_SUM(A)

  • REAL A(-1:,:),THE_SUM,SUMX !A为假定形状数组

  • INTEGER I,J

  • SUMX=0.0

  • DO J=1,UBOUND(A,2)

  • DO I= -1,UBOUND(A,1)

  • SUMX=SUMX+A(I,J)

  • END DO

  • END DO

  • THE_SUM=SUMX

  • END FUNCTION

  • END PROGRAM


5938258

假定形状数组虚参采取和实参数组的形状相同,或者说,实参

数组将形状传递给虚参数组,然后两者按列主方式逐个元素进

行对应,在例 5-7 中,实参数组和虚参数组的对应关系为:

  • A1:A1(3,2), A1(4,2), A1(5,2), A1(3,3), A1(4,3), A1(5,3)

  • A: A(-1,1), A(0,1), A(1,1), A(-1,2), A(0,2), A(1,2)

    程序中采用 UBOUND 函数,直接获取对应后的虚参数组上界。

    若外部例程采用假定形状数组参数,则须在调用程序中建立其接口块,例如:

  • INTERFACE

  • FUNCTION THE_SUM(A)

  • REAL A(-1:,:)

  • END FUNCTION

  • END INTERFACE


5938258

3. 假定大小数组

假定大小:是指虚参数组和实参数组的大小相同。假定大小数组的形状规定为:

  • ([expli-shape-spec,]…[dl:]*)

    其中:expli-shape-spec 代表固定形状规定,dl 指最后一维的下界,缺省值为1,*指最后一维的上界。具体见实例5-8:假定大小虚参数组的使用。

  • PROGRAM Main

  • IMPLICIT NONE

  • REAL,DIMENSION(3,2) ::A1=(/1.0,2.0,3.0,4.0,5.0,6.0/)

  • INTEGER ::ROW=3,COL=2

    !使用代表行、列数的参数,来对数组中的各元素进行循环

  • PRINT*,THE_SUM(A1,ROW,COL)

  • CONTAINS

  • FUNCTION THE_SUM(A,M,N)

  • INTEGER I,J,M,N

  • REAL A(M,*),THE_SUM,SUMX !A为假定大小数组

  • SUMX=0.0

  • DO J=1,N

  • DO I=1,M

  • SUMX=SUMX+A(I,J)

  • END DO

  • END DO

  • THE_SUM=SUMX

  • END FUNCTION

  • END PROGRAM


5938258

第五节 动态数组

动态数组:有时数组的实际大小事先无法确定,为适应可能的情况,通常声明一个超大的数组,这无疑会浪费内存空间。因此定义动态数组,程序执行时,决定数组的实际大小和为数组动态分配内存空间,当不需要时,将动态分配给数组的内存释放掉,从而高效地利用资源。 Fortran 90 支持动态数组,Fortran 77不支持动态数组。

动态数组的使用一般要经历3个步骤:

(1) 声明动态数组,规定数组的维数,但不给出维的大小和上、下界。

如:REAL,DIMENSION(:),ALLOCATABLE ::X。

(2) 给动态数组分配内存。如:ALLOCATE( X(N) )。

(3) 将分配的内存释放掉。如:DEALLOCATE( X )。

实例:动态数组的使用,例5-9,5-10


5938258

例5-9 动态数组的使用之一,根据输入的学生人数,动态设置数组的大小。

  • PROGRAM Main

  • IMPLICIT NONE

  • INTEGER Students ! 学生人数

  • REAL,ALLOCATABLE::Mark(:) ! 声明动态数组,学生成绩

  • INTEGER I

  • WRITE(*,’(A)’,ADVANCE=‘NO’) ‘How many students:’

  • READ*,Students

  • ALLOCATE(Mark(Students)) ! 动态分配内存

  • DO I=1,Students

  • WRITE(*,”(‘No.’,I,‘’‘s mark:’)”,ADVANCE=‘NO’)I

  • READ*,Mark(I)

  • END DO

  • PRINT*,Mark

  • DEALLOCATE(Mark) ! 释放内存

  • END PROGRAM

    *** 动态数组大小的设置可以使用变量,一般数组大小要使用常量。


5938258

例 5-10 动态数组的使用之二

  • PROGRAM Main

  • IMPLICIT NONE

  • CHARACTER(20),DIMENSION(:,:),ALLOCATABLE::X,OldX

  • CHARACTER(20),DIMENSION(3)::A

  • INTEGER IOI,J,N

  • OPEN (1,FILE=‘DATA.TXT’)

  • CALL Proc_1

  • CALL Proc_2

  • CLOSE(1)

  • CONTAINS

  • SUBROUTINE Proc_1

  • !先确定文件记录数 N,再重读文件中的数据

  • N=0

  • DO

  • READ(1,*,IOSTAT = IO) !将变量列表置空

  • IF(IO<0)EXIT

  • N=N+1

  • END DO

  • ALLOCATE(X(N,3)) !动态分配内存

  • REWIND(1) !定位文件指针到文件头

  • READ(1,*)((X(I,J),J=1,3),I=1,N)

  • PRINT*,N

  • PRINT*,((X(I,J),J=1,3),I=1,N)

  • DEALLOCATE(X) !释放内存

  • END SUBROUTINE

    !例程 Proc_1 是先确定文件行数(或记录数),再为动态数组分配适当大小的存储单元。


5938258

  • SOBROUTINE Proc_2

  • !在读文件的过程中,动态分配内存和释放内存

  • ALLOCATE(X(0,3)) !可分配 0 大小的内存

  • N=0

  • REWIND(1)

  • DO

  • READ(1,*,IOSTAT = IO)(A(I),I=1,3)

  • IF(IO<0)EXIT

  • N=N+1

  • ALLOCATE(OldX(N-1,3))

  • OldX=X !数组整体赋值

  • DEALLOCATE(X)

  • ALLOCATE(X(N,3))

  • X(:N-1,:) = OldX

  • X(N,:) = A(:)

  • DEALLOCATE(OldX)

  • END DO

  • PRINT*,N

  • PRINT*,((X(I,J),J=1,3),I=1,N))

  • DEALLOCATE(X) !释放内存

  • END SUBROUTINE

  • END PROGRAM

    例程 Proc_2 是在确定文件行数的过程中,边分配边释放,直至最后一行。


5938258

注意事项:

(1)Fortran 90 的动态数组与其他语言(如 Visual Basic)不同,要增加动态数组的大小,必须将原来的动态数组释放掉,再重新指定动态数组的大小。

(2)计算机的内存是有限的,用户不可能无休止地请求分配内存,所以 ALLOCATE 分配内存并不总是成功的。

(3)为检查内存配置是否成功,Fortran 90提供了可选状态参数 STAT,例如:

  • ALLOCATE(X(SIZE),STAT=ERROR)

    ERROR 为事先声明好的整形变量,如果 ERROR 等于0,则表示内存配置成功,否则内存配置失败。

    (4)与动态分配内存有关的函数还有 ALLOCATED,用来检查一个动态数组是否已配置内存,其返回值为逻辑真或者假。例如:

  • IF(.NOT. ALLOCATED(X)) ALLOCATE(X(0,3))

    (5)动态数组不能作为例程虚参来使用。


5938258

第六节 数组型函数

Fortran 90 中函数可以返回一个值(标量),也可以返回多个值(矢量) —数组,例 5-11 所示。

例 5-11 函数的返回值为二维字符数组。

  • MODULE Mod

  • IMPLICIT NONE

  • CONTAINS

  • FUNCTION FileRow(FileName) !返回文件中的数据行数

  • CHARACTER(10),INTENT(IN)::FileName

  • INTEGER FileRow

  • INTEGER N,IO

  • OPEN(1,FILE=FileName)

  • N=0

  • DO

  • READ(1,*,IOSTAT=IO) !将变量列表置空

  • IF(IO<0)EXIT

  • N=N+1

  • END DO

  • FileRow=N

  • CLOSE(1)

  • END FUCTION


5938258

  • FUCTION FileData(FileName,N) !返回二维字符数组

  • CHARACTER(10),INTENT(IN)::FileName

  • INTEGER,INTENT(IN)::N !文件中的行数

  • CHARACTER(10),DIMENSION(N,3)::FileData,X !二维字符数组

  • INTEGER I,J

  • OPEN(1,FILE=FileName)

  • READ(1,*)((X(I,J),J=1,3),I=1,N) !数组隐式循环

  • FileData=X !数组整体赋值

  • CLOSE(1)

  • END FUNCTION

  • END MODULE

  • PROGRAM Main

  • USE Mod

  • IMPLICIT NONE

  • CHARACTER(10),DIMENSION(:,:),ALLOCATABLE::X !声明动态数组X

  • INTEGER N,I,J

  • N=FileRow(‘Data.txt’) !数据行数,依据函数 FileRow 返回的行数动态分配大小

  • ALLOCATE(X(N,3))

  • X=FileData(‘Data.txt’,N) !二维字符数组,函数 FileData 返回的数组直接赋给动态数组 X

  • PRINT*,N

  • WRITE(*,’(3A)’) ((X(I,J),J=1,3),I=1,N)

  • DEALLOCATE(X) ! 动态数组X释放

  • END PROGRAM


5938258

小 结

(1) Fortran 90 的数组声明形式为 :

TYPE,DIMENSION([dl:]du[,[dl:]du]…)::Arr 或 TYPE [::] Arr([dl:]du[,[dl:]du]…)

(2) Fortran 90 中,一些场合下数组按列主方式存储,在另一些场合下并不规定数组按何种方式存储。

(3) * 数组赋初值一般使用 DATA 语句,其中还可以使用隐式循环;

* Fortran 90 允许对数组元素、数组段及数组整体进行操作;

* Fortran 90 的 WHERE构造相当于 DO 循环内嵌 IF 块,WHERE 语句形式上类似于 IF 语句;

* Fortran 95 的 FORALL 构造相当于隐式循环结合隐式 IF 语句,是对数组元素进行操作,FORALL 构造允许内嵌;

* 一维矢量可以作为数组下标,用来规定一个数组段,该数组段中的元素依次可以是非线性的;

* Fortran 90 提供了许多有关数组操作的标准函数。

(4) Fortran 90 有三种形式的数组参数:固定形状数组、假定形状数组和假定大小数组。

固定形状数组包括可调大小数组;假定形状数组和实参数组的形状保持一致,若外部例程含有假定形状数组参数,须在调用程序中建立接口块;假定大小数组和实参数组的元素个数保持相同。


5938258

(5) 动态数组的使用要经历声明、分配和释放三个步骤。

声明时,动态数组须是延迟形状数组,具有 ALLOCATABLE 属性;分配和释放分别使用 ALLOCATE 和 DEALLOCATE 语句;若要增加动态数组的大小,须将原来的动态数组释放掉,再重新指定大小。

(6) Fortran 90 的函数返回值,既可以是标量,也可以是矢量(数组)。


  • Login