当前位置:文档之家› fortran语言教程第3章

fortran语言教程第3章

fortran语言教程第3章
fortran语言教程第3章

第3章顺序结构设计

本章介绍数据输入/输出语句及其他基本语句,简单介绍顺序结构及程序设计的基本步骤,书写简单程序。

3.1 变量的赋值

变量代表计算机内存中的存储单元,它可以接收外部设备输入的数据,也可保留运算器的运算结果,还可以被送到外部设备输出。FORTRAN语言要求变量必须被预先赋值,然后才能被使用,并提供了下面几种为变量赋值的方式,因此,程序中的变量都应该在使用之前用下列方式之一获得数据。

3.1.1 赋值语句

1)赋值语句的格式和功能

语句的格式:

变量 = 表达式

语句的功能:将一个表达式的计算结果值赋给一个变量。

关于赋值语句的说明:

(1)赋值语句是执行语句。

(2)赋值语句中的“=”号叫做“赋值号”,它的作用是将其右边的表达式的结果赋给其左边的变量,即将表达式的值放入变量对应的内存单元中,因此,赋值号的意义是带有方向性和动作性的。例如“A=5.5”的作用是将5.5 送到变量A对应的内存单元中。

(3)赋值语句兼有计算和赋值双重功能。即先计算出表达式的值,然后将该结果赋给一个变量。例如“N=N+1”的作用是用N的当前值加上1后再送入N中,假设N的当前值是5,则执行N=N+1后,N的值为6。

(4)根据赋值语句的功能,由于赋值号的方向性特性,赋值号左边只能是变量,以便提供一个获得数据的空间。因此,“A=B”和“B=A”具有完全不同的意义,前者表示将B中的数据送入A中,后者表示将A中的数据送入B中。语句“X+Y=10”是错误的,因为在内存中找不到名字为X+Y的变量。

2)执行赋值语句时的类型转换问题

执行赋值操作时,被赋值的变量和表达式的类型可以相同,也可以不相同。FORTRAN语言作如下规定:(1)变量与表达式的类型相同,则将表达式的结果直接赋值。

M=4 (变量M和4都是整型)

A=3.5*SIN(X)(变量A和表达式3.5*SIN(X)都是实型)

(2)如果类型不同,则应先进行表达式的计算,然后将该表达式的值转换为被赋值变量的类型。

I=3.5*3.1

表达式3.5*3.1的计算结果为10.85,而变量I为整型,因此系统会先将10.85转换成整数10,再送入变量I中,最后I的值为10。

具体赋值过程中的类型关系见表3.1。

当赋值号两侧的类型不同时,往往会产生预想不到的结果,如上面的10.85,赋值后的结果却为10。所以,在编写程序时,应该尽可能使赋值号两边的类型保持一致。另外,类型转换还要花费机器时间。

表3.1 赋值语句的类型转换

3.1.2 DATA语句

1)DATA语句的格式和功能

语句的格式:

DATA 变量表/初值表/,变量表/初值表/,…

语句的功能:程序在编译时将“初值表”中的数据依次赋给“变量表”中的各变量单元。在程序执行时,DATA语句就不起作用了。

关于DATA语句的说明:

(1)DATA语句是非执行语句,一定要出现在执行语句之前,同一个变量不能在DATA语句中被多次赋初值。

(2)变量表中可以出现所有提供存储空间的量,如变量名、数组名、数组元素名、隐含DO循环。初值表中只允许出现常量,不允许出现任何形式的表达式。变量表中的变量个数与对应初值表中常量的个数必须相同,类型按从左到右的顺序一一对应。变量之间、初值之间都用逗号分隔。

(3)对于多个相同的初值可以采用简化形式书写,例如:DATA X,Y,Z/-1.0,-1.0,-1.0/,可以写成DATA X,Y,Z/3*-1.0/ 形式。3*-1.0表示“三个-1.0”,在这里*号绝不代表乘号,因此不能写成算术表达式的形式3*(-1.0)。

2)DATA语句应用举例

program main

DATA I/10/

PRINT *,'1. I=',I

I=I+1

PRINT *,'2. I=',I

END

程序执行后正确的输出结果应该是:

1.I=10

2.I=11

3.2 数据的输入和输出

FORTRAN语言中也提供了专门实现数据输入、输出的read和write(print) 语句,功能类似VB语言中的inputbox函数和窗体的print方法。

