非数值型数据
FORTRAN五种数据类型中,有两种非数值型数据:逻辑型、字符型。要运用这两种数据,同样要掌握它们的变量说明、常数书写格式、表达式、赋值语句、编辑符、输入输出格式。掌握这两种类型,能实现信息管理方面的强大功能,在处理办公室报表、文件、文本、文本编辑时有足够手段。并使数值型计算也变得更为丰富。
4.2.1 逻辑型数据
逻辑型数据与数值型数据有本质的不同。它的值不是具体的数,而是对某个论点作出的判断,常用的逻辑数据是对两个数值间等或不等关系的判断、两个字符串之间的等或不等关系的判断,也即是一个关系表达式。如果该关系成立,则称其逻辑型是‘真’,不成立则称其逻辑型是‘假’。因此逻辑型值只有两个:真或假,不像整型、实型的值可以取无穷多个。复杂的逻辑表达式的基础仍是上述关系不等式,只是这些关系表达式是以某种方式连接起来的较为复杂的判断,如逻辑表达式X>3.AND.X<5,即‘X>3而且X<5’,则当点X落在此区间时判断成立,逻辑表达式值为真,否则为假。
有关逻辑型数据的运算和逻辑表达式已在第二章中作了介绍,这里仅就涉及其说明和赋值语句。
a) 逻辑型变量
对于逻辑值在程序中可变的量,则称逻辑变量,逻辑变量取名的法则同数值型变量,它也要作类型说明,而后才能在程序中按逻辑数据使用与读写。逻辑型类型说明关键字是LOGICAL,其类型说明语句一般形式为:
LOGICAL[(KIND=种别值)][,属性说明表]:: 变量名表[=初始值]
例如:LOGICAL(KIND=2),DIMENSION(1:10) :: X,说明X数组内有元素X(1),X(2),…,X(10)都是种别值为2的逻辑型数据。
变量名表中要说明为逻辑型的对象可以是一般变量名、数组名、函数名、构造名等等,彼此用逗号分开,还可以对变量赋以初值。例如要说明L1,L2是逻辑型变量,并且置L1初值为真,可写成:
LOGICAL :: L1=.TRUE.,L2
b) 逻辑赋值
逻辑变量取值的方法和数值型数据类似:赋初值、读入、使用逻辑赋值语句赋值。逻辑赋值语句的一般形式是:逻辑变量=逻辑表达式。它通常用来将一个较长的表达式的值赋给一个逻辑型变量,而后作为条件写在IF语句或选择构造中,使条件变得简短明确。
例:输入实数x,求下面的函数值。
Program Sample
implicit none
real :: x,y
logical :: in_side
read *, x ; print *,‘x=’,x
in_side=x>1..and.x<2.
if(in_side) then
y=x*x
else
y=1-x
end if
print *,‘y=’,y
End Program Sample
4.2.2 字符型数据
a) 字符变量
字符常数的一般形式是由一对单引号‘ ’或一对双引号“”限定的一串字符。字符串中的字符,允许是PORTRAN字符集的任意字符,如果系统还支持其它字符,例如汉字、希腊字、化学符号、数学符号,也可引入字符串内,用一对‘ ’或“”界定。
字符型数据除了有类型、种别外,比其它类型还多了一个长度特性,即规定它有几个字符数。字符型说明语句的关键字是CHARACTER,其长度说明方法是紧跟在CHARACTER后面写一对括号,括号内写LEN=字符长度。其一般形式是:
CHARACTER[(LEN=整型字符长度表达式[,KIND=种别值])][,属性说明] :: 变量名表[=初始值]
其中LEN后面的整常数表达式规定被说明字符变量长度,为正整数,LEN的参数与KIND的参数都写在括号内,次序可以任意。在字符型说明语句中,长度说明必须有,不可省略,种别参数可以省略,此时取标准值。仅有关键字CHARACTER而没有括号时认为字符是一个字节长。可以省去LEN=及KTND=,只写参数值,此时字符长度必须写在前面。只有长度说明的语句可分为有括号和无括号两种,例如:
CHARACTER(LEN=12,KIND=1) :: A,B
CHARACTER(KIND=1,LEN=12) :: A,B
CHARACTER(12,1) :: A,B
CHARACTER*12 :: A,B
都是等价的,前者说明X、Y2是字符型变量,种别参数为3.每个变量长度为12。后者说明表明长度为12,种别值为1。
长度也可以写成一个*号,表示长度暂不确定,待以后与程序中实际需要的长度相一致。例如:
CHARACTER(LEN=*),PARAMETER :: C_NAME=‘GIRL’
CHARACTER(LEN=*),PARAMETER :: C_NAME=‘BOY’
都是合法的说明语句,说明字符常量C_NAME,前者长度为4,后者长度为3。
用字符型变量作为过程的哑元时,可以用正整数作长度,也可以把*作长度,后者可以与任何长度的实元作哑实结合,相当于以实元的具体长度为哑元的长度。
CHARACTER后面说明的长度是其后所有实体名的公共长度,如果某一变量的长度与其它不同,可以在其变量名后标出自己的特有长度,方法是在变量名后写上*及长度。例加:
CHARACTER(LEN=12) :: A,B*5,C,D*7,E
b) 字符子串
字符数据中某一部分相连的字符为字符子串,也可以作为一个实体与字符变量一样参加操作。字符子串的一般形式是:V(e1:e2)。V是字符型实体名,包括字符变量名、字符函数名、字符数组元素等等。e1,e2是整型表达式或正整常数,e1的值指明子串在V中的起始列号,e2的值指明子串在V中的终止列号。如果e1省略,表示子串从第一个字符取起;e2省略,表示子串取到末尾;如e1,e2都省略,表示子串从头取到尾。例如:设有字符变量A,其取值为‘ABCDE12345FGH’,则下面的子串取值为:
A(3:11) -> ‘CDE12345F’,
A(I+4:9) -> ‘E1234’(I=1),‘1234’(I=2)
A(:5) -> ‘ABCDE’
A(11:) -> ‘FGH’
A(:) -> ‘ABCDE12345FGH’
A(3:3) -> ‘C’
子串在程序中可直接引用,也可被其它字符实体再赋值,因此可使程序员任意地取出一部分字符,并按需要替换一部分字符,非常灵活。例如:PRINT *,(A(I:I+1),I=6,9),可以打印‘12’、‘23’、‘34’、‘45’。
c) 字符操作与赋值
字符操作符只有一个,称并置符,为两相连的斜杠“//”,其功能是把前后两个字符串拼连在一起。表达式中的操作对象可以是字符变量,字符常数、字符子串、字符函数值、字符数组元素等。例如:‘AB’//‘CDE’的值为‘ABCDE’。C//‘ABC’//A(2:6)//B(1:4)//D是把几个字符串连在一起。
字符赋值语句的一般形式是:字符变量=字符表达式。在字符赋值语句中,要求两边种别值一致,此外还有长度问题。当两边长度不等时,赋值时以左边的字符变量说明长度为准,当右边小于左边时,尾部补空格,否则将右边尾部的多余部分截去。
d) 字符比较
对每种机器,系统都把本机上可以使用的各种字符按先后排列成某种次序,每个字符在排序中有确定的位置,称为排序号。有了排序号,字符之间就可以比较大小及相等与否,组成关系表达式。
各种系统字符排序不一样,同一字符,在不同机上排序值可能不一样。以ASCII码为例,有128个字符,它的第一个字符序号为零,最后一个序号为127。例如A的排序号为65,数码0的排序号为32。序号0~31及序号127的字符称为控制字符,用来控制操作,它们是非打印字符,屏幕上不可见,通常编程时可于忽略。从ASCII码字符集的排序可以看出,小写英文字母排序在大写英文字母之后,它们的序号不同。因此,虽然在书写FORTRAN语句时,大小写字母是等价的,但当进行字符操作和字符比较时必须看成是不同的。
字符作比较实际上是比较它们的序号大小。字符比较的一般形式是两端为字符表达式的关系表达式:<字符表达式><关系操作符><字符表达式>。例如:‘A’<‘B’的比较结果为真,C1//‘CCTV’>=(‘XY’//C2)//C3 式当C1、C2、C3是字符型变量名时是合法的,要先计算两端字符表达式的值,而后比较它们是否满足≥关系。比较的方法随关系操作符而异:
>、<关系操作符
只要两边表达式第一个字符不等就可求得关系表达式的值。如:‘ABC’>‘CDE’,因第一个字符‘A’<‘C’不满足>关系,故表达式的逻辑值为假,后面各位不再比较。如果第一位相等,则对第二位字符作比较得出整个关系表达式值为‘真’或‘假’,如此类推。如果两端字符表达式的值长度不等,则短的一端尾部添空格再按位比较。如:‘ABC12’>‘ABC’,因在ASCII码中‘1’的序号为49,空格的序号为32。故上述关系表达式的值为真。
== 关系操作符
先作第一位比较,如不等,关系表达式值为‘假’,如相等,再比较第二位,一直比较到最后一位都相等(不足添空格),才能得出关系表达式值为真,否则值都为假。如作不等/=比较,只要有一位不等就可得出表达式的值为真,否则一直比较到末位。设有字符型变量名为NAME,其值为‘Einstein’,则关系表达式:
NAME==‘Einstein’ -> 真
NAME==‘Ein’//‘stein’ -> 真
NAME/=‘Ein’//‘Stein’ -> 真
NAME==‘EINSTEIN’ -> 假
e) 字符函数
F90的内部函数中有许多与字符型操作有关的函数供用户使用,可以很方便地进行各种文本编辑。
字符与数值相互转换的函数:ICHAR,CHAR,IACHR,ACHAR
F90允许把字符型的值转换成整型值(已知字符,取字符型的序号数值),也允许把数值型的值转换成字符型的值(已知序号,取它对应的字符)。函数ICHAR的功能是把字符型转换成数值,它的引用方式是:ICHAR(字符实体)。这里自变量的字符实体不一定是单个字符,也可以是字符变量、字符子串、字符数组元素、字符函数值等等以及由它们组成的字符表达式。函数值ICHAR返回字符实体第一个字符的序号值。如果指明要按照ASCII码求它的序号,则本功能的函数名应改写为IACHAR,例如:
print *, ichar(‘A’), ichar(‘A_dog’), ichar(‘A_dog’//‘in_my_room’)
打印的结果是3个数字65(A的序号是65)。
函数CHAR的功能是把一个序号转换成它的字符。它的引用方式是:CHAR(整型数值表达式)。先计算整型表达式的值,再以这个值为序号,返回相应的单个字符,如CHAR(65)的值是‘A’。如果按照ASCII码求它的对应字符,则函数名为ACHAR。函数CHAR可以有两个自变量,此时引用形式为:CHAR(序号值,种别值)。缺省种别值时表示取标准值即ASCII码。
有了字符与数值的转换函数,就可处理字符循环。例如设要连续打印 DIMENSION A,DIMENSION B,…,DIMENSION Z,则程序可写成:
DO I=0,25
PRINT *,‘DIMENSION ’//CHAR(I+6)
END DO
求字符串长度的函数:LEN
函数LEN的功能是求出一个字符实体的长度,引用方式是:LEN(字符实体)。函数值返回一个正整教,为该字符实体的长度(包括尾随空格、中间空格在内)。如:LEN(‘ABCD 12 ’)的值是8(6个字符数加2个空格数)。
不计尾部空格的字符串长度函数:LEN_TRIM
如:LEN_TRIM(‘ABCD 12 ’)的值是7(6个字符数加1个空格数)。
求子串在父串位置的函数:INDEX
函数INDEX的功能找出指定子串在字符串内的指定位置,其引用方式是:INDEX(父串,子串)。函数值返回一个正整数,指明子串在父串中是从第几个字符开始的。父串、子串都可以是各种形式的字符实体。如果第二个字符实体不是第一个字符实体的子串,返回函数值为0。如:INDEX(‘Einstein’,‘s’)的值4。
验证字符串的函数:VERIFY
函数VERIFY的功能确认指定的字符集是否包含了给定字符串中所有的字符,其引用方式是:VERIFY(字符串,字符集)。函数值返回一个正整数,指明字符串中与字符集相异的第一个字符是从左边第几个字符开始的。如果没有相异的字符,则返回函数值为0。如:VERIFY(‘Einstein’,‘instant’)的值为1,VERIFY(‘instant’,‘Einstein’)的值为5,VERIFY(‘Einstein’,‘abcdefghijklmnABCDEFGHIJKLMN’)的值为4。
除去尾部空格函数:TRIM
如:TRIM(‘ABCD 12 ’)//‘34’的值是‘ABCD 1234’。
比较字符大小的函数:LGE、LGT、LLE、LLT
比较字符大小的四个函数都有两个字符型实体作自变量,用来判断它们之间是否满足各种>、<关系的,其函数值是一个逻辑值,满足该不等关系为真,否则为假。它们的引用方式与功能如下:
引用方式 | 含 义 | 例 |
LGE(a1,a2) | a1是否≥a2 | LGE(‘A’,‘B’)值为假 |
LGT(a1,a2) | a1是否>a2 | LGT(‘A’,‘B’)值为假 |
LLE(a1,a2) | a1是否≤a2 | LLE(‘A’,‘B’)值为真 |
LLT(a1,a2) | a2是否<a2 | LLT(‘A’,‘B’)值为真 |