Рейтинг:  5 / 5

Звезда активнаЗвезда активнаЗвезда активнаЗвезда активнаЗвезда активна
 

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

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

«если ..., то ххх»

где «...» - предикат

ххх - действие, совершаемое при истиности предиката

Единственное отличие - это то, что этот оператор пишется на английском языке, т.е. «if ... then xxx;». Для примера рассмотрим выражение «Если сегодня понедельник, то нужно сходить в магазин». В этом примере в роли предиката (Алгебра высказываний) выступает словосочетание «сегодня понедельник», которое зависит от дня недели сегодняшнего для, а действием, которое будет выполнено при истиности данного предиката это «нужно сходить в магазин». В данном примере, вполне естественно, что если сегодня не понедельник, а какой-либо другой день недели, то мы в магазин не пойдем и что мы будем делать в другие дни недели в выражении не сказано. Именно поэтому данный вид условного оператора называют неполным или сокращенным.

Но, как Вы поняли, есть и полная форма условного уператора, которая вводится в язык программирования как

«если ... , то ххх, иначе ууу».

где «...» - предикат

ххх - действие, совершаемое при истиности предиката

ууу - действие, совершаемое при ложности предиката

На языке программирования PascalABC.NET этот оператор записывается как «if ... then xxx else yyy;». Обозначения точно такие же, как я привел выше. Опять рассмотрим пример с магазином, но уже с полной формой условного оператора: «Если сегодня понедельник, то нужно сходить в магазин, иначе отдыхаем». В данном примере уже сказано, что нужно делать в другие дни. Так в понедельник идем в магазин, а во все остальные дни «отдыхаем».

В не зависимости от формы (сокращенной или полной) всегда по ведкам «то» или «иначе» компьютер будет ждать от Вас только одной комманды. Если Вы решите использовать полную форму и при этом по одной из веток (думаю, понятно, о чем идет речь (то, что делаем по «то» или то, что делаем по «иначе»)) или по обеим напишите несколько действий, то компьютер выдаст Вам ошибку, так как компьютер ждал только одну комманду. Таким образом, компьютер не выполнит следующий код:

begin

              var x:integer:=readinteger();

              if (x<0) then

                            writeln('отрицательное число')

              x:=0;

              else

                            writeln('положительное число');

              x:=0;

end.

Я специально сделал форматирование, которое позволит получше понять, почему компилятор выдаст ошибку. Давайте разберем этот код. Мы обьявили переменную целочисленную «x» и считываем ее значение с клавиатуры с помощью комманды «readinteger». Далее следует условный оператор с предикатом «х<0», который проверяет число на отрицательность. Далее следует комманда «writeln(‹отрицательное число’);», которая выводит «отрицательное число», если выполнился предикат, то есть, если значение переменной «х» отрицательно. После этого идет обнуление значения переменной «х» (это обнуление должно было попасть в ветку «то», но оно находится за веткой и будет выполнено обязательно в не зависимости от ложности или истиности предиката). А на следующей строке идет «else». Увидев это компьютер просто-напросто не поймет к какому условному оператору относится эта ветка (Program1.pas(11) : Встречено 'else', а ожидался оператор), поскольку перед этой строкой шел оператор «x:=0;», который не является условным. Из-за этого компьютер выдаст ошибку на этапе компиляции. В ветке «else» аналагичная ошибка: компьютер ожидал одну комманду по этой ветке, а встречено две.

Некоторые могут сказать, что это неудобно, чедь часто нужно выполнить несколько комманд. И вообще так оно и есть. То, что по веткам «то» и «иначе» нужно писать только одну комманду это жудко неудобно, но, видно, самые первые разработчики Паскаля (который был разработан еще в восьмидесятых годах) посчитали, что нужно сделать, что по веткам должно идти не более одной комманды. Да и их понять можно. В те годы программирование только зараждалось, да и компьютер (который обладал не лучшей вычислительной способностью (Мой преподаватель рассказывал, что компьютер, в то время, обрабатывал совершенно простую программу в течение дня. То есть запускали в компьютере программу в один день, о получали результаты на следующий день. Да и надо учесть, что в тот момент не было таких умных компиляторов, которые встроены почти в каждый язык программирования, и поэтому нужно было перед запуском программы сотни раз ее перепроверить, а затем уже запускать, а, если в коде программы ошибка (не важно какая (синтаксическая или пунктуационная)), то об этом можно было узнать не раньше, чем программа дойдет до строки, в которой содержится ошибка)) мог себе позволить далеко не каждый (в лучшем случае могли себе позволить университеты и институты, а о пользовательских компьютерах вообще речи не было), поэтому никто не знал, что будет в будующем, каким образом что и как делать, поэтому сделали так как на тот момент требовало программирование. А оно требовало только одну комманду по веткам, а большее количество требовалось очень редко.

