FORTRAN结构化程序设计
第一章 FORTRAN语言程序设计初步
1.1 Fortran语言发展概况
- Formula Translation
- 适用于工程及科学计算的一种高级程序语言
- 1951年由约翰·贝克斯等人开始研究Fortran语言
- 1957年第一个Fortran程序在IBM704机上运行
- 1958和1962年先后推出Fortran ll和FortranIV
- 1966和1978年先后颁布Fortran66和Fortran77
- 1991年颁布了Fortran90, 1997年颁布Fortran95, 2004年颁布Fortran2003
1.2 简单的FORTRAN程序分析
Fortran程序的基本结构
(1) 一个Fortran源程序由一个或多个程序单位组成,每个独立的程序单位以“end”语句结束。
(2) 每个程序单位包括若干行(不能一行写多条语句,但可以几行写一条语句);
语句行(执行语句行和非执行语句行)和 非语句行(注释行)
(3) 程序必须按规定格式书写
1.3 FORTRAN源程序书写格式
Fortran77源程序必须按以下格式书写:
(1)Fortran 不区分大小写;每行只能在80列内书写,并把80列分为四个区
(2)1 ~ 5列:标号区(1 ~ 5位整数;第一列为 “ * ” 或 “ c " 时,为注释行)
(3)第 6 列:续行标志区(非空格或非”零“;最多19个续行)
(4)7 ~ 72列:语句区(书写语句;一行只能写一条语句)
(5)73 ~ 80列:语句注释区(一般做编号注释)
1.4 Fortran程序的编辑与运行
一、创建源程序文件并编写源程序
二、编译并连接源文件
三、运行程序编译生成的可执行文件
1.5 常量
常量:在程序执行期间其值固定不变的量
Fortran处理六种类型的常量:
(1)整型常量(Integer)(4位)
(2)实型常量(Real)(4位)
(3)双精度常量(Double precision)(8位):±a.bDd,D是双精度标志,不能省,指数d必须有
(4)复型常量(Complex)(8位)
(5)逻辑型常量(Logical)(4位)
(6)字符型常量(Character)(1位)
1.5.1 整型常量
整数(Integer):包括正、负整数和零。
说明:在(32位)微机中,整数的取值范围为:-231~231-1 (-2147483648 ~ 2147483648)
1.5.2 实型常量
-
实数(Real)
-
两种表示形式:
1、小数形式;
2、指数形式(通常表示较大的或较小的数)
说明:
(1)一个数值用指数形式表示时有两种表达方式:
① 一个基本实数后面跟指数部分。如:0.876
→8.76E-1
② 一个整数后面跟指数部分。如:0.876
→876E-3
(2)同一个数值可用不同的指数形式表示。如:0.876
→8.76E-1
→87.6E-2
→876E-3
(3)在微机中,一般用四个字节存放一个实数,其取值范围:10-38 ~ 1038 ,超出此范围时”溢出“。
(4)下列形式为不合法的指数形式:
① 单独的小数点和单独的指数部分。如:.E5
, E10
② 指数部分只能是整数,不能带小数点。如:8E0.5
, 12.3E1.5
1.6 变量
1.6.1 变量的概念
**变量:**在程序执行期间其值可以改变的量。Fortran为每一个变量分配一个相应的存储单元;每个变量在每个时刻只能有一个确定的值。
注:在程序中用到的变量都必须要有确定的值
1.6.2 变量名
**变量名:**标识一个变量所用的名字。
**命名规则: ** 1)变量名的第一个字符必须是字母;
2)在第一个字符后可跟1~5个字母或数字。
注意几点:
(1)变量名不区分大小写字母。如: TOTAL
, Total
, total
代表同一变量
(2)变量名中的空格不起作用。如: abc
, ab c
, a bc
, a b c
代表同一变量
(3)允许变量名与语言中具有特定含义的字(“保留字”)同名。但建议不要使用。如: sin
、read
……
(4)尽量“见名知义”,如:root
、aver
、result
等
1.6.3 变量类型
不同类型的变量用来存放不同类型的常量数据。变量具有六种类型。变量在使用前,应首先对其进行类型说明。变量类型的三种说明方法:
1)**类型说明语句:**类型 变量名列表
各个变量名之间用逗号隔开,如:
REAL A,B,C
DOUBLE PRECISION X,Y,Z !(也可以写成 REAL*8 X,Y,Z)
CHARACTER*5 STR1,STR2*8,STR3*19
2)IMPLICIT 语句: IMPLICIT 类型(字母表)[,类型(字母表)……]
如:
IMPLICIT REAL(A-D),INTEGER(I-M),DOUBLE PRECISION(X,Z)
表示所有以A到D开头的变量为实型,I-M开头的为整型,X和Z开头的为双精度型。
3)**I ~ N规则:**Fortran规定,如果不加专门说明时,以I ~ N开头的变量为整型,其他都为实型。
几点说明:
(1)三种类型说明的优先级:类型说明语句>IMPLICIT
语句>I~ N规则
(2)类型说明语句位于所有可执行语句的前面,IMPLICIT
语句位于最前面
(3)IMPLICIT NONE
取消IMPLICIT
说明和I ~ N规则,此时所有变量均需显式说明
(4)只在本程序单位内有效
1.7 Fortran内部函数
在编制Fortran程序时,经常要用到一些基本的数学函数,如三角函数、指数函数、对数函数等。为方便用户, Fortan编译系统已提供了这些函数的计算程序,需要时即可调用。
**Fortran内部函数调用格式:**函数名(自变量)
如:sin(90*3.14159/180)
注意几点:
(1)函数自变量(参数)必须用括号括起来(一个或多个)。 如: sinx+cosx
→sin(x)+cos(x)
(2)函数自变量可以是常量、变量或表达式。如: exp(3.0)
,sin (x+cos(x))
(3)函数的类型是由函数值的类型确定的,但有些函数的类型是由自变量的类型确定的。如:mod(8.0,3.0)
→2.0
;mod(8,3)
→2
(4)三角函数的角度单位是”弧度“而不是”度“
1.8 Fortran算数表达式
**表达式:**是用一些特定的运算符将Fotran基本成分;连接起来的具有确定意义的式子。
**基本成分包括:**常量,变量,函数,字符串,数组等
**Fortran规定有四种表达式:**算术表达式、逻辑表达式、字符表达式、关系表达式
1.8.1 算术运算符和运算优先级
1)5种算术运算符:+
,-
,*
,/
,**
(乘方)
2)优先级:()
→**
→*
,/
→+
,-
**注意:**1.书写问题
①”/“号,如:(A+B)/(C+D)
②”*“不能省略,如:2AB
→2*A*B
③括号部分大小,均用()表示,成对出现。如:((((A+1)+1)+1)+1)
④多次乘方按”先右后左“的原则处理。如:4**3**2
→(4**(3**2))
⑤单边运算符:”-“负号
注:运算符不能连续出现,要用小括号隔开。如:A*(-B)-T/(-Q)
2.运算顺序:()
→函数
→**
→*
,/
→+
,-
1.8.2 表达式运算中的类型问题
两种情况:
-
溢出:超出有效数值范围
解决:很大或很小的数用实型的指数形式表示
-
误差:由于有效数字的位数限制,实型数运算存在误差
解决1:转换为双精度型
解决2:避免因书写不当造成有效数字的丢失,如:0.001+1234567.0-1234566.0
1.9 赋值语句
作用:将一个确定的值赋给一个变量
一般格式:变量=表达式
例:
X=3.2, Y=SQRT(X+5.0)/2.0
说明:
- “=”为赋值号
- 左端只能是变量名,如:
x+y=5
是不合法的 - 类型转换问题
- 类型相同,直接赋值(I=3)
- 类型不同,计算表达式的值,将结果类型转换为左端变量的类型
- 为避免出现类型转换过程中的错误,应保证两侧类型一致。
1.10 简单输出语句
- 输出语句的作用:将内存的数据传送到显示器、打印机或保存到磁盘指定区域。
- 输入/输出三要素:对象: 哪些数据 ; 格式 ; 设备。
- 输出语句的分类:格式输出(第五章);表控格式输出(系统标准格式);无格式输出(二进制)
1.10.2 表控输出语句
按计算机系统规定的格式输出;系统自动为每种类型的数据规定了列数。
一、表控输出格式
-
整数的表控格式输出(与具体的计算机系统有关)
规定:每个整数占13列,打印在右端,左补空格
-
实数的表控格式输出
规定:每个实数占17列,打印在右端,左补空格,小数部分占7列。
-
当实数值的绝对值≥107或<1是时,按标准的指数形式输出。
-
共占15列,指数4列,小数6列
例:
print *, -10000000. ,0.98
输出结果:
︺︺-1.000000E+07︺︺︺9.800000E-01
-
二、表控格式输出语句
一般格式:
print *, <输出表列>
write( * , * ) <输出表列>
例1:
print * , 56.8, 125
!或
print * , 'z=' , z
1.11 简单输入语句
- 输入语句的作用:将外部介质(键盘、磁盘)上的数据传送到内存变量指定的单元中。
- 输入/输出三要素:对象(哪些数据)、格式、设备
- 输入语句的分类:格式输入(第五章)、表控格式输入(系统标准格式)、无格式输入
1.11.2 表控输入语句
-
自由格式输入
-
语句:
read *,<输入表列> read (*,*) <输入表列>
注意:
-
执行时,程序会停止,等待用户从键盘上输入数据。
-
输入时,数据间以“,”或空格间隔。
-
变量名称为输入表。
-
输入的数据应和输入表的变量个数、类型、次序严格地一一对应。
例1:
read(*,*) a,b,i,j
输入: 108.6, -37.8, 5 (回车) --少一个数,则 j 没有被赋值,程序停止等待
输入: 108.6, -37.8, 5, 6, 9 (回车) --多一个数,则输入的9不起作用,程序正常执行
例2:
read(*,*) a, b, i, j, c, k, l, p
输入: 25.8, -8.2 (回车)
5, 8, 2.7 (回车)
2, 6, 6.9 (回车)
— 数据太多,可以分几个记录输入
**记录:**以回车结束的一批输入/输出数据
例3:
read(*,*) A, B, C, D, E, F, G
输入: 7*3.5 ——相同的数据可以用重复系数输入
例4:
read(*,*) A, B, C read(*,*) D, I, J
输入: 2.3, -63.5 (回车)
6.4, 91.0 (回车)
5, 8 (回车)
结果: A=2.3, B=63.5, C=6.4, D=5.0, I=8, J 未被赋值
——每个
read
语句从一个新的记录开始读数 ——每个
write
语句也是从一个新的记录开始输出
1.12 PARAMETER语句
-
作用:将程序中经常用到的常数或字符串定义成一个符号常量,其值不可改变。
-
语句:
parameter(p1=c1[,p2=c2,...pn=cn])
其中: pn—符号常量; cn—常量
注意:
- 符号常量的命名规则与变量名相同,但在程序中它的值不能改变,也不能对它赋值。
- 符号变量也有类型,可用前面的三种类型说明方法说明类型。
- 参数语句是非执行语句,位于所有可执行语句的前面,但位于类型说明语句后面
- 一条语句可以定义多个符号常量。
- 优点:方便修改程序。
1.13 END, STOP, PAUSE语句
END
语句:结束标志;有且仅有一条PAUSE [n]
语句:暂停执行;用于调试程序, n可以是一个字符串或不超过5位的数。STOP [n]
语句:停止运行程序;用于调试程序, n可以是一个字符串或不超过5位的数。
总结
顺序结构程序主要用于进行确定的显式计算。
一般结构:由5部分组成
- 说明部分(类型说明语句,非执行语句)
- 赋初值部分(赋值语句,
read
语句) - 计算部分(数学公式一算术表达式)
- 输出部分(
write
,print
部分) - 结束部分(
END
语句)
第二章 逻辑运算和选择结构
2.1引言
-
分支结构:控制转向语句。
-
分类:
GOTO
类;无条件GOTO
语句;计算GOTO
语句。(尽量避免使用GOTO
语句)IF
类(条件类);逻辑IF
语句;块IF
语句;计算IF
语句
2.2关系表达式
- 条件: 关系表达式 和 逻辑表达式;
- 是构成选择结构判断条件的基本式子;
- 算术表达式——由算术运算符将常量,变量,函数等基本成分连接在一起的式子
- 关系表达式——由关系运算符将算术表达式连接起来的式子
一、关系运算符
.GT. | 大于 | .GE. | 大于等于(greater than or equal to) | ||
.LT. | 小于 | .LE. | 小于等于 | .EQ. | 等于 |
二、关系表达式的一般形式
<算术量> <关系运算符> <算术量>
例: x+y>15.4
→x+y.gt.15.4
-
注:
- 参与运算的元素:算术量或算术表达式
- 运算结果:逻辑值:真(.TRUE. )、假(.FALSE.)
- 运算顺序:算术运算>关系运算。如:
a+b.ne.a-b
等同于(a+b) .ne. (a-b)
-
缺点:只能表达简单的关系,如: 5≤x≤10无法用关系表达式实现,此时要用逻辑表达式。
2.3 逻辑表达式
一、逻辑运算符
.and. (与) | .or.(或 | .not.(非) | .eqv. (逻辑等) | .neqv. (逻辑不等) |
---|
二、逻辑表达式的一般形式
<逻辑量> <逻辑运算符> <逻辑量>
运算结果为逻辑值:真(.TRUE.
)、假(.FALSE
)
- 逻辑量包括:逻辑常量、逻辑变量和关系表达式
三、逻辑常量: 两个: ①.TRUE.
(真) ② .FALSE.
(假)
**四、逻辑变量: **用于存放逻辑常量的变量。
逻辑变量可以通过赋值语句来接受逻辑常量的值,但在使用前,要进行类型说明。
五、逻辑运算符的运算规则
设a, b为两个逻辑量,则:
a.and.b
(当a,b同时为真时,为真)
a.or.b
(当a、b中任意一个为真或同时为真时,为真)
.not.a
(当a为真,其值为假;当a为假,其值真)
a.eqv.b
(当a,b为同一逻辑常量时,为真)
a.neqv.b
(当a、b不为同一逻辑常量时,为真)
六、逻辑表达式的运算次序
运算次序为: 算术运算→关系运算→逻辑运算
逻辑运算: .not.
→.and.
→.or.
→.eqv.
→.neqv.
2.4 用块IF实现选择结构
- 有以下三种典型的块IF选择结构:
-
基本形式:
IF(条件) THEN (块IF语句) 块1 (THEN块) ELSE (ELSE语句) 块2 (ELSE块) ENDIF (ENDIF语句)
说明:
-
)
IF…THEN
语句: 块IF结构的入口语句 -
)
ENDIF
语句:出口语句 -
必须一一对应,配对使用
-
THEN
块、ELSE
块是一条或多条可执行语句 -
执行过程:
条件为真 (T)→
THEN
块→ENDIF
语句后的语句条件为假 (F)→
ELSE
块→ENDIF
语句后的语句 -
-
简单结构:
IF (条件) THEN (块IF语句) 块 (THEN块) ENDIF (ENDIF语句)
注:不包含
ELSE
块,可实现单边选择的功能 -
嵌套结构:
IF (条件1) THEN 块1 ELSE IF (条件2) THEN 块2 (ELSE IF 块) ………… ELSE IF (条件N) THEN 块N [ELSE 块(N+1)] ENDIF
说明:
- )每个块
IF
中可以完整地包含一个(或多个)块IF
结构,即构成块IF
的嵌套结构。 - )一个块
IF
语句必须和一个ENDIF
语句相对应。 - )块
IF
中的"THEN
块”、"ELSE
块”和"ELSE IF
块”可省
2.5逻辑IF语句
逻辑IF
语句也是一种选择结构,但与块IF
不同,主要表现在:
①只用一行表示一个选择结构;
②仅当条件成立时执行,并且只执行一条语句。
相对而言,称为行IF
语句。逻辑IF
语句的一般形式:
IF <条件>语句
-
实现单边选择。例:
IF (N.LE.100) N=N+1
-
块
IF
语句中,当ELSE
块是空块,THEN
块只有一条语句时,用逻辑IF
语句更方便。
2.6算术IF语句
一般形式:
IF <算术表达式> N1, N2, N3
当算术表达式的值小于0时执行标号为N1的语句,等于0时执行标号为N2的语句,大于0时执行标号为N3的语句。
第三章循环结构的实现
所谓循环,是指在程序执行过程中需要重复执行的程序段。
**循环结构包括: **
(1)循环体:由一些可执行语句组成;
(2)循环控制语句:控制循环的开始和结束。
- 根据循环控制语句,将循环结构分两类:条件型循环和计数型循环(DO循环)
3.1用GOTO语句实现循环
GOTO
语句的一般形式:
GoTo <s1>
其中: s1为语句标号
功能:程序执行到此语句时,无条件的转向标号为s1的语句。
3.2用DO语句实现循环
当循环的初值、终值和循环次数都已知时,可用DO
语句实现循环。
用DO语句实现的循环称为"DO
循环”, DO
循环是由一个DO
语句和循环体组成。
一、一般形式
DO S1 I=E1, E2 [, E3]
…………
S1 <终端语句>
!或者——————————————————————
DO I=EI, E2 [, E3]
…………
END DO
例:
DO 10 I=1,19,2
SUM = SUM + I
10 CONTINUE
DO 10 I=1,19,2
10 SUM = SUM + I
DO 10 I=1,19,2
SUM = SUM + I
END DO
注意:
-
I
为循环变量,S1
为语句标号,是本程序单位中另一可执行语句的标号; -
步长可以省略,缺省值=1.如:
DO 10 N=1, 15, 1
→DO 10 N=1, 15
-
循环初值(
E1
),终值(E2
)和步长(E3
)都可以是常量,变量或表达式;例:
DO 30 K=3, 16, A+1
:DO 100 N=KI, K2, K3
-
由于实数在内存中存储的误差,
I
,E1
,E2
,E3
尽可能用整型量; -
E1
,E2
,E3
可正可负,E1
,E2
可为0,但E3
不能为0.
二、具体执行过程
①执行DO
语句,首先计算表达式E1
, E2
,E3
的值,若它们的类型与循环变量I
的类型不一致,则自动转换成循环变量的类型
②将E1
赋给循环变量I
,即执行赋值语句: I=E1
③计算循环次数: R=MAX0((E2-E1+E3)/E3, 0)
, MAX0
表示从多个整型变量中取最大的一个;
④检查循环次数:若R=0
则不执行循环体内的语句,跳出循环; R≠0
则执行循环体内语句;
⑤执行循环终端语句: I=I+E3
,即是循环变量获得一个新值,而循环次数R
自动减1;
⑥返回④继续执行,直到R=0
为止。
三、CONTINUE语句
循环终端语句必须是可执行语句。那么,这种作为循环终端语句的语句具有双重作用:一是作为循环终端的标志,二是要完成自身的功能。因此影响了程序的可读性.FORTRAN用一个专门的语句作为DO
循环的终端语句,即CONTINUE
语句。它自身没有任何功能。
四、一些规定:
- 循环变量在循环体内只能被引用,不能被赋值;
- 在执行
DO
循环体期间,E1
,E2
,E3
的值不能改变,因为它们决定了循环次数 - 离开
DO
循环后,循环变量可以在循环体外被引用,它的值为脱离循环时最后一次被赋的值; - 程序中用到转移语句,规定:只允许从循环体内→体外;不允许从体外→体内;
- 循环终端语句必须是除
GOTO
,块IF
,ENDIF
,END
和STOP
语句外的任何可执行语句。
五、DO
循环的嵌套
在一个DO
循环中还可以包含一套或多套完整的DO
循环,这就是DO
循环的嵌套。
一般形式: (以双重循环为例)
DO 10 I=1, 10
┆
DO 20 J=1, 10
┆
20 CONTINUE
┆
10 CONTINUE
注意:
-
嵌套要完整,不能交叉
-
循环变量的名字,规定:
并列的循环:循环变量可以同名
嵌套的循环:循环变量不能同名
-
若多层循环的结束语句在同一个地方,可以共用一条
CONTINUE
语句 -
控制转向语句的使用(体内→体外)
3.3当型循环的实现
在无法确定循环次数的情况下可以使用当型循环。当型循环是指执行循环体要依据事先给定的条件: 当条件成立时执行循环,否则就不执行循环。
一、用DO WHILE
语句实现当型循环
一般形式
Do S1[,] WHILE (条件)
…………
S1 <终端语句>
结构类似DO循环的结构。执行情况:条件为真→执行循环体;若条件为假→退出循环体。
二、用块IF
和GOTO
语句实现循环
一般形式:
S1 IF (条件) THEN
块
GOTO S1
ENDIF
3.4直到型循环的实现
所谓直到型循环,是指先执行循环体,再判断条件。如果条件为“假”,继续执行循环,直到条件为“真”时终止循环。
用逻辑IF语句实现直到型循环:
S1 循环体
IF (条件) GOTO S1
3.5几种循环形式的关系和比较
一、DO循环适用于已知循环次数的情况
二、几种循环可以互换
DO
循环:条件型循环(可用次数作条件)
当型循环:直到型循环
当型:块IF
语句(单边)+GOTO
语句(先判断后执行)
直到型:逻辑IF
语句+GOTO
语句(先执行后判断)
三、各种循环可以相互嵌套。
第四章FORTRAN的数据结构
4.1程序中的数据结构
-
程序代数表达式:
算法+数据结构=程序
-
对于同一个问题的求解,即一个程序的实现,可以采用不同的数据结构和不同的算法。选择合适的数据结构可以降低算法的复杂度。
- 在计算机高级语言中用数据类型来表示不同的数据结构。
数据结构一般有以下三类:
基本类型(FORTRAN支持)
构造类型(FORTRAN支持)
指针类型
FORTRAN支持如下几种基本类型:
整型、实型、双精度型、复型、字符型、逻辑型
FORTRAN支持如下几种构造类型:
数组、记录、文件
4.2双精度数据类型
-
由于实型数据提供的有效数字的位数有限,一方面满足不了精度的需要,另一方面还会产生误差。
-
双精度类型以两倍于实型的字节来存储数据,提供15-17位有效数字,解决了上述的问题。
-
FORTRAN中双精度常数要用指数表示:如:
12.3456789
→1.2345656789D+1
-
FORTRAN中双精度变量使用前要用类型说明语句或
IMPLICIT
语句加以说明: 如:
DOUBLE PRECISION A,B,C
或IMPLICIT DOUBLE PRECISION(A-C)
4.3复型类型数据
-
FORTRAN中复型常数要用一个括弧中的两个实数来表示,第一个表示实部,第二个表示虚部。
如:
1+2.5i
→(1.0, 2.5)
-
FORTRAN中复型变量使用前要用类型说明语句或
IMPLICIT
语句加以说明:如:
COMPLEX A, B, C
或IMPLICIT COMPLEX(A-C)
-
直接赋值。如:
C=(3.0, 4.0)
或D=(8.76E+5, -6.8E-3)
-
当实部和虚部不是常数,而是表达式时,则应该用
CMPLX
函数将实部和虚部组成复型数据再赋给复型量。如:CMPLX(3.0*A, 6.0+B)
-
如果
CMPLX
函数只有一个自变量,则它代表实部。如:CMPLX(3.0)
→(3.0, 0.0)
-
在内存中一个复型数据占两个实数的存储单元。
4.4四种数值型数据之间的转换和运算
- 不同类型数据之间的运算的规则:低级别向高级别转换,整型→实型→双精度型→复型。FORTRAN中不允许双精度型与复型进行运算,但现在有的系统作了放宽。
- 不同类型数据的赋值规则:先转换,后赋值。
- 类型转换函数:
INT(A)
,REAL(A)
,DBLE(A)
,CMPLEX(A)
,CMPLX(A,B)
。 - 不同类型数据间的比较规则:将低级别转换成高级别后在比较。但复型只能比较等于或不等于。
4.5字符型数据
**一、字符型常量:**又称字符串,是用撇号(单引号)括起来的若干个字符。如: ‘CHINA’, ‘U.S.A’
-
Fortran77规定在程序语句中可以使用的字符如下:
- 英文字母26个(不分大小写)
- 数字0-9,共10个字符
- 专用字符,共13个: ︺ ‘ $ ( ) + - * / , = . :
-
注意:
-
空格也是有效字符
-
Fortran77规定字符和系统字符之间的区别
-
Fotran77字符型常量允许使用系统可以使用的字符集,即系统字符。
如:
"How are you?"
,'abe@sina.com.cn'
都是合法字符串 -
当字符串本身有撇号时,用两个撇号表示。如:
'That"s right'
-
**二、字符型变量:**用来存放字符型常量的变量
-
字符型变量在使用前必须先定义。可以用
IMPLICIT
语句和CHARACTER
语句,如:IMPLICIT CHARACTER*5 (A-C)
,CHARACTER*4 (X)
或CHARACTER*5 STRI, STR2*10
-
如果在
CHARACTER
语句中不指定长度则隐含指定长度为1 -
如果统一指定的字符长度与变量个别指定的长度不一致,则以个别指定的长度为准
如:
CHARACTER*5 A,B*6, C*7
定义A
的长度为5,B
的长度为6,C
的长度为7
三、字符变量的赋值
- 用赋值语句直接对字符型变量赋值
- 通过
READ
语句从键盘或其它输入设备读入字符常量给字符变量。用表控语句进行输入字符串时要用撇号将字符串括起来,如:READ*, A, B, C
输入:'CHINA','NANJNG','NJUT'
**四、子字符串:**一个字符串连续的一部分
如:一个字符串 NANJNG ,则 NA , NAN , NANJ , NANJI,…… 都是其子串。
- 子串表示形式:**字符变量名
(E1,E2)
** 其中E1
和E2
是整型表达式,分别表示子字符串在原字符串中的起止位置,且1≤E1≤E2≤L
,L
是字符变量的长度。 - 如:
STR='STRUCTURED PROGRAMMING IN FORTRAN',
子字符串 | 子串的值 | 备注 |
---|---|---|
STR(12:22) | PROGRAMMING | |
STR(27:) | FORTRAN | 与STR(27:33)相同 |
STR(:10) | STRUCTURED | 与STR(1:10)相同 |
STR(5:5) | C | |
STR( : ) | 原字符串 | 与STR(1:33)相同 |
- 可以将一个子字符串赋给一个字符变量或另一个子字符串。如:
NAME=STR(27:33)
- 赋值号两侧的子串不能相互覆盖。如:
STR(25:29)=STR(27:33)
是不行的
五、字符表达式
- Fortan77只提供一种字符运算符"//",即为字符连接符,其功能是把前后两个字符型数据连接起来。如:
'a//b'='ab'
六、字符关系表达式
-
格式: <字符(串)> <关系运算符> <字符(串)>
如:
'A'.GT.'B'
,'NANJING'.EQ.'NANJING'
-
比较规则: 按其字符ASCII码的值进行比较;
-
两个单个字符比较,以其代码比较,代码大者为大;如:
'A'<'B'
-
两个字符常量(字符串)比较,将两个字符串中的字符自左向右进行比较;
-
如果两个字符串长度不等,则系统会自动将短的字符补以空格,使两者等长再比较。
七、用于字符处理的内部函数
LEN(A)
:给出A的长度
INDEX(a,b)
:给出b在a中出现的位置,若a不包含b则返回0
CHAR(I)
:给出ASCII码为1的字符, ICHAR(a)
:给出a的第一个字符的ASCII码 LGT(a,b)
、LGE(a,b)
、LLT(a,b)
、LLE(a,b)
:比较大小,当a>b
时LGT(a,b)
为真,当a>=b
时LGE(a,b)
为真,当a<b
时LLT(a,b)
为真,当a<=b
时LLE(a,b)
为真。
第五章数据的输入和输出
5.1概述
在程序设计中总是要有输入和输出。一般说来,在进行输入或输出时要确定三个基本要素:输入输出的设备、输入输出的格式 和 输入输出的数据。
注:系统隐含的输入输出设备为:键盘、显示器和打印机。
5.2有格式的输出
一、有格式的输出语句
一般形式:
-
WRITE(*,S1) <输出列表> S1 FORMAT(格式说明)
-
PRINT S1, <输出列表> SI FORMAT(格式说明)
二、格式说明符
主要介绍: I、F、E、D、G、L、A、’(撇号)、H、X、 r (重复系数)、/ (斜杠)
1、I
编辑符(Integer)
作用:用于整型数据的输出。一般形式: Iw
或Iw.m
其中: I
表示整型输出, w
为字段宽度, m
表示输出数据的最少数字位数。
注意:数据输出时,在指定的区域内向右靠齐;
如果数据的实际位数大于指定的字段宽度w
,则不输出数据,而在该区域内充满“*"
号。
当m
大于数据的实际位数时,前面添0,若小于数据实际位数,则不起作用
2、F
编辑符(Fixed point number)
作用:用于实数的小数形式输出。一般形式: Fw.d
其中: F
表示实数的小数形式输出;;w
为字段宽度; d
为输出数据的小数位数。
3、E
编辑符(Exponent)
作用:用于实数的指数形式输出。一般形式: Ew.d
其中: E
表示实数的指数形式输出;w
为字段宽度;d
为数字部分的小数位数。
注意:指数部分占4列,负号占一列,小数点前为0。如123.45
→0.12345E+03
、
4、D
编辑符(Double precision)
作用:用于双精度数的指数形式输出,用法与E
编辑符相仿。一般形式:Dw.d
5、G
编辑符
作用:由系统根据实际数据的大小来决定用F
编辑符或E
编辑符。一般形式: Gw.d
6、L
编辑符(Logical)
作用:用于逻辑型数据的输出。一般形式:Lw
其中: L
表示逻辑型数据的输出;w
为字段宽度。
7、A
编辑符
作用:用于字符型数据的输出。一般形式: Aw
或A
其中: A
表示字符型数据的输出; w
为字段宽度,若不指定,则表示按实际长度输出。
8、'
(撇号编辑符)
作用:用于输出字符常量,即把撇号内的字符串原样输出。
注:如果输出的字符中包含撇号,则用两个连续的撤号代表一个要输出的撇号。
9、H
编辑符
作用:用于输出字符常量。一般形式: nH<str>
其中: H
表示输出字符常量: n
为输出字符个数, str
为输出的字符串。(较少用)
10、X
编辑符
作用:用于输出空格。一般形式:nx
其中,X
表示输出空格,n
为输出的空格数。
11、重复系数r
在format
语句中,如果出现几个(或几组)相同的格式编辑符,则可以利用重复系数而只写一个(或一组)编辑符。如: FORMAT('A=', /, 4(5(1X,F4.0),/))
12、斜杠编辑符“/"
作用:结束本记录的输出,开始下一行记录的输出。(通常指换行)
三、WRITE
语句和FORMAT
语句的相互作用
WRITE
语句中的输出变量个数与FORMAT
语句中的编辑符(不含撇号、H
和x
)个数可以相等,也可以不等:如果编辑符个数多,则剩余的编辑符不起作用;如果变量个数多,则当编辑符用完后,重新使用该格式说明,但如果格式说明中包含带重复系数的编辑符组,则格式说明用完后,只有最右面一个带重复系数的编辑符组(包含重复系数)及其右面的编辑符被重复使用。- 可以有空格式说明,如:
FORMAT()
,用于输出一个空行。
5.3有格式的输入
一、有格式的输入语句
一般形式:
READ(*,S1)<输入表列>
S1 FORMAT(格式说明)
其中: “格式说明”是由各种“格式编辑符”构成。
例:
READ(*,100)A,B,C
100 FORMAT(F5.1,E12.2,F7.2)
END
键盘输入: ︺15.7︺2345.67E+04︺705.83
5.4在PRINT
, WRITE
和READ
语句中包含格式说明
在格式输入输出时,也可以将FORMAT
语句中的格式说明放到PRINT
, WRITE
和READ
语句中。
例:
PRINT 100,K,Y
100 FORMAT(I8,F7.2)
也可以写成: PRINT '(I8,F7.2)',K,Y
, K,Y
注意写法: '(……)'
第六章 数组
在FORTRAN中要使用数组必须遵循“先说明,后使用”的原则。说明的目的是通知编译系统为数组分配相应的存贮单元。有两种方法说明数组:
(1)用类型说明语句(“显式说明”)
(2)用DIMENSION
语句(“隐式说明")
6.1数组的说明和数组元素的引用
一、用类型语句说明数组
一般形式: 类型说明 数组说明符, …
其中,数组说明符的一般形式为: 数组名(维数说明符, …)
其中,维数说明符由“下标下界:下标上界”组成。
例:
REAL X(1:10), W(1:2, 1:3),K(10:20)
或 INTEGER B (1:100),PY(0:2,0:3,0:5)
二、用DIMENSION
语句说明数组
一般形式: DIMENSION 数组说明符,...
说明:
-
在数组说明符中,维数说明符(下标)的个数称为数组的维数。
-
维数说明符只能使用整型常量或整型符号常量表达式。
如:
PARAMETER (I=1,J=10) REAL KX(1:J+5)
-
维数说明符的下标下界为1时,可以省略。如:
REAL X(1:10)
→REAL X(10)
-
数组说明语句必须写在所有可执行语句之前。(属于非执行语句)
三、数组元素的引用
一般形式: 数组名 (下标, …)
即要有确定的数组名和下标值。如: XN(5)
, w(1, 3)
, KW(1, 2, 3)
引用数组元素时,下标可用算术表达式,如果表达式的值为实型,则自动取整。
6.2数组的逻辑结构和存储结构
了解数组的逻辑结构和存储结构,对我们合理地选用数组和对数组进行输入输出有很大好处。
数组的逻辑结构:数组所表示的实际数据结构。
数组的存储结构:数组在机器内存储时的排列结构。
一、一维数组
逻辑结构为一组依次排列的一串数据。
存储结构为一组连续存放的一列数据块。
二、二维数组
逻辑结构为一张二维数据表。
存储结构为一组按列连续存放的数据块。
三、三维数组
逻辑结构为若干张二维表数据。
存储结构为一组按页连续存放的数据块。
6.3数组的输入和输出
有三种方式:用DO
循环、用隐含DO
循环、用数组名
一、用DO循环进行数组的输入输出
用DO
循环进行数组的输入输出既有优点也有缺陷。
优点:数组元素的输入输出次序可由用户控制。
缺点:作一次循环就换行输入或输出。
二、用隐含DO
循环进行数组的输入输出
用隐DO
循环进行数组的输入输出,使我们既能控制数组元素的输入输出次序,又能控制一行内输入输出数据的个数。如:
READ(*, *) ((G(I,J),J=1,3), I=1,2)
由于是一个READ
语句,所以既可以一行输入,也可以分多行输入,键盘输入如下:
86,75,72 ↓
87,70,83↓
注:一个READ
语句可以分多行输入,而有多个READ
语句时,每一个READ
语句必须从新的一行读数。
三、用数组名进行数组的输入输出
在用数组名进行数组的输入输出时,其顺序要与数组元素在机内的存储顺序一致。如:
DIMENSION K(5)
READ *, K ←对数组的整体进行操作
等价于:
READ*, K(1), K(2), K(3), K(4), K(5)
也等价于:
READ*, (K(1), I=1, 5)
6.4使用DATA语句给数组赋初值
在FORTRAN程序中,可用DATA
语句给变量或数组赋初值。
一般形式: DATA
变量列表/初值表/ , 变量列表/初值表…
功能:在程序编译期间给变量或数组赋初值。其中,变量列表可以是变量名、数组名、数组元素、隐DO
循环;初值表只能是常量,不允许出现任何形式的表达式。
例:
DATA A, B/7.85,9.1/, I, J, K/5, 10, 15/
例:
DIMENSION K(2,3)
DATA((K(I, J), J=1,3), I=1, 2)/90, 23, 20, 42, 14, 32/
或:
DATA K/90, 42, 23, 14, 20, 32/
例:
DIMENSION A(10)
DATA A/10*1.0/ (表示"10个1.0")
注: DATA
语句属说明语句,但它可以放在END语句之前的任意行;当程序中有多个DATA
语句给同一个变量赋初值时,以最后一条DATA
语句为准;程序在编译期间给变量赋定初值,在程序执行期间, DATA
语句不起任何作用。
第七章 语句函数
前面我们介绍了FORTRAN的内部函数。FORTRAN编译程序把一些常用的运算(如求平方根,绝对值,三角函数……)编程为一个一个内部子程序,当我们程序中出现这些内部函数时,系统就会自动调用相应的子程序以完成所需的运算。但我们实际需要用到的函数是远远不止这些基本的内部函数,这个时候,我们就有必要自己定义一些我们需要的函数:语句函数或者子程序。
7.1语句函数的定义
一、语句函数的定义形式: F(X1,X2,...XN)=EXPR
其中: F
为语句函数名,其函数值也具有类型,所以在使用之前,必须对函数名象变量的类型说明一样对其进行类型说明;
X1,X2, XN
代表语句函数的自变量,称为虚拟参数。它们本身是没有值,只有在函数被引用时用实参代替虚参时,函数才能得到函数值;一个语句函数可以没有虚参,但函数名后面的一对括号不能少;虚参名可以和变量名相同,但它们之间没有任何其他联系。
EXPR
:语句函数的表达式; EXPR
中除了包含有关虚参外,还可以包含常量、变量、数组元素引用、外部和内部函数和已定义过的语句函数等。
二、定义语句函数的一些规则
- 语句函数名不能与本程序单位中的任何其他对象(变量,数组等)同名;
- 当函数可以用一条语句定义时才可以使用;
- 语句函数定义语句是非执行语句,它应放在所有可执行语句的前面和所有的说明语句之后;
- 语句函数只在其所在的程序单位中才有意义:
- 语句函数中的虚参应是变量形式,不可以是常量、表达式和数组元素,并且所有的虚参必须在函数表达式中出现。
7.2语句函数的引用
语句函数一旦被定义后,就可以在同一个程序单位中引用它。引用的形式和引用内部函数一样,即用实参代替虚参。实参可以是与虚参类型一致的常量、变量、或表达式,实参必须有确定的值。如:
F(K)=K+1
Y=F(F(3)) //Y值为5.0
第八章 子程序
在实际工作中,我们经常要编制一些求解特定问题的程序,如:排序、求积分、解线性方程组、插值等。如果每使用一次就编写一次,程序就会显得冗长、累赘。因此常把它们编制成独立的程序单位,需要时可随时调用。即:将那些比较复杂,但又需要经常用到的操作编写成具有独立名字的子程序。由主程序随时调用。
**子程序:**完成某一特定功能的程序单位。
FORTRAN子程序包括:函数子程序,子例行程序,数据块子程序
执行时:从主程序开始执行,遇到调用语句再执行相应的子程序。
不同类型的子程序,关键字不同,调用方法也不同。
8.1 函数子程序
从使用的角度讲, “函数子程序”就是一种可以作为函数来调用的子程序(也称“外部函数”)。
一、函数子程序的定义
一般形式:
类型说明 FUNCTION 函数名([虚参表]) …… (子程序体) END | 类型说明 FUNCTION 函数名([虚参表]) 类型说明 函数名 …… (子程序体) END |
其内容由两部分组成: FUNCTION
语句和子程序体
-
FUNCTION
语句:是函数子程序的第一条语句,标志着该函数子程序的开始。类型说明
FUNCTION
函数名([虚参表])注意:
-
虚元也有类型,需在子程序体中说明
例:
REAL FUNCTION INTEP(X1,X2,X3) INTEGER X1,X2,X3
-
函数名的命名规则和类型都与变量相同
-
虚参可以是变量名、数组名和子程序名,但不允许用常量和数组元素,它表示了函数自变量的个数,顺序和类型
-
-
子程序体:用来完成具体任务的一个程序段。
注意:
- ) 若无虚参时,括号不能省。例:
FUNCTION PROC()
- ) 函数子程序中所有变量和标号(除函数名和虚参外),与其它程序单位无任何联系。
- ) 函数体的说明部分包括对虚参和本函数体内所用变量和数组的说明。
- ) 函数体中可设置一条或多条
RETURN
语句,表示执行到此语句时返回调用程序。- ①当
RETURN
语句和END
语句紧挨着时,可省略RETURN
语句 - ②也可以不设
RETURN
语句,但需从中间返回时,RETURN
语句必不可少。
- ①当
- ) 函数名的作用:函数名在函数体中一定要被赋值,因为函数名把函数值带回调用程序
- ) 若无虚参时,括号不能省。例:
二、函数子程序的调用
调用方式与内部函数相似。一般形式:
**函数名 (实参表)**或 函数名 ()
说明:
- 调用程序中函数名必须与函数子程序中定义的函数名相同
- 实参与虚参在个数、类型、位置上必须一对应,但名字可以不同。
- 当虚参是变量名时,实参可以是常量、变量、数组元素或表达式;但当虚参要在函数体中被赋值时,则实参不能为常量或表达式。(因为虚参和实参共用一个存储单元)
- 函数子程序是一个独立的程序单位,可以作为一个单独的源文件进行存贮和编译,并与调用,程序连编后才能起作用。(也可以与调用程序放在同一文件中。)
8.2 子例行程序
子例行程序也是FORTRAN77的子程序,它与函数子程序的主要差别在于:
- 名字的作用不同:函数子程序名除了供调用外,还代表函数值,而子例行程序名只供调用。
- 要求返回值的方式不同:函数子程序是通过函数名将函数值带回调用程序,而子例行程序是通过“虚实结合”将其新值转送回调用程序
- 子例行程序可以带回一批值(数组),或者完成特定的操作。(如:交换,排序等)
- 调用方式不同:函数子程序的调用出现在表达式中,而子例行程序必须用一条独立的语句调用。
一、子例行程序的定义
一般形式:
SUBROUTINE 子例行程序名(虚参表)
......
END
说明:
- 子例行程序名的命名规则与变量名相同。(但不用标识类型)
- 如果没有虚参,括号可以省略。例:
SUBROUTINE ABC
- 虚参可以是变量名、数组名和子程序名,但不允许用常量和数组元素。
- 它的说明部分包括对虚参和本子例行程序所用变量和数组的说明。
- 子例行程序的名字只起标识作用,没有值的概念,仅仅为了调用。
二、子例行子程序的调用
一般形式:
CALL 子例行程序名(实参表) 或 CALL 子例行程序名
8.3 实参和虚参之间的数据传递
在FORTRAN程序设计中子程序的虚参可以是变量名、数组名、函数名、子例行程序名和星号“*
”。这里分别讨论当虚参为变量名、数组名、子程序名时的实参和虚参之间的数据传递问题,也称“虚实结合”问题。
一、变量名作虚参时的虚实结合
对应的实参可为同类型的常量、变量或数组元素。
结合方式:是按地址结合的。即虚参和实参共用一个存储单元。
注意:
- 当实参是数组元素时,虚实结合的过程和变量名相同。
- 如果虚参是字符变量,则其定义长度必须小于等于对应实参的长度,或用“
*
",表示长度不定。当调用子程序时,具有不定长度的虚参将自动定义为与对应实参相同的长度。
二、数组名作虚参时的虚实结合(仅说明数值型数组)
此时,对应的实参必须为同类型的数组名或数组元素。
-
实参为数组名时的虚实结合:按地址结合。即实参数组的第一个元素与对应虚参数组的第一个元素结合;实参数组的第二个元素与对应虚参数组的第二个元素结合,… ,依此类推。
-
实参为数组元素时的虚实结合:仍按地址结合,但该数组元素与对应虚参数组的第一个元素结合;该数组元素的下一个元素与对应虚参数组的第二个元素结合, …,依此类推。
注:虚参数组的最后一个元素必须落在实参数组范围内,否则会出现“超界错误”
三、虚参是可调数组
从数组的虚实结合规则可知,如果虚参数组的下标不可调,那么就会极大地影响子程序的通用性和灵活性。设计可调数组可以较好地解决这一问题。
**可调数组:**只能在子程序中使用,其上、下界可以是整型虚参变量,其值通过对应的实参传递。
注意:
- 可调数组只能出现在子程序中,不允许出现在主程序里
- 可调数组的数组名和界都必须作为虚参出现在虚参表中。
- 虚参数组的最后一维的上界可以用“
*
"表示。 - 如果在实参表中出现内部函数名时,必须在调用程序的说明部分用
INTRINSIC
语句说明 - 在调用程序单位中,如果实参中出现函数子程序名或子例行程序名时,必须在调用程序单位的说明部分用
EXTERNAL
语句说明这些名字。
程序举例
编写一个函数子程序,通过函数名的传送,使之既能求正切TAN
值(X)又能求余切值CTN
(X)
取函数名: TRIANGLE (FI, F2, X )
函数表式: TRIANGLE=F1(X)/F2(X)
F1
, F2
是虚拟函数名, X
是自变量(弧度)
当把SIN
传给F1
,把cos
传给F2
时,求正切;把COS
传给F1
,把SIN
传给F2
时,求余切。
PROGRAM MAIN
INTRINSIC SIN,COS
X=3.14159/5.0
Y1=TRIANGLE(SIN,COS,X)
Y2=TRIANGLE(COS,SIN,X)
WRITE(*,100)'TAN(',X*180/314159,')=',Y1
WRITE(*,100)'CTN(',X*180/314159,')=',Y2
100 FORMAT(1X,A,F6.2,A,E13.6)
END
FUNCTION TRIANGLE(F1,F2,X)
TRIANGLE=F1(X)/F2(X)
END
第九章 数据共用存储单元
9.1等价语句(EQUIVALENCE语句)
等价语句是说明语句,它的作用是使同一个程序中的两个或者多个变量共用一个存储单元
一般形式: EQUIVALENCE (变量列表1), (变量列表2) ......
每个变量列表中必须有两个以上的变量,表示每对括号内的变量共用一个存储单元,即等价。
**说明: **
- 等价语句是说明语句,它必须出现在程序单位的执行语句之前。
- 等价语句每对括号中的变量可以具有不同类型,但不建议大家这样使用。
- 数组的等价。
- 不能利用等价关系建立矛盾的等价关系
9.2 公用语句
程序中不同程序单位之间的数据交换是通过虚实结合来完成的。另外FORTRAN还可以通过建立公用区的方法来实现各程序单位之间的数据交换。公用区和虚实结合比较起来,其缺点:程序阅读性下降;其优点:运行速度快(特别当有大量数据需要传送时)。
在不同的程序单位中,各自的变量是相互独立的,尽管它们的变量名有时相同。但如果我们在主程序和子程序中都加上一条COMMON
语句的话,如: “COMMON X
”,此时编译程序在存储区中开辟了一个公用数据区。这时主程序和子程序中的两个变量X
就共用一个存储单元,而不是相互独立了。在FORTRAN中,可用COMMON
语句来开辟无名公用区和有名公用区。
9.2.1无名公用区
一、开辟无名公用区的COMMON语句的一般格式:
COMMON A1, A2, ...
其中A1
, A2
、…允许是普通变量名、数组名和数组说明符(不能是数组元素)
例如: 在主程序中写: COMMON X, Y, K, Z(3)
在子程序中写: COMMON A, B, J, T(3)
此时,在无名公用区中变量X
和A
, Y
和B
, K
和J
分别被分配在同一个存储单元中;数组Z
和T
同占3个存储单元。
解释: FORTRAN编译程序在编译时为以上的COMMON
语句开辟一个无名公用区,当把不同的程序单位连编在一起的时候,不同的程序单位在COMMON
语句中的变量按其在语句中出现的先后顺序,依次连续的占用无名公用区的存储单元,也就是说每个程序单位中的COMMON
语句总是把出现在语句中的第一个变量分配在无名公用区的第一个存储单元位置。
程序举例: 通过虚实结合交换数据,求一元二次方程的根程序:
主程序:
READ*, A1,A2,A3
CALL QUAD(A1,A2,A3,Z1,Z2)
WRITE(*,*) Z1,Z2
END
子程序:
SUBROUTINE QUAD(A,B,C,X1,X2)
P=-B/(2.0*A)
Q=SQRT(B*B-4.0*A*C)/(2.0*A)
X1=P+Q
X2=P-Q
END
通过虚实结合和公用区两种方式交换数据,求一元二次方程的根:
主程序:
COMMON Z1, Z2
READ*,A1,A2,A3
CALL QUAD(A1,A2,A3)
WRITE(*,*)Z1,Z2
END
子程序:
SUBROUTINE QUAD(A,B,C)
COMMON X1,X2
P=-B/(2.0*A)
Q=SQRT(B*B-4.0*A*C)/(2.0*A)
X1=P+Q
X2=P-Q
END
完全通过公共区域来交换数据,求一元二次方程的根:
主程序:
COMMON Z1,Z2,A1,A2,A3
READ*,A1,A2,A3
CALL QUAD
WRITE(*,*)Z1,Z2
END
子程序:
SUBROUTINE QUAD()
COMMON X1,X2,A,B,C
P=-B/(2.0*A)
Q=SQRT(B*B-4.0*A*C)/(2.0*A)
X1=P+Q
X2=P-Q
END
二、无名公用区的COMMON语句使用规则
COMMON
语句是说明语句,必须出现在所有可执行语句之前COMMON
语句中只允许出现变量名、数组名或数组说明符,如:COMMON A, NP(15)
- 用于
COMMON
语句中的变量在编译时已经被分配在实在的存储单元中,因此在COMMON
语句中不能出现虚拟参数。同样,可调数组名也不能出现在COMMON
语句中。但是可调数组的维的上、下界变量可以通过COMMON
语句传送 - 一个程序在运行过程中只有一个无名公用区。在同一个程序单位中可以出现几个
COMMON
语句,它们的作用相当于一个COMMON
语句 - 各程序单位
COMMON
语句中的变量类型必须按位置一一对应才能正确传送数据 - 在一个程序单位中,分配在公用区中的名字只能在
COMMON
语句中出现一次 - 在不同的程序单位中,无名公用区中的变量个数可以不一样,但必须保证对应的变量类型要一致
- 如果公用区中出现字符型数据或字符数组,则要求整个公用区中的变量为字符类型,不允许字符变量与其他类型变量放在同一个公用区中。
9.2.2有名公用区
我们已经知道,无名公用区中各程序单位之间数据传送按公用区中变量名的排列顺序一一对应进行。但我们在实际使用中常常会遇到下面的问题
例:我们的主程序要和两个子程序进行数据传送。
主程序:COMMON A, B, C, J, K, L
子程序1需要与主程序传送A
,B
,C
三个数据;
子程序2需要与主程序传送J
,K
,L
三个数据:
根据一一对应的原则。解决方法一:
主程序: COMMON A, B, C, J, K, L
子程序1: COMMON A1,B1,C1
子程序2: COMMON A2,B2,C2,J2,K2,L2
此时子程序2中的A2
, B2
,C2
,从语法角度是必需的,但它们从使用角度却是冗余的。当一个主程序和若干个子程序间进行大量的数据传送时,书写COMMON
语句就显得很烦琐,而且也容易出错。解决方法二:利用有名公用区
主程序: COMMON A, B, C/C2/J, K, L
子程序1: COMMON A1, B1, C1
子程序2: COMMON /C2/J2, K2, L2
此时A
, B
, C
仍放在无名公用区中;而J
, K
, L
放在名为C2
的公用区中。
利用有名公用区就避免了无名公用区的弊病,使之做到公用之中有“专用”,我们只需在各个程序单位中做到同名共用区中数据顺序一一对应就行了
一、开辟有名公用区的COMMON语句的一般格式:
COMMON /n1/变量表1, /n2/变量表2,......
其中, n1
, n2
为公用区名,它们放在两个斜杠“/”之间,它们的取名方法与变量名同:变量表代表各有名公用区中的变量名、数组名或数组说明符。我们也可以用两个连续的斜杠来表示无名公用区,例如:
COMMON x, Y, Z/C2/A, B, C
可以写成: COMMON //X, Y, Z/C2/A, B, C
或者 COMMON /C2/A, B, C//X, Y, Z
COMMON
语句中的公用区的变量可以“化整为零”,只要它们在有名公用区中的顺序不变。例如:
COMMON X, Y, Z/C2/A, B, C
可以写成: COMMON /C2/A//X, Y, Z/C2/B, C
也可以写成下面两句: COMMON /C2/A
``COMMON X, Y, Z/C2/B,C`
建议:一个有名公用区用一条COMMON
语句来完成,例如:
COMMON X,Y,Z
COMMON /C1/A,B,C
COMMON /C2/J,K,L
二、有名公用区和无名公用区规则的区别
- 各程序单位的同名公用区的大小必须相同,而无名公用区则无此要求
- 有名公用区的成员可以通过数据块子程序赋初值,而对无名公用区的成员则无任何方法赋初值
- 在执行
RETURN
语句或END
语句时,有时会导致有名公用区中的成员变为无定义,但无名公用区中的成员不存在这个问题。
9.3数据块子程序
功能:是一种特殊的子程序,它只是用来给有名公用区中的变量赋初值。
数据块子程序格式和规则说明如下:
-
数据块子程序必须以
BLOCK DATA
作为第一个语句,以END
作为最后一条语句。说明形式如下:BLOCK DATA 子程序名 ...... END
可以没有子程序名,这时的数据块子程序称为无名数据块子程序;一个程序中只能有一个无名数据块子程序,但可以有任意多个有名数据块子程序。
-
数据块子程序只是用来给有名公用区的变量赋值,不能被被别的程序单位调用。
-
在数据块子程序中不允许出现可执行语句,只允许出现
COMMON
、DIMENSION
、DATA
、EQUIVALENCE
和类型说明语句。其中DATA
和COMMON
语句是必不可少的。(数据块子程序由DATA
语句给指定变量赋初值,并由COMMON
语句与其他相连接的程序单位沟通)。 -
数据块子程序中的
DATA
语句只能给有名公用区中的变量赋初值,不允许给无名共用区中的变量赋初值。 -
指定的某个有名公用区中所有变量(即使其中有些变量不要求在
DATA
语句中赋初值),都必须一一按顺序列在COMMON
语句中。例如:
BLOCK DATA INIT DIMENSION A(10),B(5) COMMON /COM/A.X,Y,Z,B,I INTEGER X,Y,Z DATA X,Y,Z/3*0/,B/5*0.0/ END
这是一个完整的的数据块子程序。虽然
DATA
语句只需给COM
共用区中X
,Y
,Z
变量和B
数组赋初值,但仍需列出COM
中所有的变量。 -
一个FORTRAN程序可以包含任意多个数据块子程序,但每个有名公用区中的变量只能在一个数据块子程序中赋一次初值,不允许把一个有名公用区中的变量分在几个数据块子程序中赋值。
第十章 文件
10.1 概述
FORTRAN程序结构:
输入数据(赋值, READ)——从键盘输入
计算
输出结果(WRITE,PRINT)——输出到屏幕
END
**输入: **
①赋值语句:不易修改,需重新编译
②READ
语句:输入量很大时,麻烦,且易出错
**输出:**只能看到屏幕或打印纸上的结果(.EXE)
要看结果,必须首先运行程序
解决办法:使用文件
**输入:**将要输入的数据存放在文件中——数据文件;用任何编辑工具均可建立,在程序中用READ
语句读入,并可以反复使用
**输出:**将结果保存在文件中,方便。
10.2文件的基本概念
一、文件的定义
FORTRAN中,文件指存储在外部介质上的数据集合。由文件名代表。
取名字:与其它命名规则类似。作为文件的标识,可在程序中反复引用
不取名字:临时性使用
FORTRAN中的文件仅指数据文件:原始数据、中间结果、最终结果等。
二、文件的组成
文件是由记录组成, FORTRAN中对文件的存取以记录为单位。而每个记录又是由字段(数据项)组成。三、文件的分类
- 按存取方式(读取记录的顺序)
- (1)顺序存取文件:从第一个记录开始,一个接一个地依次存取记录。
- (2)直接存取文件:可对任意指定的记录进行存取(也称随机文件)。
- 按存放形式
- (1)有格式存放(也称字符形式存放)。
- (2)无格式存放(也称二进制形式存放)。
10.3数据文件的建立和使用
一、数据文件的建立
- 利用编辑程序或FORTRAN开发环境编辑器建立。(存放原始数据)
- 在程序执行期间建立。(存放中间结果和最终结果)
二、数据文件的使用
一般形式:
OPEN(说明项) (打开文件)
......
READ/WRITE(控制项),输入/出表列 (读写文件)
......
CLOSE(设备号) (关闭文件)
其中:
-
**
OPEN
语句:**形式为:OPEN
(说明符)作用为:打开一个已存在的文件(对文件操作的前提),实现一个设备号和一个文件的连接。若不存在,则新建一个指定文件名的文件元素。如:
OPEN(5,FILE='SCORE.DAT', STATUS='OLD')
OPEN语句所包含的说明项
-
)设备号说明:
[UNIT=]U
(其值为1~99) -
)文件名说明:
FILE=FN
(其值为数据文件名) -
)状态说明:
STATUS=ST
(其值为OLD
,NEW
) -
)存取方式说明:
ACCESS=ACC
(其值为SEQUENTIAL
,DIRECT
,缺省为SEQENTIAL
) -
)记录格式说明:
FORM=FM
(其值为FORMATTED
,UNFORMATTED
,缺省时,顺序文件为有格式,直接文件为无格式) -
)记录长度说明:
RECL=RL
(其值>0,仅用于直接文件)对于有格式顺序存取文件,
OPEN
语句中的ACCESS=
和FORM=
两项可以省略
-
-
**
CLOSE
语句:**对应OPEN
语句- 作用:用来解除文件和设备号的连接
- 形式:
CLOSE
(设备号)。如:CLOSE(5)
- 设备号:对应
OPEN
语句中的设备号
-
**
READ/WRITE
语句:**格式同前述通用:
READ(设备号,格式) 输入表
这里:
READ(5,*) X1,X2,X3,X4,X5
注意:
①如果用格式输入,则文件中数据的格式一定要严格按照格式的要求。
②表控格式时,与普通键盘输入有区别:
键盘输入时:数据可多可少
文件输入时:可多,不可少,将剩余的变量赋值0。
③同样要注意新记录的问题。
例:
READ (5,*) X1,X2,X3
READ (5,*) X4,X5
-
该例中,文件的作用是用于将原始数据输入(
READ
语句);还可以保存中间数据与最终结果数据(WRITE
语句)。 -
使用时,数据文件与源程序文件最好位于同一个目录下。
例:调用
SCORE.DAT
文件,将全班30个同学的三门课成绩求和,且保存在文件ORDER.DAT
文件中。源程序:
DIMENSION A(30,3),SUM(30) OPEN(8,FILE='SCORE30.DAT',STATUS='OLD') READ(8,*)((A(I,J),J=1,3),I=1,30) DO 10 I=1,30 SUM(I)=0.0 DO 10 J=1,3 SUM(I)=SUM(I)+A(I.J) 10 CONTINUE OPEN(9,FILE='ORDER.DAT',STATUS='NEW') WRITE(9,100)(SUM(I),I=1,30) 100 FORMAT(3F8.2) CLOSE(8) CLOSE(9) END
这里:
-
OPEN(9,FILE='ORDER.DAT',STATUS='NEW')
中文件用来保存运算结果。 -
WRITE
语句的格式与READ
语句类似.WRITE(9,100)(SUM(I),I=1,30)
-
与普通格式说明语句不同的是:
FORMAT
语句中不需要1X
纵向走纸控制符。 -
这里的
STATUS='NEW'
,若当程序再次运行时,会出现错误。解决方法:A.在再次运行前,将生成的文件删除
B.用
STATUS='UNKNOWN'
,此时,编译系统会自动检索目录,若存在,则取值'OLD'
,将原数据覆盖;否则,='NEW'
-
生成的文件位于与源程序文件相同的文件夹中。
例:
C 从文件读取数据 FIN="DATA.DAT" OPEN(93,FILE=FIN,ACCESS='DIRECT',RECL=8) DO J=1,N READ(93,REC=J) x(J) ENDDO CLOSE(93) C 将数据写入文件 FOUT='ERRADI.DAT' OPEN(93,FILE=FOUT,ACCESS='DIRECT',RECL=ITER MAX*8) WRITE(93,REC=1) (RRES(I),I=1,ITER_MAX) CLOSE(93)
-