#9 Условный оператор IF (оператор ветвления if else) в Паскаль. Полная и неполная формы условного оператора. Вложенность условий

Условный оператор -- что это такое

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

Структура условного оператора. Блочность

Условный оператор в общем виде состоит из трёх частей:

  1. Проверка логического значения
  2. Ветка истинности (обязательна) -- выполнится если логическое значение истинно (true)
  3. Ветка ложности (необязательна) -- выполнится если логическое значение ложно (false)

Сразу отметим, что логическое значение -- это фактически ответ на вопрос формата "да/нет" , напомним, что логическим типом значением обладают:

  1. логические литералы
  2. логические переменные
  3. и логические выражения

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

В программном коде структуру условного оператора можно проиллюстрировать следующей схемой:

if (<логическое_значение>) then // проверка выражения  и начало тела ветки истинности
begin
  {здесь код, который выполнится,
  если логическое значение истинно}
end else //  начало ложной ветки (её тела)
begin
  {здесь код, который выполнится,
  если логическое значение ложно}
end; // конец ложной ветки и оператор ветвления         

Например:

if ( 5 > 7) then // проверка выражения  и начало тела ветки истинности
begin
  writeln('5 > 7 верно');
  writeln('5 > 7 верно');
end else //  начало ложной ветки (её тела)
begin
  writeln('5 > 7 неверно');
  writeln('5 > 7 неверно');
end; // конец ложной ветки и оператор ветвления   

-- в данном случае выполнится "ложная" ветка, так как $5 > 7$ возвращает результат false.

Точка с запятой перед else

Заметьте (см. примеры выше и ниже), что перед else точка с запятой не ставится.

Операторные скобки условного оператора

В предыдущем примере обратите внимание на операторные скобки, окружающие тела веток оператора ветвления -- begin и end необходимы, если в ветке выполняется более одной операции, если же в ветке содержится только одна операция, то операторные скобки не нужны.

Например для ситуации, изображённой на этой блок-схеме:
Паскаль ветвление условный оператор без begin end операторных скобок
Эту же ситуацию можно проиллюстрировать кодом:

if ( 5 > 7) then // проверка выражения  и начало тела ветки истинности
  writeln('5 > 7 верно') // конец ветки истинности
else //  начало ложной ветки (её тела)
  writeln('5 > 7 неверно'); // конец ветки ложности    

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

Полная и неполная формы оператора IF

Оператор IF в программе может быть представлен в следующих формах:

  1. Полная форма -- форма оператора if, в которой присутствуют обе ветки -- и then и else
  2. Неполная форма -- форма в которой присутствует только then.

Полная форма условного оператора IF

В полной форме оператора IF присутствуют обе ветки -- именно полную форму мы рассматривали выше, например:

if (a > 5) then
  b := 2 // в ветки истинности одно  действие
else begin
  b := 3;  // в ветки ложности два действия
  a := 2;
end.  

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

В последнем примере кода, у нас в ветке истинности одна операция, а в ветки ложности 2 -- эту ситуацию можно изобразить на блок-схеме так (с каким-то предварительным действием до if):
Полная форма оператора IF Паскаль

Неполная форма условного оператора IF

В неполной форме условного оператора есть только сценарий истинности, ветка ложности же вообще не описывается, например:

if (a > 5) then
  b := 2 // в ветки истинности одно действие   

-- в ветке ложности здесь вообще ничего нет, то есть если $a$ не больше $5$, то и никаких действий предпринято не будет.

На блок-схеме неполная форма оператора ветвления выглядит так:
Неполная форма условного оператора ветвления

-- правило использования операторных скобок действует и здесь: в данном же случае у нас только одна операция в ветке then, а потому begin и end не нужны.

Полная форма IF с пустой веткой then. Почему стоит избегать

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

if условие then
else
  дейстия

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

if not(условие) then
  дейстия  

Например, код:

var f : integer;
begin
  write('Введите число : ');
  readln(f);
  if f = 0 then 
  else // в ветке then ничего нет!
    writeln('Не равно нулю!');

  readln();
end.

-- можно переписать так:

var f : integer;
begin
  write('Введите число : ');
  readln(f);
  if not(f = 0) then
    writeln('Не равно нулю!');

  readln();
end.  

Или еще короче:

var f : integer;
begin
  write('Введите число : ');
  readln(f);
  if f <> 0 then
    writeln('Не равно нулю!');

  readln();
end.  

Разбор задач

Пример №1 -- неполная форма IF

