كوبول و 2020202.02 دولار

في السنوات الماضية ، حتى في العام أو العامين الماضيين ، صادفت أحيانًا أخبارًا تفيد بأن شخصًا ما تلقى فاتورة أو تحقق من مبلغ سخيف قدره 2020202 دولارًا ... و 02 سنتًا.



إذا رأيت هذا ، فهو (شبه مؤكد) خطأ في برمجة 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. لاحظ كيف يتم نقل المساحات لتهيئتها. كانت هذه هي الطريقة النموذجية لتهيئة السجل.



وبالتالي ، هناك فراغات في جميع مجالات الموافقة المسبقة عن علم 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 أو ثنائي 0010 0000.



يخزن COMP-3 الأرقام على هيئة أربعة بتات ، لذلك يتم عرض مسافة واحدة على شكل 20. إذا كان لديك 9 أرقام مثل dr-amount ، فهذا يتطلب 10 ذاكرة للقضم للأرقام وواحد للتوقيع) أو 5 بايت. سينتج عن



نقل المسافات في dr-datarec5 مسافات أو يتم تخزين القيمة السداسية العشرية 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.020202.02 دولار ، ستعرف بالضبط ما حدث!



All Articles