为啥在 Fortran 中使用命令 PRINT 会覆盖输入文件?
Posted
技术标签:
【中文标题】为啥在 Fortran 中使用命令 PRINT 会覆盖输入文件?【英文标题】:Why does using command PRINT in Fortran overwrite the input file?为什么在 Fortran 中使用命令 PRINT 会覆盖输入文件? 【发布时间】:2016-11-27 11:15:00 【问题描述】:我正在编写代码并在 Fortran 中使用输入和输出功能。代码如下所示(仅用于简化):
PROGRAM TEST
REAL, DIMENSION(1000):: A
REAL:: B
INTEGER::T
!Defining input and output
OPEN(UNIT=1, FILE='input.dat', STATUS='OLD')
OPEN(UNIT=2, FILE='output.dat', STATUS='NEW')
!Reading from file "input.dat"
READ(1,*) (A(I),I=1,1000)
!Just for initial condition
B=0.0
DO T=1, 10
PRINT *, 'Step =', T
DO I=1, 1000
B=B+1.0
A(I)=A(I)/B
END DO
END DO
!Writing results into file "output.dat"
DO I=1, 1000
WRITE (2,100) I, A(I)
END DO
100 FORMAT (' ',T3, I12, T17, F14.4)
END PROGRAM TEST
我使用的是 Gfortran 5.3,结果与我预期的不一样。我希望在程序运行时在屏幕(或 Ubuntu OS 中的终端)上获得变量T
的结果,并将变量I
和A(I)
写入文件output.dat
。我对变量I
和A(I)
没有问题,因为它们已成功写入文件output.dat
。问题在于变量T
,它没有出现在终端上,但它被写入了文件input.dat
。好吧,即使是文件input.dat
中的前一个文件也没有被覆盖。谁能给我建议?
仅供参考,我也尝试过其他编译器(使用 Windows 操作系统),例如:
-
Microsoft Fortran Powerstation(非常旧的):但它的工作方式符合我的预期。
MinGW-w64(适用于 Windows 的 GCC 版本):但它不能正常工作。
【问题讨论】:
嗯,Linux 上的 GCC 5.3 正在按预期工作。 @AlexanderVogt:你在 Gfortran 5.3 上也试过了吗,你和我得到了同样的结果吗?我认为我上面写的代码没有错误,不是吗? 代码对我来说很好用。乍一看 - 我没有看到问题。虽然我个人不会自己选择单位(提示:newunit=
),尤其是十以下的数字。这可能会干扰 STDIN/STDERR/STDOUT。
@AlexanderVogt:对不起,我没有收到你的消息。对于“代码对我来说很好”,您是说您也在使用 Gfortran,但代码运行良好还是您使用的是 gcc?
gfortran
是 GCC 的 Fortran 编译器。
【参考方案1】:
这可能是因为对于您的平台/编译器/编译器版本/编译器选项的特定组合,单元 1 是控制台的预连接单元。
您的 OPEN 语句将该单元定向到您的输入文件。因此,隐式寻址该单元的 PRINT 语句会将其输出定向到同一文件。
使用不同的单元编号 - 选择大于 10 的值通常对编译器预连接的单元是安全的。为了进一步安全,您可以使用INQUIRE(UNIT=unit_number, EXIST=some_logical_variable)
语句来检查特定单元是否在您的 OPEN 语句之前连接到文件 - 如果是,请选择不同的单元号。理想情况下,如果您正在写入 Fortran 2008,您可以使用 NEWUNIT 说明符。
(不要将单位编号的值硬编码到您的输入/输出语句中 - 它们应该始终由变量或命名常量表示,以便可以在一个地方轻松设置/更改值。)
【讨论】:
【参考方案2】:我找到了答案。实际上,我上面发布的代码将在 Gfortran 5.3 上运行良好,因为我使用了 OPEN(UNIT=1,...)
和 OPEN(UNIT=2,...)
,因为我使用的是 1
和 2
,所以没有问题。我只是写了这个简单的案例来代表我的真实代码,而没有先检查它。但实际上在我的真实代码中,我使用了两个存在 OPEN(UNIT=5,...)
和 OPEN(UNIT=6,...)
的语句,这在 Fortran 中是不允许的,因为:
UNIT=5
声明 Standard In
用于从键盘读入数据。
UNIT=6
声明 Standard Out
用于将一般输出打印到屏幕。
UNIT=0
声明 Standard Error
用于将错误消息打印到屏幕上。
我之前没有意识到,因为我正在处理相当旧的代码,所以 O 需要将它重写为更新的版本。因此,为了避免这些问题,请不要使用UNIT=5
、UNIT=6
和UNIT=0
。
【讨论】:
使用更大的数字。 5,6 和 0 不是标准的,也可以预先连接其他小数字。不要使用低于 10 的任何东西。 @VladimirF:就我而言,我只需将OPEN(UNIT=5,...)
和OPEN(UNIT=6,...)
更改为OPEN(UNIT=25,...)
和OPEN(UNIT=26,...)
,它就可以正常工作。但是,是的,出于安全考虑,您绝对正确,最好使用大于10
。以上是关于为啥在 Fortran 中使用命令 PRINT 会覆盖输入文件?的主要内容,如果未能解决你的问题,请参考以下文章
fortran中怎样避免输出字符时自动换行。如 print*,"a" print*,''b" 输出时:a b 怎样设计使输出ab