Download presentation
Presentation is loading. Please wait.
Published byHartanti Hadiman Modified 6年之前
1
第五章 数 组 Fortran 90数组的特点: *** 可以逐个元素对数组进行操作,也可以对数组整体、数组段直接进行操作;
第五章 数 组 Fortran 90数组的特点: *** 可以逐个元素对数组进行操作,也可以对数组整体、数组段直接进行操作; *** Fortran 90提供了针对数组操作的构造块和函数; *** Fortran 90提供了动态数组,以有效利用内存; *** Fortran 90 数组具有隐式循环和数组赋值的功能。
2
第一节 数组声明 数组声明实例 REAL,DIMENSION(15) ::X !下界缺省值为1
第一节 数组声明 数组声明实例 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 形状相同。
3
数组声明的一般形式: 下列都是合法的数组声明: TYPE,DIMENSION( [dl:],du[[dl:] du]…) ::Arr
TYPE [::] Arr( [dl:], du[[dl:] du]…) TYPE代表数据类型,dl 和du 分别为维的下界和上界,Arr 为数组变量。 下列都是合法的数组声明: REAL,DIMENSION(100) ::R REAL,DIMENSION(1:10,1:10) ::S REAL ::T(10,10) REAL,DIMENSION(-10: -1) ::X INTEGER,PARAMETER ::1da=5 REAL,DIMENSION(0:1da-1) ::Y REAL,DIMENSION(1+1da*1da,10) ::Z 表明: (1)上、下界可以任意规定; (2)缺省下界为1; (3)可省略 DIMENSION 属性,如 T ; (4)数组大小可以为0; (5) Fortran 77数组声明分2步:先数组类型,再数组维数及大小。
4
例 5-1 一维数组的使用,从保存有学生学号、姓名和成绩三列数据的文件中读取全部数据,并在屏幕上显示
PROGRAM Main IMPLICIT NONE INTEGER,PARAMETER :: MAX = ! 最大行数 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
5
例5-2 二维数组的使用,从保存有学生学号、姓名和成绩三列数据的文件中读取全部数据,并在屏幕上显示
例5-2 二维数组的使用,从保存有学生学号、姓名和成绩三列数据的文件中读取全部数据,并在屏幕上显示 PROGRAM Main IMPLICIT NONE INTEGER,PARAMETER :: MAX = !最大行数 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
6
第二节 数组存储 1. 自由存储 不规定数组在内存中如何存储,便于编写可移植的程序,编译器可以自由地实现存储优化。例如:在分布式计算环境中,一个大的数组可以被存储到100 个处理器中,每个存储数组中的部分元素。在 High Performance Fortran 中,自由存储被广泛应用。 2. 列主存储 先存储第一列,然后是第二列、第三列,直到最后一列,称为列主存储。例如:向另一个语言编写的例程传递数组、数组构造、数组输入/输出、系统提供的一些数组函数(TRANSFER,RESHAPE,PACK,UNPACK和MERGE)时,需要明确给出数组的存储方式 — 列主存储。
7
第三节 数组操作 1. 数组赋初值 (1) 使用 DATA 的一般形式为: (2) 使用乘号(*) (3) 使用隐式循环
第三节 数组操作 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
8
(4) 省略 DATA 隐式循环也可以嵌套使用,例如: Fortran 90可以省略 DATA 关键字,直接给数组设置初值。例如:
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)
9
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 为同类型的数值型数组。
10
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,其他值不变。
11
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个元素,注意必须保持元素个数的一致。
12
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 = Whole Array = Array Transosed =
13
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
14
SUBROUTINE Proc_Where ! Where构造
WHERE(income< ) tax = income*0.1 ELSEWHERE(income< ) tax = income*0.12 ELSEWHERE tax = income*0.15 END WHERE END SUBROUTINE SUBROUTINE Proc_IF ! IF构造 DO I = 1,10 IF(income(I)< )THEN tax(I)=income(I)*0.1 ELSE IF(income(I)< )THEN tax(I)=income(I)*0.12 ELSE tax(I)=income(I)*0.15 END IF END DO END PROGRAM
15
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) 执行语句
16
WHERE 构造也可以被命名,例如: name:WHERE(income>50000) income = 50000 END WHERE name WHERE 构造也可以嵌套使用,例如: WHERE(income< ) WHERE(income< ) tax = income*0.1 ELSEWHERE tax = income*0.12 END WHERE tax = income*0.15
17
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 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 PROGRAM
18
例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 CONTAINS SUBROUTINE Proc_1 FORALL(I=1:N,J=1:N,I<J)A(I,J)= !上三角 FORALL(I=1:N,J=1:N,I==J)A(I,J)= !对角线 FORALL(I=1:N,J=1:N,I>J)A(I,J)= !下三角 END SUBROUTINE !内部例程Proc_1采用FORALL来实现
19
FORALL 语句的一般形式为: FORALL 构造的一般形式为: SUBROUTINE Proc_2 DO I = 1,N
DO J =1,N IF(I<J) A(I,J)= !上三角 IF(I==J) A(I,J)= !对角线 IF(I>J) A(I,J)= !下三角 END DO END SUBROUTINE END PROGRAM !内部例程Proc_2采用DO循环结合IF语句来实现 FORALL 语句的一般形式为: FORALL(循环表达式1,[循环表达式2]…,[条件判别式]) 执行语句 FORALL 构造的一般形式为: [name:] FORALL (循环表达式1, [循环表达式2]…,[条件判别式]) FORALL 语句块 END FORALL [name]
20
关于FORALL的说明如下: (1)循环表达式,相当于 DO 循环中的表达式1、表达式2和表达式3,循环表达式的数量和数组维数相对应;
(2)条件判别式,逻辑表达式,若省略该项(缺省),则条件为真,条件判断式可使用循环表达式中的循环变量; (3)FORALL 语句块,要被赋值的变量须是数组元素或数组段,且须引用出现在循环表达式中的所有循环变量(或数组下标),赋值表达式不能是字符表达式; (4)Name规定FORALL 构造的名字; (5)FORALL 可以嵌套,可以在 FORALL 构造中使用 WHERE,但 WHERE构造中不能使用 FORALL ,FORALL 的嵌套及 FORALL中使用 WHERE的例子详见课本68页的程序代码段。
21
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)矢量下标的效率非常的低,不应轻易使用。
22
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
23
(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)
24
第四节 数组参数 1. 固定形状数组 ([dl:] du[,[dl:] du]…)
第四节 数组参数 作为例程参数使用的数组有固定形状、假定大小和假定形状数组3种形式,不管是哪一种形式的数组参数,其传递均采取引用方式传递。 1. 固定形状数组 固定形状数组,其维具有明确的上、下界,其形状规定采取如下形式: ([dl:] du[,[dl:] du]…) 其中:dl 和 du 分别代表下、上界,若下界省略,其缺省值为1,维的上、下界取整数。 说明: 假设至少有一维的界由非常量表达式表示,这样的数组称为大小可调数组,其实际大小待例程调用时方能确定。非常量表达式中的变量,要么是虚参,要么是公用区中的变量。 实例:例5-6。
25
例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 THE_SUM=SUMX END FUNCTION END PROGRAM *** 函数THE_SUM 中的虚参数组A为可调大小数组,运行时,可调大小数组A的大小由与虚参M和N对应的实参决定。
26
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 THE_SUM=SUMX END FUNCTION END PROGRAM
27
假定形状数组虚参采取和实参数组的形状相同,或者说,实参 数组将形状传递给虚参数组,然后两者按列主方式逐个元素进
行对应,在例 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
28
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 THE_SUM=SUMX END FUNCTION END PROGRAM
29
第五节 动态数组 动态数组:有时数组的实际大小事先无法确定,为适应可能的情况,通常声明一个超大的数组,这无疑会浪费内存空间。因此定义动态数组,程序执行时,决定数组的实际大小和为数组动态分配内存空间,当不需要时,将动态分配给数组的内存释放掉,从而高效地利用资源。 Fortran 90 支持动态数组,Fortran 77不支持动态数组。 动态数组的使用一般要经历3个步骤: (1) 声明动态数组,规定数组的维数,但不给出维的大小和上、下界。 如:REAL,DIMENSION(:),ALLOCATABLE ::X。 (2) 给动态数组分配内存。如:ALLOCATE( X(N) )。 (3) 将分配的内存释放掉。如:DEALLOCATE( X )。 实例:动态数组的使用,例5-9,5-10
30
例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 *** 动态数组大小的设置可以使用变量,一般数组大小要使用常量。
31
例 5-10 动态数组的使用之二 !例程 Proc_1 是先确定文件行数(或记录数),再为动态数组分配适当大小的存储单元。
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 是先确定文件行数(或记录数),再为动态数组分配适当大小的存储单元。
32
例程 Proc_2 是在确定文件行数的过程中,边分配边释放,直至最后一行。
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 是在确定文件行数的过程中,边分配边释放,直至最后一行。
33
注意事项: (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)动态数组不能作为例程虚参来使用。
34
第六节 数组型函数 Fortran 90 中函数可以返回一个值(标量),也可以返回多个值(矢量) — 数组,例 5-11 所示。
第六节 数组型函数 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
35
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
36
小 结 (1) Fortran 90 的数组声明形式为 :
小 结 (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 有三种形式的数组参数:固定形状数组、假定形状数组和假定大小数组。 固定形状数组包括可调大小数组;假定形状数组和实参数组的形状保持一致,若外部例程含有假定形状数组参数,须在调用程序中建立接口块;假定大小数组和实参数组的元素个数保持相同。
37
(5) 动态数组的使用要经历声明、分配和释放三个步骤。
声明时,动态数组须是延迟形状数组,具有 ALLOCATABLE 属性;分配和释放分别使用 ALLOCATE 和 DEALLOCATE 语句;若要增加动态数组的大小,须将原来的动态数组释放掉,再重新指定大小。 (6) Fortran 90 的函数返回值,既可以是标量,也可以是矢量(数组)。
Similar presentations