Квант

48

Заочная школа программирования

Урок 7: Функции, графики, локальные и тексты на Рапире

Функции и графики

На уроке 6 («Квант», № 2) мы изучали описание процедур на языке Рапира. При этом мы рассматривали только такие процедуры, в которых не указывается имя-результат. Однако синтаксический диаграммой предусмотрен вариант описания процедуры, в котором используется имя-результат. Такими процедурми мы сейчас и займемся.

Процедура, в описании которого указано имя-результат, называется на языке Рапира функцией. Значением функции считается то значение, которое присваивается имену-результату (т. е. имени, стоящему вслед за знаком =>) после использования функции. Это значение, вообще говоря, зависит от значений параметров, указанных в заголовке процедуры.

Посмотрим сперва, что делает ЭВМ, когда ей впервые сообщают описание функции. Например, если в программе написано:

ПРОЦ КВАТ X = > РЕЗ;
2X! 2—5X+10 —> РЕЗ; КНЦ;

ЭВМ выберет у себя блок памяти, дакт ему инициатива.

Тепер посмотрим, как машина будет вызывать храняшуюся в памяти функцию. Важно помнить, что, в отличие от обычной процедуры, вызов функции может встречаться внутри выражения. Например, если в той же программе встречались такие predписания:

28.5 — > A;
5*(A+KBAT(2)) — > C;

ЭВМ сперва запишет число 28.5 в блок памяти с именем A (то есть присвоит имену A значение 28.5). Чтобы выполнить второе предписание, ЭВМ должен сложить значение выражений A и KBAT(2). Первое из них ЭВМ просто прочитает в блоке памяти с именем A. Второе выражение — это вызов функции. Чтобы узнать его значение, ЭВМ должен найти в памяти описание этой функции, присвоить ее параметром (в нашем случае параметру X будет присвоено значение 2), выполнить все операторы и прочитать значение имен-результата. Легко подчитать, что имя РЕЗ получит значение 8. Это число и будет использовано в качестве значения выражения KBAT(2). В конце концов имя C получит значение 182.5.

Возможны и более сложные выражения с функциями: KBAT(2+KBAT(1*(-KBAT(2))))

Задание 7.1. Вычислить значение этого выражения.

В языке Рапира есть стандартные функции SIN (X), COS (X), EXP (X), LN (X), ARCTAN (X) и некоторые другие. Значением показательной функции EXP (X) будет eXe^X, где e≈2.71828e \approx 2.71828, словом ARCTAN обозначен арктигенс, LN обозначает натуральный логарифм. Учащиеся шестого и седьмого классов пока не

50

программе:
5.213 —> A; 2A—> B;
КВАКУБ (2)—> C;
ПЕЧАТЬ (‘A=’, A, ‘B=’, B, C=’, C);

Верятно, он будет очень удивлен, когда ЭВМ отпечатает:
A=4 B=8 C=8,
ведь он хотел присвоить именам A и B совсем другие значения!

Что бы избежать таких непряятностей, можно объявить имена, используемые в процедуре, с помощью такого предписания (знак «обозначает пропуск):

Например, процедура КВАКУБ с объявлением именами выглядела бы так:
ПРОЦ КВАКУБ X=>Y;
ИМЕНА А’В;
X!2—> A; X!3—> B;
ЕСЛИ A>B TO A—>Y ИНАЧЕ В—>Y ВСЕ; КНЦ;

Объявленные имена известны только внутри процедуры и не влияют на другие части программы. Это значит, во-первых, что после использования процедуры значения этих имен прочитать невозможно. Во-вторых, если в программе встречаются другие имена с таким же обозначениями, то их значения не изменятся при использовании процедуры. Например, если приведенная выше программа будет использоваться с новым вариантом процедуры КВАКУБ, то ЭВМ отпечатает
A=15.63 B=31.26 C=8,
то есть именно то, что требовалось второму программисту.

Такими же свойствами, как объявленные имена, обладают параметры процедуры и имя-результат, поэтому объявлять их не нужно.

Имена, известные только внутри процедуры, называются локальными (то есть местными, внутренними)

именами. Если какая-либо процедура должна использовать много раз в большой программе, то все имена в ней стоит сделать локальные — тогда можно не описаться случайных совпадений в обозначениях имен. Именно так организованы все стандартные процедуры и функции.

Работа с текстами

Если слова «караул» хорошо отслеживают, получится «ура».

