PIC-клаузы: типы данных COBOL
Разбираемся, как загадочная запись PIC 9(5) описывает число, а PIC X(20) — текст, и почему длина поля здесь не деталь, а важнейшая часть объявления.
PIC-клауза (от англ. picture — «картинка») — часть объявления переменной COBOL, которая описывает вид и точный размер данных, которые в ней будут храниться.
Зачем нужна «картинка» данных
В прошлом уроке мы уже видели записи вроде PIC X(20) и PIC 9(3), но не разбирали подробно, что означают эти символы. Слово PIC — сокращение от picture, «картинка» или «шаблон». Идея в том, что клауза PIC буквально рисует шаблон будущих данных: сколько позиций займёт число или текст и какого рода символы там могут стоять. Это принципиально другой подход по сравнению с типами вроде int или str в современных языках — там тип говорит «это число» или «это строка», но не говорит, сколько именно места оно займёт. COBOL говорит и то, и другое сразу.
Почему это важно? COBOL-программы часто работают с файлами фиксированной структуры — например, файл с миллионом строк, где каждая строка описывает одного клиента банка, и в ней ровно 80 символов: 20 под имя, 4 под номер счёта, 10 под сумму и так далее. Если знать точную длину каждого поля, можно мгновенно найти нужный байт в файле, не читая его целиком — не нужно искать разделители вроде запятых, как в CSV. Это одна из причин, почему мейнфреймы десятилетиями обрабатывают огромные объёмы данных быстро: структура известна заранее, до последнего байта.
Символ 9 — цифровое поле
Символ 9 в PIC-клаузе означает «здесь стоит одна десятичная цифра». Число повторений цифры 9 можно не расписывать вручную — вместо PIC 99999 удобнее написать PIC 9(5), что значит ровно то же самое: пять позиций под цифры.
01 VOZRAST PIC 9(3) VALUE 16.
01 ZARPLATA PIC 9(6) VALUE 45000.Здесь VOZRAST (возраст) — поле из трёх цифр, а ZARPLATA (зарплата) — из шести. Если попробовать записать в VOZRAST число больше 999, поле просто не сможет вместить лишние цифры — они «обрежутся». Именно поэтому при проектировании программы важно заранее прикинуть, какого размера может быть максимальное значение.
Символ X — текстовое поле
Символ X означает «здесь может стоять любой символ» — буква, цифра, пробел, знак препинания. Так же, как с цифрами, число повторений можно свернуть в скобки: PIC X(20) значит «ровно 20 любых символов».
01 GOROD PIC X(15) VALUE "Kazan".
01 FAMILIYA PIC X(25) VALUE "Ivanov".Если фактическое значение короче объявленной длины (как «Kazan» в поле из 15 символов), COBOL дополнит остаток пробелами справа. Если значение длиннее поля, лишние символы обрежутся. Это важно помнить — в отличие от Python-строк, которые «резиновые» и подстраиваются под любую длину, COBOL-текст всегда занимает фиксированное место, как ячейка в таблице Excel заданной ширины.
Числа с десятичной точкой: символ V
Что если нужно хранить не целое число, а сумму с копейками? Для этого есть специальный символ V — он обозначает подразумеваемую десятичную точку, которая физически не хранится в данных, но учитывается при вычислениях.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SUMMA PIC 9(4)V99 VALUE 125.50.
PROCEDURE DIVISION.
DISPLAY "Summa: " SUMMA.
STOP RUN.Вывод:
Summa: 012550Обратите внимание: клауза PIC 9(4)V99 означает «четыре цифры до точки и две цифры после», то есть число вида 0125.50. Но в выводе точки нет вообще — она «виртуальная», существует только в голове компилятора для правильных арифметических операций, а физически хранятся только цифры: 012550. Если нужно красиво напечатать сумму с настоящей точкой на экране, для этого используют отдельные форматирующие клаузы вывода — это уже более продвинутая тема, выходящая за рамки вводного курса.
Разбираем построчно ещё раз
Возьмём строку 01 SUMMA PIC 9(4)V99 VALUE 125.50. целиком. 01 — уровень записи (базовый, о котором подробнее в следующем уроке). SUMMA — имя переменной, придуманное программистом. PIC 9(4)V99 — клауза, описывающая форму данных: 4 цифры, невидимая точка, ещё 2 цифры. VALUE 125.50 — начальное значение, которое компилятор сам преобразует в нужное представление. Точка в самом конце строки — как обычно, обязательный знак завершения предложения COBOL, не путайте её с десятичной точкой из 125.50.
Мини-пример: карточка ученика
Соберём несколько типов PIC в одном объявлении — карточку ученика с именем, возрастом и средним баллом.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 UCHENIK PIC X(20) VALUE "Petrov".
01 KLASS PIC 9(2) VALUE 9.
01 SREDNIY-BALL PIC 9V99 VALUE 4.75.
PROCEDURE DIVISION.
DISPLAY "Uchenik: " UCHENIK.
DISPLAY "Klass: " KLASS.
DISPLAY "Ball: " SREDNIY-BALL.
STOP RUN.Вывод:
Uchenik: Petrov
Klass: 09
Ball: 475Здесь хорошо видно: имя дополнилось пробелами до 20 символов (в примере вывода они просто не видны глазу после текста), класс напечатался с ведущим нулём как «09», а средний балл 4.75 хранится как последовательность цифр «475» без явной точки — ровно та же логика подразумеваемой десятичной точки, что и в примере с суммой.
Частые ошибки новичков
Самая частая ошибка — забыть, что поле PIC 9 имеет ограниченный размер, и попытаться записать туда число, которое не помещается. Например, в PIC 9(3) нельзя корректно сохранить число 1500 — оно либо обрежется, либо программа завершится с ошибкой переполнения, в зависимости от настроек компилятора.
Вторая ошибка — путать V с настоящей точкой при выводе на экран. Начинающие удивляются, почему DISPLAY печатает «012550» вместо «0125.50» — как мы разобрали выше, точка V виртуальна и в чистом выводе не появляется сама по себе.
Третья ошибка — не оставлять запас в размере поля. Если проектировать поле PIC 9(2) под возраст ученика, всё хорошо, пока это ученик — а если та же структура позже понадобится для взрослого (например, 105 лет для очень старого архивного значения), двух цифр не хватит. В реальных мейнфрейм-системах такие просчёты в размере полей исторически вызывали серьёзные проблемы (вспомните знаменитую «проблему 2000 года», Y2K — она возникла именно потому, что год хранился всего в двух цифрах PIC 99).
Итоги
- PIC-клауза описывает точный «шаблон» данных: их вид (число или текст) и фиксированную длину в позициях.
- Символ
9— цифра, символX— любой символ, символV— подразумеваемая десятичная точка, которая не хранится физически. - Число повторений символа можно свернуть в скобки:
9(5)вместо99999. - Если значение не помещается в объявленный размер, оно обрежется — поэтому размер поля нужно продумывать заранее, с запасом на будущее.