Сравните два числа, если первое больше второго, то выведите на экран "22" и затем отдельным вызовом writeln() число 555.

-- в этой задаче указано, что надо предпринимать какие-то действия только в одном случае ("если первое больше второго"), а значит будет использовать оператор ветвления в неполной форме:

var a,b: integer;
begin
  writeln('vvedite dva celih chisla: ');
  readln(a, b);

  if (a > b) then // сравниваем
  begin
    writeln(22);
    writeln(555);
  end;

  readln();
end.   

-- в ветке истинности здесь было две операции, а потому мы использовали для неё операторные скобки.

Пример №2 -- полная форма, по одному действию в каждой ветке

Сравните два числа, если первое больше второго, то выведите на экран "22", а иначе выведете на экран 'abc'.

-- в этой задаче указаны два альтернативных действия, а потому будем использовать оператор ветвления в его полной форме:

var a,b: integer;
begin
  writeln('vvedite dva celih chisla: ');
  readln(a, b);

  if (a > b) then // сравниваем
    writeln(22)   // если да
  else
    writeln('abc');    // если нет

  readln();
end. 

-- обратите внимание, что перед else точка с запятой не ставится.

Пример №3 - логические выражения и оператор ветвления IF

Задача:

Коля набрал $k$ баллов, Миша $n$ баллов, а Петя $d$ баллов в ходе соревнований. Если:

  1. сумма баллов Коли и Миши больше $20$
  2. и сумма баллов Пети и Миши меньше $55$

--то тогда вывести в консоль сообщение о том, что ничья, в противном случае вывести сообщение, что победил Коля.

В этой задаче по условию требуется выполнение сразу двух требований, причем не одного либо другого из них, а двух одновременно, потому в логическом выражении для if мы будем использовать логическую операцию AND, тогда решение может выглядетьн например так:

// переменные для хранения баллов, набранных ребятами
var k, n, d: integer; 
begin
  // сначала получаем данные от пользователя
  writeln('vvedite chislo ballov Koli: ');
  readln(k);
  writeln('vvedite chislo ballov Mishi: ');
  readln(n);
  writeln('vvedite chislo ballov Peti: ');
  readln(d);

  { далее начинаем проверку условий:
  используем "логическое И" (одновременность }
  if ((k + n > 20) AND (n + d < 55)) then
    writeln('Pobedila druzhba!')
  else
    writeln('Pobedil Kolya!');

  readln();
end.

Пример №4 - вложенные условные операторы

Операторы могут вкладываться один в другой так, как как это показано на блок-схеме (на деле внутренний оператор вкладывается в одну из веток внешнего):
вложенные условные операторы IF ветвление Паскаль пример блоксхемы

Рассмотрим задачу, решение которой будет соответствовать этой блок-схеме:

Получите от пользователя два целых числа, если первое больше второго, то выведите на экран их сумму, а затем их разность, иначе:

  1. сначала сравните их сумму с числом $25$, если она больше, то выведите на экран первое число, а если меньше, то только второе.
  2. затем выведите на экран второе число в квадрате

Реализуем решение в виде программы:

var a,b: integer;
begin
  writeln('vvedite dva celih chisla: ');
  readln(a, b);

  if (a > b) then
  begin
    writeln('ih summa:', a + b);
    writeln('ih raznost:', a - b);
  end   // перед else точка с запятой не ставится даже после end
  else begin
    { вложенные оператор условия -- первая вложенная операция
     в ветке ложности внешнего оператора }
    if ((a + b) > 25) then
      writeln('vivodim peroe:', a)
    else
      writeln('vivodim vtoroe:', b); // конец вложенного оператора ветвления и его ветки ложности (так как нет операторных скобок, то к ветке вложенности относится только одна операция)

    writeln(b*b); // вторая вложенная операция
  end;

  readln(); // удерживаем косоль
end.

Пример №5 - вложенные условные операторы

Например задачу из более раннего примера:

Коля набрал $k$ баллов, Миша $n$ баллов, а Петя $d$ баллов в ходе соревнований. Если:

  1. сумма баллов Коли и Миши больше $20$
  2. и сумма баллов Пети и Миши меньше $55$

--то тогда вывести в консоль сообщение о том, что ничья, в противном случае вывести сообщение, что победил Коля.

можно было бы решить с помощью вложенных блоков условного оператора IF:

program Project1;
var k, n, d: integer; // переменные для хранения баллов, набранных ребятами
begin
  // сначала получаем данные от пользователя
  writeln('vvedite chislo ballov Koli: ');
  readln(k);
  writeln('vvedite chislo ballov Mishi: ');
  readln(n);
  writeln('vvedite chislo ballov Peti: ');
  readln(d);

  // далее начинаем проверку условий
  if ((k + n) > 20) then
    if ((n + d) < 55) then // вкладываем второе условие
      writeln('Pobedila druzhba!')
    else
      writeln('Pobedil Kolya!')
  else
    writeln('Pobedil Kolya!');

  readln();
end.    

-- обратите внимание, что begin и end не нужны для ветки истинности внешнего оператора, так как в него вложен лишь один if -- а остальные строки относятся к этому вложенному if.

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

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

Пример №6 - жизненный выбор

То есть ситуацию, в которую попал богатырь на этой иллюстрации:
паскаль условный оператор IF ветвление ситуация выбора

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

{Программа жизненного выбора}
program qwe;
var a: integer; // число, означающее выбор пользователя (богатыря)
  res: string; // его будущее
begin
  writeln ('vvedite: 1 esli napravo, 2 esli pryamo, 3 esli nalevo ');
  readln(a); // читаем, куда пойдёт пользователь

  // далее определяем будущее
  if (a = 1) then
    res := ' konya poteryaesh '
  else if (a = 2) then
    res := ' zhenat budesh '
  else if (a = 3) then
    res := ' ubitum budesh '
  else  // если пользователь выбрал что-то другое
    res := ' buduchee ne izvestno ';

  writeln('otvet: ', res);
  readln();
end.

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

Пример №7 Вложение оператора if в неполной форме в оператор if в полной форме

При решении задач или при просмотре/анализе кода написанного не вами может возникнуть проблема понимания того, к какому именно then относится данный else, обычно такая проблема возникает в случае, если количество else не равно количеству then (если эти количества равны, то понять что во что вложено не трудно).

Рассмотрим пример (фрагмент кода), в котором есть подвох:

if (a > b) then
  if (a > c) then
    writeln('переменная а самая большая!')
else // подразумеваем, что работает когда  a<=b
  writeln('переменная a не больше b');

-- данный код отформатирован неверно, ведь он как бы показывает что else относится к первому then, в то время как Паскаль будет считать (всегда), что else относится к ближайшему then (не "отделённому" от этого else операторными скобками), итак, повторим эту идею ещё раз, назовём её правило "прикрепления" else:

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

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

if (a > b) then
  if (a > c) then
    writeln('переменная а самая большая!')
  else // !оказывается сработает если: c >= a >= b
    writeln('переменная a не больше b'); // значит это высказывание неверно!

-- но это значит, что уже неверна логика решения, из за того что на деле при подобной записи else относится к ближайшему then (мы показали это правильным форматированием и комментариями).

Но как же нам добиться задуманного в начале, т.е. той ситуации, когда в случае если a > b не верно, мы получили бы сообщение ""переменная a не больше b""?
Для этого нам придётся отделить ближайший then от else операторными скобками, то есть сделать так:

if (a > b) then
begin
  if (a > c) then
    writeln('переменная а самая большая!')
end
else // работает когда  a<=b
  writeln('переменная a не больше b'); 

Теперь ближайшим не изолированным операторными скобками от else словом then оказывается первое (то, где "if (a > b)"), а не второе (т.е. не то, где "if (a > c)") -- что мы и хотели изначально запрограммировать ;)

Пример №8 -- Интерактивный сценарий текстовой консольной игры

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

var
  s, a: string;
begin
  writeln('>>Куда пойдем? (домой/на улицу)');
  readln(s);

  if (s = 'домой') then
  begin
    writeln('>>Вы пришли домой');
    writeln('>>Будем делать уроки? (да/нет)');
    readln(a);
    if (a = 'да') then
      writeln('>>Хороший выбор!')
    else
      writeln('>>Готовься к проблемам в школе');
  end
  else
    writeln('>>Происходит что-то непонятное');

  writeln('>>>>>>>>>Конец сценария<<<<<<<<<<<');
  readln();
end.

Для лучшего понимания см. видео-разбор создания этого сценария.

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

Мы уже начинали рассматривать вопрос форматирования кода, вернемся к нему в этом уроке. Это важно, т.к. теперь помимо блока тела программы мы знаем еще два блока:

  1. Блок ветки then ()
  2. и блок ветки else

-- оба этих блока требуют дополнительный (помимо базового отступа тела программы) отступ для кода, который находит в этих ветках.

Дополнительный отступ внутри блока равен базовому, например:

var a:integer;
begin // нулевой отступ (ноль пробелов слева)
  readln(a); // одинарные отступ (два пробела слева)

  if (a > 2) then
    writeln('Больше'); // двойной отступ
  else
    writeln('Больше'); // двойной отступ

  readln(); // одинарный отступ
end;

-- else пишется под тем if, которому он относится.

Для каждого вложенного блока отступ увеличивается на один базовый отступ, например:

var a:integer;
begin // нулевой отступ (ноль пробелов слева)
  readln(a); // одинарные отступ (два пробела слева)

  if (a > 2) then // одинарный
    if (a > 5) then  // двойной
      writeln('Больше!'); // тройной

  readln(); // одинарный отступ
end; 

-- в данном случае в тройном отступе у нас используется шесть пробелов (2x3=6)

Форматирование IF с операторными скобками

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

var a:integer;
begin // нулевой отступ (ноль пробелов слева)
  readln(a); // одинарные отступ (два пробела слева)

  if (a > 2) then // одинарный
    if (a > 5) then  // двойной
    begin
      writeln('Больше'); // тройной
      writeln(' пяти!'); // тройной
    end
    else // двойной
    begin
      writeln('Не больше'); // тройной
      writeln(' пяти!'); // тройной
    end
  else // одинарный
    writeln('Не больше двух'); // двойной

  readln(); // одинарный отступ
end;   

-- открывающая операторная скобка begin располагается ровно под ключевым словом if или под else (в зависимости от того, к чему относится).

Видео-пояснения

Для этого урока есть следующие видео:

Самостоятельная работа

Вопросы

  1. Для чего нужен оператор ветвления (условный оператор)?
  2. Какие ветви условного оператора вы знаете?
  3. Чем полная форма условного оператора отличается от неполной?
  4. Когда нужны операторные скобки в ветвях оператора IF, а когда нет?