例如,用海伦公式求三角形面积。

)

)(

)(

(C

P

B

P

A

P

P

S-

-

-

=,其中

2C

B

A

P +

+

=,A,B,C为三角形的三边长,写程序求三角形面积。

根据问题要求可以画出如图3.1所示的算法流程图。

图3.1 用海伦公式求三角形面积的算法流程图

所谓输入是指从外部设备上将数据送进计算机内存中。向计算机输入数据又叫做“计算机从外部设备读入数据”,计算机向外部设备输出数据又叫做“向外部设备写数据”。在讨论输入输出时,需要确定几个因素:

(1)在什么外部设备上输入或输出;

(2)用什么格式输入输出;

(3)输入输出那些数据。

一般情况下,每一个计算机系统都隐含指定一种输入设备和输出设备,只要程序不作其它声明,系统就认为用户所指的输入输出设备就是隐含指定的设备。在微型机中,隐含的输入设备一般是键盘,隐含的输出设备一般是显示器,并且规定隐含设备用 * 表示。

具体进行输入/输出时的格式可以有三种方式:

(1)根据用户规定的格式输入/输出;

(2)计算机约定的自由格式输入/输出(又称表控格式);

(3)无格式输入/输出,即以二进制形式输入/输出,一般用于数据文件和计算机之间交换数据。

FORTRAN语言用READ语句描述输入数据操作,用WRITE、PRINT语句描述输出数据操作。对输入输出的三个因素及格式都可以通过语句的书写形式来确定。

3.2.1 简单的输入和输出语句

最简单的输入/输出语句即自由格式(又称表控格式)输入/输出语句,在输入/输出语句中用户不必指定数据的格式,计算机会按照约定的格式对数据进行输入/输出。

1)表控输出语句

(1)输出语句的格式:

表控输出语句的格式:

PRINT *,输出项表

WRITE(*,*)输出项表

表控输出语句的功能:在系统隐含的输出设备上,按照系统约定的格式输出各个输出项的值。

表控输出语句的说明:

①表控输出是“表控格式”输出的简称。

② WRITE语句括号中的第一个“*”表示在系统隐含的输出设备(一般指显示器)上输出;第二个“*”

表示按照表控格式输出。

③ PRINT语句只能在系统隐含输出设备上输出,“*”表示按照表控格式输出。

④“输出项表”是用“,”分隔的将要输出的多个输出项,输出项形式可以是常量、变量、函数、表达式,他们最终输出的都将是一个数据。

⑤用表控格式输出数据时,计算机自动地分别为每一种不同类型的数据规定所占的列数和表数形式(例如实数是用小数形式输出还是用指数形式输出,小数点位置在何处等),用户完全不用安排输出数据的格式。

例如在输出时,如果一个实数的整数部分的位数多于机器系统规定的有效位数,或实数的数值小于1,则在输出时会自动转换成规范化的指数形式输出。

但要注意的是,不同的计算机系统对表控格式输出的规定不同,例如对一个整型数,有的系统规定输出占13列,有的系统规定输出占10列,也有的系统不规定固定的列数而按照数据的实际长度输出,再用一个空格作分隔符。要想知道所使用系统到底是怎样规定表控格式的,读者可以自己上机试一下。

(2)输出语句示例

I=45

J=128

PRINT *,‘I,J=',I,J

A=13.567

B=-186.75

PRINT *,‘A,B=',A,B

C=162E25

D=-11.72E-13

PRINT *,‘C,D=',C,D

E=123E6

F=0.132

PRINT *,‘E,F=',E,F

PRINT *,‘’

PRINT *,‘I,J,A,B,C,D,E,F=',I,J,A,B,C,D,E,F

END

读者可以运行该示例程序,体会一下输出语句的作用。

2)表控输入语句

(1)表控输入语句的格式和功能

表控输入语句的格式:

READ *,变量表

READ(*,*)变量表

表控输入语句的功能:执行该语句时,计算机将等待用户从键盘上输入数据,然后再将这些数据依次赋给各个变量。

表控输入语句的说明:

①对带括号的READ语句,括号中的第一个“*”表示在系统隐含输入设备(一般指键盘)上读数,括号中的第二个“*”号表示按照机器系统约定的“表控格式”读入数据;对不带括号的READ语句,“*”表示按“表控格式”读入数据。

②“变量表”是用逗号分隔的将要获得数据的多个变量。

③该语句是执行语句,表控输入又称自由格式输入,用户不必指定输入数据的格式,只需将数据按其合法形式依次输入即可,数据间用逗号或空格间隔。

例如有输入语句 READ *,I,J,A,B,要求从键盘上读入两个整型数赋给I和J,两个实型数赋给A和B,可以从键盘输入以下形式的数据:

10,20,80.5,62.35 (数据间用逗号分隔)

或者:10□□20□80.5□□□62.35(数据间用一个或多个空格间隔)

执行语句时,机器将从键盘读入4个数,分别赋给变量I,J,A,B。

(2)使用表控输入语句应注意的问题

①从键盘输入的数据个数必须≥变量表中的变量个数,即保证变量表中的每个变量都能获得数据;如果输入的数据不够,计算机将等待用户继续输入,直到全部变量获得数据为止。对上述例子来讲,下面的输入方式都可以:

方法一:10,20,80.5,62.35 (一个行内输入4个数据)

方法二:10,20 (第一行输入2个数)

80.5,62.35 (第二行输入2个数)

方法三:10 (第一行输入1个数)

20,80.5,62.35 (第二行输入3个数)

方法四:10,20,80.5 (第一行输入3个数)

62.35 (第二行输入1个数)

方法五:10 (分4行输入4个数)

20

80.5

62.35

从上述输入方式可以看出,数据分几行输入都可以,但一定要保持数据输入的顺序不变。

②输入数据的类型要与变量表中的变量类型一致,以保证变量获得数据的正确性。

③如果输入的数据个数多于变量个数,则多余的数据无用。

④每执行一个READ语句都是从一个新的输入行开始读数。例如将上述语句改成两句:

READ *,I,J

READ *,A,B

则输入数据时必须保证整型数和实型数不在同一行(因为获得A的数据时已经是执行一个新的READ语句了),下面的输入方式都可以。

方法一: 10,20 (第一个READ语句需要的数)

80.5,62.35 (第二个READ语句需要的数)

方法二: 10

20 (第一个READ语句需要的数)

80.5,62.35 (第二个READ语句需要的数)

方法三: 10,20 (第一个READ语句需要的数)

80.5

62.35 (第二个READ语句需要的数)

方法四: 10

20 (第一个READ语句需要的数)

80.5

62.35 (第二个READ语句需要的数)

④如果在输入数据行中出现“/”号,表示对READ语句的输入到此结束,未被赋值的变量将不予赋值。

例如有如下程序段:

DATA I,J,K/10,20,30/

PRINT *,I,J,K

READ *,I,J,K

PRINT *,I,J,K

如果执行程序时输入数据为:

40,50/60

则输出结果为:

10 20 30

40 50 30

可见变量K没有从READ语句获得新数据。利用这种方法可以控制READ语句中的部分或全部变量(只输入一个/)不被赋值。

⑤在一个数据的数字之间不要插入空格,因为空格是数据之间的分隔符。

利用表控格式的输入、输出语句,可以将图3.1描述的流程图写成程序。

READ *,A,B,C

P=(A+B+C)/2

S=SQRT(P*(P-A)*(P-B)*(P-C))

PRINT *,‘S=’,S

END

执行程序时如果输入数据:

