FORTRAN 77 - 将8个a1字符打包成一个整数* 8

时间:2015-03-28 20:21:46

标签: fortran

这是一个奇怪的问题。我正在将包含8个a1字符的传统F77代码转换为64位整数,并且代码在当天重新运行。但是在今天的世界中,我需要将8个字符转换为整数* 8变量,并且在这种情况下代码失败。它一直工作,直到它包含4个字符,但字符5只是旋转并覆盖第一个打包字符。这是“hello world”的示例输出,值得注意的是整数* 8变量OUTBUF突然收缩并且似乎也转换为整数* 4变量:

    hello world
in='hello world                                                             '
cn= 8,k=1,j='h',outbuf(k)='h       '
cn=16,k=1,j='e',outbuf(k)='he      '
cn=24,k=1,j='l',outbuf(k)='hel     '
cn=32,k=1,j='l',outbuf(k)='hell'
cn=40,k=1,j='o',outbuf(k)='oell'
 # SPACE
cn= 8,k=2,j='w',outbuf(k)='w       '
cn=16,k=2,j='o',outbuf(k)='wo      '
cn=24,k=2,j='r',outbuf(k)='wor     '
cn=32,k=2,j='l',outbuf(k)='worl'
cn=40,k=2,j='d',outbuf(k)='dorl'
 # SPACE

我已将代码提炼到此代码段,任何人都知道F77,看看发生了什么?感谢。

          program cow

      implicit integer*8 (a-z)
      integer inbuf(72)
      integer*8 outbuf(40)

c将整数* 1更改为整数* 8修复了问题!!!!!!!!!

      integer*1 j

      read 99, inbuf
99    FORMAT(BZ,72a1)
      print 1, inbuf
 1    format("in='",72a1,"'")

      IP=0
      k = 1

      DO 100 I=1,40
         OUTBUF(I)= 8H
 100  CONTINUE

 200  IP=IP+1
      IF(IP.GT.72) GO TO 6000
      J= INBUF(IP)
      IF(J.EQ." ") GO TO 6000
      CN = (MOD(CP,8)+1) * 8
      outbuf(k) = outbuf(k) .and. (.not. lshift('377'O, (cn-8)))
      OUTBUF(K) = OUTBUF(K) .OR. lSHiFT( j,(CN-8))
      print 4301, cn, k, j, outbuf(k)
 4301 format("cn=",i2,",k=",i1,",j='",a1,"',outbuf(k)='",a8,"'")
      CP=CP+1
      GO TO 200

 6000 continue
      print *,'# SPACE'
      call exit
      end

请注意,此代码适用于小端机器。

4 个答案:

答案 0 :(得分:1)

  

"所以忽略代码,FORTRAN 77中的任务就是打包8   a1字符为整数* 8变量。 "

好的,但在此之后我将不得不洗手:

INTEGER*8  i
CHARACTER*8  ch

EQUIVALENCE (i, ch)

ch = "abcdefgh"

当然,转移更好,但肯定不是FORTRAN 77。

答案 1 :(得分:0)

这是一个非常可怕的代码,可以在较新的Fortran中做一些微不足道的事情 (自F77 ......)。

你可以用

之类的东西替换整个例行程序
  integer, parameter :: llen=72
  character(len=llen) inbuf
  character(len=llen) output
  integer :: i,k
  read (*,'(BZ,A)') outbuf
  k = 1
  do i=1,llen
    if (inbuf(i) /= ' ') then
       outbuf(k) = inbuf(i)
       if (mod(k,8) == 0) then
           ! Some output goes here
       endif 
       k = k + 1
    end if
 end do

答案 2 :(得分:0)

好的,这是第二个答案; 首选,最好使用字符重写程序。

警告:整数* 8是非标准的。

program main
  character(len=8) :: c
  integer*8 output(10)
  c = "12345678"
  call foo(output,10,c)
  write (*,'(Z16)') output(1)
end program main

subroutine foo(a,n,b)
  integer*8 :: a(1)
  character(len=8) :: b

  a(1) = transfer(b,mold=a(1))
end subroutine foo

答案 3 :(得分:0)

正如我所提到的,这个输入解析器采用Hollerith数据,并以不区分大小写的方式将其与数据库中的Hollerith数据进行比较。该代码是为60-64位大端机器编写的,并使用硬件特定的移位,掩码,AND和OR将A1输入字符打包成A8 INTEGER字,以便与数据库进行比较。

虽然我确实设法调整所有这些移位,掩码和按位操作以在64位小端机器(x86_64)上工作,但它是一个PITA,只能用于pgf77和ifort,gfortran没有那废话!所以这就是我提出的,更好,独立于硬件,并且适用于我可用的所有编译器:

  • 解析器仍接受存储在INTEGER(80a1)中的A1输入字符,并以INTEGER * 8字返回打包的A8字符,以便向后兼容。

  • 它将80a1输入数据转换为CHARACTER * 80变量IN0:

      write( in0, '80a1' ) (inbuf(i), i=1,80)
    
  • 由于这是所有ASCII数据,我使用此代码将IN0中的所有内容小写为新字符* 80变量IN:

      do i = 1, len(in0)
      #if (! defined __GFORTRAN__)
          j = ichar(in0(i:i))
          if (j>= ichar("A") .and. j<=ichar("Z") ) then
             in(i:i) = char(ichar(in0(i:i))+32)
          else
               in(i:i) = in0(i:i)
          end if
      #else
          j = iachar(in0(i:i))
          if (j>= iachar("A") .and. j<=iachar("Z") ) then
             in(i:i) = achar(iachar(in0(i:i))+32)
          else
               in(i:i) = in0(i:i)
          end if
      #endif
      end do
    
  • 这是一个简单的事情,循环遍历CHARACTER * 80变量IN,将非空格字符收集到字符变量WORD中,然后将它们编码为INTEGER * 8数组OUTBUF:

      read( word(1:8), ‘a8' ) outbuf(outbufc)
    

谢谢大家。