本节详细介绍了 Fortran 库中属于 Sun Studio Fortran 95 软件但不是 Fortran 95 标准内例程和函数的子例程和函数。
下面以表的形式概要说明调用接口
数据声明 带参数的调用原型概要说明 |
|||
参数 1 名称 |
数据类型 |
输入/输出 |
说明 |
参数 2 名称 |
数据类型 |
输入/输出 |
说明 |
返回值 |
数据类型 |
输出 |
说明 |
可以在 Sun Studio 手册页的第 3f 节中找到其他手册页。例如,执行 man -s 3f 命令将显示 access() 函数的手册页。在本手册中,手册页参考均表示为 manpagename(section)。例如,有关 access() 函数的手册页参考表示为 access(3f),有关 Fortran 95 编译器的手册页参考表示为 f95(1)。
该子例程的调用方式如下所示:
call abort |
abort 刷新 I/O 缓冲区,然后中止进程,可能会在当前目录中生成核心转储文件内存转储。有关限制或抑制核心转储的信息,请参见 limit(1)。
该函数的调用方式如下所示:
INTEGER*4 access status = access ( name, mode ) |
|||
name |
字符 |
输入 |
文件名 |
mode |
字符 |
输入 |
权限 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK;status>0:错误代码 |
access 确定是否可以使用 mode 指定的权限访问文件 name。如果可以使用 mode 指定的权限成功访问文件,access 将返回零。另请参见 gerror(3F),了解有关错误代码的信息。
可以将 mode 设置为 r、w 和 x 中的一个或多个(以任何顺序或任意组合),也可以为空白,其中 r、w 和 x 的含义如下:
’r’ |
测试是否有读取权限 |
’w’ |
测试是否有写入权限 |
’x’ |
测试是否有执行权限 |
’ ’ |
测试文件是否存在 |
示例 1:测试是否有读/写权限:
INTEGER*4 access, status status = access ( ’taccess.data’, ’rw’ ) if ( status .eq. 0 ) write(*,*) "ok" if ( status .ne. 0 ) write(*,*) ’cannot read/write’, status |
示例 2:测试文件是否存在:
INTEGER*4 access, status status = access ( ’taccess.data’, ’ ’ ) ! blank mode if ( status .eq. 0 ) write(*,*) "file exists" if ( status .ne. 0 ) write(*,*) ’no such file’, status |
该函数的调用方式如下所示:
INTEGER*4 alarm n = alarm ( time, sbrtn ) |
|||
time |
INTEGER*4 |
输入 |
等待的秒数(0=不调用) |
sbrtn |
例程名称 |
输入 |
要执行的子程序必须列在外部语句中 |
返回值 |
INTEGER*4 |
输出 |
最后一次报警的剩余时间 |
示例:alarm-等待 9 秒后调用 sbrtn:
integer*4 alarm, time / 1 / common / alarmcom / i external sbrtn i = 9 write(*,*) i nseconds = alarm ( time, sbrtn ) do n = 1,100000 ! Wait until alarm activates sbrtn. r = n ! (any calculations that take enough time) x=sqrt(r) end do write(*,*) i end subroutine sbrtn common / alarmcom / i i = 3 ! Do no I/O in this routine. return end |
另请参见:alarm(3C)、sleep(3F) 和 signal(3F)。注意以下限制条件:
子例程无法将自己的名称传递给 alarm。
alarm 例程生成的信号可能会妨碍 I/O 操作。因此被调用的子例程 sbrtn 本身不得执行任何 I/O 操作。
从并行或多线程 Fortran 程序中调用 alarm() 可能会产生不可预料的结果。
定义如下:
MIL-STD-1753 的另一可换用外部版本为:
iand( m, n ) |
对其参数进行按位与运算。 |
ior( m, n ) |
对其参数进行按位或运算。 |
ieor( m, n ) |
对其参数进行按位异或运算。 |
ishft( m, k ) |
结尾不循环进位的逻辑移位(如果 k>0 则为左移,如果 k<0 则为右移)。 |
ishftc( m, k, ic ) |
循环移位:m 最右边的 ic 位循环左移 k 个位置。 |
ibits( m, i, len ) |
提取位:从 m 中的 i 位开始提取 len 个位。 |
ibset( m, i ) |
设置位:返回值等于字 m,且位数 i 设置为 1。 |
ibclr( m, i ) |
清除位:返回值等于字 m,且位数 i 设置为 0。 |
btest( m, i ) |
测试 m 中的 i 位;如果该位是 1,则返回 LOGICAL .true.,如果该位是 0,则返回 .false.。 |
有关对位字段进行操作的其他函数,另请参见1.4.36 mvbits:移动位字段以及第 2 章和第 3 章。
对于内函数:
x = and( word1, word2 ) |
x = or( word1, word2 ) |
x = xor( word1, word2 ) |
x = not( word ) |
x = rshift( word, nbits ) |
x = lshift( word, nbits ) |
word、word1、word2 和 nbits 都是整型输入参数。这些函数是编译器内联扩展的内函数。返回值的数据类型是第一个参数的数据类型。
不测试 nbits 的值是否合理。
示例:and、or、xor 和 not:
demo% cat tandornot.f print 1, and(7,4), or(7,4), xor(7,4), not(4) 1 format(4x ’and(7,4)’, 5x ’or(7,4)’, 4x ’xor(7,4)’, 1 6x ’not(4)’/4o12.11) end demo% f95 tandornot.f demo% a.out and(7,4) or(7,4) xor(7,4) not(4) 00000000004 00000000007 00000000003 37777777773 demo% |
示例:lshift 和 rshift:
demo% cat tlrshift.f integer*4 lshift, rshift print 1, lshift(7,1), rshift(4,1) 1 format(1x ’lshift(7,1)’, 1x ’rshift(4,1)’/2o12.11) end demo% f95 tlrshift.f demo% a.out lshift(7,1) rshift(4,1) 00000000016 00000000002 demo% |
对于子例程和函数
call bic( bitnum, word ) |
call bis( bitnum, word ) |
call setbit( bitnum, word, state ) |
LOGICAL bit x = bit( bitnum, word ) |
bitnum、state 和 word 都是 INTEGER*4 输入参数。函数 bit() 的返回值是逻辑值。
各个位都进行编号,0 位表示最低有效位,31 位表示最高有效位。
bic、bis 和 setbit 是外部子例程,bit 是外部函数。
示例 3:bic、bis、setbit 和 bit:
integer*4 bitnum/2/, state/0/, word/7/ logical bit print 1, word 1 format(13x ’word’, o12.11) call bic( bitnum, word ) print 2, word 2 format(’after bic(2,word)’, o12.11) call bis( bitnum, word ) print 3, word 3 format(’after bis(2,word)’, o12.11) call setbit( bitnum, word, state ) print 4, word 4 format(’after setbit(2,word,0)’, o12.11) print 5, bit(bitnum, word) 5 format(’bit(2,word)’, L ) end <output> word 00000000007 after bic(2,word) 00000000003 after bis(2,word) 00000000007 after setbit(2,word,0) 00000000003 bit(2,word) F |
该函数的调用方式如下所示:
INTEGER*4 chdir n = chdir( dirname ) |
|||
dirname |
字符 |
输入 |
目录名称 |
返回值 |
INTEGER*4 |
输出 |
n=0:OK;n>0:错误代码 |
INTEGER*4 chdir, n n = chdir ( ’MyDir’ ) if ( n .ne. 0 ) stop ’chdir: error’ end |
另请参见:chdir(2)、cd(1) 和 gerror(3F),了解有关错误代码的信息。
路径名长度不能超过 <sys/param.h> 中定义的 MAXPATHLEN 值。路径可以是相对路径,也可以是绝对路径。
使用该函数可能会导致按单元查询失败。
某些 Fortran 文件操作会按文件名重新打开文件。执行 I/O 操作时使用 chdir 可能会导致运行时系统不能跟踪使用相对路径名创建的文件。(包括使用打开语句创建但没有文件名的文件)。
该函数的调用方式如下所示:
INTEGER*4 chmod n = chmod( name, mode ) |
|||
name |
字符 |
输入 |
路径名 |
mode |
字符 |
输入 |
chmod(1) 可以识别的任意字符, 例如 o-w、444 等。 |
返回值 |
INTEGER*4 |
输出 |
n = 0:OK;n>0:系统错误编号 |
示例:chmod-添加对 MyFile 的写入权限:
character*18 name, mode INTEGER*4 chmod, n name = ’MyFile’ mode = ’+w’ n = chmod( name, mode ) if ( n .ne. 0 ) stop ’chmod: error’ end |
另请参见:chmod(1) 和 gerror(3F),了解有关错误代码的信息。
路径名长度不能超过 <sys/param.h> 中定义的 MAXPATHLEN 值。路径可以是相对路径,也可以是绝对路径。
由于该例程只返回两位数值的年份,因此它存在“2000 年安全”问题。在 1999 年 12 月 31 日之后,使用该例程输出计算日期差异的程序可能无法正常工作。如果执行使用此 date() 例程的程序,第一次调用该例程时会显示运行时警告消息,向用户发出报警。请参见另一个可换用的例程 date_and_time()。
该子例程的调用方式如下所示:
call date( c ) |
|||
c |
CHARACTER*9 |
输出 |
变量、数组、数组元素或字符子串 |
返回的字符串 c 的格式为 dd-mmm-yy,其中 dd 表示两位数的当月日期,mmm 表示三个字母的月份缩写,yy 表示两位数的年份(因此存在 2000 年安全问题!)。
示例:date:
demo% cat dat1.f * dat1.f -- Get the date as a character string. character c*9 call date ( c ) write(*,"(’ The date today is: ’, A9 )" ) c end demo% f95 dat1.f demo% a.out Computing time differences using the 2 digit year from subroutine date is not safe after year 2000. The date today is: 9-Jan-02 demo% |
另请参见 idate() 和 date_and_time()。
这是一个 2000 年安全的 Fortran 95 内例程。
子例程 date_and_time 返回实时时钟和日期的相关数据。返回数据包括本地时间以及本地时间与通用协调时间 (Universal Coordinated Time, UTC) 之间的时差,通用协调时间也称为格林威治标准时间 (Greenwich Mean Time, GMT)。
子例程 date_and_time() 的调用方式如下:
call date_and_time( date , time, zone, values ) |
|||
date |
CHARACTER*8 |
输出 |
以 CCYYMMDD 格式表示的日期,其中 CCYY 表示四位数的年份,MM 表示两位数的月份,DD 表示两位数的当月日期。例如:19980709 |
time |
CHARACTER*10 |
输出 |
以 hhmmss.sss 格式表示的当前时间, 其中 hh 表示小时,mm 表示分钟,ss.sss 表示秒和毫秒。 |
zone |
CHARACTER*5 |
输出 |
与 UTC 的时差,以小时数和分钟数表示,采用 hhmm 格式。 |
values |
INTEGER*4 VALUES(8) |
输出 |
下面介绍的 8 个元素组成的整数数组。 |
INTEGER*4 values 数组中返回的 8 个值为
VALUES(1) |
以 4 位整数表示的年份。例如:1998。 |
VALUES(2) |
以从 1 到 12 的整数表示的月份。 |
VALUES(3) |
以从 1 到 31 的整数表示的当月日期。 |
VALUES(4) |
以分钟数表示的与 UTC 的时差。 |
VALUES(5) |
以从 1 到 23 的整数表示的当天小时时间。 |
VALUES(6) |
以从 1 到 59 的整数表示的一个小时中的分钟时间。 |
VALUES(7) |
以从 0 到 60 的整数表示的一分钟中的秒数。 |
VALUES(8) |
位于范围 0 至 999 中的毫秒数。 |
date_and_time 使用示例:
demo% cat dtm.f integer date_time(8) character*10 b(3) call date_and_time(b(1), b(2), b(3), date_time) print *,’date_time array values:’ print *,’year=’,date_time(1) print *,’month_of_year=’,date_time(2) print *,’day_of_month=’,date_time(3) print *,’time difference in minutes=’,date_time(4) print *,’hour of day=’,date_time(5) print *,’minutes of hour=’,date_time(6) print *,’seconds of minute=’,date_time(7) print *,’milliseconds of second=’,date_time(8) print *, ’DATE=’,b(1) print *, ’TIME=’,b(2) print *, ’ZONE=’,b(3) end |
2000 年 2 月 16 日在美国加利福尼亚的一台计算机上运行该例程时,输出结果如下所示:
date_time array values: year= 2000 month_of_year= 2 day_of_month= 16 time difference in minutes= -420 hour of day= 11 minutes of hour= 49 seconds of minute= 29 milliseconds of second= 236 DATE=20000216 TIME=114929.236 ZONE=-0700 |
这两个函数的返回值都是已用时间(如果为 -1.0,表示出现错误)。返回的时间以秒数表示。
缺省情况下,Fortran 95 使用的 dtime 和 etime 版本使用系统的低精度时钟。该精度是百分之一秒。但是,如果在 Sun OSTM 操作系统实用程序 ptime(1) (/usr/proc/bin/ptime) 下运行程序,则使用高精度时钟。
对于 dtime,已用时间为:
第一次调用:自开始执行后已用时间
后来调用:自上次调用 dtime 后已用时间
单处理器:CPU 占用的时间
多处理器:所有 CPU 占用时间总和,该数据没有什么用,这时可改用 etime。
在并行循环中调用 dtime 会得到不确定的结果,这是因为参与循环的所有线程都共用已用时间计数器。
该函数的调用方式如下所示:
e = dtime( tarray ) |
|||
tarray |
real(2) |
输出 |
e= -1.0:错误:tarray 值未定义 e≠ -1.0:没有错误,tarray(1) 中存储的是用户时间,tarray(2) 中存储的是系统时间 |
返回值 |
real |
输出 |
e= -1.0:错误 e≠ -1.0:tarray(1) 与 tarray(2) 之和 |
示例:dtime(),单处理器:
demo% cat tdtime.f real e, dtime, t(2) print *, ’elapsed:’, e, ’, user:’, t(1), ’, sys:’, t(2) do i = 1, 10000 k=k+1 end do e = dtime( t ) print *, ’elapsed:’, e, ’, user:’, t(1), ’, sys:’, t(2) end demo% f95 tdtime.f demo% a.out elapsed: 0.0E+0 , user: 0.0E+0 , sys: 0.0E+0 elapsed: 0.03 , user: 0.01 , sys: 0.02 demo% |
对于 etime,已用时间为:
单处理器执行-调用进程的 CPU 时间
多处理器执行-处理程序时的挂钟时间
如果环境变量 PARALLEL 或 OMP_NUM_THREADS 定义为大于 1 的某个整数值,运行时库就确定程序是在多处理器模式下执行。
该函数的调用方式如下所示:
e = etime( tarray ) |
|||
tarray |
real(2) |
输出 |
e= -1.0:错误:tarray 值未定义 e≠ -1.0:单处理器:tarray(1) 中存储的是用户时间,tarray(2) 中存储的是系统时间 多处理器:tarray(1) 中存储的是挂钟时间,tarray(2) 中存储的是 0.0 |
返回值 |
real |
输出 |
e= -1.0:错误 e≠ -1.0:tarray(1) 与 tarray(2) 之和 |
请注意,初次调用 etime 时所得结果不准确。它只是使系统时钟开始运转。请勿使用初次调用 etime 返回的值。
示例:etime(),单处理器:
demo% cat tetime.f real e, etime, t(2) e = etime(t) ! Startup etime - do not use result do i = 1, 10000 k=k+1 end do e = etime( t ) print *, ’elapsed:’, e, ’, user:’, t(1), ’, sys:’, t(2) end demo% f95 tetime.f demo% a.out elapsed: 0.02 , user: 0.01 , sys: 0.01 demo% |
另请参见 times(2) 和《Fortran 编程指南》。
该子例程的调用方式如下所示:
call exit( status ) |
||
status |
INTEGER*4 |
输入 |
示例:exit():
... if(dx .lt. 0.) call exit( 0 ) ... end |
exit 刷新并关闭进程中的所有文件,然后通知父进程(如果它在执行 wait)。
status 的低 8 位可用于父进程。此时,这 8 位左移 8 位,其他所有位均为零。(因此,status 应介于 256 到 65280 之间。)该调用从不返回任何值。
执行 C 函数 exit 时,可能会在系统最终 'exit' 之前执行清除操作。
调用 exit 时不使用参数会导致出现编译时警告消息,并自动将零作为参数。另请参见:exit(2)、fork(2)、fork(3F)、wait(2) 和 wait(3F)。
该子例程或函数的调用方式如下所示:
call fdate( string ) |
||
string |
character*24 |
输出 |
或者:
CHARACTER fdate*24 string = fdate() |
如果用作函数,调用例程必须定义 fdate 的类型和大小。 |
||
返回值 |
character*24 |
输出 |
示例 1:fdate 用作子例程:
character*24 string call fdate( string ) write(*,*) string end |
输出:
Wed Aug 3 15:30:23 1994 |
示例 2:fdate 用作函数,输出相同:
character*24 fdate write(*,*) fdate() end |
另请参见:ctime(3)、time(3F) 和 idate(3F)。
该函数的调用方式如下所示:
INTEGER*4 flush n = flush( lunit ) |
|||
lunit |
INTEGER*4 |
输入 |
逻辑单元 |
返回值 |
INTEGER*4 |
输出 |
n = 0 表示没有错误,n > 0 表示错误编号 |
flush 函数将逻辑单元 lunit 的缓冲区的内容刷新到关联文件中。逻辑单元 0 和逻辑单元 6 都与控制台终端关联时,该函数对它们特别有用。如果出现错误,该函数返回正的错误编号,否则返回零。
另请参见 fclose(3S)。
该函数的调用方式如下所示:
INTEGER*4 fork n = fork() |
|||
返回值 |
INTEGER*4 |
输出 |
n>0:n 为副本的进程 ID n<0, n 为系统错误代码 |
fork 函数创建调用进程的副本。两个进程之间的唯一区别在于返回给其中一个进程(称为父进程)的值是副本的进程 ID。副本通常称为子进程。返回给子进程的值将为零。
为了避免外部文件中的 I/O 缓冲区内容重复,在执行 fork 操作之前,会刷新所有已开放供写入的逻辑单元。
示例:fork():
INTEGER*4 fork, pid pid = fork() if(pid.lt.0) stop ’fork error’ if(pid.gt.0) then print *, ’I am the parent’ else print *, ’I am the child’ endif |
目前尚未提供对应的 exec 例程,这是因为没有一种令人满意的方法能够在整个 exec 例程中保持开放的逻辑单元。但是,可以使用 system(3F) 执行 fork/exec 的常用函数。另请参见:fork(2)、wait(3F)、kill(3F)、system(3F) 和 perror(3F)。
fseek 和 ftell 是用于实现文件复位的例程。ftell 返回文件的当前位置,以距文件开头的字节偏移量表示。在程序中后面某处,fseek 可以使用此保存的偏移值,将文件复位到原来位置以便读取。
该函数的调用方式如下所示:
INTEGER*4 fseek n = fseek( lunit, offset, from ) |
|||
lunit |
INTEGER*4 |
输入 |
开放的逻辑单元 |
offset |
INTEGER*4 或 INTEGER*8 |
输入 |
相对于 from 指定位置的字节偏移量 |
如果针对 64 位环境进行了编译,需要 INTEGER*8 偏移值。如果提供了文字常量,它必须是 64 位常量,例如:100_8 |
|||
from |
INTEGER*4 |
输入 |
0=文件开头 1=当前位置 2=文件结尾 |
返回值 |
INTEGER*4 |
输出 |
n=0:OK;n>0:系统错误代码 |
对于后续文件,在调用 fseek 后面执行输出操作(例如 WRITE)会导致 fseek 位置后面的所有数据记录被删除,并替换为新的数据记录(以及文件结束标记)。只有在使用直接访问文件时,才能将记录重新写入到位。
示例:fseek()-将 MyFile 复位到距开头两个字节处
INTEGER*4 fseek, lunit/1/, offset/2/, from/0/, n open( UNIT=lunit, FILE=’MyFile’ ) n = fseek( lunit, offset, from ) if ( n .gt. 0 ) stop ’fseek error’ end |
示例:同上,但在 64 位环境中,使用 -m64 编译:
INTEGER*4 fseek, lunit/1/, from/0/, n INTEGER*8 offset/2/ open( UNIT=lunit, FILE=’MyFile’ ) n = fseek( lunit, offset, from ) if ( n .gt. 0 ) stop ’fseek error’ end |
该函数的调用方式如下所示:
INTEGER*4 ftell n = ftell( lunit ) |
|||
lunit |
INTEGER*4 |
输入 |
开放的逻辑单元 |
返回值 |
INTEGER*4 |
输出 |
n>=0:n 为距文件开头的字节偏移量 n<0:n 为系统错误代码 |
示例:ftell():
INTEGER*4 ftell, lunit/1/, n open( UNIT=lunit, FILE=’MyFile’ ) ... n = ftell( lunit ) if ( n .lt. 0 ) stop ’ftell error’ ... |
示例:同上,但在 64 位环境中,使用 -m64 编译:
INTEGER*4 lunit/1/ INTEGER*8 ftell, n open( UNIT=lunit, FILE=’MyFile’ ) ... n = ftell( lunit ) if ( n .lt. 0 ) stop ’ftell error’ ... |
另请参见 fseek(3S) 和 perror(3F) 以及 fseeko64(3F) 和 ftello64(3F)。
fseeko64 和 ftello64 是 fseek 和 ftell 的“大型文件”版本。它们采用并返回 INTEGER*8 的文件位置偏移值。(“大型文件”是指大于 2 GB 的文件,因此字节位置必须以 64 位整型值表示。)可使用这些函数确定大型文件的位置和/或复位大型文件。
该函数的调用方式如下所示:
INTEGER fseeko64 n = fseeko64( lunit, offset64, from ) |
|||
lunit |
INTEGER*4 |
输入 |
开放的逻辑单元 |
offset64 |
INTEGER*8 |
输入 |
相对于 from 指定位置的 64 位字节偏移量 |
from |
INTEGER*4 |
输入 |
0=文件开头 1=当前位置 2=文件结尾 |
返回值 |
INTEGER*4 |
输出 |
n=0:OK;n>0:系统错误代码 |
对于后续文件,在调用 fseeko64 后执行输出操作(例如 WRITE)会导致 fseeko64 位置后面的所有数据记录被删除,并替换为新的数据记录(以及文件结束标记)。只有在使用直接访问文件时,才能将记录重新写入到位。
示例:fseeko64()-将 MyFile 复位到距开头两个字节处:
INTEGER fseeko64, lunit/1/, from/0/, n INTEGER*8 offset/200/ open( UNIT=lunit, FILE=’MyFile’ ) n = fseeko64( lunit, offset, from ) if ( n .gt. 0 ) stop ’fseek error’ end |
该函数的调用方式如下所示:
INTEGER*8 ftello64 n = ftello64( lunit ) |
|||
lunit |
INTEGER*4 |
输入 |
开放的逻辑单元 |
返回值 |
INTEGER*8 |
输出 |
n≥0:n 为距文件开头的字节偏移量 n<0:n 为系统错误代码 |
示例:ftello64():
INTEGER*8 ftello64, lunit/1/, n open( UNIT=lunit, FILE=’MyFile’ ) ... n = ftello64( lunit ) if ( n .lt. 0 ) stop ’ftell error’ ... |
getarg 和 iargc 访问命令行上的参数(在命令行预处理程序扩展后)。
该子例程的调用方式如下所示:
call getarg( k, arg ) |
|||
k |
INTEGER*4 |
输入 |
参数索引(0=第一个=命令名称) |
arg |
character*n |
输出 |
第 k 个参数 |
n |
INTEGER*4 |
arg 的大小 |
大得足以容纳最长的参数 |
该函数的调用方式如下所示:
返回值 |
INTEGER*4 |
输出 |
命令行中参数的数量 |
示例:使用 iargc 和 getarg 获取参数的数量和每个参数:
demo% cat yarg.f character argv*10 INTEGER*4 i, iargc, n n = iargc() do 1 i = 1, n call getarg( i, argv ) 1 write( *, ’( i2, 1x, a )’ ) i, argv end demo% f95 yarg.f demo% a.out *.f 1 first.f 2 yarg.f |
另请参见 execve(2) 和 getenv(3F)。
getc 和 fgetc 从输入流中获取下一个字符。请勿将这些例程的调用与相同逻辑单元中进行的正常 Fortran I/O 混在一起。
该函数的调用方式如下所示:
INTEGER*4 getc status = getc( char ) |
|||
char |
字符 |
输出 |
下一个字符 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK status=-1:文件结束 status>0:系统错误代码或 f95 I/O 错误代码 |
示例:使用 getc 获取从键盘输入的每个字符;请注意 Ctrl-D (^D):
character char INTEGER*4 getc, status status = 0 do while ( status .eq. 0 ) status = getc( char ) write(*, ’(i3, o4.3)’) status, char end do end |
编译之后,运行以上源代码的样例如下:
demo% a.out ab Program reads letters typed in 0 141 Program outputs status and octal value of the characters entered 0 142 141 represents ’a’, 142 is ’b’ 0 012 012 represents the RETURN key ^D terminated by a CONTROL-D. -1 377 Next attempt to read returns CONTROL-D demo% |
对于逻辑单元,请勿将正常的 Fortran 输入与 getc() 混在一起。
该函数的调用方式如下所示:
INTEGER*4 fgetc status = fgetc( lunit, char ) |
|||
lunit |
INTEGER*4 |
输入 |
逻辑单元 |
char |
字符 |
输出 |
下一个字符 |
返回值 |
INTEGER*4 |
输出 |
status=-1:文件结束 status>0:系统错误代码或 f95 I/O 错误代码 |
示例:使用 fgetc 从 tfgetc.data 中获取每个字符;请注意换行 (Octal 012):
character char INTEGER*4 fgetc, status open( unit=1, file=’tfgetc.data’ ) status = 0 do while ( status .eq. 0 ) status = fgetc( 1, char ) write(*, ’(i3, o4.3)’) status, char end do end |
编译之后,运行以上源代码的样例如下:
demo% cat tfgetc.data ab yz demo% a.out 0 141 ”a’ read 0 142 ”b’ read 0 012 linefeed read 0 171 ”y’ read 0 172 ”z’ read 0 012 linefeed read -1 012 CONTROL-D read demo% |
对于逻辑单元,请勿将正常的 Fortran 输入与 fgetc() 混在一起。
另请参见:getc(3S)、intro(2) 和 perror(3F)。
该函数的调用方式如下所示:
INTEGER*4 getcwd status = getcwd( dirname ) |
|||
dirname |
character*n |
输出 返回当前目录的路径 |
当前工作目录的路径名称。n 必须足够大,以便能容纳最长的路径名称 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK status>0:错误代码 |
示例:getcwd:
INTEGER*4 getcwd, status character*64 dirname status = getcwd( dirname ) if ( status .ne. 0 ) stop ’getcwd: error’ write(*,*) dirname end |
另请参见:chdir(3F)、perror(3F) 和 getwd(3)。
注意:路径名长度不能超过 <sys/param.h> 中定义的 MAXPATHLEN 值。
该子例程的调用方式如下所示:
call getenv( ename, evalue ) |
|||
ename |
character*n |
输入 |
寻找的环境变量名称 |
evalue |
character*n |
输出 |
找到的环境变量值,如果不成功,则为空白。 |
ename 和 evalue 的大小必须足够大,以便能容纳相应的字符串。
如果 evalue 太短而不能容纳整个字符串值,则字符串将被截断以符合 evalue。
子例程 getenv 在环境列表中搜索格式为 ename=evalue 的字符串,如果找到,则通过 evalue 返回值;否则在 evalue 中填入空白。
示例:使用 getenv() 打印 $SHELL 值:
character*18 evalue call getenv( ’SHELL’, evalue ) write(*,*) "’", evalue, "’" end |
另请参见:execve(2) 和 environ(5)。
该函数的调用方式如下所示:
INTEGER*4 getfd fildes = getfd( unitn ) |
|||
unitn |
INTEGER*4 |
输入 |
外部单元编号 |
返回值 |
INTEGER*4 或 INTEGER*8 |
输出 |
如果已连接文件,则返回文件描述符;如果未连接文件,则返回 -1。如果针对 64 位环境进行了编译,返回 INTEGER*8 值 |
示例:getfd():
INTEGER*4 fildes, getfd, unitn/1/ open( unitn, file=’tgetfd.data’ ) fildes = getfd( unitn ) if ( fildes .eq. -1 ) stop ’getfd: file not connected’ write(*,*) ’file descriptor = ’, fildes end |
另请参见 open(2)。
irtn = c_read( getfilep( unitn ), inbyte, 1 ) |
|||
c_read |
C 函数 |
输入 |
用户自己的 C 函数。请参见示例。 |
unitn |
INTEGER*4 |
输入 |
外部单元编号。 |
getfilep |
INTEGER*4 或 INTEGER*8 |
返回值 |
如果已连接文件,则返回文件指针;如果未连接文件,则返回 -1。如果针对 64 位环境进行了编译,则返回 INTEGER*8 值 |
该函数用于将标准的 Fortran I/O 与 C I/O 混在一起。此类混合不可移植,也不保证在使用后续发行版本的操作系统或 Fortran 时可以进行此操作。建议不要使用该函数,并且没有提供直接的接口。必须创建自己的 C 例程,才能使用 getfilep 返回的值。下面所示是一个 C 例程样例。
示例:Fortran 通过将 getfilep 传递给 C 函数来使用 getfile:
demo% cat tgetfilepF.f character*1 inbyte integer*4 c_read, getfilep, unitn / 5 / external getfilep write(*,’(a,$)’) ’What is the digit? ’ irtn = c_read( getfilep( unitn ), inbyte, 1 ) write(*,9) inbyte 9 format(’The digit read by C is ’, a ) end |
实际使用 getfilep 的 C 函数样例:
demo% cat tgetfilepC.c #include <stdio.h> int c_read_ ( fd, buf, nbytes, buf_len ) FILE **fd ; char *buf ; int *nbytes, buf_len ; { return fread( buf, 1, *nbytes, *fd ) ; } |
下面是编译-生成-运行该函数的样例:
demo% cc -c tgetfilepC.c demo% f95 tgetfilepC.o tgetfilepF.f demo% a.out What is the digit? 3 The digit read by C is 3 demo% |
有关更多信息,请参见《Fortran 编程指南》中介绍 C-Fortran 接口的章节。另请参见 open(2)。
该子例程的调用方式如下所示:
call getlog( name ) |
|||
name |
character*n |
输出 |
character*18 name call getlog( name ) write(*,*) "’", name, "’" end |
该函数的调用方式如下所示:
INTEGER*4 getpid |
|||
返回值 |
INTEGER*4 |
输出 |
INTEGER*4 getpid, pid pid = getpid() write(*,*) ’process id = ’, pid end |
另请参见 getpid(2)。
getuid 和 getgid 分别获取进程的用户 ID 和组 ID。
该函数的调用方式如下所示:
INTEGER*4 getuid uid = getuid() |
|||
返回值 |
INTEGER*4 |
输出 |
进程的用户 ID |
该函数的调用方式如下所示:
INTEGER*4 getgid gid = getgid() |
|||
返回值 |
INTEGER*4 |
输出 |
进程的组 ID |
示例:getuid() 和 getpid():
INTEGER*4 getuid, getgid, gid, uid uid = getuid() gid = getgid() write(*,*) uid, gid end |
另请参见:getuid(2)。
该函数的调用方式如下所示:
INTEGER*4 hostnm status = hostnm( name ) |
|||
name |
character*n |
输出 |
当前主机系统的名称。n 必须足够大,以便能容纳主机名。 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK status>0:错误 |
示例:hostnm():
INTEGER*4 hostnm, status character*8 name status = hostnm( name ) write(*,*) ’host name = "’, name, ’"’ end |
另请参见 gethostname(2)。
idate 将当前系统日期放入一个整型数组中:日期、月份和年份
该子例程的调用方式如下所示:
call idate( iarray ) 标准版本 |
|||
iarray |
INTEGER*4 |
输出 |
三元素数组:日期、月份和年份 |
示例:idate(标准版本):
demo% cat tidate.f INTEGER*4 iarray(3) call idate( iarray ) write(*, "(’ The date is: ’,3i5)" ) iarray end demo% f95 tidate.f demo% a.out The date is: 10 8 1998 demo% |
这些子程序提供了在 Fortran 程序中充分利用 ANSI/IEEE 标准 754-1985 算术所需的模式和状态。它们与函数 ieee_flags(3M)、ieee_handler(3M) 和 sigfpe(3) 一一对应。
表 1–5 IEEE 算术支持例程
ieeer = ieee_flags( action,mode,in,out ) ieeer = ieee_handler(action,exception,hdl ) ieeer = sigfpe( code, hdl ) |
||
action |
字符 |
输入 |
code |
sigfpe_code_type |
输入 |
mode |
字符 |
输入 |
in |
字符 |
输入 |
exception |
字符 |
输入 |
hdl |
sigfpe_handler_type |
输入 |
out |
字符 |
输出 |
返回值 |
INTEGER*4 |
输出 |
有关如何有策略地使用这些函数的详细信息,请参见 Sun 的《数值计算指南》。
如果使用 sigfpe,必须在浮点状态寄存器中设置对应的陷阱-启用-掩码位。SPARC 体系结构手册中介绍了详细信息。libm 函数 ieee_handler 可为您设置这些陷阱-启用-掩码位。
mode 和 exception 接受的字符关键字取决于 action 值。
表 1–6 ieee_flags( action , mode , in , out) 参数和操作
action = 'clearall' |
mode、in 和 out 未使用;返回 0 |
|
action = 'clear' 清除 mode,in、 out 未使用;返回 0 |
mode = 'direction' | |
mode = 'exception' |
in = 'inexact' 或 'division' 或 'underflow' 或 'overflow' 或 'invalid' 或 'all' 或 'common' |
|
action = 'set' 设置浮点 mode,in、 out 未使用;返回 0 |
mode = 'direction' |
in = 'nearest' 或 'tozero' 或 'positive' 或 'negative' |
mode = 'exception' |
in = 'inexact' 或 'division' 或 'underflow' 或 'overflow' 或 'invalid' 或 'all' 或 'common' |
|
action = 'get' 测试 mode 设置 in 和 out 可为空白或要测试的其中一个设置,返回的当前设置取决于 mode,也可为 'not available'。如果 mode = 'exception',该函数返回 0 或当前异常标志。 |
mode ='direction' |
out = 'nearest' 或 'tozero' 或 'positive' 或 'negative' |
mode ='exception' |
out = 'inexact' 或 'division' 或 'underflow' 或 'overflow' 或 'invalid' 或 'all' 或 'common' |
表 1–7 ieee_handler( action , in , out) 参数
action = 'clear' 清除 in 的用户异常处理;out 未使用 |
in = 'inexact' 或 'division' 或 'underflow' 或 'overflow' 或 'invalid' 或 'all' 或 'common' |
action = 'set' 设置 in 的用户处理异常;out 是处理程序例程的地址,或者是 floating point.h 中定义的 SIGFPE_DEFAULT、SIGFPE_ABORT 或 SIGFPE_IGNORE |
in = 'inexact' 或 'division' 或 'underflow' 或 'overflow' 或 'invalid' 或 'all' 或 'common' |
示例 1:将舍入方向设置为向零舍入,除非硬件不支持要求的舍入模式:
INTEGER*4 ieeer character*1 mode, out, in ieeer = ieee_flags( ’set’, ’direction’, ’tozero’, out ) |
示例 2:将舍入方向清理为缺省方向(向最近的值舍入):
character*1 out, in ieeer = ieee_flags(’clear’,’direction’, in, out ) |
示例 3:清除所有由于产生异常而出现的位:
character*18 out ieeer = ieee_flags( ’clear’, ’exception’, ’all’, out ) |
示例 4:按如下所示检测溢出异常:
character*18 out ieeer = ieee_flags( ’get’, ’exception’, ’overflow’, out ) if (out .eq. ’overflow’ ) stop ’overflow’ |
上述代码将 out 设置为 overflow 并将 ieeer 设置为 25(该值视平台而定)。类似的编码可检测异常,例如 invalid 或 inexact。
示例 5:hand1.f,编写并使用信号处理程序:
external hand real r / 14.2 /, s / 0.0 / i = ieee_handler( ’set’, ’division’, hand ) t = r/s end INTEGER*4 function hand ( sig, sip, uap ) INTEGER*4 sig, address structure /fault/ INTEGER*4 address end structure structure /siginfo/ INTEGER*4 si_signo INTEGER*4 si_code INTEGER*4 si_errno record /fault/ fault end structure record /siginfo/ sip address = sip.fault.address write (*,10) address 10 format(’Exception at hex address ’, z8 ) end |
将 address 和 function hand 的声明更改为 INTEGER*8,以便示例 5 可以在 64 位 SPARC 环境中使用 (-m64)。
请参见《数值计算指南》。另请参见:floatingpoint(3)、signal(3)、sigfpe(3)、floatingpoint(3F)、ieee_flags(3M) 和 ieee_handler(3M)。
头文件 floatingpoint.h 定义了根据 ANSI/IEEE 标准 754-1985 实现标准浮点所使用的常量和类型。
在 Fortran 95 源程序中包含该文件的方式如下所示:
#include "floatingpoint.h" |
如果要使用该 include 文件,需在进行 Fortran 编译之前进行预处理。如果引用该 include 文件的源文件的扩展名为 .F、.F90 或 .F95,则会自动预处理该文件。
fp_direction_type |
IEEE 舍入方向模式的类型。枚举顺序随硬件的不同而异。 |
sigfpe_code_type |
SIGFPE 代码的类型。 |
sigfpe_handler_type |
处理特定的 SIGFPE 代码时调用的用户自定义 SIGFPE 异常处理程序的类型。 |
SIGFPE_DEFAULT |
表示缺省 SIGFPE 异常处理的宏:得到缺省结果时,IEEE 异常继续出现;如果是其他 SIGFPE 代码,IEEE 异常将中止。 |
SIGFPE_IGNORE |
表示另外一种可用的 SIGFPE 异常处理的宏,即忽略异常并继续执行。 |
SIGFPE_ABORT |
表示另外一种可用的 SIGFPE 异常处理的宏,即中止核心转储。 |
N_IEEE_EXCEPTION |
不相同的 IEEE 浮点异常数。 |
fp_exception_type |
N_IEEE_EXCEPTION 异常的类型。每个异常都指定有一个位编号。 |
fp_exception_field_type |
专门用于至少容纳与按 fp_exception_type 列入的 IEEE 异常对应的 N_IEEE_EXCEPTION 位的类型。因此,fp_inexact 对应于最低有效位,fp_invalid 对应于第五个最低有效位。有些操作可以设置多个异常。 |
IEEE 分类:
fp_class_type |
IEEE 浮点值和符号分类的列表。 |
请参见《数值计算指南》。另请参见 ieee_environment(3F)。
这些函数通过字符串搜索:
index(a1,a2) |
字符串 a1 中第一次出现的字符串 a2 的索引 |
rindex(a1,a2) |
字符串 a1 中最后一次出现的字符串 a2 的索引 |
lnblnk(a1) |
字符串 a1 中最后一个非空白字符串的索引 |
index 有以下几种形式:
索引是通过以下方式调用的内函数:
n = index( a1, a2 ) |
|||
a1 |
字符 |
输入 |
主字符串 |
a2 |
字符 |
输入 | |
返回值 |
INTEGER |
输出 |
n>0:a1 中第一次出现的 a2 的索引 n=0:a2 不在 a1 中 |
如果声明了 INTEGER*8,在针对 64 位环境进行了编译且字符变量 a1 是非常大的字符串(大于 2 GB)时,index() 将返回 INTEGER*8 值。
该函数的调用方式如下所示:
INTEGER*4 rindex n = rindex( a1, a2 ) |
|||
a1 |
字符 |
输入 |
主字符串 |
a2 |
字符 |
输入 |
子串 |
返回值 |
INTEGER*4 或 INTEGER*8 |
输出 |
n>0:a1 中最后一次出现的 a2 的索引 n=0:a2 不在 a1 中,在 64 位环境中返回 INTEGER*8 值 |
该函数的调用方式如下所示:
n = lnblnk( a1 ) |
|||
a1 |
字符 |
输入 |
字符串 |
返回值 |
INTEGER*4 或 INTEGER*8 |
输出 |
n>0:a1 中最后一个非空白字符串的索引 n=0:a1 全部不为空白,在 64 位环境中返回 INTEGER*8 值 |
示例:index()、rindex() 和 lnblnk():
demo% cat tindex.f * 123456789012345678901 character s*24 / ’abcPDQxyz...abcPDQxyz’ / INTEGER*4 declen, index, first, last, len, lnblnk, rindex declen = len( s ) first = index( s, ’abc’ ) last = rindex( s, ’abc’ ) lastnb = lnblnk( s ) write(*,*) declen, lastnb write(*,*) first, last end demo% f95 tindex.f demo% a.out 24 21 <- declen is 24 because intrinsic len() returns the declared length of s 1 13 |
对于编译为要在 64 位环境中运行的程序,必须将 index、rindex 和 lnblnk(以及它们的接收变量)声明为 INTEGER*8,以便处理非常大的字符串。
该函数的调用方式如下所示:
m = inmax() |
|||
返回值 |
INTEGER*4 |
输出 |
最大正整数 |
示例:inmax:
demo% cat tinmax.f INTEGER*4 inmax, m m = inmax() write(*,*) m end demo% f95 tinmax.f demo% a.out 2147483647 demo% |
另请参见 libm_single(3F) 和 libm_double(3F)。另请参见第 3 章中介绍的 FORTRAN 77 非标准内函数 ephuge()。
itime 将当前系统时间放入整型数组中:小时、分钟和秒。该子例程的调用方式如下所示:
call itime( iarray ) |
|||
iarray |
INTEGER*4 |
输出 |
三元素数组: iarray(1) = 小时 iarray(2) = 分钟 iarray(3) = 秒 |
示例:itime:
demo% cat titime.f INTEGER*4 iarray(3) call itime( iarray ) write (*, "(’ The time is: ’,3i5)" ) iarray end demo% f95 titime.f demo% a.out The time is: 15 42 35 |
另请参见 time(3F)、ctime(3F) 和 fdate(3F)。
该函数的调用方式如下所示:
status = kill( pid, signum ) |
|||
pid |
INTEGER*4 |
输入 |
其中一个用户进程的进程 ID。 |
signum |
INTEGER*4 |
输入 |
有效的信号编号。请参见 signal(3)。 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK status>0:错误代码 |
示例(片段):使用 kill() 发送消息:
INTEGER*4 kill, pid, signum * … status = kill( pid, signum ) if ( status .ne. 0 ) stop ’kill: error’ write(*,*) ’Sent signal ’, signum, ’ to process ’, pid end |
该函数将信号 signum 和整型信号编号发送到进程 pid。有效的信号编号列在 C include 文件 /usr/include/sys/signal.h 中。
另请参见:kill(2)、signal(3)、signal(3F)、fork(3F) 和 perror(3F)。
link 创建指向现有文件的链接。symlink 创建指向现有文件的符号链接。
该函数的调用方式如下所示:
status = link( name1, name2 ) |
|||
INTEGER*4 symlnk status = symlnk( name1, name2 ) |
|||
name1 |
character*n |
输入 |
现有文件的路径名 |
name2 |
character*n |
输入 |
要链接到文件 name1 的路径名。 name2 不得已存在。 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK status>0:系统错误代码 |
示例 1:link:创建一个指向文件 tlink.db.data.1 的链接 data1:
demo% cat tlink.f character*34 name1/’tlink.db.data.1’/, name2/’data1’/ integer*4 link, status status = link( name1, name2 ) if ( status .ne. 0 ) stop ’link: error’ end demo% f95 tlink.f demo% ls -l data1 data1 not found demo% a.out demo% ls -l data1 -rw-rw-r-- 2 generic 2 Aug 11 08:50 data1 demo% |
示例 2:symlnk:创建一个指向文件 tlink.db.data.1 的符号链接 data1:
demo% cat tsymlnk.f character*34 name1/’tlink.db.data.1’/, name2/’data1’/ INTEGER*4 status, symlnk status = symlnk( name1, name2 ) if ( status .ne. 0 ) stop ’symlnk: error’ end demo% f95 tsymlnk.f demo% ls -l data1 data1 not found demo% a.out demo% ls -l data1 lrwxrwxrwx 1 generic 15 Aug 11 11:09 data1 -> tlink.db.data.1 demo% |
另请参见:link(2)、symlink(2)、perror(3F) 和 unlink(3F)。
注意:路径名长度不能超过 <sys/param.h> 中定义的 MAXPATHLEN 值。
该内函数的调用方式如下所示:
k = loc( arg ) |
|||
arg |
任意类型 |
输入 |
变量或数组 |
返回值 |
INTEGER*4 或 INTEGER*8 |
输出 | |
如果使用 -m64 进行编译以在 64 位环境中运行,则返回 INTEGER*8 指针。参见下面的说明。 |
示例:loc:
INTEGER*4 k, loc real arg / 9.0 / k = loc( arg ) write(*,*) k end |
对于编译为要在 64 位环境中运行的程序,应将接收 loc() 函数输出的变量声明为 INTEGER*8。
long 和 short 处理 INTEGER*4 与 INTEGER*2 之间的整型对象转换,在子程序调用列表中特别有用。
该函数的调用方式如下所示:
call ExpecLong( long(int2) ) |
||
int2 |
INTEGER*2 |
输入 |
返回值 |
INTEGER*4 |
输出 |
该函数为:
INTEGER*2 short call ExpecShort( short(int4) ) |
||
int4 |
INTEGER*4 |
输入 |
返回值 |
INTEGER*2 |
输出 |
示例(片段):long() 和 short():
integer*4 int4/8/, long integer*2 int2/8/, short call ExpecLong( long(int2) ) call ExpecShort( short(int4) ) … end |
ExpecLong 是用户程序调用的某子例程,要使用 long (INTEGER*4) 整型参数。而类似的子例程 ExpecShort 要使用 short (INTEGER*2) 整型参数。
如果在库例程调用中使用了常量且编译代码时使用了 -i2 选项,long 很有用。
在长型对象必须作为短整型传递的这类上下文环境中,short 很有用。将整数传递给幅度太大的短整型虽然不会导致出现错误,但会导致出现未预料的行为。
isetjmp 为 longjmp 设置位置;而 longjmp 返回到该位置。
该内函数的调用方式如下所示:
ival = isetjmp( env ) |
|||
env |
INTEGER*4 |
输出 |
env 是由 12 个元素组成的整数数组。在 64 位环境中,它必须声明为 INTEGER*8。 |
返回值 |
INTEGER*4 |
输出 |
如果显式调用 isetjmp,ival = 0 如果通过 longjmp 调用 isetjmp,ival ≠ 0 |
该子例程的调用方式如下所示:
call longjmp( env, ival ) |
|||
env |
INTEGER*4 |
输入 |
env 是由 isetjmp 初始化并由 12 个元素组成的整型数组。在 64 位环境中,它必须声明为 INTEGER*8 |
ival |
INTEGER*4 |
输出 |
如果显式调用 isetjmp,ival = 0 如果通过 longjmp 调用 isetjmp,ival ≠ 0 |
isetjmp 和 longjmp 例程用于处理在程序的低级例程中遇到的错误和中断。它们属于 f95 内函数。
如非必要,不应使用这些例程。它们受规范约束,且不可移植。有关错误和其他详细信息,请参见 setjmp(3V) 手册页。
isetjmp 在 env 中保存堆栈环境。它还会保存寄存器环境。
longjmp 会恢复上次调用 isetjmp 时保存的环境,并以继续执行这种方式返回值,就好像刚执行 isetjmp 调用返回 ival 值一样。
如果未调用 longjmp,从 isetjmp 返回的整型表达式 ival 为零,如果调用了 longjmp,则返回的 ival 不为零。
示例:使用 isetjmp 和 longjmp 的代码片断:
INTEGER*4 env(12) common /jmpblk/ env j = isetjmp( env ) if ( j .eq. 0 ) then call sbrtnA else call error_processor end if end subroutine sbrtnA INTEGER*4 env(12) common /jmpblk/ env call longjmp( env, ival ) return end |
必须先调用 isetjmp,然后才能调用 longjmp。
isetjmp 和 longjmp 的 env 整型数组参数长度必须至少为 12 个元素。
必须以常规方式或通过参数将 env 变量从调用 isetjmp 的例程传递给调用 longjmp 的例程。
longjmp 会尝试清理堆栈。必须从较低的调用级别而不是 isetjmp 调用 longjmp。
不能将 isetjmp 作为属于过程名称的参数进行传递。
请参见 setjmp(3V)。
函数 malloc()、malloc64() 和 realloc() 分配内存块并返回块的起始地址。返回值可以用于设置 INTEGER 或 Cray 样式的 POINTER 变量。realloc() 根据新的大小重新分配现有内存块。free() 解除分配由 malloc()、malloc64() 或 realloc() 分配的内存块。
这些例程在 f95 中以内函数实现,而在 f77 中是外部函数。它们不应该出现在 Fortran 95 程序的类型声明和 EXTERNAL 语句中,除非您要使用自己的版本。只有 f95 中实现 realloc() 例程。
符合标准的 Fortran 95 程序应该将 ALLOCATE 和 DEALLOCATE 语句用于 ALLOCATABLE 数组,以便执行动态内存管理,且不能直接调用 malloc/realloc/free。
传统的 Fortran 77 程序可以使用 malloc()/malloc64() 为 Cray 样式的 POINTER 变量赋值,这些变量的数据表示形式与 INTEGER 变量的数据表示形式相同。在 f95 中实现了 Cray 样式的 POINTER 变量,以便能够从 Fortran 77 进行移植。
malloc() 函数的调用方式如下所示:
k = malloc( n ) |
|||
n |
INTEGER |
输入 |
内存的字节数 |
返回值 |
INTEGER(Cray POINTER) |
输出 |
k>0:k 为分配的内存块起始位置的地址 k=0:错误 |
如果使用 -m64 针对 64 位环境进行了编译,则返回 INTEGER*8 指针值。参见下面的说明。 |
该函数在 Fortran 95 中属于内函数,而在 Fortran 77 中属于外部函数。对于编译为要在 64 位环境中运行的 Fortran 77 程序,应将 malloc() 函数和接收其输出的变量声明为 INTEGER*8。有一个函数 malloc64(3F),它用于实现在 32 位环境与 64 位环境之间移植程序。
k = malloc64( n ) |
|||
n |
INTEGER*8 |
输入 |
内存的字节数 |
返回值 |
INTEGER*8 (Cray POINTER) |
输出 |
k>0:k 是分配的内存块起始位置的地址 k=0:错误 |
这些函数会分配一片内存区域,并返回该区域起始位置的地址。(在 64 位环境中,返回的字节地址可能超出 INTEGER*4 数值范围-必须将接收变量声明为 INTEGER*8 以免内存地址被截断。)内存区域并未以任何方式初始化,因此,不应假设它已预设为什么内容,尤其是零!
示例:使用 malloc() 的代码片段:
parameter (NX=1000) integer ( p2X, X ) real*4 X(1) … p2X = malloc( NX*4 ) if ( p2X .eq. 0 ) stop ’malloc: cannot allocate’ do 11 i=1,NX 11 X(i) = 0. … end |
在上面的示例中,获取了 4,000 字节的内存(p2X 指向该内存),并将其初始化为零。
f95 内函数 realloc() 的调用方式如下所示:
k = realloc(ptr, n ) |
|||
ptr |
INTEGER |
输入 |
现有内存块的指针。(上次调用 malloc() 或 realloc() 时返回的值)。 |
n |
INTEGER |
输入 |
请求的新内存块大小(以字节数表示)。 |
返回值 |
INTEGER (Cray POINTER) |
输出 |
k>0:k 是分配的新内存块起始位置的地址 k=0:错误 |
如果使用 -m64 针对 64 位环境进行了编译,则返回 INTEGER*8 指针值。参见下面的说明。 |
realloc() 函数将 ptr 指向的内存块的大小更改为 n 字节,并返回指向(可能已移动的)新内存块的指针。内存块的内容保存不变,其大小为新内存块大小和旧内存块大小中较小者。
如果 ptr 为零,则 realloc() 的行为与 malloc() 的行为相同,其分配大小为 n 字节的新内存块。
如果 n 为零而 ptr 不为零,则指向的内存块可以进一步进行分配,且仅在终止应用程序后才返回给系统。
示例:使用 malloc() 和 realloc() 以及 Cray 样式的 POINTER 变量:
PARAMETER (nsize=100001) POINTER (p2space,space) REAL*4 space(1) p2space = malloc(4*nsize) if(p2space .eq. 0) STOP ’malloc: cannot allocate space’ ... p2space = realloc(p2space, 9*4*nsize) if(p2space .eq. 0) STOP ’realloc: cannot reallocate space’ ... CALL free(p2space) ... |
请注意,只有 f95 中实现 realloc() 例程。
该子例程的调用方式如下所示:
call free ( ptr ) |
||
ptr |
Cray POINTER |
输入 |
free 解除分配先前由 malloc 和 realloc() 分配的内存区域。此时,该内存区域返回给内存管理器,用户程序不能再使用它。
示例:free():
real x pointer ( ptr, x ) ptr = malloc ( 10000 ) call free ( ptr ) end |
该子例程的调用方式如下所示:
call mvbits( src, ini1, nbits, des, ini2 ) |
|||
src |
INTEGER*4 |
输入 |
来源 |
ini1 |
INTEGER*4 |
输入 |
来源中初始位的位置 |
nbits |
INTEGER*4 |
输入 | |
des |
INTEGER*4 |
输出 |
目标 |
ini2 |
INTEGER*4 |
输入 |
目标中初始位的位置 |
demo% cat mvb1.f * mvb1.f -- From src, initial bit 0, move 3 bits to des, initial * bit 3. * src des * 543210 543210 <- Bit numbers * 000111 000001 <- Values before move * 000111 111001 <- Values after move INTEGER*4 src, ini1, nbits, des, ini2 data src, ini1, nbits, des, ini2 1 / 7, 0, 3, 1, 3 / call mvbits ( src, ini1, nbits, des, ini2 ) write (*,"(5o3)") src, ini1, nbits, des, ini2 end demo% f95 mvb1.f demo% a.out 7 0 3 71 3 demo% |
请注意以下事项:
位是从 0 到 31 依次编号,0 是最低有效位,31 是最高有效位。
mvbits 只更改 des 位置的 ini2 位到 ini2+nbits-1 位,而不更改 src 位置的位。
限制包括:
ini1 + nbits ≥ 32
ini2 + nbits≤ 32
perror |
将消息打印到 Fortran 逻辑单元 0 stderr。 |
gerror |
获取(上一次检测到的系统错误的)系统错误消息。 |
ierrno |
获取上一次检测到的系统错误的错误编号。 |
该子例程的调用方式如下所示:
call perror( string ) |
|||
string |
character*n |
输入 |
消息。它写在上一次检测到的系统错误的标准错误消息前面。 |
示例 1:
call perror( "file is for formatted I/O" ) |
该子例程或函数的调用方式如下所示:
call gerror( string ) |
|||
string |
character*n |
输出 |
上一次检测到的系统错误的消息 |
示例 2:gerror() 用作子例程:
character string*30 … call gerror ( string ) write(*,*) string |
示例 3:gerror() 用作函数;未使用 string:
character gerror*30, z*30 … z = gerror( ) write(*,*) z |
该函数的调用方式如下所示:
n = ierrno() |
|||
返回值 |
INTEGER*4 |
输出 |
上一次检测到的系统错误的编号 |
该数值只有在真正出现错误时才更新。可能会生成此类错误的大多数例程和 I/O 语句在调用之后会返回错误代码;该值能够比较可靠地反映导致出现错误状况的原因。
示例 4:ierrno():
INTEGER*4 ierrno, n … n = ierrno() write(*,*) n |
另请参见 intro(2) 和 perror(3)。
注意:
perror 调用中的 string 的长度不能超过 127 个字符。
gerror 返回的字符串长度由调用程序决定。
《Fortran 用户指南》中列出了 f95 的运行时 I/O 错误代码。
putc 向逻辑单元 6 写入(通常是控制终端输出)。
fputc 向逻辑单元写入。
这些函数绕过正常的 Fortran I/O,将字符写入与 Fortran 逻辑单元关联的文件中。
请勿将正常的 Fortran 输出与相同单元中这些函数的输出混在一起。
请注意,要写入任何特殊的 \ 转义符(如换行符 '\n'),需要在编译时使用 FORTRAN 77 兼容选项 -f77=backslash。
该函数的调用方式如下所示:
INTEGER*4 putc status = putc( char ) |
|||
char |
字符 |
输入 |
要写入单元的字符 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK status>0:系统错误代码 |
示例:putc():
demo% cat tputc.f character char, s*10 / ’OK by putc’ / INTEGER*4 putc, status do i = 1, 10 char = s(i:i) status = putc( char ) end do status = putc( ’\n’ ) end demo% f95 -f77=backslash tputc.f demo% a.out OK by putc demo% |
该函数的调用方式如下所示:
INTEGER*4 fputc status = fputc( lunit,char ) |
|||
lunit |
INTEGER*4 |
输入 |
要写入的单元 |
char |
字符 |
输入 |
要写入单元的字符 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK status>0:系统错误代码 |
示例:fputc():
demo% cat tfputc.f character char, s*11 / ’OK by fputc’ / INTEGER*4 fputc, status open( 1, file=’tfputc.data’) do i = 1, 11 char = s(i:i) status = fputc( 1, char ) end do status = fputc( 1, ’\n’ ) end demo% f95 -f77=backslash tfputc.f demo% a.out demo% cat tfputc.data OK by fputc demo% |
另请参见 putc(3S)、intro(2) 和 perror(3F)。
该子例程的调用方式如下所示:
call qsort( array, len, isize, compar ) call qsort64( array, len8, isize8, compar ) |
|||
array |
array |
输入 |
包含要排序的元素。 |
len |
INTEGER*4 |
输入 |
数组中的元素数量。 |
len8 |
INTEGER*8 |
输入 |
数组中的元素数量。 |
isize |
INTEGER*4 |
输入 |
元素的大小,通常: 4 代表整数或实数 8 代表双精度或复数 16 代表双复数 字符数组的字符对象长度 |
isize8 |
INTEGER*8 |
输入 |
元素的大小,通常: 4_8 代表整数或实数 8_8 代表双精度或复数 16_8 代表双复数 字符数组的字符对象长度 |
compar |
函数名 |
输入 |
用户提供的 INTEGER*2 函数的名称。 确定排序的顺序。compar(arg1,arg2) |
可在 64 位环境中将 qsort64 用于大于 2 GB 的数组。请确保将数组长度 len8 和元素大小 isize8 指定为 INTEGER*8 数据。可使用 Fortran 95 样式的常量显式指定 INTEGER*8 常量。
compar(arg1, arg2) 参数是 array 的元素,它返回以下值:
负数 |
如果认为 arg1 排在 arg2 前面 |
零 |
如果 arg1 与 arg2 的位置相同 |
正数 |
如果认为 arg1 排在 arg2 后面 |
例如:
demo% cat tqsort.f external compar integer*2 compar INTEGER*4 array(10)/5,1,9,0,8,7,3,4,6,2/,len/10/, 1 isize/4/ call qsort( array, len, isize, compar ) write(*,’(10i3)’) array end integer*2 function compar( a, b ) INTEGER*4 a, b if ( a .lt. b ) compar = -1 if ( a .eq. b ) compar = 0 if ( a .gt. b ) compar = 1 return end demo% f95 tqsort.f demo% a.out 0 1 2 3 4 5 6 7 8 9 |
反复调用 ran 可生成一个分布均匀的随机数序列。请参见 lcrans(3m)。
r = ran( i ) |
|||
i |
INTEGER*4 |
输入 |
变量或数组元素 |
r |
REAL |
输出 |
变量或数组元素 |
示例:ran:
demo% cat ran1.f * ran1.f -- Generate random numbers. INTEGER*4 i, n real r(10) i = 760013 do n = 1, 10 r(n) = ran ( i ) end do write ( *, "( 5 f11.6 )" ) r end demo% f95 ran1.f demo% a.out 0.222058 0.299851 0.390777 0.607055 0.653188 0.060174 0.149466 0.444353 0.002982 0.976519 demo% |
请注意以下事项:
该范围包括 0.0,但不包括 1.0。
该算法是一种倍增叠合型通用随机数生成器。
通常,在执行调用程序期间,将会设置一次 i 值。
i 的初始值应该是较大的奇整数。
每次调用 RAN 都会获得同一序列的下一个随机数。
要在每次运行程序时获得不同的随机数序列,必须在每次运行时将参数设置为不同的初始值。
RAN 使用该参数存储根据以下算法计算出来的下一个随机数的值:
SEED = 6909 * SEED + 1 (MOD 2**32) |
SEED 包含 32 位数,高 24 位转换为浮点,并返回该值。
rand 返回介于 0.0 到 1.0 之间的实数值。
drand 返回介于 0.0 到 1.0 之间的双精度值。
irand 返回介于 0 到 2147483647 之间的正整数。
这些函数使用 random(3) 生成随机数序列。这三个函数共用同一个 256 字节的状态数组。这些函数的唯一优点是它们可以广泛用于 UNIX 系统上。要获得更好的随机数生成器,请比较 lcrans、addrans 和 shufrans。另请参见 random(3) 和《数值计算指南》。
i = irand( k ) r = rand( k ) d = drand( k ) |
|||
k |
INTEGER*4 |
输入 |
k=0:获取同一序列的下一个随机数 k=1:重新开始序列,返回第一个数 k>0:用作新序列的种子,返回第一个 数 |
rand |
REAL*4 |
输出 | |
drand |
REAL*8 |
输出 | |
irand |
INTEGER*4 |
输出 |
示例:irand():
demo% cat trand.f integer*4 v(5), iflag/0/ do i = 1, 5 v(i) = irand( iflag ) end do write(*,*) v end demo% f95 trand.f demo% a.out 2078917053 143302914 1027100827 1953210302 755253631 demo% |
该函数的调用方式如下所示:
INTEGER*4 rename status = rename( from, to ) |
|||
from |
character*n |
输入 |
现有文件的路径名 |
to |
character*n |
输入 |
文件的新路径名称 |
返回值 |
INTEGER*4 |
输出 |
status=0:OK status>0:系统错误代码 |
如果 to 指定的文件已存在,则 from 和 to 必须属于相同的文件类型,并且必须位于相同的文件系统中。如果 to 已存在,应先将其删除。
示例:rename()-将文件 trename.old 重命名为 trename.new
demo% cat trename.f INTEGER*4 rename, status character*18 from/’trename.old’/, to/’trename.new’/ status = rename( from, to ) if ( status .ne. 0 ) stop ’rename: error’ end demo% f95 trename.f demo% ls trename* trename.f trename.old demo% a.out demo% ls trename* trename.f trename.new demo% |
另请参见 rename(2) 和 perror(3F)。
注意:路径名长度不能超过 <sys/param.h> 中定义的 MAXPATHLEN 值。
t0 |
REAL |
输入 |
常量、变量或数组元素 |
返回值 |
REAL |
输出 |
自午夜起的秒数减去 t0 所得值 |
示例:secnds:
demo% cat sec1.f real elapsed, t0, t1, x, y t0 = 0.0 t1 = secnds( t0 ) y = 0.1 do i = 1, 10000 x = asin( y ) end do elapsed = secnds( t1 ) write ( *, 1 ) elapsed 1 format ( ’ 10000 arcsines: ’, f12.6, ’ sec’ ) end demo% f95 sec1.f demo% a.out 10000 arcsines: 0.009064 sec demo% |
请注意:
set_io_err_handler() 声明每当在指定的输入逻辑单元中检测到错误时要调用的用户自定义例程。
get_io_err_handler() 返回当前声明的错误处理例程的地址。
这些例程为模块子例程,只有当调用例程中有 USE SUN_IO_HANDLERS 时,才能访问这些例程。
USE SUN_IO_HANDLERS call set_io_err_handler(iu, subr_name, istat) |
|||
iu |
INTEGER*8 |
输入 |
逻辑单元编号 |
subr_name |
EXTERNAL |
输入 |
用户提供的错误处理程序子例程的名称。 |
istat |
INTEGER*4 |
输出 |
返回状态。 |
USE SUN_IO_HANDLERS call get_io_err_handler(iu, subr_pointer, istat) |
|||
iu |
INTEGER*8 |
输入 |
逻辑单元编号 |
subr_pointer |
POINTER |
输出 |
当前声明的处理程序例程的地址。 |
istat |
INTEGER*4 |
输出 |
返回状态。 |
SET_IO_ERR_HANDLER 设置用户提供的子例程 subr_name,它在出现输入错误时用作逻辑单元 iu 的 I/O 错误处理程序。对于格式化的文件,iu 必须是连接的 Fortran 逻辑单元。如果有错误,istat 将设置为非零值,否则设置为零。
例如,如果在打开逻辑单元 iu 之前调用 SET_IO_ERR_HANDLER,istat 将设置为 1001(“非法单元”)。如果 subr_name 为 NULL,用户错误处理将关闭,且程序恢复到缺省的 Fortran 错误处理。
可使用 GET_IO_ERR_HANDLER 获取当前用作相应逻辑单元的错误处理程序的函数的地址。例如,先调用 GET_IO_ERR_HANDLER 保存当前 I/O,然后再切换到另一个处理程序例程。以后可以通过保存的值恢复错误处理程序。
subr_name 是用户提供的例程的名称,用于处理逻辑单元 iu 上的 I/O 错误。运行时 I/O 库将所有相关信息传递给 subr_name,以使该例程可以诊断问题并在可能的情况下修复错误,然后继续运行。
SUBROUTINE SUB_NAME(UNIT, SRC_FILE, SRC_LINE, DATA_FILE, FILE_POS, CURR_BUFF, CURR_ITEM, CORR_CHAR, CORR_ACTION ) INTENT (IN) UNIT, SRC_FILE, SRC_LINE, DATA_FILE INTENT (IN) FILE_POS, CURR_BUFF, CURR_ITEM INTENT (OUT) CORR_CHAR, CORR_ACTION |
|||
UNIT |
INTEGER*8 |
输入 |
报告错误的输入文件的逻辑单元编号 |
SRC_FILE |
CHARACTER*(*) |
输入 |
引起输入操作的 Fortran 源文件名称。 |
SRC_LINE |
INTEGER*8 |
输入 |
输入操作的 SRC_FILE 中有错误的行号。 |
DATA_FILE |
CHARACTER*(*) |
输入 |
正在读取的数据文件名称。仅适用于已打开的外部文件。如果名称不可用(例如,逻辑单元 5),DATA_FILE 将设置为长度为零的字符数据项。 |
FILE_POS |
INTEGER*8 |
输入 |
在输入文件中的当前位置(以字节数表示)。只有当 DATA_FILE 的名称已知时,才能定义该项。 |
CURR_BUFF |
CHARACTER*(*) |
输入 |
包含输入记录中剩余数据的字符串。错误的输入字符是字符串中的第一个字符。 |
CURR_ITEM |
INTEGER*8 |
输入 |
检测到错误时,记录中已读取的输入项数(包括当前输入项)。例如:READ(12,10)L,(ARR(I),I=1,L) 在此示例中,如果 CURR_ITEM 的值为 15,表示在读取 ARR 的第 14 个元素时出现错误,L 是第一项,ARR(1) 是第二项,依此类推。 |
CORR_CHAR |
CHARACTER |
输出 |
由处理程序返回的用户所提供的更正字符。只有当 CORR_ACTION 不为零时,才使用该值。如果 CORR_CHAR 是无效字符,将会再次调用处理程序,直到返回有效字符。这可能会导致出现无限循环,用户要防止出现这种情形。 |
CORR_ACTION |
INTEGER |
输出 |
指定 I/O 库要采取的更正措施。如果值为零,则不采取特殊措施,库将恢复到其缺省的错误处理。如果值为 1,CORR_CHAR 将返回到 I/O 错误处理例程。 |
I/O 处理程序只能用另一个字符替换一次。它不能用多个字符替换一个字符。
错误恢复算法只能修复当前读取的错误字符,而不能修复在其他上下文环境中已经解释为有效字符的错误字符。例如,在进行列表控制的读取时,如果输入是 "1.234509.8765",而正确的输入应该是 "1.2345 9.8765",I/O 库将在第二个阶段遇到错误,因为它不是有效的数字。但此时不能回去将 '0' 更改为空白。
当前,这种错误处理功能不适用于名称列表控制的输入。在进行名称列表控制的输入时,如果出现错误,不会调用指定的 I/O 错误处理程序。
只能为外部文件而不能为内部文件设置 I/O 错误处理程序,这是因为没有与内部文件关联的逻辑单元。
只能针对语法错误而不能针对系统错误或语义错误(例如溢出的输入值)调用 I/O 错误处理程序。
如果用户提供的 I/O 错误处理程序不断向 I/O 库提供错误的字符,从而导致反复调用用户提供的 I/O 错误处理程序,则可能出现无限循环。如果在同一个文件位置反复出现错误,错误处理程序应该自行终止运行。一种解决方法就是通过将 CORR_ACTION 设置为 0 来采用缺省的错误路径。这样,I/O 库将继续运行并进行正常的错误处理。
INTEGER*4 sh status = sh( string ) |
|||
string |
character*n |
输入 |
包含执行命令的字符串 |
返回值 |
INTEGER*4 |
输出 |
执行的 shell 的退出状态。有关该值的说明,请参见 wait(2)。 |
示例:sh():
character*18 string / ’ls > MyOwnFile.names’ / INTEGER*4 status, sh status = sh( string ) if ( status .ne. 0 ) stop ’sh: error’ ... end |
函数 sh 将 string 作为输入传递给 sh shell,就好像以命令方式键入该字符串。
当前进程将等到命令终止。
函数 sh(3f) 和 system(3f) 将参数字符串传递给 shell 用于执行。它们将参数字符串从 Fortran 字符值转换为 C 字符串值,并将其传递给 C 例程 system(3c)。例程 sh(3f) 和 system(3f) 的不同之处在于,system 在调用 C 例程系统前将刷新 Fortran I/O 缓冲区,而 sh 则不会刷新缓冲区。由于刷新缓冲区需要很长时间,因此,如果 Fortran 输出与调用结果无关,那么优先使用例程 system,而非例程 sh 。
sh() 函数不能安全地用于多线程程序。请勿从多线程或并行程序中调用该函数。
另请参见:execve(2)、wait(2) 和 system(3c)。
注意:string 不能超过 1,024 个字符。
该函数的调用方式如下所示:
INTEGER*4 signal 或 INTEGER*8 signal n = signal( signum, proc, flag ) |
||||
signum |
INTEGER*4 |
输入 |
信号编号,请参见 signal(3) |
|
proc |
例程名称 |
输入 |
处理例程的用户信号名称;必须在外部语句中。 |
|
flag |
INTEGER*4 |
输入 |
flag < 0:将 proc 用作信号处理程序 flag ≥ 0:忽略 proc;传递 flag 来指定操作: flag = 0:使用缺省操作 flag = 1:忽略该信号 |
|
返回值 |
INTEGER*4 |
输出 |
n=-1:系统错误 n>0:上一个操作的定义 n>1:n 是本应调用的例程的地址 n<-1:如果 signum 是有效的信号编号:n 是本应调用的例程的地址。如果 signum 不是有效的信号编号:n 是错误编号。 |
|
INTEGER*8 |
在 64 位环境中,必须将 signal 和接收其输出的变量声明为 INTEGER*8 |
如果调用 proc,则将信号编号作为整数参数传递给它。
如果进程引发信号,缺省的操作通常是清理并中止。信号处理例程提供了捕捉特定异常或中断以便进行特殊处理的功能。
返回值可以用于后续 signal 调用中,以便恢复以前的操作定义。
即使没有错误,您也有可能会获得负返回值。事实上,如果将有效的信号编号传递给 signal(),获得的返回值小于 -1,这是正常的。
floatingpoint.h 定义 proc 值 SIGFPE_DEFAULT、SIGFPE_IGNORE 和 SIGFPE_ABORT。请参见1.4.26.1 floatingpoint.h:Fortran IEEE 定义。
在 64 位环境中,必须将 signal 和接收其输出的变量声明为 INTEGER*8,以免可能返回的地址被截断。
另请参见 kill(1)、signal(3) 和 kill(3F) 以及《数值计算指南》。
该子例程的调用方式如下所示:
call sleep( itime ) |
|||
itime |
INTEGER*4 |
输入 |
要休止的秒数 |
由于系统守时粒度的影响,实际时间最多可能会比 itime 少 1 秒钟。
示例:sleep():
INTEGER*4 time / 5 / write(*,*) ’Start’ call sleep( time ) write(*,*) ’End’ end |
另请参见 sleep(3)。
这些函数返回以下信息:
stat 和 lstat 都是按文件名查询。fstat 是按逻辑单元查询。
该函数的调用方式如下所示:
INTEGER*4 stat ierr = stat ( name, statb ) |
|||
name |
character*n |
输入 |
文件的名称 |
statb |
INTEGER*4 |
输出 |
文件的状态结构,由 13 个元素组成的数组 |
返回值 |
INTEGER*4 |
输出 |
ierr=0:OK ierr>0:错误代码 |
示例 1:stat():
character name*18 /’MyFile’/ INTEGER*4 ierr, stat, lunit/1/, statb(13) open( unit=lunit, file=name ) ierr = stat ( name, statb ) if ( ierr .ne. 0 ) stop ’stat: error’ write(*,*)’UID of owner = ’,statb(5),’, 1 blocks = ’,statb(13) end |
该函数的调用方式如下所示:
INTEGER*4 fstat ierr = fstat ( lunit, statb ) |
|||
lunit |
INTEGER*4 |
输入 |
逻辑单元编号 |
statb |
INTEGER*4 |
输出 |
文件的状态:由 13 个元素组成的数组 |
返回值 |
INTEGER*4 |
输出 |
ierr=0:OK ierr>0:错误代码 |
示例 2:fstat():
character name*18 /’MyFile’/ INTEGER*4 fstat, lunit/1/, statb(13) open( unit=lunit, file=name ) ierr = fstat ( lunit, statb ) if ( ierr .ne. 0 ) stop ’fstat: error’ write(*,*)’UID of owner = ’,statb(5),’, 1 blocks = ’,statb(13) end |
该函数的调用方式如下所示:
ierr = lstat ( name, statb ) |
|||
name |
character*n |
输入 |
文件名 |
statb |
INTEGER*4 |
输出 |
文件夹的状态数组,共 13 个元素 |
返回值 |
INTEGER*4 |
输出 |
ierr=0:OK ierr>0:错误代码 |
示例 3:lstat():
character name*18 /’MyFile’/ INTEGER*4 lstat, lunit/1/, statb(13) open( unit=lunit, file=name ) ierr = lstat ( name, statb ) if ( ierr .ne. 0 ) stop ’lstat: error’ write(*,*)’UID of owner = ’,statb(5),’, 1 blocks = ’,statb(13) end |
INTEGER*4 数组 statb 中返回的信息的含义在 stat(2) 的 stat 结构中进行了介绍。
备用值不包括在内。顺序如下表所示:
statb(1) statb(2) statb(3) statb(4) statb(5) statb(6) statb(7) statb(8) statb(9) statb(10) statb(11) statb(12) statb(13) |
索引节点所在的设备 相应索引节点的编号 保护 文件的硬链接数 属主的用户 ID 属主的组 ID 属于设备的索引节点的设备类型 文件的总大小 上次访问文件的时间 上次修改文件的时间 上次更改文件状态的时间 文件系统 I/O 操作的最佳块大小 分配的实际块数 |
另请参见 stat(2)、access(3F)、perror(3F) 和 time(3F)。
注意:路径名长度不能超过 <sys/param.h> 中定义的 MAXPATHLEN 值。
它们是 stat、lstat 和 fstat 的 64 位“长文件”版本。除了由 13 个元素组成的数组 statb 必须声明为 INTEGER*8 之外,这些例程与非 64 位例程相同。
INTEGER*4 system status = system( string ) |
|||
string |
character*n |
输入 |
包含执行命令的字符串 |
返回值 |
INTEGER*4 |
输出 |
执行的 shell 的退出状态。有关该值的说明,请参见 wait(2)。 |
示例:system():
character*8 string / ’ls s*’ / INTEGER*4 status, system status = system( string ) if ( status .ne. 0 ) stop ’system: error’ end |
函数 system 将 string 作为输入传递给 shell,就好像以命令方式键入该字符串。注意:string 不能超过 1,024 个字符。
如果 system 可以找到环境变量 SHELL,则 system 会将 SHELL 值用作命令解释程序 (shell);否则使用 sh(1)。
当前进程将等到命令终止。
一直以来,对 cc 开发时进行了不同的假设:
如果 cc 调用 system,则 shell 始终为 Bourne shell。
system 函数会刷新打开的所有文件:
对于输出文件,缓冲区将刷新到实际文件中。
对于输入文件,无法预见指针的位置。
函数 sh(3f) 和 system(3f) 将参数字符串传递给 shell 用于执行。它们将参数字符串从 Fortran 字符值转换为 C 字符串值,并将其传递给 C 例程 system(3c)。例程 sh(3f) 和 system(3f) 的不同之处在于,system 在调用 C 例程 system 前将刷新 Fortran I/O 缓冲区,而 sh 则不会刷新缓冲区。由于刷新缓冲区需要很长时间,因此,如果 Fortran 输出与调用结果无关,那么优先使用例程 system,而非例程 sh 。
另请参见:execve(2)、wait(2) 和 system(3)。
system() 函数不能安全地用于多线程程序。请勿从多线程或并行程序中调用该函数。
这些例程具有以下函数:
标准版本:获取以整数表示的系统时间(自 GMT 1970 年 1 月 1 日 0 时起至今的秒数) VMS 版本:获取以字符表示的系统时间 (hh:mm:ss) |
|
将系统时间转换为 ASCII 字符串。 |
|
将系统时间分解成当地时间的月份、日期等等。 |
|
将系统时间分解成 GMT 时间的月份、日期等等。 |
time() 函数的调用方式如下所示:
INTEGER*4 time 或 INTEGER*8 n = time() 标准版本 |
|||
返回值 |
INTEGER*4 |
输出 |
自 GMT 1970 年 1 月 1 日 0:0:0 时起至今的时间(秒) |
INTEGER*8 |
输出 |
在 64 位环境中,time 返回 INTEGER*8 值 |
函数 time() 返回自 GMT 1970 年 1 月 1 日 00:00:00 起至今的时间(秒)整数。这是操作系统时钟值。
示例:在操作系统中使用的 time() 标准版本:
demo% cat ttime.f INTEGER*4 n, time n = time() write(*,*) ’Seconds since 0 1/1/70 GMT = ’, n end demo% f95 ttime.f demo% a.out Seconds since 0 1/1/70 GMT = 913240205 demo% |
函数 ctime 转换系统时间 stime,并以由 24 个字符组成的 ASCII 字符串返回该值。
该函数的调用方式如下所示:
CHARACTER ctime*24 string = ctime( stime ) |
|||
stime |
INTEGER*4 |
输入 |
通过 time()(标准版本)获得的系统时间 |
返回值 |
character*24 |
输出 |
以字符串表示的系统时间。ctime 和 string 声明为 character*24。 |
下面的示例中显示了 ctime 返回值的格式。ctime(3C) 手册页中对此进行了介绍。
示例:ctime():
demo% cat tctime.f character*24 ctime, string INTEGER*4 n, time n = time() string = ctime( n ) write(*,*) ’ctime: ’, string end demo% f95 tctime.f demo% a.out ctime: Wed Dec 9 13:50:05 1998 demo% |
该子例程的调用方式如下所示:
call ltime( stime, tarray ) |
|||
stime |
INTEGER*4 |
输入 |
通过 time()(标准版本)获得的系统时间 |
tarray |
INTEGER*4(9) |
输出 |
当地系统时间,包括年份、月份、日期等 |
有关 tarray 中各元素的含义,请参见下一节。
demo% cat tltime.f integer*4 stime, tarray(9), time stime = time() call ltime( stime, tarray ) write(*,*) ’ltime: ’, tarray end demo% f95 tltime.f demo% a.out ltime: 25 49 10 12 7 91 1 223 1 demo% |
该例程将系统时间分解成 GMT 时间的月份、日期等。
此子例程的调用方式如下所示:
call gmtime( stime, tarray ) |
|||
stime |
INTEGER*4 |
输入 |
通过 time()(标准版本)获得的系统时间 |
tarray |
INTEGER*4(9) |
输出 |
GMT 系统时间,包括年份、月份、日期等 |
demo% cat tgmtime.f integer*4 stime, tarray(9), time stime = time() call gmtime( stime, tarray ) write(*,*) ’gmtime: ’, tarray end demo% f95t tgmtime.f demo% a.out gmtime: 12 44 19 18 5 94 6 168 0 demo% |
下面是 ltime 和 gmtime 的 tarray() 值:索引、单位和范围:
1 2 3 4 5 |
秒 (0 - 61) 分钟 (0 - 59) 小时 (0 - 23) 一个月中的天数 (1 - 31) 自一月起的月份 (0 - 11) |
6 7 8 9 |
年份-1900 星期几(星期日= 0) 一年中的天数 (0 - 365) 夏令时,如果实行夏令时,则为 1。 |
C 库例程 ctime(3C) 对这些值进行了定义,它解释了系统可能会返回值大于 59 的秒数的原因。另请参见:idate(3F) 和 fdate(3F)。
这些是例程 ctime、gmtime 和 ltime 的对应版本,用于在 64 位环境中进行移植。除了输入变量 stime 必须是 INTEGER*8 之外,它们与这些例程相同。
在 32 位环境中使用且 stime 为 INTEGER*8 时,如果 stime 值超出 INTEGER*4 范围,ctime64 的返回值全是星号,而 gmtime 和 ltime 在 tarray 数组中填入 -1。
ttynam 和 isatty 处理终端端口的名称。
函数 ttynam 返回与逻辑单元 lunit 关联的终端设备的空白填充路径名。
该函数的调用方式如下所示:
CHARACTER ttynam*24 name = ttynam( lunit ) |
|||
lunit |
INTEGER*4 |
输入 |
逻辑单元 |
返回值 |
character*n |
输出 |
如果返回非空白字符串:name 为 lunit 中设备的路径名。大小 n 必须足够大,以便能容纳最长的路径名。 如果返回空白字符串(全部为空白):lunit 与目录 /dev 中的终端设备没有关联。 |
函数 isatty 根据逻辑单元 lunit 是否为终端设备返回 true 或 false。
该函数的调用方式如下所示:
terminal = isatty( lunit ) |
|||
lunit |
INTEGER*4 |
输入 |
逻辑单元 |
返回值 |
LOGICAL*4 |
输出 |
terminal=true:是终端设备 terminal=false:不是终端设备 |
示例:确定 lunit 是否为 tty:
character*12 name, ttynam INTEGER*4 lunit /5/ logical*4 isatty, terminal terminal = isatty( lunit ) name = ttynam( lunit ) write(*,*) ’terminal = ’, terminal, ’, name = "’, name, ’"’ end |
输出为:
terminal = T, name = "/dev/ttyp1 " |
该函数的调用方式如下所示:
INTEGER*4 unlink n = unlink ( patnam ) |
|||
patnam |
character*n |
输入 |
文件名 |
返回值 |
INTEGER*4 |
输出 |
n=0:OK n>0:错误 |
函数 unlink 删除由路径名 patnam 指定的文件。如果这是指向该文件的最后一个链接,则该文件的内容将会丢失。
示例:unlink()-删除文件 tunlink.data:
demo% cat tunlink.f call unlink( ’tunlink.data’ ) end demo% f95 tunlink.f demo% ls tunl* tunlink.f tunlink.data demo% a.out demo% ls tunl* tunlink.f |
另请参见:unlink(2)、link(3F) 和 perror(3F)。注意:路径名长度不能超过 <sys/param.h> 中定义的 MAXPATHLEN 值。
该函数的调用方式如下:
INTEGER*4 wait n = wait( status ) |
|||
status |
INTEGER*4 |
输出 |
子进程的终止状态 |
返回值 |
INTEGER*4 |
输出 |
n>0:子进程的进程 ID。 n<0:n 为系统错误代码;请参见 wait(2)。 |
wait 暂停调用程序,直到收到信号或其中一个子进程终止。如果自上一次执行 wait 后所有子进程都已终止,则立即返回子进程 ID。如果没有子进程,则立即返回错误代码。
示例:使用 wait() 的代码片段:
INTEGER*4 n, status, wait … n = wait( status ) if ( n .lt. 0 ) stop ’wait: error’ … end |
另请参见:wait(2)、signal(3F)、kill(3F) 和 perror(3F)。