Если вы такое увидите, то (почти наверняка) это ошибка программирования на 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
.
Обратите внимание, как перемещаются пробелы для её инициализации.
Это был типичный метод инициализации записи.Таким образом, пробелы есть во всех полях PICX. Но! Все поля 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 нибблов памяти (9 нибблов для цифр и один для знака) или 5 байт.
Перемещение пробелов в
dr-datarec
приведёт к тому, что
в это поле сохранится 5 пробелов или шестнадцатеричное значение
2020202020. Если попытаться использовать неинициализированную
переменную, это интерпретируется как 2020202,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
Так что в следующий раз, когда увидите бедную вдову, которой пришёл счёт за коммунальные услуги $2020202,02, вы будете точно знать, что произошло!