Copyright (C) А.Гавва V-0.4w май 2004

3. Управляющие структуры

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

Управляющие структуры языка Ада по своему стилю и назначению подобны тем конструкциям, которые встречаются в большинстве других современных языках программирования. Однако, при этом присутствуют и некоторые отличия.

Как и язык в целом, управляющие структуры языка Ада, были разработаны так, чтобы обеспечить максимальную читабельность. Все управляющие структуры языка Ада можно разделить на простые и составные инструкции. Все инструкции языка Ада должны завершаться символом точки с запятой. Все составные инструкции завершаются конструкцией вида "end что-нибудь ;".

3.1 Пустая инструкция

В отличие от многих других языков программирования, в Аде явно присутствует инструкция, которая не вызывает каких-либо действий. Такая инструкция называется пустой, и она имеет следующий вид:


null;

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

3.2 Инструкция присваивания

Инструкция присваивания используется в Аде для установки и изменения значений переменных. Она использует операцию присваивания, и в общем случае имеет следующий вид:


result := expression;

Операция присваивания ":=" разделяет инструкцию присваивания на левую и правую части (между символами двоеточия и знак равенства, пробелы - не допустимы!). В левой части записывается имя переменной (result) содержимому которой будет производится присваивание нового значения. Следует заметить, что в левой части может распологаться имя только одной переменной. В правой части записывается выражение (expression) результат вычисления которого становится новым значением переменной result. Выражение expression, расположенное в правой части, может быть одиночной переменной или константой, может содержать переменные, константы, знаки операций и вызовы функций. Тип переменной определяемой как result должен быть совместим по присваиванию с типом результата вычисления выражения expression.

Выполнение присваивания разделяется на несколько действий. Сначала производится вычисление имени переменной result и результата выражения expression (порядок следования этих действий не регламентирован стандартом языка). После этого, в случае успеха, для переменных скалярных типов проверяется принадлежность значения результата вычисления выражения expression подтипу переменной. Если проверка успешна, то значение результата вычисления выражения expression становится новым значением содержимого переменной result. При этом старое значение содержимого result - теряется. Иначе, в случае какой-либо неудачи, возбуждается исключение ошибки ограничения или, проще говоря, - ошибка, а значение переменной result остается без изменений.

Приведем несколько примеров инструкций присваивания:


A := B + C
X := Y

Следует заметить, что в Аде, в результате выполнения присваивания производится изменение только содержимого result (значение содержимого переменной указанной в левой части). Необходимо также подчеркнуть, что операция присваивания в Аде, в отличие от языков C/C++, не возвращает значение и не обладает побочными эффектами. Кроме того, напомним, что операция присваивания, в Аде, не допускает совмещение, переименование и использование псевдонимов, а также она запрещена для лимитированных типов.

3.3 Блоки

Блок содержит последовательность инструкций, перед которой может располагаться раздел описаний (все описания локальны для блока и не доступны вне блока). За последовательностью инструкций могут следовать обработчики исключений (обработка исключений в Аде рассматривается позже). В общем случае инструкция блока Ады имеет вид:


declare

    -- локальные описания

begin

    -- последовательность инструкций

exeption

    -- обработчики исключений

end;

Блок может иметь имя. Для этого перед инструкцией блока записывается идентификатор, за которым ставится двоеточие. При именовании блока, имя блока должно указываться после end завершающего блок:


Some_Block:
declare
    X : Integer;
begin
    X := 222 * 333;
    Put(X);
end Some_Block;

3.4 Условные инструкции if

Для организации условного выполнения последовательностей алгоритмических действий (то есть, построения разветвляющихся алгоритмов), в Аде могут использоваться условные инструкции if.

Каждая инструкция if заканчивается конструкцией "end if".


if <логическое_выражение> then

    -- последовательность инструкций

end if;

if <логическое_выражение> then

    -- последовательность инструкций 1

else

    -- другая последовательность инструкций 2

end if;

В первом примере, приведенном выше, последовательность инструкций, описывающая алгоритмические действия, будет выполнена только в случае когда результат вычисления логического выражения будет иметь значение True. Во втором примере, в случае когда результат вычисления логического выражения - True будет выполняться "последовательность инструкций 1", в противном случае - "последовательность инструкций 2".

Для сокращения инструкций вида "else if ... ", и в целях улучшения читабельности, введена конструкция elsif, которая может быть использована столько раз, сколько это будет необходимо.


if <логическое_выражение> then

    -- последовательность инструкций 1

elsif <логическое_выражение> then

    -- последовательность инструкций 2

elsif <логическое_выражение> then

    -- последовательность инструкций 3

else

    -- последовательность инструкций

end if;

В этой форме инструкции if, заключительная конструкция else - опциональна.

Необходимо также заметить, что результат вычисления логического выражения всегда должен иметь предопределенный тип Standard.Boolean.

