在R中包含遗留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
文本文件(“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
虽然子程序编译得很好(在MacOS 10.11.6,R 3.5.0上)
R CMD SHLIB rfort.f
并且还可以在R中调用
dyn.load("rfort.so")
并运行没有错误
.Fortran("rfort")
它奇怪地只读入“RESULT.DAT”测试的整数列。无论我尝试什么,都会忽略字符列。完全相同的代码作为独立的Fortran程序(使用gfortran 6.1.0编译)可以正常工作,所以我怀疑它与格式化有关。但是,我在我的智慧结束,所以任何帮助表示赞赏!
我认为READ格式的8X应该是4X。让我们看看第一个输入行(我添加了列号):
1 2
1234567890123456789012345
1 395 1232 1084
格式是8X,2I8,A6
。我们跳过第1-8列并开始读取第9-16列中的第一个整数,即b395bbbb
,第二列来自第17-24行1232bb10
。如您所见,部分字符数据被读取为第二个整数。 BLANK ='NULL'的默认值意味着忽略嵌入的空格(我假设您没有使用FORTRAN 66编译器!)
为什么你说它似乎与gfortran合作,我不知道。我也不知道为什么结果应该根据你调用子程序的方式而有所不同。
在您的示例中,您似乎希望输出文件包含来自TEST.DAT的最后3列,但输出不是您期望看到的。您有两种选择:1)更改TEST.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
如您所见,值'726'被读入IX(10),但'12393107'被读入IY(10),'8d'被读入NAME(10)。真棒,对,但不是你的期望!然后在输出打印时,默认情况下数字是右对齐的,而默认情况下字符是左对齐的,因此在RESULTS.DAT中的最后两列打印时它们之间没有空格:
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)
您可以对写入语句执行相同的操作:write(9,*), IX(i), IY(i), NAME(i)
将使用合理的默认字段宽度,并保证I / O列表中每个项目之间存在空格。如果您想要更多地控制输出的格式,请继续使用格式语句,但要更改它以便保证在每个项目之间放置一定数量的空格:
write(9, "(4x,I8,I8,1x,A6)") IX(i), IY(i), NAME(i)