Шаг 49.
Объявление и использование формата (начало)

    На этом шаге мы рассмотрим объявление и использование формата.

    Формат - языковая единица, которая требует обязательного объявления в программе Perl. Он используется в качестве "руководства" функцией write (), которая выводит на экран монитора, принтер или в файл информацию из программы в соответствии с записанными в формате "инструкциями" форматирования строк вывода. При объявлении формата определяется, как должна быть отформатирована каждая его строка при отображении на устройстве вывода.

    Формат объявляется в программе с помощью ключевого слова format, после которого следуют "инструкции" по форматированию определенных в нем строк. Завершается объявление формата строкой, первым символом которой является точка ".". Общий синтаксис конструкции объявления формата следующий:

  format ИМЯ_ФОРМАТА = 
   ФОРМУЛЫ_СТРОК

    Пример использования формата приведен на 3 шаге.

    Параметр ИМЯ_ФОРМАТА представляет собой правильный идентификатор Perl. Он должен в точности соответствовать имени дескриптора файла, который используется в качестве единственного параметра в функции вывода write (). Например, если форматированный отчет выводится в файл, определенный в программе дескриптором FILE, то и имя формата должно быть также FILE. Функцию write() можно вызывать без параметра. В этом случае вывод осуществляется на стандартное устройство вывода (STDOUT), и имя формата в этом случае должно быть равным STDOUT. Если функцией select() установлен дескриптор файла вывода по умолчанию, то вывод функцией write() без параметра будет осуществляться в этот файл, причем имя формата вывода должно быть изменено на имя дескриптора файла.


    Замечания.
  1. Объявление формата может осуществляться в любом месте программы. Обычно все объявления форматов задают либо в начале, либо в конце программы.
  2. Имя формата обычно определяют прописными (большими) буквами, что способствует лучшей читаемости программы.

    В теле формата (до завершающей строки с точкой) определяются форматы для каждой строки вывода. Формат строки состоит из двух строк: первая, называемая строкой шаблонов, определяет, как отображается информация, вторая, называемая строкой переменных, задает переменные, содержащие выводимую информацию. Вместе эти две строки определяют формат и содержимое одной строки вывода функцией write ().

    Строка шаблонов печатается точно так, как она выглядит в тексте программы (включая пробельные символы), за исключением некоторых полей, в которые подставляются значения переменных из строки переменных. Эти поля (иногда их называют шаблоны, что и дало название соответствующей строке формата) начинаются с символа "@" или "^", за которым следуют символы форматирования (таблица 1), определяющие ширину поля вывода значения переменной в символах и выравнивание выводимого значения внутри поля. Количество символов форматирования определяет ширину поля вывода, причем для одного поля все символы должны быть одинакового типа.

    Переменные, определяющие значения для полей строки шаблонов, задаются через запятую в строке переменных. Порядок их задания соответствует порядку задания полей вывода в строке шаблонов: значение первой переменной выводится в первое поле, второй - во второе и т. д. Все переменные в строке переменных вычисляются в списковом контексте. Это позволяет задавать выводимые значения в элементах массива скаляров.


    Замечание. Если строка шаблонов не содержит полей, то для нее не надо задавать строку переменных. Она отображается в точности так, как она задана в формате (смотри пример на 3 шаге).