В состав выражений языка Рапира могут входить не только числа, но и тексты, а также имена, значениями которых являются тексты. Разумеется, общные арифметические операции — сложение, вычитание, умножение, деление и т. д. — к ним не применены. В то же время существует специальные операции для работы с текстами:

  1. Конкатенация («склеивание») текстов. Эта операция обозначается знаком +, как и сложение. Например, после выполнения предписаний ‘ИЛ’—>A; ‘КОД’—>B;
    ‘KPO’+B+A—>C;

значением имена С станет текст ‘KРОКОДИЛ’.

  1. Определение длин текста, то есть количество символов в нем. Эта операция обозначется знаком ≠. Например:
    ≠ ‘KРОКОДИЛ’—>A;
    ‘ЗАЙЧИК’—>B;
    ≠ B+≠ ‘БЕЛКА’—>K;
    ПЕЧАТЬ (‘A=’, A,‘K=’, K);

по этой программе ЭВМ отпечатает:
A=8 K=11

  1. Вырезание участка текста. Это, пожалуй, самая интересная операция над текстами. Ее можно описать такой diagramмой:

Значением имена должен быть текст, а значениями выражений, стоящих в квадратных скобках,— натуральные числа. Эти числа считаются номерами начального и

51

конечного символов выражемого участка. Если в скобках указано одно выражение, выражается один символ с соответствующим номером. Пусть, например, выполнены такие присваивания:
‘КРОКОДИЛ’—>К; ‘ЛАНЬ’—>Л;
‘СОВА’—>С;
‘ЕЛКА’—>Е;

тогда значением выражения К [4:6] будет текст ‘КОД’, значением выражения Л [2] будет текст ‘А’, а значением выражения К [4:5] + К[2:3] + С[3:4] будет текст, ‘КОРОВА’.

Задание 7.5. Найти значение выражения
С[1] + Л[2] + К[2] + К[6] + Е[1:2] + Л[4] + Е[3:4]

Выражения над текстами можно использовать и в условиях предложении. Попробуем, например, описать функцию, параметром которого будет текст, а результатом количественного букв ‘А’ в этом тексте:
ПРОЦ БУКВА ТЕК=>РЕЗ;
ИМЕНА НОМЕР;
0—>РЕЗ; 1—>НОМЕР;
ПОКА НОМЕР=<(≠ТЕК)::
ЕСЛИ ТЕК [НОМЕР]=‘А’ ТОРЕЗ+1—>РЕЗ ВСЕ;
НОМЕР +1—>НОМЕР;
ВСЕ;
КНЦ;

Операция вырезания участка текста, в отличие от большинства других операций, может использоваться справа от стрелки присваивания. Таким способом можно изменять значения отдельных букв и участков текста. Пусть, например, значение имени К — текст ‘КРОКОДИЛ’. Тогда после присваивания ‘Я’—>К[3]

значением этого имени будет текст ‘КРЯКОДИЛ’, а после следующего присваивания
К[1:3]≥К[4:6];

значением этого имени станет текст ‘КРЯКРЯИЛ’.

Задание 7.6. «Отредактировать текст ‘КАРАУЛ’ так, чтобы получилось ‘УРА’.

Урок 8: Множества и кортежи на Раппире

В статье о IV Всегоизной летней школе юных программистов («Квант», 1979, № 2) мы уже писали, для чего нужны множества, кортежи и другие сложные типы данных. Восьмой урок заочный школь посвящен описанию средств работы с множествами и кортежами в языке Раппира.

Задание множества

Значениями любых имен в языке Раппира, нарушу с числами, текстами и описаниями процедур, могут быть сложные структуры данных: множества и кортежи.

Множество обозначется угловыми скобками со звездочками: «* и *». Внутри скобок перечисляются через запятую все элементы множества. Например, после выполнения предписания
«1, ‘ЮНЫЙ ПРОГРАММИСТ’, 2, ‘КВАНТ’»—>А;
значением имена А станет множество. Элементы этого множества — числа 1 и 2 и тексты ‘ЮНЫЙ ПРОГРАММИСТ’ и ‘КВАНТ’.

Все, что может быть значением имена в Раппире, может быть и элементом множества. В частиности, элементами одних множества могут быть другие множества:
«*1, 2, «4, 5, ТЕКСТ»»—>В;

В этом примере значение имена В — это множество из трех элементов: двух чисел и одного множества.

Если в списке элементов множества указано имя или более сложное выражение, то элементом множества станет значение такого выражения; например, после выполнения предписания
5—>А; 10—>В;
‘КАРАУЛ’—>С;
«A, 4, 40A+B, C[5]+
C[3:4]*»—>А;

значением имена А станет множество
«5, 4, 210, ‘УРА’»
Задание 8.1. Чему будет равны значения имена A и B после выпол-

