Тверской государственный университет
Опубликован: 03.10.2011 | Доступ: свободный | Студентов: 3247 / 56 | Оценка: 4.33 / 3.83 | Длительность: 19:48:00
ISBN: 978-5-9963-0573-5
Лекция 8:

Структуры управления

Условный оператор: пример

Усовершенствуем наш последний пример с циклом. Представьте, что мы хотим, чтобы на пересадочных станциях вместо красной точки отображалась бы желтая мигающая точка в течение более длительного времени. Класс TOURISM предусмотрительно заготовил для этих целей метод show_blinking_spot, который дополняет метод show_stop, используемый ранее.

Для достижения требуемого результата в нашей программе придется сделать следующее изменение:

from 
  Line8.start 
invariant
  not_before_unless_empty: (not is_empty) implies (not is_before) 
  — "Точка отображена для всех станций перед позицией курсора" 
until
  Line8.is_after
loop
  if Line8.item.is_exchange then
    show_blinking_spot (Line8.item.location) 
  else
    show_spot (Line8.item.location)
  end
  Line8.forth
variant
  Line8.count - Line8.index + 1
end
Листинг 7.2.

В условном операторе трижды используется выражение Line8.item - вызов запроса. Более элегантно вычислять такой результат один раз, дав ему имя, а затем использовать это имя. Вскоре мы покажем, как это делать.

Время программирования!
Используйте условный оператор

Измените предыдущий пример - метод traverse в классе ROUTES - с учетом приведенного выше условного оператора. Запустите систему и получите результат.

Для записи условного оператора нам понадобятся четыре новых ключевых слова: if, then и else, а также elseif, которое появится чуть позже. Базисная структура оператора перед вами:

if condition then 
  Compound_1
else
  Compound_2
end

Здесь condition (условие) — это булевское выражение, а Compound_1 и Compound_2 — составные операторы, последовательности из нуля или более операторов.

Структура условного оператора и ее вариации

Будучи последовательностями из нуля и более операторов, как Compound_1, так и Compound_2 могут быть пустыми операторами, поэтому можно писать (хотя такой стиль не рекомендуется):

if condition then 
  Compound_1
else
    <--------- Здесь ничего
end

В этом варианте else-часть, хотя и присутствует, но в ней ничего нет. Это соответствует частому случаю, когда нужно выполнить некоторые действия при выполнении определенного условия; в противном случае делать ничего не нужно. Вместо того чтобы писать else-часть без операторов, разрешается просто ее опускать. Можно писать (рекомендуемый стиль):

if condition then  
  Compound_1
    <--------- Без предложения else
end

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

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

Стиль этого примера не рекомендуется. Рекомендуемый стиль записи появится чуть позже.

from ... invariant ... until ... loop
        — Пропущенные предложения цикла смотри в листинге 2.2
  if Line8 .item .is_exchange then
    show_blinking_spot (Line8 .item .location)
  else
    if Line8 .item .is railway connection then 
      show_big_blue_spot ( Line8 .item .location)
    else
      show_spot ( Line8 .item .location)
    end
  end
  Line8 .forth
variant ... end
Листинг 7.3.

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

Почувствуйте стиль
Какой может быть глубина вложенности?

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

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

В примерах, таких как пример 7.3, глубина вложенности делает структуру более сложной, чем это фактически необходимо. Ее можно упростить, не обращаясь к подпрограммам. Это упрощение применимо к условным операторам, вложенным в else-часть других условных операторов:

if condition_1 then
  ...
else
  if condition_2 then 
    ...
  else
    if condition_3 then
      ...
    else
      ...
      ...Последующие вложенные вхождения if ... then ... else ... end ...
    end
  end
end

В такой структуре вложенность производит обманчивое впечатление сложности, в то время как фактическая структура решения — последовательная:

  • если имеет место condition_l, выполните первую then-часть и ничего более;
  • для i > 1, если имеет место condition_i но ни одно из предыдущих условий condition_j не выполнено для j < i, выполните i-ю then-часть и ничего более;
  • если ни одно из условий condition_i не выполняется, то выполните наиболее вложенную else-часть и ничего более.