Задачи

    Форматирование кода условного оператора (необязательный блок)

  1. Сдавать/выладывать решение не обязательно:
    Есть код:
    var a,b : integer;
    begin
      readln(a);
      if (a > 2) then
        writeln(a)
      else
      writeln(2);
    
    readln();
    end. 
    

    Если он отфроматирован неправильно - исправьте это, и объясните для себя почему нужно исправить именно так.

  2. Сдавать/выладывать решение не обязательно:
    Есть код:
    var a, b, c, d : integer;
    begin
    writeln('vvedite a, b, c, d');
    readln(a, b, c, d);
    if (a > b) then
    if (a > c) then
    begin
    if (a > d) then
    writeln ('Выбираем a');
    writeln ('Может выбрали a');
      end;
    readln();
    end.  
    

    -- исправьте форматирование.

    Подсказка: если непонятно как решить или хотите закрепить знания см. этот видео-разбор.

  3. Самостоятельное программирование

  4. Сравните два числа, если первое больше второго, то выведите на экран "12". (здесь нужно использовать неполную форму условного оператора)
  5. Сравните два числа, если первое больше второго, то выведите на экран "12", а если нет, то выведите на экран "888".
  6. Даны три целых числа: $A$, $B$, $C$. Проверить истинность высказывания: «Число $A$ находится между числами $B$ и $C$» -- выведите "да", если истинно и "нет" если ложно.

    ПРИМЕЧАНИЕ: эта и следующая задача базируются на том, что мы уже решали (см. задачи в конце урока).

  7. Даны три целых числа: $A$, $B$, $C$. Проверить истинность высказывания: « Число $A$ и число $B$ больше 17, а $C$ > 7». -- выведите "да", если истинно и "нет" если ложно.
  8. Пользователь вводит два числа, найдите из них максимальное. (тут всё просто)

    Примечание: если не просто или для лучшего понимания решения, см. этот видео-разбор.

  9. Пользователь вводит три числа, найдите из них максимальное.

    Решите тремя способами:

    1. С использованием логической операции and.
    2. С вложенными блоками (без and, все операторы if должны быть в полной форме).
      (Если не получается - см. разбор решения)
    3. Без вложенных блоков (без and) -- запомнив максимум из первых двух чисел в специальной переменной.
      (Если не получается - см. разбор решения)

    Указание: Сначала постарайтесь написать все три решения самостоятельно (хотя бы по 20 минут размышления на каждую задачу, но не более часа на каждую), если не получается (или после решения) также можно посмотреть это видео-пояснение.

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

    Примечание: решение с помощью AND более удобно на практике, но для тренировки понимания тут мы решаем через вложенные блоки.

  11. Коля набрал $k$ баллов, Миша $n$ баллов, а Петя $d$ баллов в ходе соревнований. Если:
    1. сумма баллов Коли и Миши больше $20$
    2. или произведение баллов Пети и Миши меньше $55$

    --то тогда вывести в консоль сообщение о том, что ничья, в противном случае вывести сообщение, что победил Коля.

  12. Есть программа, где стоит проверка на ввод пользователем числа 1 или числа 5:
    var s:integer;
    begin
      writeln('Vvedite chislo 1 ili 5');
      readln(s);
      if (s = 1) then
        writeln('soobchenie 1');
      if (s = 5) then
        writeln('soobchenie 2');
    
      readln();
    end;  
    

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

    Перепишите программу оптимальным образом.

    Подсказка: если самостоятельно разобраться не получается, смотрите этот видео-разбор.

  13. Есть программа:
    var m,s:integer;
    begin
      writeln('Vvedite chislo M');
      readln(m);
      s:=1;
      if (s = 1) then
        writeln('soobchenie 1');
      if (s = m) then
        writeln('soobchenie 2');
    end;
    

    -- при этом известно, что если s равно 1, то на экран должно вывестись только первое сообщение (а второе выводиться не должно), а если s не равно 1, но равно m, то второе (а первое выводиться не должно).
    Но сейчас программа работает не так, исправьте это.

  14. Есть программа:

    var z,s:integer;
      f:boolean;
    begin
      readln(z);
      f := z > 5;
      s:=1;
      if (z=s) and (f=false) then
      begin
        writeln();// делаем перенос строки
        z:=0;
        s:=s+1;//но увеличиваем кол-во строк
      end;
    
      if (z=s) and (f=true) then
      begin
        writeln(); // делаем перенос строки
        z:=0;
        s:=s-1;//но уменьшаем кол-во строк
      end;
    end.  
    

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

    Подсказка: используйте вложенные блоки if().
    Если идей нет, смотрите разбор решения.

  15. Изучите код:

    var s, t:integer;
        f, b:boolean;
    begin
      f := true;
      b := false;
    
      if (f=true) then
        t:=1
      else
        t:=2;
    
      if (b=false) then
        s:=3
      else
        s:=4;
    end. 
    

    -- блоки условий можно переписать более кратко, без использования сравнения = true или = false, с сохранением той же логики работы программы.

    Подсказки:

    • оператор if итак неявно сравнивает значение логического выражения в скобках с true (и принимает решение, какую именно ветку then или else выполнить)
    • для второго if в коде выше потребуется исползование оператора Not.

    Если подсказки не помогают и/или для лучшего понимания - см. этот видео-разбор.

  16. У вас есть код:
    var f : integer;
    begin
      write('Введите число : ');
      readln(f);
      if f > 5 then
      else
        writeln('Не больше 5!');
    
      readln();
    end.

    -- который сообщает пользователю, что число не равно нулю (если это действительно так), или в обратной ситуации не делает вообще ничего.

    Задача: Перепешите это код в неполной форме (без использования else).

    Примечание: если не получается решить, или для лучшего понимая решения см. этот видео-разбор.

  17. У вас есть три числа (три переменные) найдите их медиану.

    Примечание: это условие давалось как простая разминочная задачка для собеседования в Яндекс.

  18. Решать по желанию, сдавать на проверку не обязательно:

    Запрограммируйте историю:

    • 1) Вы дома, пойдем в лес или в центр города?
    • 2) Если пойдем в лес то будем жечь костер или кататься на лыжах?
    • 3) Если будем кататься на лыжах, то по кругу или с гор (придумайте последния выбора)
    • 4) Если будем жечь костер - то будем ли что-то готовить или просто (придумайте последствия выбора)
    • 5) Если выбрали поход в центр - пойдем ли в кино или погуляем по центру
    • 6) Если пойдем в кино будет смотреть исторический фильм или комедию (придумайте последствия выбора)
  19. В качестве примера см. пример №8 выше, и/или видео-разбор.

Источники (что ещё почитать)

  1. Урок 8. Блок-схема оператора if: http://learnpascal.ru/operator-if/blok-s...

Есть программа:

Тут решение с помощью полной формы условного оператора невозможно посколько s всегда будет равно 1 не зависимо от m. Стоит ли тут избавиться от s := 1 и вводить в консоли ее?

var m,s:integer;
begin
writeln('Vvedite chislo M');
readln(m);
s:=1;
if (s = 1) then
writeln('soobchenie 1');
if (s = m) then
writeln('soobchenie 2');
end;

Pages