1.4,3.5,4.5

则输出的结果为:

S= 1.9293510

3.2.2 格式输出

如果用户想安排输出数据的格式(这里的格式是指数据位数、小数位数等),可以利用格式输出方式。FORTRAN语言的输出格式是利用FORMAT语句描述的。

FORMAT语句和WRITE语句配合使用的形式为:

WRITE(*,标号)输出量表

……

标号 FORMAT(1X,格式描述符)

1)FORMAT语句

语句格式:

标号 FORMAT(格式描述符)

语句功能:为WRITE语句提供组织数据的格式。

说明:

(1)FORMAT语句是非执行语句,可以出现在程序标识语句之后,END语句之前的任何位置。

FORMAT语句中的标号应该是某个WRITE语句中书写的标号,表示WRITE语句中的输出项应该按此FORMAT语句中指定的格式输出,并且一条FORMAT语句可以被多个WRITE语句使用。

执行WRITE语句时,计算机系统就按照“标号”指出的FORMAT语句中的“格式描述”来组织“输出量表”中的各个数据并输出。

(2)“格式描述符”也叫“格式编辑符”、“编辑符”。

2)格式描述符

FORMAT语句中的“格式描述符”,作用是为输入/输出语句提供组织输入/输出数据的格式说明。对于不同类型的数据,使用的“格式描述符”也不相同。下面将一一介绍各种描述符。

(1)I描述符

I描述符是专门用于整型数据的格式描述符,它的形式有两种:

Iw 或 Iw.n

大写字母I是整数Integer的第一个字母,用来表示“整型数描述”。w表示数据占用的宽度(位数),n表示需要输出的最少数字位数。

例如:已知I=40,J=-25,K=1890。可执行输出语句:

WRITE(*,100)I,J,K

100 FORMAT(1X,I3,I5,I7)

FORMAT语句“格式描述符”中包含了1X,I3,I5,I7,其中1X是换行控制符(走纸控制),I3表示I变量的值输出占3列,I5表示J变量的值输出占5列,I7表示K变量的值输出占7列。

注意:

①数字在指定的区域内向右端靠齐,如果数字位数比Iw的w小(如40为二位数字,而格式描述符用I3,即w=3),则左边补以空格。一个数据所占的宽度称为“字段宽度”,所以w用来指定字段宽度。

②数的符号也包含在字段宽度内。例如,I=-40,则I3可以容纳,如果I=-400,则I3就不能容纳了。

③如果格式描述符说明的宽度不能容纳数据,则输出时不输出该数据,而是在描述的宽度内充满“*”符号。例如I=-400,而格式描述符是I3,则输出为:***。

下面是用I编辑符输出整数的结果:

要输出的值描述符输出结果说明

1640 I5 □1640 左补空格

736 I7.4 □□□0736 输出4位数字

8736 I8.3 □□□□8736 按数据实际位数输出

-67896 I5 ***** W不够,则输出W个* (2)F描述符

F是fixed point number(定点数)的第一个字母,用于实型数的小数格式描述。它的形式为:

Fw.d

w的含义仍为“字段宽度”,d的含义是:输出的小数位数。

可以看出:用F描述符输出时,由于难以事先确切估计出数据的大小,输出大的数时容易产生“宽度不够”的错误(由于w不够大),输出小的数时会丢掉有用数字的情况(由于d不够大而将后面的数字截去),这就是“大数印错,小数印丢”的现象。所以使用F描述符时应该特别注意这一点。

下面是用F描述符输出实型数的结果:

要输出的数格式描述符输出结果说明

18.5 F6.2 □18.50 第二位小数补零

1875.478 F9.2 □□1875.48 多余小数四舍五入

-78567.83 F9.3 ********* w位数不够,用*填满w位

0.000678576 F10.4 □□□□□.0007 截去了有效数字

(3)E描述符

E描述符用于实型数的格式描述,但它是指数形式(采用规格化的指数形式)输出。E是Exponent(指数)的第一个字母。其一般形式为:

Ew.d

其中w仍然为字段宽度,d为数据的尾数部分小数的位数。

用指数格式输出数据时,一般指数部分自动占4位(其中字母E和指数的符号各占1位,指数占2位),小数部分占d位(尾数用小于1的规格化形式),再加上一个小数点,如果为负数则还应该加上符号位。因此,为了保证输出数据的正确性,应该使w≥4+d+1+1。

用E描述符可以避免“大数印错,小数印丢”的问题,在实数的值大时,都能保证可以输出必要的有效位数。

另外,有的系统还允许使用扩充的指数格式编辑符,可以指定输出更多位指数,这种编辑符形式为:

Ew.dEe

其中e是指数的位数,例如E16.4E5,表示指数部分中有5位数字。

下面是用E描述符输出实数的结果:

要输出的值格式描述符输出结果说明

123.45 E12.4 □□□.1235E+03 第5位小数四舍五入

-0.005 E11.3 □□-.500E-02

876.53 E8.3 ******** w不够大

7621.2 E15.6E3 □□□.762120E+004 规定指数为三位数(4)G描述符

用F描述符输出数据虽然直观,但会出现“大数印错,小数印丢”的问题,用E描述符输出数据虽然保险,但又不太直观。FORTRAN语言提供了一种“两全其美”的方法,就是使用G描述符。G描述符在输出时可以根据被输出的数据的大小,自动调整用F格式或E格式。其一般形式为:

Gw.d

凡绝对值小于0.1的数用E格式形式输出,凡绝对值大于10d的数用F格式输出。如果输出变量为A,可以表示为:

10d>|A|≥0.1 用F格式,有效位为d位

|A|<0.1或|A|≥10d 用E格式,尾数的有效位为d位

下面是用G描述符输出的结果:

要输出的数格式描述符输出结果说明

0.0234 G12.4 □□□.2340E-01 <0.1

23467.34 G12.4 □□□.2347E+05 >10d

3467.34 G12.4 □□□3467.□□□□<10d

