COBOL e $ 2.020 202,02

Nos últimos anos, mesmo nos últimos dois anos, às vezes me deparava com a notícia de que alguém havia recebido uma fatura ou cheque no valor ridículo de 2.020.202 dólares ... e 02 centavos.



Se você vir isso, é (quase certamente) um erro de programação COBOL. A maioria dos programadores COBOL comete esse erro estúpido, e não sou exceção.



O problema é causado pela maneira como geralmente inicializamos o registro. Vamos pegar um pequeno programa como este:



       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.


Neste programa, o registro de entrada dr-datarec. Normalmente vem de algum lugar no disco, mas para este teste simples, é criado manualmente.



Assim que um registro de entrada é recebido, o cálculo é executado e, em seguida, o registro é enviado usando dt-detail.



O problema é como o registro é criado dr-datarec. Observe como os espaços são movidos para inicializá-lo. Este era o método típico para inicializar um registro.



Assim, existem espaços em todos os campos PIC X. Mas! Todos os campos COMP-3 também são inicializados, mas não para zero. O programador deve ter certeza de que valores válidos são gerados para todos os campos COMP-3. O programa de teste faz certo:



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


dr-amountclaramente 100 no campo. Depois de começar, verifica-se:



./mistake 
test                       100.00


E se houver um erro de codificação e o registro dr-amountnão for inicializado corretamente?



Ainda há espaços ASCII lá. Este é um valor hexadecimal de 20 ou binário 0010 0000.



COMP-3 armazena dígitos como nibbles de quatro bits, então um espaço é exibido como 20. Se você tiver 9 dígitos como dr-amount, então isso requer 10 nibbles de memória (9 nibbles para dígitos e um para sinal) ou 5 bytes.



Mover espaços dr-datarecresultará em 5 espaços ou o valor hexadecimal 2020202020 sendo armazenado neste campo. Se você tentar usar uma variável não inicializada, ela será interpretada como 2020 202.02.



Se você comentar a inicialização dr-amount, pode forçar este erro:



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


Agora, ao iniciar o programa:



./mistake 
test                 2,020,202.02


Para corrigir esse problema, o COBOL 85 introduziu o verbo INITIALIZE. Em vez de mover espaços para um registro, você o inicializa e ele move espaços para campos alfanuméricos e zeros para campos numéricos:



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


Resultado da execução:



./mistake 
test                         0.00


Portanto, da próxima vez que vir uma viúva pobre que recebeu uma conta de serviços públicos de $ 2.020.202,02, você saberá exatamente o que aconteceu!



All Articles