【问题标题】:Why is the counter variable unexpectedly increased in every subroutine call? [duplicate]为什么每次调用子程序时计数器变量都会意外增加? [复制]
【发布时间】:2019-01-17 23:49:19
【问题描述】:

[社论:我读过this question,但是(事后看来,它最终的关联方式与这里的每个问题都相关——即“为什么计算机会出现故障?”)这个答案不是答案我的问题。这个问题是问为什么一个标准机构在语言中设计了一个特定的特性。而且,答案并没有回答我的问题,即我在调试这个问题时错过了什么。]

QUESTION:为什么下面显示的这个 Fortran 程序 (ExhaustiveListing.f08 + unicodeSupport.f08) 的输出表明 Fortran 的 DO WHILE有大bug吗?

这是输出,后面是环境描述,最后是两个文件的源代码:

意外输出

十六进制现在是:2500H
2500─
2501━
2502│
2503┃
2504┄
2505~
2506┆
2507┇
2508┈
2509┉
250A┊
250B┋
250C┌
250D┍
250E┎
250F┏
十六进制现在是:2510H
十六进制现在是:2520H
十六进制现在是:2530H
十六进制现在是:2540H
十六进制现在是:2550H
十六进制现在是:2560H
十六进制现在是:2570H

运行完成;退出值 0;实时:530ms;用户:0ms;系统:0ms

预期输出

我希望在每个“Hex is now: xxxxH”行之间有 16 行细节,例如打印在 2500H2510H 行。

以前解决问题的尝试

这个程序是我在一个更大的项目中解决问题的尝试。该项目有问题(一个这样的问题围绕在 Fortran 中使用 Unicode),我创建了这个项目来隔离 Unicode 问题。起初,我将微不足道的 unicodeSupport 模块与主程序组合在同一个文件中。我将其删除到自己的文件中。不,这无关紧要,而且——它不影响结果。这个程序非常简单,我看不出我做错了什么。因此,我来​​到 SO 是希望新的眼睛能发现我的错误。否则,是时候使用 gFortran 提交错误报告了。

环境

我工作的环境是:
操作系统Ubuntu 17.10 IDENetbeans 8.2 JDKOracle(内部版本 1.8.0_161-b12) 编译器gFortran 7.2.0 编译器标志-std=f2008ts -fno-unsafe-math-optimizations -frounding-math -fsignaling-nans theGeeko61在 BASIC、Pascal、FORTRAN、C、Prolog、C++、Java 等许多其他方面发展了 4 年(按我学习它们的时间顺序排列)

ExhaustiveListing.f08

! File:   ExhaustiveListing.f08
! Author: geeko
!
! Created on March 25, 2018, 7:05 PM
!
! ☐ U2610 ☑ U2611 ☒ U2612
! Use above symbols for indicating items to
! be tested (☐), and items which have either
! passed (☑) or failed (☒) testing.
!
SUBROUTINE displayLine(hex)
    USE unicodeSupport
    IMPLICIT NONE
    INTEGER :: hex, counter=0, point

    DO WHILE (counter < 16)
        point = hex+counter
        WRITE(*,'(Z4.4,A)') point, CHAR(INT(point), ucs4)
        counter = counter+1
    END DO
END SUBROUTINE

PROGRAM ExhaustiveListingOfUnicodeBoxDrawingChars ! ☒
    USE ISO_FORTRAN_ENV
    USE unicodeSupport
!!!!!USE testUnicodeSupport         ! ☑
    IMPLICIT NONE
    INTEGER  :: hex

    open(output_unit, encoding='UTF-8')

    hex = 9472
    DO WHILE(hex<9600)
        PRINT '(A,Z4.4,A)', "Hex is now: ", hex, "H."
        CALL displayLine(hex)   ! ☒
        hex = hex+16
    END DO

!!!!CALL performTest()              ! ☑
END PROGRAM ExhaustiveListingOfUnicodeBoxDrawingChars

unicodeSupport.f08

! File:   unicodeSupport.f08
! Author: geeko
!
! Created on March 25, 2018, 10:09 PM
!

MODULE unicodeSupport
    INTEGER, PARAMETER  :: ASCII = SELECTED_CHAR_KIND('ASCII')
    INTEGER, PARAMETER  :: UCS4 = SELECTED_CHAR_KIND('ISO_10646')
END MODULE unicodeSupport

【问题讨论】:

  • 以后,如果您认为自己在 Fortran 中发现了“重大错误”,请创建尽可能少的示例来显示相同​​的问题。
  • @francescalus:这就是我试图做的......“最小”过于主观......这是我的最小......你会是什么样子? ;) (在 Fortran 中,一个只有 1 个文件的项目是最小的,不是吗?)
  • 如果你看到了我必须支持的一些恐怖事件,你可能会看到一个源文件是多么的非最小:(。但是在这里,你可以很容易地表现出同样的问题,而无需任何 Unicode 部分和注释掉的代码。
  • "为什么这个 Fortran 程序的输出......
  • 不用担心。我同意“初始化意味着保存”作为此类问题的根源远非直观(如果这真的是一个糟糕的问题,我会否决而不回头)。不过,将困难的案例减少到最低限度是一项非常有价值的技能。

标签: unicode fortran do-while gfortran


【解决方案1】:

这里声明的变量counter

INTEGER :: hex, counter=0, point

拥有save 属性,因为它的值在初始化行上定义。

第二次进入子程序,其值为16,因此不会出现循环。

从声明行中删除=0并写入

counter = 0

之后。

【讨论】:

  • 您的远见卓识。我很高兴这是我的失误。我讨厌提交错误报告。 :)
猜你喜欢
  • 1970-01-01
  • 2022-06-27
  • 2019-12-24
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 2014-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多