346.734 G12.4 □□346.73□□□□<10d

0.234 G12.4 □□.23400□□□□>0.1

(5)D描述符

D编辑符用于双精度数据的输出,其一般形式为:

Dw.d

D是Double Precision(双精度)的第一个字母。采用此格式的数据按双精度指数形式输出。双精度数可以用E编辑符描述,也可以用F编辑符描述,但同样会出现“大数印错,小数印丢”的情况。

(6)L描述符

L描述符用于逻辑型数据的格式描述,其一般的形式为:

Lw

L是Logical的第一个字母。如果A1,A2已经定义为逻辑型变量,且A1=.TRUE.,A2=,则:

WRITE(*,100)A1,A2,.TRUE.

100 FORMAT(1X,L4,L5,L2)

输出的结果为:

□□□T□□□□F□T

对值为“真”的,在输出时打印一个字母T(表示.TRUE.),“假”则以一个字母F(表示.FALSE.)。T和F 在字段范围内的右端。可以看出,逻辑常量(.TRUE.和.FALSE.)也可以直接输出。

(7)A描述符

用于字符型数据的格式描述。其一般形式为:

Aw 或 A

w是字段宽度。例如有程序:

CHARACTER *5 S

S=‘CHINA’

WRITE(*,100)S

100 FORMAT(1X,A7)

END

执行后输出的结果为:

□□CHINA

S长度为5,在输出时指定的字段宽度为7,字符向右对齐,所以左边有两个空格。如果在FORMAT语句中,用A3代替A7,则只输出左边的三个字符,结果为:

CHI

如果在A后面不指定宽度w,则表示按字符的实际长度输出(即按程序定义该变量时长度)。例如,将格式语句改为:

100 FORMAT(1X,A)

则输出的结果为:

CHINA

(8)撇号描述符

利用撇号(‘)描述符可以在FORMAT语句中直接插入所需要的字符串。例如:

I=123

J=2345

WRITE(*,100)I,J

100 FORMAT(1X,‘I=’,I3,‘J=’,I4)

则输出的结果为:

I=123J=2345

如果需要输出的字符串包括撇号,则用两个连续的撇号代表一个被输出的撇号字符,例如:

CHARACTER*10 STUD

READ *,STUD

WRITE(*,100)STUD

100 FORMAT(1X,A,‘IS LI''S STUDENT.’)

END

执行程序时输入给STUD变量的值:

ZHANG SUN

则输出的结果为:

ZHANG SUN IS LI'S STUDENT.

(9)H描述符

使用H描述符也可以输出字符型常量,其一般形式为:

nH <字符串>

n是字符串中字符个数。它的作用与撇号描述符相似,例如,上面用撇号描述符的例子也可以用H描述符改成:

I=123

J=2345

WRITE(*,100)I,J

100 FORMAT(1X,2HI=,I3,2HJ=,I4)

输出结果与上面相同:

I=123J=2345

另外一个例子也可以改为:

CHARACTER*10 STUD

READ *,STUD

WRITE(*,100)STUD

