在遗产fortran中读取带有字符的文本文件



在项目包装旧代码中,r fort text-fortran代码的" rfort"读取。子例程的工作简化版本如下:

  SUBROUTINE rfort()
  implicit none
  INTEGER I,IX,IY
  DIMENSION IX(10),IY(10)
  CHARACTER*6 NAME(10)
  OPEN(UNIT=8,FILE='TEST.DAT',STATUS='OLD')
  OPEN(UNIT=9,FILE='RESULT.DAT',STATUS='UNKNOWN')
  DO I=1,10
  READ(8,1020)IX(I),IY(I),NAME(I)
1020      FORMAT(8X,2I8,A6)
  WRITE(9,1030)IX(I),IY(I),NAME(I)      
1030      FORMAT(8X,2I8,A6)
  ENDDO
  CLOSE (8)
  CLOSE (9)
  END

text-file(" test.dat")由四个变量组成:一个行标识符(忽略),两个整数变量(" ix"," iy")和一个字符变量(" name")。

       1     395    1232 1084
       2     415    1242 1024
       3     433    1253 125
       4     409    1204 1256
       5     427    1217 105
       6     446    1226 1253
       7     489    1239 1254
       8     560    1255 1260a
       9     720    1270 1067
      10     726    1293 1078d

subroutine用

编译罚款(在MacOS 10.11.6,r 3.5.0上)
R CMD SHLIB rfort.f

,也可以在r

中调用
dyn.load("rfort.so")

并且在没有错误的情况下运行

.Fortran("rfort")

它仅在" result.dat"测试的整数列中奇怪地读取。无论我尝试什么,字符列都被忽略了。与预期的代码相同的代码与独立的fortran-Programme(用Gfortran 6.1.0编辑),因此我怀疑这与格式有关。但是,我处于智慧,因此任何帮助都将受到赞赏!

我认为您的读取格式的8倍应该为4倍。让我们看一下第一个输入行(我添加了列号):

         1         2
1234567890123456789012345
   1     395    1232 1084

格式为 8X,2I8,A6。我们跳过1-8列,然后开始从9-16列的第一个整数读取第一个整数,即b395bbbb,第二列是17-24 1232bb10列的第二个整数。如您所见,角色数据的一部分被读为第二个整数。空白的默认值='null'意味着嵌入式空白被忽略(我认为您不使用Fortran 66编译器!)

为什么您说这似乎与Gfortran合作,我不知道。我也不知道为什么结果应该不同,具体取决于您如何调用子例程。

在您的示例中,您似乎希望输出文件由test.dat的最后3列组成,但是输出不是您期望看到的。您有两个选择:1)更改test.dat中的间距。DAT匹配格式语句,或2)更改格式语句以匹配test.dat中的间距。

让我们看一下您的格式语句。1020格式说要跳过前8列,从接下来的16列中读取2种整数类型(每个INT的8列),然后从接下来的6列中读取字符类型。例如,test.dat的第10行读取如下:

TEST.DAT (line 10) with spacing illustrated:
       |       |       |     |
123456781234567812345678123456
  10     726    1293 1078d

您可以看到,读取为ix(10)的值'726',但'12393107'被读取为IY(10),而'8d'读为名称(10)。太棒了,是的,但不是您所期望的!然后,当打印输出的数字默认为正确地对准时,默认情况下左对准了字符,因此结果中的最后两个列之间都没有它们之间没有空白空间:

RESULTS.DAT (line 10) with spacing illustrated:
       |       |       |     |
123456781234567812345678123456
             726 12931078d    

这是我的建议:更改您的阅读格式,以使其更加宽容和灵活。只需将1020指示符替换为*,这意味着线上的每个项目(逗号或空间分离)形成一个序列,该序列将转移到I/O列表中的相应变量中。这称为list-directed格式指定符。请注意,由于行号已成为输入列表的一部分,因此您需要定义一个整数integer dummy_val(在子例程的顶部),然后您可以忽略它。现在使用:

读取每一行
read(8, *) dummy_val, IX(i), IY(i), NAME(i)

您可以为您的写Statment做同样的事情:write(9,*), IX(i), IY(i), NAME(i),它将使用合理的默认字段宽度,并确保I/O列表中每个项目之间存在空白空间。如果您想更多地控制输出格式的格式,请继续使用格式语句,但要更改它,以便保证在每个项目之间放置一定数量的空间:

write(9, "(4x,I8,I8,1x,A6)") IX(i), IY(i), NAME(i)

最新更新