【问题标题】:Why does my COBOL working storage variable have trailing zeroes?为什么我的 COBOL 工作存储变量有尾随零?
【发布时间】:2022-06-11 00:40:47
【问题描述】:

我正在构建一个 COBOL 程序来计算最多 15 个整数的平均值。执行显示的数字远大于预期,并带有很多尾随零。以下是相关代码:

       Data Division.
       Working-Storage Section.
       01 WS-COUNTER          PIC 9(10).
       01 WS-INPUT-TOTAL      PIC 9(10).
       01 WS-NEXT-INPUT       PIC X(8).
       01 WS-CONVERTED-INPUT  PIC 9(8).
       01 WS-AVG              PIC 9(8)V99.

       Procedure Division.
       PROG.
           PERFORM INIT-PARA
           PERFORM ADD-PARA UNTIL WS-COUNTER = 15 OR WS-NEXT-INPUT = 'q'
           PERFORM AVG-PARA
           PERFORM END-PARA.
       INIT-PARA.
           DISPLAY 'This program calculates the average of inputs.'.
           MOVE ZERO TO WS-COUNTER
           MOVE ZERO TO WS-INPUT-TOTAL
           MOVE ZERO TO WS-AVG.
       ADD-PARA.
           DISPLAY 'Enter an integer or type q to quit: '
           ACCEPT WS-NEXT-INPUT
           IF WS-NEXT-INPUT NOT = 'q'
               MOVE WS-NEXT-INPUT TO WS-CONVERTED-INPUT
               ADD WS-CONVERTED-INPUT TO WS-INPUT-TOTAL
               ADD 1 TO WS-COUNTER
           END-IF.
       AVG-PARA.
           IF WS-COUNTER > 1
               DIVIDE WS-INPUT-TOTAL BY WS-COUNTER GIVING WS-AVG
               DISPLAY 'Your average is ' WS-AVG '.' WS-NEXT-INPUT
           END-IF.

如果满足IF 条件,我将WS-NEXT-INPUT 设置为字母数字并将其移动到数字WS-CONVERTED-INPUT 的原因是因为我希望它能够使用“q”来打破UNTIL 循环,但是在满足条件之后,我想要一个用于算术语句的数字变量。以下是数字 10 和 15 作为输入时的样子:

10is program calculates the average of inputs.
Enter an integer or type q to quit:
15
Enter an integer or type q to quit:
q
Your average is 1250000000.

控制台有点问题,所以大部分时间它迫使我在左上角输入 10。不用担心。

你在那个执行中看到了我的问题。结果应该是 00000012.50 而不是 1250000000。我尝试将一些其他变量插入到该显示语句中,它们基本上都应该是除了WS-INPUT-TOTAL 之外的数字组合最终是 0025000000 0000000025 如我所料。为什么这些数字会以如此奇怪和意想不到的方式存储?

【问题讨论】:

  • 你在PICTURE字符串中使用了V,这对于计算是正确的,但是如果你想用小数点显示它你需要MOVE它到一个带有@987654331的变量@。您可能还需要在MOVE 之前清理PIC X(8) 字段。
  • 这将是一个受欢迎的问题 - 如果您花时间将输出粘贴为文本 - 对于大多数 Q+A,图像没有多大帮助。

标签: cobol


【解决方案1】:

由于未定义的行为 - 使用空格计算,您会得到奇怪的输出。

您呈现的 MOVE 具有完全相同的 USAGE 和相同的大小 - 它通常会“按原样”被接管,它通常不会通过某种魔法转换尾随空格,所以 WS-CONVERTED-INPUT 最终会10 。正如标准所说的那样:

仅当发送操作数是数字编辑的数据项且接收项目是数字或数字编辑的数据项时,才会进行去编辑。

如果它是一个已编辑的字段,那么它仍然应该在 MOVE 上引发异常:

当数字编辑的数据项是反编辑 MOVE 语句的发送操作数并且该数据项的内容不是该数据项中任何编辑操作的可能结果时,MOVE 操作的结果未定义且EC-DATA-INCOMPATIBLE 异常条件设置为存在。

使用空格进行计算时,您通常会引发致命错误,但您的编译似乎没有激活该错误(并且因为您没有共享您的编译命令甚至您的编译器,我们对此无能为力)。

不同的 COBOL 方言通常对无效数据使用零(仅在未激活会导致中止的检查时部分使用)零,至少对于空格(但它们可以使用所有内容。这将导致到WS-CONVERTED-INPUT“视为”10000000 - 所以你的计算将包括那些大数字。

因此,如果您在输入时输入必要数量的前导零,您的程序应该可以工作。

一般:

  • “从不信任输入数据 - 验证”(必要时出错或转换)
  • 至少如果某些东西看起来可疑 - 激活所有可用的运行时检查,然后重试。

解决方案 - 进行显式转换:

MOVE FUNCTION NUMVAL(WS-NEXT-INPUT) TO WS-CONVERTED-INPUT,这将去除周围的空格,然后从左到右转换,直到找到无效数据。优秀的编码员也会使用FUNCTION TEST-NUMVAL 预先检查,否则如果有人输入“TWENTY”,则计算为零。

【讨论】:

  • 你也可以使用 unstring
猜你喜欢
  • 1970-01-01
  • 2015-04-28
  • 2016-03-22
  • 1970-01-01
  • 2011-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多