100 FORMAT(1X,A,17H IS LI'S STUDENT.)

注意此时撇号不必再用两个连续的撇号来表示。输出结果仍然为:

ZHANG SUN IS LI'S STUDENT.

用H描述符时必须准确地数出字符串中字符的个数,如果数错了就要出错,如:

WRITE(*,100) AMOUNT

100 FORMAT(1X,10HAMOUNT IS,F10.2)

本来想输出的字符串是:‘AMOUNT IS’,包含9个字符,但数成了10字符,用了10H格式描述,机器编译时,将按10个字符去截取H后面的字符,结果把逗号也截取进去了,认为‘AMOUNT IS,’是要输出的字符,这样原来作为分隔符的逗号就没有了,编译就会出现语法错。因此,建议读者最好不用H描述符,而是使用撇号描述符,避免错误。

可以单独用撇号描述符或H描述符输出字符串,而不必要求WRITE语句中有相应的输出项,例如: WRITE(*,100)

100 FORMAT(1X,‘NAME SEX NUM ADDRESS GRADE’)

或 100 FORMAT(1X,33HNAME SEX NUM ADDRESS GRADE)

可以利用这种方法方便地打印一行标题或文字。

(10)X描述符

X描述符用来输出空格,其一般形式为:

nX

前面用I,F,E等描述符输出数据时,数据间没有空格,例如:

I=146

A=124.32

B=1247.32

WRITE(*,100)I,A,B

100 FORMAT(1X,I3,F6.2,E11.5)

END

执行时输出结果为:

146124.32.12473E04

可以看见,输出的数据连成了一片,难以区分。为了使各数据能分隔开,需要插入一些空格,当然可以用上面介绍的撇号描述符或H描述符实现,也可以直接用X描述符实现。将格式语句改为下面形式:100 FORMAT(1X,2X,I3,2X,F62,2X,E115)

执行时输出结果为:

146 124.32 .12473E04

(11)纵向走纸控制

FORTRAN语言规定:将输出记录中的第一个字符作为纵向走纸(换行)控制符,这个字符不再被打印输出,而是从第二个字符开始输出。因此,在前面的FORMAT语句中都给了一项“1X”,就是专门提供了一个“空格”符号作为“纵向走纸控制”,以免机器错将有效数字作为走纸符号,输出错误结果。

FORTRAN规定的走纸控制符如下:

纵向走纸控制符打印前纵向走纸控制

空格走纸一行(即正常换行)

0 走纸二行(即空一行)

1 换页(到下一页打印)

+ 不走纸(不换行)再从本行左边重新打印

其它字符走纸一行

特别提醒:如果在FORMAT语句中不提供专门的“换行”控制符,机器将把输出记录的第一个字符用作“换行”控制符,例如:

WRITE(*,100) 'good! '

100 FORMAT(A)

输出的结果为:

ood!

第一个字母被吃掉用作“换行”控制符不被输出。

当I=100,J=1234时,执行WRITE(*,100)I,J,对应的输出结果如下表:

FORMAT语句输出的结果说明

FORMAT(1X,I3,I4)1001234 1X被用作换行符号

FORMAT(‘I=’,I3,‘J=’,I4)=100J=1234 I被吃掉用作换行符号

FORMAT(I3,I4)001234 数字1被吃掉作换行符号

FORMAT(‘0’,I3,I4)1001234 字符0被用作换行符号,走纸两行后输出数据(12)重复系数

FORMAT语句中重复使用的描述符可以象数学中的公因式一样加上系数,其形式为:rIw,rFw.d,rEw.d,rGw.d,rAw,rLw等,r被称为重复系数,例如下面三个语句等价:

100 FORMAT(1X,I3,I3,F6.2,F6.2,F6.2,I3,I3,F6.2,F6.2,F6.2)

100 FORMAT(1X,2I2,3F6.2,2I3,3F6.2)

100 FORMAT(1X,2(2I2,F6.2))

重复系数r只能是正整数,不能是其它的类型或其它形式的量。

(13)斜杠描述符

斜杠描述符的作用是:结束本记录的输出并开始下一个记录的输出。例如:

WRITE(*,100)‘Begin’,‘Middle’,‘End’

WRITE(*,200)‘Begin’,‘Middle’,‘End’

WRITE(*,100)‘Begin’,‘Middle’,‘End’

100 FORMAT(1X,A6,A7,A4)

200 FORMAT(1X,A6/1X,A7//1X,A4/)

执行时第一条WRITE语句的输出为:

Begin Middle End

第二条WRITE语句的输出为:

Begin

Middle

(空一行)

End

(空一行)

共输出了5个记录;第三条WRITE语句的输出为:

Begin Middle End

从输出结果可以看见,由于在第二条FORMAT语句的右括号之前还有一个斜杠,当输出了‘End’之后,还将继续开始一个新记录,遇到右括号以后才结束输出,所以最后还有一个空行。

(14)WRITE语句和FORMAT语句的相互作用

通过前面内容的介绍,可以看见输出记录的内容是由WRITE语句和FORMAT语句共同决定的。WRITE语句提供输出的数据,FORMAT语句提供字符串、空格以及数据输出的格式。因此,在输出时要求WRITE语句和FORMAT语句配合使用。当WRITE语句中提供的“输出项”个数和FORMAT语句中提供的对应“格式描述符”个数不一致时,应该按下面规则输出。

①如果“输出项”的个数少于“格式描述符”个数,则多余的格式描述符作废。

例如:已知I=123,J=5678

WRITE(*,100)I,J

100 FORMAT(1X,‘I=’,I4,1X,‘J=’,I5,F4.1)

执行时输出结果为:I=□123□J=□5678,格式描述符F4.1由于没有输出项与之对应,故作废。

②如果“输出项”的个数多于“格式描述符”个数,即WRITE语句中还有数据没有对应的格式描述,

则重新使用FORMAT语句,但是要产生一个新记录,即换行输出。

例如:已知I=123,J=5678

WRITE(*,100)I,J

100 FORMAT(1X,‘JieGuo=’,I6)

执行时输出结果为:

JieGuo=□□□123

JieGuo=□□5678

重新使用FORMAT语句时应该注意格式描述符和输出数据之间一定要匹配,如果将上面例子中的J改为A,则输出就会出错,因为重新使用FORMAT语句时,A变量需要的是F、E或G描述符,而语句中提供的是I描述符。

③如果在格式描述中包含有重复使用的描述符组,则重新使用FORMAT语句时,只有最右边的一个“描述符组”(包括其重复系数)和它右面的描述符被重复使用。例如:

已知 I1=123,I2=234,I3=4567,I4=567,I5=12345,I6=5678,I7=89098,I8=3456,I9=89000,I10=34567。

WRITE(*,100)I1,I2,I3,I4,I5,I6,I7,I8,I9,I10

100 FORMAT(1X,2(I3,2X),2(I4,2X),2(I5,2X),I6)

执行时输出结果为:

123□□234□□4567□□□567□□12345□□□5678□□□89098

3456□□89000□□□34567

由于重新使用了FORMAT语句,结果输出为两个记录。第二个记录使用的格式描述符为“2(I5,2X),I6”,其中的第一个数据本应占5位(□3456),但第一个字符(空格)被吃掉作为换行控制符,只输出4位。

④如果WRITE语句中有输出项,而FORMAT语句中无对应的“格式描述符”,则输出永不停止。

例如: WRITE(*,100)I

100 FORMAT(1X,‘I=’,)

执行时将反复输出记录,永不停止:

I=

I=

I=

⑤可以有“空格式说明”,如FORMAT(),用来输出空行,但此时要求WRITE语句中不能有输出数据。

WRITE(*,100)

100 FORMAT()

⑥ FORMAT语句出现的H、X、撇号等描述符,在WRITE语句中不能有对应的输出项。如:

WRITE(*,100)I

100 FORMAT(1X,‘I=’,I6)

输出时,变量I使用I6描述符,1X和‘I=’都在记录中输出(1X被用作换行控制符)。

⑦ FORMAT语句与WRITE语句可以相邻,也可以放在程序中任何地方(只要在程序标识语句之后,END 语句之前)。习惯上将程序单元中的全部FORMAT语句集中放在最前或最后,并给FORMAT语句以较大的标号(一般执行语句给小标号,FORMAT语句给大标号),使程序结构更清晰。

3.2.3 格式输入

1)格式输入的一般形式

格式输入是指:按指定的格式输入数据。需要用FORMAT语句与READ语句配合实现。

格式输入的一般形式:

READ(*,标号)输入变量表

标号 FORMAT(格式说明)

格式说明:包含I、F、E、A、L、D等描述符。另外,格式输入的FORMAT语句中不要考虑“换行控制符”。同时,格式输入数据时不能加任何分隔符。

2)整数的输入

整数输入用Iw描述符,w规定输入数据的位数,如:

