COBOL和$ 2,020 202.02

在过去的几年中,甚至在过去的一两年中,我有时还碰到一个消息,有人收到一张发票​​或支票,金额为2,020,202美元……和2美分。



如果您看到此消息,那么(几乎可以肯定)这是一个COBOL编程错误。大多数COBOL程序员都会犯这个愚蠢的错误,我也不例外。



问题是由我们通常初始化记录的方式引起的。让我们来看一个像这样的小程序:



       identification division.
       program-id.
           mistake.
       
       data division.
       working-storage section.
      
      * *** Input record, typically maintained on disk/tape somewhere.
       01  dr-datarec.
           03  dr-name                 pic x(20).
           03  dr-amount               pic s9(7)v99, comp-3.

      * *** print record, sent to a line printer.
       01  dt-detail.
           03  dt-name                 pic x(20).
           03  filler                  pic x.
           03  dt-amount               pic z,zzz,zz9.99.            
       
       procedure division.
       
           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
           move 100                    to dr-amount.

           move spaces                 to dt-detail.
           move dr-name                to dt-name.
           move dr-amount              to dt-amount.

           display dt-detail.
       
           stop run.


在此程序中,输入记录dr-datarec通常它来自磁盘上的某个位置,但是对于此简单测试,它是手动创建的。



收到输入记录后,将执行计算,然后使用输出记录dt-detail



问题是如何创建记录dr-datarec注意如何移动空格以对其进行初始化。这是初始化记录的典型方法。



因此,PIC X的所有字段中都有空格。但是!所有COMP-3字段也都被初始化,但不为零。程序员必须确保为所有COMP-3字段生成了有效值。测试程序可以正确执行:



           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
           move 100                    to dr-amount.


dr-amount显然 ,该字段中有100个



./mistake 
test                       100.00


如果出现编码错误并且记录dr-amount未正确初始化怎么办?



那里仍然有ASCII空格。这是十六进制值20或二进制00100000。COMP



-3将数字存储为四位半字节,因此一个空格显示为20。如果您有9位数字(例如dr-amount),则需要10个存储半字节(9个半字节)代表数字,一个代表符号)或5个字节。



在其中移动空格dr-datarec将导致5个空格或十六进制值2020202020存储在此字段中,如果尝试使用未初始化的变量,它将被解释为2020 202.02。



如果注释掉初始化dr-amount,则可以强制执行此错误:



           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
     *     move 100                    to dr-amount.


现在,当启动程序时:



./mistake 
test                 2,020,202.02


为了解决此问题,COBOL 85引入了INITIALIZE动词。不用将空格移动到记录中,而是对其进行初始化,然后将空格移动到字母数字字段,将零移动到数字字段:



      *    move spaces                 to dr-datarec.
           initialize dt-detail.
           move "test"                 to dr-name.
      *    move 100                    to dr-amount.


执行结果:



./mistake 
test                         0.00


因此,下一次您看到一位可怜的寡妇得到2,020,202.02美元的水电费时,您将确切知道发生了什么!



All Articles