#9 Условный оператор IF (оператор ветвления if else) в Паскаль. Полная и неполная формы условного оператора. Вложенность условий
Primary tabs
Условный оператор -- что это такое
Условный оператор IF служит для программирования ситуаций выбора (моделирования различных вариантов развития ситуации, с которым мы сталкиваемся в жизни, но теперь уже внутif (a > 5) then // двойнойри программы).
Структура условного оператора. Блочность
Условный оператор в общем виде состоит из трёх частей:
- Проверка логического значения
- Ветка истинности (обязательна) -- выполнится если логическое значение истинно (true)
- Ветка ложности (необязательна) -- выполнится если логическое значение ложно (false)
Сразу отметим, что логическое значение -- это фактически ответ на вопрос формата "да/нет" , напомним, что логическим типом значением обладают:
- логические литералы
- логические переменные
- и логические выражения
-- точно также как и любой простой тип данных может быть представлен литералами, переменными или выражениями из них.
В программном коде структуру условного оператора можно проиллюстрировать следующей схемой:
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 необходимы, если в ветке выполняется более одной операции, если же в ветке содержится только одна операция, то операторные скобки не нужны.
Например для ситуации, изображённой на этой блок-схеме:
Эту же ситуацию можно проиллюстрировать кодом:
if ( 5 > 7) then // проверка выражения и начало тела ветки истинности writeln('5 > 7 верно') // конец ветки истинности else // начало ложной ветки (её тела) writeln('5 > 7 неверно'); // конец ветки ложности
-- здесь в обеих ветках только одна операция, а потому операторные скобки не нужны.
Полная и неполная формы оператора IF
Оператор IF в программе может быть представлен в следующих формах:
- Полная форма -- форма оператора if, в которой присутствуют обе ветки -- и then и else
- Неполная форма -- форма в которой присутствует только then.
Полная форма условного оператора IF
В полной форме оператора IF присутствуют обе ветки -- именно полную форму мы рассматривали выше, например:
if (a > 5) then b := 2 // в ветки истинности одно действие else begin b := 3; // в ветки ложности два действия a := 2; end.
-- здесь в качестве условия мы сравнивали переменную с числом, а потом описывали два сценария, один из которых выполнится в зависимости от значения условия.
В последнем примере кода, у нас в ветке истинности одна операция, а в ветки ложности 2 -- эту ситуацию можно изобразить на блок-схеме так (с каким-то предварительным действием до if):
Неполная форма условного оператора IF
В неполной форме условного оператора есть только сценарий истинности, ветка ложности же вообще не описывается, например:
if (a > 5) then b := 2 // в ветки истинности одно действие
-- в ветке ложности здесь вообще ничего нет, то есть если $a$ не больше $5$, то и никаких действий предпринято не будет.
На блок-схеме неполная форма оператора ветвления выглядит так:
-- правило использования операторных скобок действует и здесь: в данном же случае у нас только одна операция в ветке then, а потому begin и 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$ баллов в ходе соревнований. Если:
- сумма баллов Коли и Миши больше $20$
- и сумма баллов Пети и Миши меньше $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 - вложенные условные операторы
Операторы могут вкладываться один в другой так, как как это показано на блок-схеме (на деле внутренний оператор вкладывается в одну из веток внешнего):
Рассмотрим задачу, решение которой будет соответствовать этой блок-схеме:
Получите от пользователя два целых числа, если первое больше второго, то выведите на экран их сумму, а затем их разность, иначе:
- сначала сравните их сумму с числом $25$, если она больше, то выведите на экран первое число, а если меньше, то только второе.
- затем выведите на экран второе число в квадрате
Реализуем решение в виде программы:
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$ баллов в ходе соревнований. Если:
- сумма баллов Коли и Миши больше $20$
- и сумма баллов Пети и Миши меньше $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 - жизненный выбор
То есть ситуацию, в которую попал богатырь на этой иллюстрации:
Можно запрограммировать следующим образом:
{Программа жизненного выбора} 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.
Для лучшего понимания см. видео-разбор создания этого сценария.
Форматирование кода условного оператора
Мы уже начинали рассматривать вопрос форматирования кода, вернемся к нему в этом уроке. Это важно, т.к. теперь помимо блока тела программы мы знаем еще два блока:
- Блок ветки then ()
- и блок ветки 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 (в зависимости от того, к чему относится).
Видео-пояснения
Для этого урока есть следующие видео:
- IF, Условный оператор, оператор ветвления, разбор
- Когда работает Ветка ложности else в условном операторе IF для неравенств -- Часть 1
- Ветка ELSE и отрицание неравенств, пояснение с числовой прямой, "преобразование" строгих неравенств и нестрогие и обратно
Самостоятельная работа
Вопросы
- Для чего нужен оператор ветвления (условный оператор)?
- Какие ветви условного оператора вы знаете?
- Чем полная форма условного оператора отличается от неполной?
- Когда нужны операторные скобки в ветвях оператора IF, а когда нет?
Задачи
-
Сдавать/выладывать решение не обязательно:
Есть код:var a,b : integer; begin readln(a); if (a > 2) then writeln(a) else writeln(2); readln(); end.
Если он отфроматирован неправильно - исправьте это, и объясните для себя почему нужно исправить именно так.
-
Сдавать/выладывать решение не обязательно:
Есть код: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.
-- исправьте форматирование.
Подсказка: если непонятно как решить или хотите закрепить знания см. этот видео-разбор.
- Сравните два числа, если первое больше второго, то выведите на экран "12". (здесь нужно использовать неполную форму условного оператора)
- Сравните два числа, если первое больше второго, то выведите на экран "12", а если нет, то выведите на экран "888".
- Даны три целых числа: $A$, $B$, $C$. Проверить истинность высказывания: «Число $A$ находится между числами $B$ и $C$» -- выведите "да", если истинно и "нет" если ложно.
ПРИМЕЧАНИЕ: эта следующая задача базируются на том, что мы уже решали (см. задачи в конце урока).
- Даны три целых числа: $A$, $B$, $C$. Проверить истинность высказывания: « Число $A$ и число $B$ больше 17, а $C$ > 7». -- выведите "да", если истинно и "нет" если ложно.
- Пользователь вводит два числа, найдите из них максимальное. (тут всё просто)
Примечание: если не просто или для лучшего понимания решения, см. этот видео-разбор.
- Пользователь вводит три числа, найдите из них максимальное.
Решите тремя способами:
- С использованием логической операции and.
- С вложенными блоками (без and, все опараторы if должны быть в полной форме).
(Если не получается - см. разбор решения) - Без вложенных блоков (без and) -- запомнив максимум из первых двух чисел в специальной переменной.
(Если не получается - см. разбор решения)
Указание: Сначала посрайтесь написать все три решения самостоятельно (по 20 минут размышления на каждую задачу хотя бы), если не получается (или после решения) также можно посмотреть это видео-пояснение.
- Пользователь вводит четыре числа, найдите из них максимальное -- решите через вложенные блоки if в полной форме (без использования логических операций).
Примечание: решение с помощью AND более удобно на практике, но для тренировки понимания тут мы решаем через вложенные блоки.
- Коля набрал $k$ баллов, Миша $n$ баллов, а Петя $d$ баллов в ходе соревнований. Если:
- сумма баллов Коли и Миши больше $20$
- или произведение баллов Пети и Миши меньше $55$
--то тогда вывести в консоль сообщение о том, что ничья, в противном случае вывести сообщение, что победил Коля.
-
Есть программа, где стоит проверка на ввод пользователем числа 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 сравнения, при этом код можно переписать так, что при вводе одного из двух значений, которые приводят к выводу сообщения, сравнение будет выполняться только один раз.
Перепишите программу оптимальным образом.
Подсказка: если самостоятельно разобраться не получается, смотрите этот видео-разбор.
-
Есть программа:
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
, то второе (а первое выводиться не должно).
Но сейчас программа работает не так, исправьте это. -
Есть программа:
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()
.
Если идей нет, смотрите разбор решения. -
Изучите код:
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.
Если подсказки не помогают и/или для лучшего понимания - см. этот видео-разбор.
-
У вас есть три числа (три переменные) найдите их медиану.
Примечание: это условие давалось как простая разминочная задачка для собеседования в Яндекс.
-
Решать по желанию, сдавать на проверку не обязательно:
Запрограммируйте историю:
- 1) Вы дома, пойдем в лес или в центр города?
- 2) Если пойдем в лес то будем жечь костер или кататься на лыжах?
- 3) Если будем кататься на лыжах, то по кругу или с гор (придумайте последния выбора)
- 4) Если будем жечь костер - то будем ли что-то готовить или просто (придумайте последствия выбора)
- 5) Если выбрали поход в центр - пойдем ли в кино или погуляем по центру
- 6) Если пойдем в кино будет смотреть исторический фильм или комедию (придумайте последствия выбора)
Форматирование кода условного оператора (необязательный блок)
Самостоятельное программирование
В качестве примера см. пример №8 выше, и/или видео-разбор.
Источники (что ещё почитать)
- Урок 8. Блок-схема оператора if: http://learnpascal.ru/operator-if/blok-s...
- Log in to post comments
- 46860 reads
Evgeny1618
Sat, 05/14/2022 - 22:23
Permalink
Урок 9 задача 12
Есть программа:
Тут решение с помощью полной формы условного оператора невозможно посколько 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