READ(*,100)I,J

100 FORMAT(I4,I5)

执行时输入的数据为:

□□23□6789

则变量获得的数据是:

I=□□23,J=□6789

机器读数是按宽度截取。在规定宽度内,空格被看作0,因此上例输入数据如果是:23□□6789□,则I=2300,J=67890。数据的符号也在宽度内。

下面是整数输入的实例:

输入的数据描述符输入后变量的值说明

-234 I4 -234

+□04 I4 4

-4□4□I5 -4040 空格按0处理

-12345 I5 -1234 只取5列,多余无效3)实数、复数、双精度数的输入

(1)用F描述符输入实数,输入数据时可以不带小数点,也可以带小数点

READ(*,100)A,B

100 FORMAT(F6.2,F8.3)

执行时如果输入数据为(不带小数点):12345□6789056,机器将按宽度截取6位赋给A,截取8位赋给B,同时按d指定的位数加上小数点,所以A,B最后获得的值为:

A=123.45 B=6789.056

执行时如果输入数据为(自带小数点):□123.4□6789.056,机器将按宽度截取6位赋给A,截取8位赋给B,由于截取的数据已经自带小数点,则以截取的数据为准(自带小数点优先,F6.2中的小数位数2就不起作用),所以,A,B最后获得的值为:

A=123.4 B=6789.05

输入时自带小数点比较直观,容易检查,不易出错,但必须保证数据在指定宽度内,否则可能导致输入数据错误。

(2)输入实数时可以任选F、E、G描述符,三者作用相同。输入的数据可以是小数形式或指数形式。如果用指数形式输入数据而其数字部分不带小数点,则按照Fw.d(或Ew.d)中的d对其加上小数点。

下面是实数输入的例子:

描述符输入的数据输入后变量的值说明

F8.2 □□135798 1359.98

F8.2 137.2356 137.2356 自带小数点优先

F10.2 □256.7E+02 256.7×102E和F描述符作用相同

F10.2 237567E+03 2375.67×103数字部分无小数点,按F10.2加上小数点

E8.3 □30□7067 3007.067 E和F描述符作用相同

G6.1 7654324 76543.2 只截取6列

3)复数输入时按两个实数输入

如果已经定义C为复型变量,对下面语句

READ(*,100)C

100 FORMAT(2F6.2)

执行时输入两个实数:123.45678.89,则C的值为(123.45,678.89)。注意:格式输入时,不能带括号和表示虚部的字母“i”。

4)双精度数的输入

可以用D、F、E、G描述符,输入方式与实型数据相同。

5)逻辑型数据的输入

执行时输入的数据可以是逻辑值.TRUE.或.FALSE.,也可以是以T或F字母开头的任何字符串。

下面是逻辑数据输入的例子

输入字符描述符变量得到的值

T□L2 .TRUE.

□□F L3 .FALSE.

.FAL. L4 .FALSE.

.FALSE. L7 .FALSE.

.T□F□F L5 .TRUE.

6)字符型数据的输入

(1)用Aw描述符

输入字符时不要加撇号,机器仍然按照w的宽度截取字符赋给变量。例如:

CHARACTER STR1*5,STR2*4,STR3*3

READ(*,100)STR1,STR2,STR3

100 FORMAT(A5,A4,A3)

执行时输入字符为:CHINAWANGNEW

则几个字符变量的值为:STR1=‘CHINA’,STR2=‘WANG’,STR3=‘NEW’。

上述示例中字符变量的长度L和Aw中的w是相同的(L=w),如果它们不同(L≠w),机器又怎样处理呢?FORTRAN语言规定:

①如果w<L,则在w个字符后面补(L-w)个空格,然后赋给变量。

②如果w>L,则只取最右边的L个字符送给变量(注意:不是最左边的L个字符,这是和表控输入时不同的,表控输入时是取最左边的L个字符)。

例如,有语句:

CHARACTER *4,STR1,STR2,STR3

WRITE(*,100)STR1,STR2,STR3

100 FORMAT(1X,A5,A4,A3)

即现在定义的L=4,使用FORMAT语句提供的格式描述符时,对STR1来讲,w>L,对STR2来讲,w=L,对STR3来讲,w<L。如果输入以下数据:

CHINAWANGNEW

则STR1=‘HINA’,STR2=‘WANG’,STR3=‘NEW□’。

(2)用A描述符

用A描述符时,由于未指定w,则按字符变量定义时的长度截取字符。

例如,有语句:

CHARACTER STR1*5,STR2*4,STR3*3

READ(*,100)STR1,STR2,STR3

100 FORMAT(3A)

如果输入数据为:CHINAWANGNEW

则STR1=‘CHINA’,STR2=‘WANG’,STR3=‘NEW’。

7)对格式输入的说明

(1)如果FORMAT语句中出现了X描述符,则表示在读输入记录时“跳过若干位”。

(2)如果格式描述符的个数少于READ语句中变量的个数,即格式描述符不够,则重复使用该格式说明,但要求换行输入(即开始一个新记录)。

READ(*,100)I,J,K

100 FORMAT(I3)

输入的数据应该为(三个记录):

123

456

789

(3)斜杠描述符表示本记录输入结束,并接着输入一个空记录。

READ(*,100)I,J,K

100 FORMAT(I3)

执行时输入的数据应该为:

123

空记录

456

3.2.4 自带格式的输入和输出

FORTRAN语言允许将FORMAT的格式描述放在WRITE、PRINT和READ语句中,其功能与分开书写相同,即:

WRITE(输出设备,‘(格式说明)’)输出项表

PRINT ‘(格式说明)’,输出项表

READ(输入设备,‘(格式说明)’)输入变量表

READ‘(格式说明)’,输入变量表

因此,下列语句格式是合法的:

READ(*,‘(I3,F4.1)’)I,A

READ‘(I3,F4.1)’,I,A

WRITE(*,‘(I3,F4.1)’)I,A