3.5 Инструкция выбора сase

Еще одним средством позволяющим строить разветвляющиеся алгоритмы является инструкция выбора сase.

Инструкция выбора сase должна предусматривать определенное действие для каждого возможного значения переменной селектора (переключателя). В случаях, когда невозможно перечислить все значения переменной селектора, нужно использовать метку others.

Каждое значение выбора может быть представлено как одиночное значение (например, 5), как диапазон значений (например, 1..20), или как комбинация, состоящая из одиночных значений и/или диапазонов значений, разделенных символом '|'.

Каждое значение выбора должно быть статическим значением, то есть оно должно быть определено компилятором во время компиляции программы.


case  выражение  is
    when значение_выбора => действия
    when значение_выбора => действия
      . . .
    when others => действия
end case;

Важные примечания:


case Letter is
    when 'a'..'z'| 'A'..'Z' => Put ("letter");
    when '0'..'9'           => Put ("digit! Value is"); Put (letter);
    when ''' | '"' | '`'    => Put ("quote mark");
    when '&'                => Put ("ampersand");
    when others             => Put ("something else");
end case;

В некоторых случаях, в качестве действий, указываемых для метки others, может использоваться пустая инструкция null:


    . . .
    when others  => null;  -- ничего не делать
    . . .

3.6 Организация циклических вычислений

При решении реальных задач часто возникает необходимость в организации циклических вычислений. Все конструкции организации циклических вычислений в Аде имеют форму "loop ... end loop" с некоторыми вариациями. Для выхода из цикла может быть использована инструкция exit.

3.6.1 Простые циклы (loop)

Примером простейшего цикла может служить бесконечный цикл. Обычно он используется совместно с инструкцией exit, рассматриваемой позже.


loop

    -- инструкции тела цикла

end loop;

3.6.2 Цикл while

Во многих случаях, прежде чем выполнять действия которые описываются инструкциями тела цикла, необходимо проверить какое-либо условие. Для таких случаев Ада предусматривает конструкцию цикла while.

Цикл while идентичен циклу while в языке Паскаль. Проверка условия выполнения цикла производится до входа в блок инструкций составляющих тело цикла. При этом, если результат вычисления логического выражения будет True, то будет выполнен блок инструкций тела цикла. В противном случае, тело цикла - не выполняется.


while логическое_выражение loop

    -- инструкции тела цикла

end loop;

Необходимо заметить, что результат вычисления логического выражения должен иметь предопределенный тип Standard.Boolean

3.6.3 Цикл for

Еще одним распространенным случаем является ситуация когда необходимо выполнить некоторые действия заданное количество раз, то есть организовать счетный цикл. Для этого Ада предусматривает конструкцию цикла for.

Конструкция цикла for Ады аналогична конструкции цикла for, представленной в языке Паскаль.

Существует несколько правил использования цикла for:

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


for счетчик in диапазон_значений_счетчика loop

    -- инструкции тела цикла

end loop;


for  Count in 1..20 loop
    Put (Count);
end loop;

Возможен перебор значений диапазона в обратном порядке:


for счетчик in reverse диапазон_значений_счетчика loop

    -- инструкции тела цикла

end loop;


for Count in reverse 1..20 loop
    Put (Count);
end loop;

Любой дискретный тип может использоваться для указания диапазона значений переменной-счетчика.


declare
    subtype List is Integer range 1..10;

begin
    for Count in List loop
        Put (Count);
    end loop;
end;

Здесь, тип List был использован для указания диапазона значений переменной-счетчика Count. Подобным образом также можно использовать любой перечислимый тип.

3.6.4 Инструкции exit и exit when

Инструкции exit и exit when могут быть использованы для преждевременного выхода из цикла. При этом, выполнение программы будет продолжено в точке непосредственно следующей за циклом. Два варианта, показанных ниже, имеют одинаковый эффект:


loop

    -- инструкции тела цикла

    if логическое_выражение then
        exit;
    end if;
end loop;


loop

    -- инструкции тела цикла

    exit when логическое_выражение;
end loop;

3.6.5 Именованые циклы

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


outer_loop:
loop

    -- инструкции

    loop

        -- инструкции

        exit outer_loop when логическое_выражение;
    end loop;
end loop outer_loop;

Примечательно, что в случае именованого цикла end loop также необходимо именовать меткой.

3.7 Инструкция перехода goto

Инструкция перехода goto предусмотрена для использования в языке Ада, в исключительных ситуациях, и имеет следующий вид:


goto Label;

<<Label>>

Использование инструкции goto очень ограничено и четко осмысленно. Вы не можете выполнить переход внутрь условной инструкции if, внутрь цикла (loop), или, как в языке Паскаль, за пределы подпрограммы.

Вообще, при таком богатстве алгоритмических средств Ады, использование goto едва-ли можно считать оправданным.


Copyright (C) А.Гавва V-0.4w май 2004