这是一个奇怪的问题。我正在将包含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
请注意,此代码适用于小端机器。
答案 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)
谢谢大家。