PRINT‘(I3,F4.1)’,I,A

本章介绍的格式输入输出,规则繁多,一时是记不住的,也不必死记硬背。只需要理解和记住最基本的内容即可。有关各规定可以随时查阅书本和资料,或查询FORTRAN系统所带的帮助信息,并通过上机逐步掌握其用法。

3.3 其他基本语句

3.3.1 END语句

FORTRAN中END语句的作用有二个:一个是结束本程序单元的运行,另一个是作为程序单元的结束标记。END语句应该出现在程序单元中的最后一行,一个程序单元中只能有一个END语句。

在主程序中,END语句的功能是使程序停止运行,控制回到操作系统。在子程序中,END语句的功能一方面是结束子程序的标记,另一方面是使流程返回调用程序(接着执行调用程序中的其他语句)。

3.3.2 PAUSE语句

PAUSE是暂停语句,其格式是:PAUSE[n],n是一个不超过5位的无符号整数或字符串,并且是可选项,PAUSE语句是执行语句,功能是使程序“暂时停止执行”,但不是“结束运行”,系统只是把程序的执行暂时“挂起来”,让用户做其他工作。如果选择了n,则执行该语句时将在屏幕上输出n,方便用户辨别

程序流程。例如有语句

PAUSE ‘暂停1!’

当执行到该语句时将输出信息“暂停1”,然后暂停。

在程序设计中,有时有意在程序中加几个PAUSE语句,即设几个“断点”,把程序分成几段,调试程序时先对第一段进行调试,待第一段通过后将第一个暂停语句删除,然后再对从开始到第二个暂停语句之间的程序段进行调试,这样一段一段地调试检查,再将暂停语句一个一个地删除。

暂停后恢复程序运行(从断点接着往下运行)的方法和命令在各个系统上是不一样的,但大多数是输入“回车”键就可恢复运行。

3.3.3 STOP 语句

STOP是停止运行语句,其格式是:STOP [n],其中可选项n的意义与PAUSE中相同。STOP语句是可执行语句,功能是停止运行,一个程序单元中可以有多个STOP语句,执行到任何一个STOP语句都将结束程序的运行。在子程序中如果有STOP语句也将结束整个程序的运行,而不是返回主程序。

3.3.4 PARAMETER语句

在程序中常要多次用到某些常数,例如π=3.1415926,如果每次用到π时都重复写3.1415926,是很不方便的,并且也容易写错,FORTRAN语言中允许使用符号名字来代替一个常量,称为符号常量,经过定义的符号常量在程序中就可以代表相应的常量。符号常量用PARAMETER语句来定义。

PARAMETR语句格式:

PARAMETER (符号常量1=常数1,符号常量2=常数2,…)

符号常量:顾名思义即用符号表示一个常量值,其命名方式与变量名相同。

PARAMETRE语句功能:定义符号常量的值。

说明:

(1)PARAMETER语句是非执行语句,其功能是在程序编译时完成的,当定义了一个符号常量后,就不能以任何方式改变它的值。例如,下列程序段是错误的:

PARAMETER(PI=3.1415926)

…..

READ *,R

S=PI*R**2

L=2.0*PI*R

PRINT *,S,L

PI=1.5(或READ *,PI)(改变PI的值是错误的)

(2)由于PARAMETER是说明性的非执行语句,它应该写在所有执行语句之前。

(3)符号常量也有类型,也可以用类型说明语句、IMPLICIT语句和I-N规则确定其类型。例如:REAL PI

PARAMETER(PI=3.1415926)

(4)符号常量可以是数值型、逻辑型、字符型的。

(5)符号常量不能作为语句标号,也不能出现在FORMAT语句中代替常数,除此之外,凡出现常量的地方均可以用符号常量代替。

使用符号常量的好处是:如果需要改变程序中在多处出现的某个常数时,只需要改变PARAMETER语句中符号常量的值即可,而不必一一在程序中修改这个常数。

3.3.5 语句函数的使用

1)语句函数的意义

在本书的第二章内容中,曾经介绍了内部函数,如SIN,SQRT等,实际上这些内部函数都是FORTRAN 语言编译程序提供的一些小程序,用户随时可以调用这些程序,无疑,这对用户是很方便的。但是,用户

除了需要内部函数以外,还常常会遇到程序中反复多次用到同一个表达式的运算,FORTRAN语言允许用户自己定义函数,在程序中需要的地方同样可以调用。

例如,为了计算表达式X2+X+1,当X=1,2.3,3.6,6.5时的值,可以用下面程序实现:X=1

PRINT *,X**2+X+1

X=2.3

PRINT *,X**2+X+1

X=3.6

PRINT *,X**2+X+1

X=6.5

PRINT *,X**2+X+1

END

本来计算式子是一样的,由于X的值不同,必须反复地使用输出语句完成计算和输出。如果将表达式定义成一个函数,则程序可以修改如下:

F(X)= X**2+X+1

PRINT *,F(1),F(2.3),F(3.6),F(6.5)

END

程序中的第一行就是用户自己定义的函数,称为“语句函数”。

2)语句函数的定义

格式:f(x1,x2,…,x n)= e

功能:定义一个形式为e的语句函数。

说明:

(1)语句函数名f

f代表一个语句函数的名字,它的命名方式与变量名相同。其类型可以预先用语句定义或遵照I—N 规则。语句函数名不能与本程序单元中的任何其它名字相同。

(2)虚拟参数x1,x2,…,x n

括号中的x1,x2,…,x n代表语句函数的自变量,也叫虚拟参数。

虚拟参量的类型可以预先定义也可以遵照I-N规则,虚参在形式上与普通变量名相同,多个虚参要用逗号(,)分隔且不能同名,它们是代表自变量的符号,用来在形式上表示右边表达式中自变量的个数、类型以及在表达式中的作用。它们没有具体的值,因此,下面的三个语句函数定义语句意义是相同的。

F(X)= X*X+X+1

F(Y)=Y*Y+Y+1

