gpt4 book ai didi

linux - Fortran 77 从旧的 sun 机器读取未格式化的序列数据

转载 作者:太空宇宙 更新时间:2023-11-04 09:01:12 24 4
gpt4 key购买 nike

我正在将一个旧的数学模型(1995 年到 2000 年之间)移植到当前的 Linux 机器上。为此,我调整了所有 makefile,如下所示:

FORTRAN  = gfortran # f90 -f77 -ftrap=%none
OPTS = -O -u -lgfortran -g -fconvert="big-endian" # -O -u
NOOPT =
LOADER = gfortran #f90
LOADOPTS = #-lf77compat

和:

SYSFFLAGS   = -O0 -u -g -fconvert="big-endian" # -f77=input
SYSCFLAGS = -DX_WCHAR
SYSLDFLAGS =
SYSCPPFLAGS = -DSYS_UNIX -DCODE_ASCII -DCODE_IEEE # -DSYS_Sun
SYSAUTODBL = -fdefault-real-8 #-r8
SYSDEBUG = -g
SYSCHECK = -C
LINKOPT =
CPPOPT =

SHELL = /bin/sh
CC = cc

FC = gfortran # f90
LD = gfortran # f90
AR = ar vru
RM = rm -f
CP = cp
MV = mv -f
LN = ln -s

所以我替换了所有过时的编译器/选项以便能够编译代码。之后,它生成没有错误的二进制文件。请注意,# 符号后面的所有选项都是 Makefile 中的原始选项。

因此,在运行程序时,无法读取样本数据。 IMO 这些文件是在 Sun 机器上以未格式化序列模式创建的。以下十六进制转储属于我需要读取的文件。

0000000: 0000 0400 2020 2020 2020 2020 2020 2020  ....
0000010: 3930 3130 7465 7374 2d63 3031 2020 2020 9010test-c01
0000020: 2020 2020 4741 5520 2020 2020 2020 2020 GAU
0000030: 2020 2020 2020 2020 2020 2020 2020 2020
0000040: 2020 2020 2020 2020 2020 2020 2020 2020
0000050: 2020 2020 2020 2020 2020 2020 2020 2020
...
...
0000390: 2020 2020 2020 2020 2020 2020 2020 2020
00003a0: 2020 2020 2020 2020 2020 2020 2020 2020
00003b0: 2020 2020 3139 3936 3037 3232 2032 3030 19960722 200
00003c0: 3434 3920 4147 434d 352e 3420 2020 2020 449 AGCM5.4
00003d0: 2020 2020 3230 3030 3036 3134 2031 3230 20000614 120
00003e0: 3831 3720 6869 726f 2020 2020 2020 2020 817 hiro
00003f0: 2020 2020 2020 2020 2020 2020 2020 2034 4
0000400: 3039 3630 0000 0400 0002 8000 bef7 21f3 0960..........!.
0000410: bf3c 55ab bf7a 8f71 bf99 e26a bfb2 db4e .<U..z.q...j...N
0000420: bfc7 425f bfd6 64b1 bfdf d44f bfe3 6a43 ..B_..d....O..jC

分析代码后,可以读取到0000410行。在 0002 8000 标记后无法继续。下面显示的源代码实际上是在读取这个文件。

...
* [INPUT]
INTEGER IFILE
CHARACTER HITEM *(*) !! name for identify
CHARACTER HDFMT *(*) !! data format
*
* [ENTRY INPUT]
REAL * 8 TIME1 !! time
REAL * 8 TIME2 !! time
REAL*8 DMIN
REAL*8 DMAX
REAL*8 DIVS
REAL*8 DIVL
INTEGER ISTYPE
INTEGER JFILE !! output file No.
INTEGER IMAXD
INTEGER JMAXD
*
* [WORK]
REAL * 8 DDATA ( NGDWRK )
REAL * 4 SDATA ( NGDWRK )
*
* [INTERNAL WORK]
INTEGER I, J, K, IJK, IJKNUM, IERR
...
...
READ ( IFILE, IOSTAT=IEOD ) HEAD
...
...
...
DO 2150 IJK = 1, IJKNUM
READ ( IFILE, END=2150 ) SDATA(IJK)
WRITE (6,*) ' IGTIO::GTZZRD: iteration=', IJK, SDATA(IJK)
2150 CONTINUE

为了轻松调试循环,我将上面的循环替换掉了。原始的是隐含的。

READ ( IFILE, IOSTAT=IEOD)
& (SDATA(IJK), IJK=1, IJKNUM )

循环的输出是:

IGTIO::GTZZRD: iteration=           1 -0.48268089    
IGTIO::GTZZRD: iteration= 2 1.35631564E-19
IGTIO::GTZZRD: iteration= 3 -0.48142704
IGTIO::GTZZRD: iteration= 4 1.35631564E-19
IGTIO::GTZZRD: iteration= 5 244.25270
IGTIO::GTZZRD: iteration= 6 1.35631564E-19
IGTIO::GTZZRD: iteration= 7 983.87988
IGTIO::GTZZRD: iteration= 8 1.35631564E-19
IGTIO::GTZZRD: iteration= 9 1.59284362E-04
IGTIO::GTZZRD: iteration= 10 1.35631564E-19
IGTIO::GTZZRD: iteration= 11 0.0000000
---error here---

我肯定迷失在这方面,所以任何帮助表示赞赏。

最佳答案

这是怎么回事 - 首先这绝对是一个 Big Enfian 文件。前4个字节

00000400

是big end 4 byte integer 1024,也就是你第一条记录的长度。这与 HEAD 的长度一致(根据评论)现在请注意,00000400 在字节位置 1024+4 处重复(十六进制转储行 400),正如您对 Fortran 未格式化文件所期望的那样......到目前为止一切顺利。

现在接下来的 4 个字节

0002 8000

开始第二条记录。 (编辑更正错误)这是 163840 (2*16^4+8*16^3) 您应该会发现它在十六进制转储中的位置 1024+8+163840+4 处重复出现。 (我认为应该是 028400 行。)

问题在于:在您的代码中,您正在将 160 KB 的记录读取到一个 4 字节的变量中,然后继续读取下一条记录。我猜你看到的是交替出现的 10^-19,因为其他所有记录都是字符类型的。

在未格式化的 fortran 中,您必须一次读取整个记录 - 尝试读取整个数组(没有循环......)

READ ( IFILE )SDATA

假设 sdata 的大小当然可以容纳 160 kb。 (例如真实*4(40960))

关于linux - Fortran 77 从旧的 sun 机器读取未格式化的序列数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21117559/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com