Ключевое слово elseif позволяет удалить излишнюю вложенность в этом случае, написав последовательные варианты на одном уровне:

if condition_1 then 
  ...
elseif condition_2 then 
  ...
elseif condition_3 then
  ...
elseif ... Последующие условия при необходимости then 
  ...
else — Как ранее, else-часть является возможной 
  ...
end

Первый вариант структуры подобен матрешке:

Второй вариант гребенчатой структуры не столь хитроумен, но более понятен: Ключевое слово elseif, написанное как единое слово, не следует смешивать с парой подряд идущих слов else и if, использованных в варианте с матрешкой, поскольку в этом случае каждое if должно иметь свои собственные then и end.

Используя elseif, мы можем переписать пример 7.3 в виде одного условного оператора без применения вложенности:

Матрешка

Рис. 7.13. Матрешка
Гребенчатая структура

Рис. 7.14. Гребенчатая структура
from ... invariant ... until ... loop
      — Опущенные предложения цикла такие же, как в листинге 2.2
  if Line8 .item .is_exchange then
    show_blinking_spot ( Line8 .item .location) 
  elseif Line8 .item .is_railway_connection then
    show_spot ( Line8 .item .location)
  else
    show_spot ( Line8 .item .location)
  end
  Line8 .forth
variant ... end

Условный оператор: синтаксис

Приведем сводку форм условного оператора.

Синтаксис
Условный оператор

Условный оператор состоит в порядке следования из:

  • "If-части" в форме if условие;
  • "Then-части" в форме then составной оператор;
  • нуля или более "Else-if" частей, каждая в форме elseif условие then составной оператор;
  • нуля или более "Еlsе"-частей, каждая в форме else составной оператор;
  • ключевого слова end.

Каждое условие является булевским выражением.

Кстати, если вы находите, что этот способ описания синтаксиса многословен и недостаточно точен, то вы правы. Лучший способ описания таких конструкций дает нотация, известная как нотация БНФ. Мы познакомимся с ней в лекции, посвященной синтаксису. Неформальные спецификации, сопровождаемые примерами, пока достаточны для понимания.

Условный оператор: семантика

Предыдущее обсуждение позволяет понять эффект действия условного оператора.

Семантика
Условный оператор

Выполнение условного оператора состоит в выполнении не более одного составного оператора, входящего в одну из частей: "Then", "Else If", если присутствует, "Else", если присутствует. Какой оператор будет выполняться?

  • Если условие, следующее за if, имеет значение True, то выполняется составной оператор части Then.
  • Если это условие ложно и существуют Else_if, то первая из таких частей, для которой выполняется условие, и определяет выполняемый составной оператор.
  • Если ни одно из рассмотренных выше условий не выполняется и существует Else-часть, то она определяет выполняемый составной оператор.
  • Если ничего из выше рассмотренного не применимо, то никакой составной оператор не выполняется и действие условного оператора в этом случае эквивалентно пустому оператору.

Условный оператор: корректность

Корректность условного оператора определяется корректностью каждой его ветви в предположении, что выполняется условие для этой ветви.

Корректность
Составной оператор

Чтобы условный оператор if c then a else b end был корректным, следует убедиться, что перед его выполнением:

  • если c имеет место, то должно выполняться предусловие a;
  • если c не выполняется, то должно выполняться предусловие b.

Из конъюнкций постусловий a and b - и условия, при котором каждое из них выполняется, - должно следовать желаемое постусловие для всего составного оператора.

Обобщите самостоятельно это правило на общую конструкцию, включающую предложения elseif.

Ирина Калашникова
Ирина Калашникова

Добрый день, подскажите на тест после каждой лекции сколько дается попыток? 

Наталья Король
Наталья Король

Что это значит?) Зранее спасибо)