F(R)=R*R+R+1

上面几个语句函数定义语句都定义了一个F函数,类型为实型,都包含一个自变量,自变量的类型都为实型,自变量在语句函数中都完成“自变量的平方+自变量+1”的运算。所以,虚参变量的名字与程序中的其它名字可以相同,此时,虚参变量的类型则应该为程序中同名变量的类型。

(3)语句函数表达式e

语句函数定义语句中,等号右边的e是语句函数f(x1,x2,…,x n)的具体形式,它应该是一个算术表达式、逻辑表达式或字符串表达式。在这个表达式中除了必须包含所有的虚参外,还可以包含常量、变量、内部函数、外部函数和已经定义的语句函数。

3)语句函数的调用

语句函数一旦被定义后,就可以在本程序单元中被调用。调用的形式和调用内部函数相同,即:

语句函数名(实参)

实参可以是与虚参类型一致的常量、变量或表达式,并且实参必须要有确定的值,函数按照代入的实参的值,根据定义的表达式将计算出函数值,因此,与内部函数一样,语句函数的调用结果是一个确定的

值。

例如,有程序如下: FNA (B )=1+B

PRINT*,FUN (FUN (FUN (1.0)) END

程序执行的结果是B=1.0时,嵌套调用语句函数FUN 的值4.0。

如果语句函数定义时就没有虚参,则调用时也不给实参。例如: CONST ( )=SQRT (2.0)+SQRT (3.0) PRINT *,CONST ( ) END 程序执行时输出0.30.2+的值。

4)定义语句函数时应该注意的问题

① 当定义的运算是在一个表达式中可以完成时才使用语句函数。

② 语句函数定义语句是非执行语句。它应该放在所有可执行语句之前和所有的说明语句之后。 ③ 语句函数只能在本程序单元中被使用。

④ 语句函数定义语句中的虚参只能是变量名,不能是其它形式的量。

⑤ 语句函数定义语句中的表达式中可以包含已经定义过的语句函数、外部函数和内部函数。 ⑥ 语句函数的调用结果是通过表达式得到的,因此,函数名和函数值之间必须满足赋值规则。 下列语句函数定义是正确的:

SUM (A ,B ,C )=A+B+C

AVER (A ,B ,C )=SUM (A ,B ,C )/3.0 IR (ID )=MOD (ID ,3) SS (I ,X ,Y )=A (I )+X*Y 下列语句函数定义是错误的:

BUL (I ,J ,K )=3*I*J (虚参K 没有出现在表达式中) EST (A ,A )SQRT (A*4.0)+A (出现了两个同名的虚参)

SF (B )=1.5—SF (B ) (表达式中使用了语句函数自己)

3.4 顺序结构程序设计

通过前面几节内容介绍,可以利用所学过的语句编写简单的FORTRAN 程序了。设计顺序结构时只要按照问题求解的过程,按顺序将每一步的操作描述出来。下面介绍几个简单的例子。

【例3.1】 鸡兔同笼,已知鸡兔总头数为H (HEADS ),总脚数为F (FEET ),求鸡兔各有多少只? 结合此问题讨论程序设计的基本步骤:

(1)建立数学模型,即找出处理此问题的数学方法,为此可以列出有关方程式: 设鸡为X 只,兔为Y 只,可以得到两个二元一次联立方程

X+Y=H 2X+4Y=F

(2)解此联立方程,找出求解X 和Y 的具体公式

Y=

22H F - , X=2

4F

H - 以上这两步是属于数学上的方法问题,在此基础上才能编写程序,将方程求解的过程一步一步地描述

出来。

(3)根据流程图写出程序。

PRINT *,‘Enter number of heads:'

READ *,H

PRINT *,‘Enter number of feet:'

READ *,F

X=(4*H-F)/2

Y=(F-2*H)/2

WRITE(*,100) ‘heads=',H,‘feet=',F

WRITE(*,100) ‘cock=',X,‘rabbit=',Y

100 FORMAT(1X,2(A,F6.1,2X))

END

运行情况如下(有下划线处是用户输入的):

①Enter number of heads:

16↙

Enter number of feet:

40↙

heads= 16.0 feet= 40.0

cock= 12.0 rabbit= 4.0

②Enter number of heads:

6↙

enter number of feet:

16↙

heads= 6.0 feet= 16.0

cock= 4.0 rabbit= 2.0

(6)将运行结果代入原方程检验结果。

第一次运算结果: 12*2+4*4=24+16=40(脚)

12+4=16 (头)

第二次运算结果: 4*2+2*4=8+8=16 (脚)

4+2+6 (头)

两次结果均正确,可以确认程序的正确性。

【例3.2】我国人口在2000年统计为12.9亿,如果年增长率为0.05%,求公元2008年末的人口数。

分析:如果设人口初值为P0,年增长率为R,P1为n年后人口,则计算公式为:

P1=P0(1+R)n

根据计算公式和计算过程,画出流程图如图3.3所示。

图3.3 例3.2的算法流程图

根据算法流程图写出程序如下:

R=0.005

P0=12.3

N=2008-2000

P1=P0*(1+R)**N

PRINT *,‘THE POPULATION OF 2008 IS ’,P1

END

运行结果如下:

THE POPULATION OF 2008 IS 10.719280

如果将程序输入方式改变一下,就可以用来计算任一年后任一增长率情况下的人口:

PRINT *,‘INPUT R,YEAR=’

READ *,R,YEAR

P0=12.3

N=YEAR-2000

P1=P0*(1+R)**N

PRINT *,‘THE POPULATION OF 2008 IS’,P1

END

运行程序时输入任一组r和year的值就可以得到相应的p1值。运行情况如下:(下划线处是用户输入的数据)INPUT R,YEAR=

0.05,2010↙

THE POPULATION OF 2008 IS 20.035400

INPUT R,YEAR=

0.15,2010↙

THE POPULATION OF 2008 IS 49.760360

相关主题
文本预览
相关文档 最新文档