52

неня программы:
‘КРОКОДИЛ’ + " + ‘ГЕНА’ -> A;
= A -> B;
(A[(B+1)/2-3] + A[(B-1)/2+1] +
A[≠A-1] + A[3] + A[B] +
A[6] + A[2], A[4] + A[11] +
A[2
3] + A[8/4], A[22+2] +
A[1+1] + A[B] + A[4:5] +
A[B-1]
) -> A;
(A, B+1, B+10) -> B;

Сравнение множества и проверка принадлежности
Множества и их имена можно использовать в условиях (в циклических и условных предложениях).
В частности, два множества можно сравнить при помощи знака =. Как известно из школьного курса математики, два множества считаются равными, если они состоит из одних и тех же элементов, независимо от порядка, в котором перечисляются эти элементы: множества
(‘НЕЗНАЙКА’, ‘ВОРЧУН’,
‘ЗНАЙКА’
),
(‘ЗНАЙКА’, ‘НЕЗНАЙКА’,
‘ВОРЧУН’
)

равны между собой, а множества (1, 2, 3) и (1 (2, 3)) не равны.
Процедура ПЕЧАТАТЬ печатает множество в таком же виде, в каком оно записывается в программе (то есть все элементы печатаются в угловых скобках со звездочками через запятую, при этом тексты будут напечатаны без кавычек). Порядок элементов при печати может быть произвольным, так что заранее нельзя представать, например, будет ли множество КВАРТЕТ из задания 8.2, приведенного ниже, напечатано как (ОСЕЛ, КОЗЕЛ, МАРТЫШКА, МИШКА)

или
(МИШКА, ОСЕЛ, КОЗЕЛ, МАРТЫШКА)

или как-нибуд еще.

Задание 8.2. Что отмечает машина, используя такой программу:
(1, 2) -> X; (‘МАРТЫШКА’, ‘ОСЕЛ’, ‘КОЗЕЛ’, ‘МИШКА’) -> KBAPTET; (X, KBAPTET) ->

СМЕСЬ1; (*KBAPTET, (1+1, 1), KBAPTET) -> СМЕСЬ2; ЕСЛИ СМЕСЬ1 = СМЕСЬ2 TO ПЕЧАТЬ (‘КАК ВЫ НИ САДИТЕСЬ…’)
ИНАЧЕ ПЕЧАТЬ (‘2*2=4’) ВСЕ;
ЕСЛИ KBAPTET = СМЕСЬ2 TO ПЕЧАТЬ (‘ОТ ПЕРЕМЕНЫ МЕСТ СЛАГАЕМЫХ’) ИНАЧЕ ПЕЧАТЬ (‘ПРОИЗВЕДЕНИЕ НЕ МЕНЯЕТСЯ’) ВСЕ;

Условие принадлежности элемента множеству записывается с помощью ключевого слова ИЗ, которое соответствует символу ∈ в общих математических обозначениях. Например, условие

‘МИШКА’ ИЗ KBAPTET

будет истинным только в том случае, если среди элементов множества KBAPTET есть текст ‘МИШКА’.

Операции над множествами
Операция объединения множества обозначется в Рапире знаком +, а пересечение множества — знаком *. Например, по программе (17, 1, 8, 27, 36, 5) -> ТИРАЖИ; (5, 25, 11, 17, 35, 4) -> ТИРАЖ2; ПЕЧАТЬ (‘ОБЪЕДИНЕНИЕ=’, ТИРАЖ1 + ТИРАЖ2); ПЕЧАТЬ (‘ПЕРЕСЕЧЕНИЕ=’, ТИРАЖ1 * ТИРАЖ2); ЭВМ отпечатает:

ОБЪЕДИНЕНИЕ =
= (17, 1, 5, 25, 11, 36, 27, 4, 35, 8) ПЕРЕСЕЧЕНИЕ = (5, 17)

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

(‘ЛЕВ’, ‘ВОЛК’, ‘ЛИСА’, ‘ЗАЯЦ’) -> (‘БЕЛКА’, ‘ЗАЯЦ’, ‘КРОЛИК’) -> ХИШНИК; ПЕЧАТЬ (ХИШНИК);

будет отпечатано:

(*ВОЛК, ЛИСА, ЛЕВ)

Число элементов множества обозначется значком ≠, как и для текстов. Например, что одинаковые элементы в множестве учитываются только один раз, так что мощность множества

(‘КРОКОДИЛ’, ‘ГЕНА’),
(1, 1, 2, 1, 2, 1+1, 1, 1, 3-1, 3-2)
одинакова и равна 2.