Kha*_*han 3 fortran gfortran fortran77
我是 Fortran 新手。所以我需要帮助。我在 SUSE 上使用 gfortran 编译我的代码并收到以下错误:
200 IF ( ID .EQ. 4HEOT ) GO TO 20
1
Error: Operands of logical operator '.eq.' at (1) are INTEGER(4)/HOLLERITH
Run Code Online (Sandbox Code Playgroud)
代码的主文件附加在下面的链接中,其中 1818 行显示了错误。
我的文件的链接是:https://files.engineering.com/getfile.aspx? folder=cd6961f3-d38b-4e61-a43d-269fa18c7d11&file=sfeng.f
如何解决这个问题?
对于简化/最小的示例,我在此处添加了代码:
SUBROUTINE CDRD ( II )
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
c ohad 15/7/08
c IMPLICIT INTEGER*8 (I-N)
IMPLICIT INTEGER*4 (I-N)
C*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=C
C THIS SUBROUTINE READS PROPULSION SYSTEM DRAG DATA. C
C C
C USE NON-ZERO "II" TO WRITE TABLE DATA. C
C*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=C
CHARACTER*80 TITLE, CDFILE
DIMENSION A(100),IREP(30),IDD(4)
COMMON /UNITS / IU5, IU6, IU7, IU8, IU9, IU16, IU17, IU18
COMMON /CYUNIT/ IU3, IU4, IU10, IU11, IU12, IU13, IU14, IU15
COMMON /CYICOM/ IENG, IPRINT, NPRINT, NPDRY, NPAB, NITMAX,
1 IVAT, LIMCD
COMMON /CDSIZE/ CDNOZ(5000)
COMMON /ICDTAB/ ICDDAT(10), NTBL
COMMON /CDLOC/ LOCCD(5)
COMMON /CDFIL / CDFILE, A10, A9REF, A10REF, XNOZ, XNREF, RCRV,
1 NAB, NABREF
C======================================================================C
IU12 = 12
IUNIT = IU12
OPEN (UNIT=IUNIT, FILE=CDFILE, STATUS='OLD', ERR=9992)
REWIND (IUNIT)
NTBL = 0
NMAX = 5000
MR = 0
IF ( NTBL .EQ. 0 ) THEN
LOC = 1
DO 10 M = 1,NMAX
10 CDNOZ(M) = 0.
ENDIF
20 READ (IU12, 5000, END=400, ERR=6666 ) IP, ITABNO, TITLE
30 IF(ITABNO .EQ. 0) THEN
NREM = NMAX-LOC
IF ( II .GT. 0 ) THEN
WRITE(IU6,5010) NTBL
WRITE(IU6,5020) (N, ICDDAT(N), LOCCD(N), N = 1,NTBL)
WRITE(IU6,5030) NMAX, NREM
ENDIF
IF( MR .GT. 0 ) WRITE(IU6,5040) (IREP(IQ), IQ = 1,MR)
RETURN
ELSE
NTBL = NTBL+1
ICDDAT(NTBL) = ITABNO
LOCCD(NTBL) = LOC
IF ( NTBL .GT. 1 ) THEN
DO 40 I = 2,NTBL
IF ( ITABNO .EQ. ICDDAT(I-1) ) GO TO 50
40 CONTINUE
GO TO 150
50 MLOC = LOCCD(I-1)
ILOC = MLOC
LOCCD(I-1) = LOC
NTBL = NTBL - 1
MR = MR + 1
IREP(MR) = ITABNO
LIBLOC = 100000
DO 60 IRK = 1,NTBL
LIBRA = LOCCD(IRK)
IF ( (LIBRA .GE. MLOC) .AND. (LIBRA .LT. LIBLOC) )
* LIBLOC = LIBRA
60 CONTINUE
LEO = LIBLOC - MLOC
IF ( LEO .NE. 0 ) THEN
IZAR = LOC - 1
DO 70 I = LIBLOC,IZAR
CDNOZ(MLOC) = CDNOZ(I)
MLOC = MLOC + 1
70 CONTINUE
DO 80 I = 1,NTBL
LLOC = LOCCD(I)
IF ( LLOC .GT. ILOC ) LOCCD(I) = LLOC - LEO
80 CONTINUE
ENDIF
DO 90 I = MLOC,LOC
90 CDNOZ(I) = 0.
LOC = MLOC
ENDIF
ENDIF
150 IF ( II .GT. 0 ) THEN
WRITE ( IU6, 5060 ) ITABNO, TITLE
IP = 1
ENDIF
ICC = 0
LZ = LOC
DO 180 ICL = 1,4
180 IDD(ICL) = 4H
190 IDL = ID
READ (IU12, 5070, END=200, ERR=6666 ) ID, N, (A(I), I = 1,N)
200 IF ( ID .EQ. 4HEOT ) GO TO 20
ICC = ICC + 1
IF ( ICC .LE. 4 ) IDD(ICC) = ID
IF ( ID .EQ. IDL ) GO TO 280
IF ( ID .NE. IDD(4) ) GO TO 210
IF ( IDL .EQ. IDD(2) ) GO TO 280
LOC = LE
L = LX
GO TO 220
210 CDNOZ(LOC) = N
L = LOC
IF ( ID .EQ. IDD(3) ) LX = L
IF ( ID .NE. IDD(2) ) GO TO 260
LY = L
LZ = LZ + 1
GO TO 260
C ... WRITE THE TABULAR DATA.
220 IF ( IP .NE. 0 ) THEN
LY = LY+1
WRITE(IU6,5080) IDD(1), CDNOZ(LZ), IDD(2), CDNOZ(LY)
JF = 0
M = N
LF = LX
240 NP = M
IF ( M .GT. 8 ) NP = 8
M = M - NP
LE = LF + NP
LF = LF + 1
WRITE(IU6,5090) IDD(3), (CDNOZ(I), I = LF,LE)
LF = LE
JE = JF + NP
JF = JF + 1
WRITE(IU6,5090) IDD(4), (A(I), I = JF,JE)
JF = JE
IF( M .GT. 0 ) GO TO 240
ENDIF
260 DO 270 I = 1,N
LOC = LOC + 1
CDNOZ(LOC) = A(I)
270 CONTINUE
LE = LOC
IF ( ID .EQ. IDD(4) ) CDNOZ(LOC+2) = 1.
LOC = L + 2*N + 6
IF ( LOC .GT. NMAX ) GO TO 300
GO TO 190
280 CDNOZ(LOC) = CDNOZ(LX)
L = LOC
DO 290 I = 1,N
LOC = LOC + 1
CDNOZ(LOC) = CDNOZ(LX+I)
290 CONTINUE
GO TO 220
300 WRITE(IU6,5100) ITABNO
ITABNO = 0
GO TO 30
400 CONTINUE
ITABNO = 0
GO TO 30
6666 CONTINUE
WRITE(IU6,6669) IU12
STOP
5000 FORMAT (I1,I4,A)
5010 FORMAT (//,33X,'TABLE DATA INPUT SUMMARY, ',I3,' TABLES',//,
1 28X,'TABLE NUMBER REFERENCE NUMBER ARRAY LOCATION')
5020 FORMAT (33X,I2,12X,I5,14X,I5)
5030 FORMAT (/,36X,'DATA STORAGE ALLOCATION ',I7,/,
1 36X,'DATA STORAGE NOT USED ',I7,/)
5040 FORMAT(10X,'THE FOLLOWING TABLES HAVE BEEN REPLACED',10(I5,','))
5060 FORMAT (//,3X,I4,A,/)
5070 FORMAT(A4,I3,3X,(T11,7F10.0))
5080 FORMAT(1X,A4,' = ',E13.5,1X,A4,' = ',E13.5)
5090 FORMAT(20X,A4,1X,8E13.5)
5100 FORMAT (' ********* TABLE OVER FLOW, TABLE ',I5,' NOT LOADED')
6669 FORMAT(/,' ERROR READING ENGINE TABULAR INPUT DATA FROM UNIT',
* I3,'.',/,' PROGRAM ABORTED IN SUBROUTINE TABRD.')
9992 CONTINUE
WRITE(IU6,9999) 'ERROR OPENING THE INPUT FILE ', CDFILE,
* ' AS UNIT ', IUNIT, '.',
* 'PROGRAM ABORTED IN SUBROUTINE CDRD.'
9999 FORMAT(//,1X,2A,/,A,I2,A,/,1X,A,/)
STOP
END
Run Code Online (Sandbox Code Playgroud)
您收到错误是因为您的代码使用了编译器 (gfortran) 不支持的非标准 FORTRAN 77 代码。
正如 gfortran 检测到的那样,您正在使用 Hollerith 常数4HEOT。
Hollerith 是字符类型的前身。最后一个允许使用 Holleriths 的 Fortran 标准是 FORTRAN 66 (ANSI X3.9-1966)。尽管不是 FORTRAN 77 标准的一部分,但它包含一个附录 C,其中向希望将其作为扩展提供的处理器提供了建议。您对 Hollerith 的使用甚至没有遵循这些建议,特别是:
C3。霍尔瑞斯常数的限制
Hollerith 常量只能出现在 DATA 语句和 CALL 语句的参数列表中。
您的代码的相关语句是
IMPLICIT INTEGER*4 (I-N)
READ (IU12, 5070, END=200, ERR=6666 ) ID, N, (A(I), I = 1,N)
200 IF ( ID .EQ. 4HEOT ) GO TO 20
5070 FORMAT(A4,I3,3X,(T11,7F10.0))
Run Code Online (Sandbox Code Playgroud)
ID使用不符合标准的integer*4语法将变量隐式声明为 4 字节整数(有关更多信息,请参阅Fortran:integer*4 vs integer(4) vs integer(kind=4) )。
该语句使用编辑描述符READ分配一个值。这是 FORTRAN 77 标准的附录 C 允许读取 Hollerith 变量的方式:IDA4
C1。霍尔瑞斯数据类型
Hollerith 是一种数据类型;但是,符号名称不能是 Hollerith 类型。除常量外,霍尔瑞斯数据以整数、实数或逻辑类型名称的形式进行标识。不得以类型字符为幌子来识别它们。[...]
Hollerith 数据是一串字符。[...] 空白字符在 Hollerith 数据中很重要。Hollerith 数据可能具有与其他数据类型不同的内部表示。
整数、实数或逻辑类型的实体可以通过 DATA 语句 (C4) 或 READ 语句 (C6) 用 Hollerith 值来定义。[...] 当使用 Hollerith 值定义整数、实数或逻辑类型的实体时,该实体及其关联对象将无法定义用作整数、实数或逻辑数据。
C6。Hollerith 数据的编辑
当输入/输出列表项的类型为整数、实数或逻辑时,Aw 编辑描述符可以与 Hollerith 数据一起使用。输入时,输入列表项将使用 Hollerith 数据定义。输出时,列表项必须使用 Hollerith 数据定义。
编辑与字符数据的 Aw 编辑所述相同,只是 len 是可以存储在单个数字存储单元中的最大字符数。
所以现在整型变量ID包含描述 4 个字符的 Hollerith 数据。每个字节一个字符,并ID定义为 4 字节变量,这看起来很好。
该IF语句将 Hollerith 变量ID与 Hollerith 常量进行比较4HEOT(在给定上下文的情况下,可能是为了检查您是否位于表末尾)。即使建议的标准扩展似乎也不支持这一点,但是,嘿,最后我们有两个由 4 个字符组成的字符串,因此确定它们是否相等应该不会很困难。只是遗憾的是 gfortran 从未被告知如何这样做(讽刺模式关闭)。
我可以想到多种可能性(除了找到编写这段代码的人,他可能已经退休,并很好地要求他修复它)。未来最好的解决方案是选项 1:
通过引入新的字符变量来重写代码,以便所有具有字符编辑描述符 (A[ w ]) 的 I/O 对应于列出的字符变量。将有问题的 Hollerith 常数替换为字符常数"EOT "。
一些 Fortran 编译器很乐意使用字符编辑描述符读取和写入整数,并且不太擅长记住这些整数是 Hollerith 变量而不是实际整数。使用这些编译器之一(例如,gfortran):如您所见,它认为这ID仍然是一个整数,而不是 Hollerith。因此,假设ID仍然是一个整数,并且读取操作只是将 4 个字符的变量读入其中。
在这种情况下,您可以将 Hollerith 常量替换为其要编码的整数。您可以通过定义来做到这一点
DATA ID_EOT/4HEOT /
Run Code Online (Sandbox Code Playgroud)
现在ID_EOT有一个整数值(可能ICHAR("E")+256*(ICHAR("O")+256*(ICHAR("T")+256*ICHAR(" ")))),您可以将有问题的IF语句替换为
200 IF ( ID .EQ. ID_EOT ) GO TO 20
Run Code Online (Sandbox Code Playgroud)
此选项不符合标准,因此不可移植,并且可能在将来(对您或其他人)造成类似于您现在遇到的问题。但是,它至少符合有关如何实现扩展的书面建议,这比您现在拥有的更好。
以下编译器(已检查版本)似乎支持带有 Hollerith 的 DATA 语句:Intel (17.0.4)、gfortran (7.3.0)、CRAY (8.5.8)、PGI (18.4)、NAG (6.2) 和 Sun (8.8)。除了 NAG 编译器之外,所有这些编译器似乎都允许使用字符编辑描述符读取/写入整数。请注意,测试非常有限,仅针对4HEOT常数。
使用可以处理您的代码的编译器 - 我相信 Intel Fortran 可以编译并运行它。
此选项不符合标准,因此不可移植,并且可能在将来(对您或其他人)造成类似于您现在遇到的问题。它甚至不符合 FORTRAN 77 标准附录 C 中的扩展建议。这种选择需要更少的工作,但代价是无法改进任何东西,也无法在未来保持问题的完整性——那时使用 FORTRAN 66 编码的人将会越来越少。