COBOL et 2020 202,02 $

Au cours des dernières années, même au cours des deux dernières années, je suis parfois tombé sur la nouvelle que quelqu'un recevait une facture ou un chèque d'un montant ridicule de 2 020 202 dollars ... et 02 cents.



Si vous voyez cela, c'est (presque certainement) une erreur de programmation COBOL. La plupart des programmeurs COBOL font cette stupide erreur, et je ne fais pas exception.



Le problème est causé par la façon dont nous initialisons habituellement l'enregistrement. Prenons un petit programme comme celui-ci:



       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.


Dans ce programme, l'enregistrement d'entrée dr-datarec. Habituellement, il vient de quelque part sur le disque, mais pour ce test simple, il est créé manuellement.



Une fois qu'un enregistrement d'entrée est reçu, le calcul est effectué, puis l'enregistrement est sorti en utilisant dt-detail.



Le problème est de savoir comment l'enregistrement est créé dr-datarec. Remarquez comment les espaces sont déplacés pour l'initialiser. C'était la méthode typique pour initialiser un enregistrement.



Ainsi, il y a des espaces dans tous les champs PIC X. Mais! Tous les champs COMP-3 sont également initialisés, mais pas à zéro. Le programmeur doit s'assurer que des valeurs valides sont générées pour tous les champs COMP-3. Le programme de test le fait correctement:



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


Il y en a dr-amountclairement 100 sur le terrain. Après le démarrage, il s'avère:



./mistake 
test                       100.00


Que faire s'il y a une erreur de codage et que l'enregistrement n'est dr-amountpas initialisé correctement?



Il y a encore des espaces ASCII là-dedans. Il s'agit d'une valeur hexadécimale de 20 ou binaire 0010 0000.



COMP-3 stocke les chiffres sous forme de quartets de quatre bits, donc un espace est affiché comme 20. Si vous avez 9 chiffres comme dr-amount, cela nécessite 10 grignotages de mémoire (9 quartets pour les chiffres et un pour le signe) ou 5 octets.



Le déplacement d'espaces dans dr-datarecentraînera le stockage de 5 espaces ou de la valeur hexadécimale 2020202020 dans ce champ. Si vous essayez d'utiliser une variable non initialisée, elle sera interprétée comme 2020 202.02.



Si vous commentez l'initialisation dr-amount, vous pouvez forcer cette erreur:



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


Maintenant, au démarrage du programme:



./mistake 
test                 2,020,202.02


Pour corriger ce problème, COBOL 85 a introduit le verbe INITIALIZE. Au lieu de déplacer des espaces vers un enregistrement, vous l'initialisez et il déplacera les espaces vers les champs alphanumériques et les zéros vers les champs numériques:



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


Résultat de l'exécution:



./mistake 
test                         0.00


Ainsi, la prochaine fois que vous verrez une pauvre veuve qui a reçu une facture de services publics de 2 020 202,02 $, vous saurez exactement ce qui s'est passé!



All Articles