Таблица 1. . Символы форматирования
Символ Описание
> Определяет символьное поле, в котором выводимое значение выровнено по правому краю
< Определяет символьное поле, в котором выводимое значение выровнено по левому краю
| Определяет символьное поле, в котором выводимое значение выровнено центру
# Определяет числовое поле (выводимое значение должно быть числом)
. Определяет положение десятичной точки в числовом поле (###.##)


    Пример 1. Пусть у нас имеется файл (назовем его books), содержащий информацию о книгах, продаваемых неким книжным магазином. Каждая строка этого файла содержит информацию об одной книге: автор(ы), название, издательство, год выпуска и стоимость. Все поля записи разделены символом двоеточие ":". Одна из строк этого файла может выглядеть так:
  В.Долженков Ю.Колесников: Excel  2000:BHV: 1999: 90

    Нам необходимо распечатать отчет о всех продаваемых книгах. Воспользуемся форматами Perl. Программа примера 1 реализует поставленную задачу.

#! perl -w
open BOOKS, "< books"; # Открытие файла на чтение.
while (<BOOKS>) 
{
  # Разбиение строки по символу ' : '.
  ($author, $title, $pub, $year, $price) = split (':'); 
  write; # Форматный вывод строки.
}
format  STDOUT  =
@<<<<<<<<<<<<<<<<<<<<<<<<< | @>>>>>>>>>>> | @||||||| | @#### | @###.##р.
$author,   $title,   $pub,   $year,   $price
.
Текст этого примера можно взять здесь.

    Результат отображения отчета на экране выглядит следующим образом:


Рис.1. Результат работы приложения

    Обратите внимание, что все символы строки шаблонов печатаются именно в тех позициях, в которых они заданы, а в поля этой же строки, определенные символом "@", подставлены значения соответствующих переменных. Эти значения отображаются в соответствии с заданными символами форматирования: для переменной $author вывод выровнен по левому краю (<), для $title по правому краю (>), для $pub по центру (|) соответствующего поля. Значения переменных $уеаr и $price форматируются в соответствии с числовым форматом. Если бы эти переменные не содержали числовые значения, то интерпретатор Perl вывел бы предупреждающее сообщение.


    Замечание. Символ начала поля в строке шаблонов ("@" или "^") учитывается при подсчете ширины поля вывода.

    Еще один нюанс, связанный с форматированием значений переменных. Если она содержит строковые данные, количество символов которых превосходит заданную ширину поля вывода, то лишние символы отсекаются справа. Именно это и произошло при выводе второй записи файла books: название второй книги напечатано не полностью.

    Как поступать в таких случаях? Можно увеличить ширину поля, если позволяют параметры выводного устройства, а можно воспользоваться еще одним символом форматирования, который как раз и предназначен для решения подобных проблем. Прежде всего следует для задания начала поля использовать символ "^". Его отличие от символа "@" заключается в том, что до начала вывода строковых данных в поле Perl в промежуточном буфере аккумулирует слова из выводимых данных, формируя строку, длина которой не превышает ширину поля. После этого сформированные данные выводятся в строке, а значение переменной вывода модифицируется: она будет содержать оставшиеся слова. При последующем использовании этой переменной в другой строке переменных того же формата будут выводиться сохраненные в ней отсеченные данные. Это позволяет выводить длинные данные в нескольких строках в одном вертикальном блоке, если задавать для вывода оставшихся данных точно такое же поле, что и при выводе первой порции.

    Заменим формат STDOUT программы примера 1 на следующий:

format  STDOUT  =
@<<<<<<<<<<<<<<<<<<<<<<<<< | ^>>>>>>>>>>> | @||||||| | @#### | @###.##р.
$author,   $title,   $pub,   $year,   $price
                           | ^>>>>>>>>>>> |          |       |~          
$title
.
Текст этого примера можно взять здесь.

    Теперь вывод нашей программы будет выглядеть так:


Рис.2. Результат работы приложения

    Символ тильда "~" в конце строки шаблона подавляет вывод пустых строк. Если не поставить его, то между первой и второй книгой в нашем отчете появится дополнительная строка, как если бы была выведена вторая строка шаблона с пустым значением переменной $title. Символ подавления вывода пустых строк можно задавать в любом месте строки шаблона, помня, что при выводе он отображается, как пробел.

    В нашем примере мы знали, что данные в переменной $title не займут более двух строк при выводе. Поэтому в формате мы использовали эту информацию, добавив еще одну строку шаблона с переменной $title. А что делать, если не известно количество строк продолжения в которых будут выводиться данные? Можно воспользоваться двумя идущими подряд символами тильда вместо одного. В этом случае алгоритм буферизации данных по словам будет продолжаться до завершения вывода всех данных переменной. Если наш формат изменить на следующий:

format  STDOUT  =
@<<<<<<<<<<<<<<<<<<<<<<<<< | ^>>>>>>>>>>> | @||||||| | @#### | @###.##р.
$author,   $title,   $pub,   $year,   $price
                           | ^>>>>>>>>>>> |          |       |~~          
$title
.
Текст этого примера можно взять здесь.

а в название второй книги добавить еще несколько слов, то вывод записи об этой книге нашей программой будет иметь следующий вид:


Рис.3. Результат работы приложения

    Таким способом можно организовать вывод длинных данных в вертикальные текстовые блоки с переносом по словам.

    На следующем шаге мы продолжим рассматривать объявление и использование формата.




Предыдущий шаг Содержание Следующий шаг