В общем, для того, чтобы сделать более одного действия по веткам вам потребуется печатать уже Вам знакомые «begin» и «end;». (причем замечу, что «end;» пишется с точкой с запятой (что указывает на конец вложенного набора операторов), а не с точкой (что указывает на конец программы)). Этим набором нам придется еще очень часто пользоваться, поскольку именно благодаря этому набору мы можем выполнить более одного действия.

Таким образом пример правильной программы из предыдущего примера будет следующим:

begin

              var x:integer:=readinteger();

              if (x<0then

              begin

                            writeln('отрицательное число');

                            x:=0;

              end

              else

              begin

                            writeln('положительное число');

                            x:=0;

              end;

end.

Теперь давайте разберемся с этим кодом. Мы также обьявляем переменную целого типа «х» и считываем ее значение с клавиатуры с помощью комманды «readinteger()» (обращу внимание, что скобки в данном случае писать не обязательно, но лучше писать, поскольку именно пустые скобки требует большинство языков программирования, а привыкать к «плохому» лучше не надо. Можно и привыкнуть, но только, если Вы будете работать только с данным языком программирования, чего я Вам не советую (Разработчики этого Паскаля зачастую опубликовывают очень некачественные версии)). Затем идет условный оператор с предикатом «x<0», проверяющем значение переменной «х» на отрицательность. Далее следует «begin», указывающий на то, что далее будет идти несколько комманд. После этого идет комманда ввывода на экран строки «отрицательное число» и обнуление значения переменной «х» (и это все будет выполненно по ветке «то»). Хочу обратить внимание: Если Вы пишите успловный оператор в полной форме, то после комманды (именно «комманды», поскольку, как я говорил, в Паскале есть только подпрограммы, то компилятор сам преобразует все, что идет между «begin» и «end;» в отдельную подпрограмму и запишет вместо этого вызов подпрограммы) ставить точку с запятой не нужно (поскольку, если Вы поставите точку с запятой, то компьютер посчитает, что вы пишите в сокращенной форме, а встретив «else» выдасть ошибку).

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

begin

     var x:integer:=readinteger();

     if (x<0then

          writeln('отрицательное число');

     if (x>=0then

          writeln('положительное число');

end.

Так в начале значение переменной «х» проверяется на отрицательность, а затем проверятеся на положительность. Таким образом мы бреобразовали условный оператор в полной форме в два оператора сокращенной формы. Опять обращу внимание, что после комманды должна стоять точка с запятой (она не должна ставиться в полной форме, так как ее отсутствие указывает компилятору (!) (именно отсутствие точки с запятой указывает на полную форму, а не слово «else». Это позволяет разобраться во вложенном условном операторе) на полную форму).

А вот, если нужно проверить несколько условий, то что делать? Естественно, можно пойти в лоб и писать условный оператор в качесве вложенной ветви условного оператора. Вот пример, проверяющий число на положительность и нечетность.

begin

     var x:integer:=readinteger();

     if (odd(x)) then

          if (x>0then

               writeln('нечетное положительное')

          else

               writeln('нечетное отрицательное')

     else

          if (x>0then

               writeln('четное положительное')

          else

               writeln('четное отрицательное');

end.

Я думаю, Вы заметили, что, если не было бы форматирования, то код был бы совершенно не понятным. Именно поэтому я рекомендую использовать форматирование кода. А там сами решайте.

В этом примере мы видим два вложенных условных оператора и только один знак «;». Он стоит в конце, указывая нам на конец условного оператора «if (odd(x)) then». У Вас, наверное возник вопрос: А как узнать, где концы вложенных условных операторов? Увы это можно сделать только по форматированию. Поскольку мы используем условный оператор в полной форме то по ветке «то» после оператора не должно быть точки с запятой. А в нашем примере в качестве этого оператора является вложенный условный оператор в полной форме. Следовательно в этом случае ни по одной из веток не должна стоять точка с запятой.

А Если бы мы везде ставили точку с запятой, то вообще бы не поняли, где что. Предположим, что в данном примере по ветке «то» находится условный оператор в сокращенной форме, а после него стоит «else». И, естественно, возникнет вопрос: к какому условному оператору относится данная ветка: к вложенному условному оператору или к главному условному оператору, если после по каждой ветке должна стоять точка с запятой?

Мы посмотрели реализацию нескольких условий через вложенный условный оператор. Но можно реализовать через сложный предикат с помощью логических действий «and» («и»), «or»(«или»), «not»(«не» (это отрицание относитсе только к одному предикату. Я просто забыл о нем упомянуть ранее)) «xor» (Алгебра высказываний). Таким образом этот же код будет иметь следующий вид:

begin

     var x:integer:=readinteger();

     if ((x>0and (odd(x))) then

          writeln('нечетное положительное');

     if ((x>0and (not (odd(x)))) then

          writeln('четное положительное');

     if ((x<0and (odd(x))) then

          writeln('нечетное отрицательное');

     if ((x<0and (not (odd(x)))) then

          writeln('четное отрицательное');

end.

Этот код абсолютно эквивалентен предыдущему, только написан с помощью сложных условий и сокращенных форм.

Оператор выбора вариантов

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

Для рассмотрения этого оператора воспользуемся более простым примером с оценками. Пусть вводится оценка (буззнаковое число от 2 до 5 (поскольку нам нужен небольшой диапазон, то воспользуемся типом byte)) и выводится на экран значения «удовлетворительно», «хорошо», «отлично» в зависимости от оценки, а по остальным случаям выводить: «некорректная оценка».

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

begin

     var o:byte;

     read(o);

     if (o=5then

          writeln('отлично')

     else

          if (o=4then

               writeln('хорошо')

          else

               if (o=3then

                    writeln('удовлетворительно')

               else

                     

                    if (o=2then

                         writeln('не удовлетворительно')

                    else               

                         writeln('некорректная оценка');

end.

В этом коде много вложенных условных операторов, что усложняет модификацию кода (если нам скажут добавить еще оценки 1,0,6,7,8,9, то код очень сильно возрастет в ширину, да и печатать его будет не очень приятно, так как даждая оценка увеличивает длину кода на 3 строчки.). Но тем не менее это вполне рабочий код. Но с помощью оператора выбора вариантов можно этот код очень сильно улучшить.

Оператор выбора вариантов это оператор вида:

 

case Params of

     parametr:action;

end;

 

где Params - это перменная от которой зависит вибор действия

parametr - это значение, которое может принимать переменная Params

action - это действие (!)(одно действие. Если Вам нужно выполнить более одного действия, то воспользуйтесь Составным оператором begin - end;), которое будет выполнено, если переменная Params принимает значение parametr.

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

begin

     var o:byte;

     read(o);

     case of

          2:writeln('не удовлетворительно');

          3:writeln('удовлетворительно');

          4:writeln('хорошо');

          5:writeln('отлично');

          else writeln('некорректная оценка');

     end;

end.

Сразу заметно, что этот код намного компактнее предыдущего, да и он более модифицируем, чем его предшественник.

Теперь разберемся в нем. «Case» в переводе с английского означает «случай». Так «case» указывает на имя оператора. Затем после имени должна идти переменная (!)(только одна) от которой зависит выбор действия. После этого идет «of», после которого идут строки следующего вида: Вначале идет значение (!)(не предикат, а конкретное значение, которое может принимать данная переменная) или несколько значений (тогда они должны перечислиться через запятую («3,4,5:writeln('хорошая оценка');») или диапазон значений («3..5:writeln('хорошая оценка');»), а после этого должно идти двоеточие, отделяющее значение от действия, а затем действие, которое будет выполнено, если значение переменной равно одному из значений, идущих перед действием. В самом конце, после всех веток, можно добавить ветку «иначе» (ее писать необязательно), действие по которой будет выполняться только тогда, когда значение переменной не равно ни одному из вышеперечисленных значений.