错误:逻辑运算符“.eq.”的操作数 (1) 处为 INTEGER(4)/HOLLERITH

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)

jme*_*e52 5

您收到错误是因为您的代码使用了编译器 (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)
  1. ID使用不符合标准的integer*4语法将变量隐式声明为 4 字节整数(有关更多信息,请参阅Fortran:integer*4 vs integer(4) vs integer(kind=4) )。

  2. 该语句使用编辑描述符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 字节变量,这看起来很好。

  3. IF语句将 Hollerith 变量ID与 Hollerith 常量进行比较4HEOT(在给定上下文的情况下,可能是为了检查您是否位于表末尾)。即使建议的标准扩展似乎也不支持这一点,但是,嘿,最后我们有两个由 4 个字符组成的字符串,因此确定它们是否相等应该不会很困难。只是遗憾的是 gfortran 从未被告知如何这样做(讽刺模式关闭)。

你该如何解决这个问题?

我可以想到多种可能性(除了找到编写这段代码的人,他可能已经退休,并很好地要求他修复它)。未来最好的解决方案是选项 1:

选项1

通过引入新的字符变量来重写代码,以便所有具有字符编辑描述符 (A[ w ]) 的 I/O 对应于列出的字符变量。将有问题的 Hollerith 常数替换为字符常数"EOT "

选项2

一些 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常数。

选项3

使用可以处理您的代码的编译器 - 我相信 Intel Fortran 可以编译并运行它。

此选项不符合标准,因此不可移植,并且可能在将来(对您或其他人)造成类似于您现在遇到的问题。它甚至不符合 FORTRAN 77 标准附录 C 中的扩展建议。这种选择需要更少的工作,但代价是无法改进任何东西,也无法在未来保持问题的完整性——那时使用 FORTRAN 66 编码的人将会越来越少。