Меню

Главная

Статистика

 

 


К управляющим конструкциям относятся операторы цикла и условного исполнения. Некоторые из них нам уже встречались, сейчас мы их рассмотрим более полно и систематично.

Самый простой цикл повторений реализует уже знакомое нам слово repeat, которое снимает со стека число повторений n и выполняемое действие (текст, заключенный в фигурные скобки) и вызывает это действие n раз. Напомним из прошлого занятия:

/star{4 {ray 90 rotate} repeat} def
        

В этой процедуре в цикле рисуются четыре луча. После каждого луча координаты поворачиваются на 90 градусов. Можно таким способом нарисовать квадрат

4 {dup 0 rlineto 90 rotate} repeat
        

Слово dup здесь нужно для дублирования лежащей в стеке длины стороны квадрата.

Более привычный при обычном программировании цикл со счетчиком выполняется словом for, которое снимает со стека три числа - b, d и e и выполняемое действие и организует цикл, в котором участвует счетчик, принимающий, как обычно, значения b, b+d, ... пока значение счетчика не выйдет за предел e. При этом каждое выполнение тела цикла начинается с того, что в стек помещается счетчик цикла. Таким образом, цикл

0 1 2 11 {dup mul add} for
        
просуммирует квадраты неотрицательных чисел от 1 до 11 и сохранит результат (376) в стеке.

Упражнение #1.
a)

Нарисуйте “нотный стан” ≈ несколько групп горизонтальных линий по пять линий в каждой.

b)

Нарисуйте разграфленный лист бумаги.

c)

Нарисуйте прямоугольник, внутренность которого заштрихована пунктирными линиями под углом 30 градусов.

d)

Вот известная демонстрация оптической иллюзии (косая штриховка нарушает ощущение параллельности линий). Напишите программу, которая делает эту картинку.

Рис. 1.

Повторим использованные нами условные операторы.

Слово if снимает со стека булево значение и действие и выполняет действие, если булево значение истинно. Например, в таком цикле

100 100 moveto
1 1 10 {box
          3 eq {gsave 1 0 0 setrgbcolor
          fill grestore} if currentpoint
           stroke shift}for
        
если предположить, что слово box рисует прямоугольник, а слово shift сдвигает начальную точку, мы получим линию из 10 прямоугольников, причем третий будет выкрашен в красный цвет.

А остальные прямоугольники? Они дожидаются конструкции if ... else:

100 100 moveto
1 1 10 {box
        gsave 3 eq {1 0 0} {0 0 1}
        ifelse setrgbcolor fill grestore
        currentpoint stroke shift}for
        

Заметьте, что конструкцию окраски в данном случае можно было бы написать и так:

gsave 0 0 1 3 eq {3 1 roll} if setrgbcolor
  fill grestore
        

Но таких “трюков” современное программирование не одобряет!

Условные операторы открывают возможность еще одной разновидности циклов - рекурсивно исполняемые процедуры. Подробное обсуждение механизма рекурсии нам еще предстоит в этой главе, пока же рассмотрим программу, которая рисует так называемую ломаную Гильберта David Hilbert, 1862 - 1943, выдающийся немецкий математик).

Обратите внимание, что ломаная составлена из четырех одинаковых квадрантов - таких же кривых меньшего “порядка”, повернутых, зеркально отраженных и соединенных перемычками.

Рис. 2.

Вот полный текст рисующей программы, даже с минимальным комментарием (и, кстати, обратите внимание на начало постскриптовского файла - первые его два символа):

%!  Joseph Romanovsky, 1995 (yet)
%    inspired by Pascal code by N.Wirth
     (A+DS=P) and
%     Metafont code by Kees van der Laan
/S{0 R rlineto currentpoint stroke moveto}def
/T{90 rotate}def /TM{T 1 -1 scale}def
/H {TM dup
    0 gt {1 sub H S TM H S H T S -1 1
          scale H 180 rotate 1 add} if
    TM}def
/R 8 def
100 100 moveto
4 H pop  % Order of the curve
showpage
        

Нас интересует сейчас, конечно, рекурсивная процедура H. Распишем ее с подробным комментарием

/H{ %  n -> n
    %  так описывают содержимое стека до и после
                  вызова процедуры
    %  в стеке лежит и сохраняется порядок
    TM      % это преобразование пространства
    dup     % копирование порядка
    0 gt    % условие выполнения действия
    {1 sub H S TM H S H T S -1 1 scale H
          180 rotate 1 add}   % Само действие см. ниже
    if
    TM      % повторное преобразование
 }def
        

Поначалу важно заметить, что основную часть процедуры составляет некое действие, выполняемое только при положительном “порядке” - параметре, лежащем в стеке. Это действие начинается и заканчивается изменением этого порядка - он на единицу уменьшается, а потом его значение восстанавливается. Условно можно записать так

{1 sub <core> 1 add}
        

Теперь распишем центральную часть процедуры

{1 sub
 H            % первый фрагмент
 S            % первый мостик
 TM           % поворот с отражением
 H            % второй фрагмент
 S            % второй мостик
 H            % третий фрагмент
 T            % поворот на 90 градусов
 S            % третий мостик
 -1 1 scale   % зеркальное отражение
 H            % четвертый фрагмент
 180 rotate   % поворот
 1 add}
         

Рисующая мостики процедура S

/S{0 R rlineto currentpoint stroke moveto}def
        
сделана так, чтобы при рисовании мостика его конечная точка оставалась текущей точкой контура. Параметр R определяет длину мостика.

Назад

раскрутка сайта в интернете. экскаваторы в аренду для рытья котлованов. осенью! Заказывайте у нас: Броен и трубопроводная арматура на 10% дешевле! Отлично.. только сейчас! Конвенция о договоре международной дорожной перевозки грузов. Обзоры