为啥在 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 的结果,并将变量IA(I) 写入文件output.dat。我对变量IA(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,...),因为我使用的是 12,所以没有问题。我只是写了这个简单的案例来代表我的真实代码,而没有先检查它。但实际上在我的真实代码中,我使用了两个存在 OPEN(UNIT=5,...)OPEN(UNIT=6,...) 的语句,这在 Fortran 中是不允许的,因为:

    UNIT=5 声明 Standard In 用于从键盘读入数据。 UNIT=6 声明 Standard Out 用于将一般输出打印到屏幕。 UNIT=0 声明 Standard Error 用于将错误消息打印到屏幕上。

我之前没有意识到,因为我正在处理相当旧的代码,所以 O 需要将它重写为更新的版本。因此,为了避免这些问题,请不要使用UNIT=5UNIT=6UNIT=0

【讨论】:

使用更大的数字。 5,6 和 0 不是标准的,也可以预先连接其他小数字。不要使用低于 10 的任何东西。 @VladimirF:就我而言,我只需将OPEN(UNIT=5,...)OPEN(UNIT=6,...) 更改为OPEN(UNIT=25,...)OPEN(UNIT=26,...),它就可以正常工作。但是,是的,出于安全考虑,您绝对正确,最好使用大于10

以上是关于为啥在 Fortran 中使用命令 PRINT 会覆盖输入文件?的主要内容,如果未能解决你的问题,请参考以下文章

在fortran 90/95中产生声音/哔哔声

FORTRAN为啥要将数据区分类型

为啥 Julia 代码性能比 Fortran 低很多?

fortran中怎样避免输出字符时自动换行。如 print*,"a" print*,''b" 输出时:a b 怎样设计使输出ab

为啥 GDB 认为我的 Fortran 字符串是 ~4GiB

为啥我在prthon写print(“hello world"),会出现无法初始化设备 PRN