355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Олег Деревенец » Песни о Паскале (СИ) » Текст книги (страница 4)
Песни о Паскале (СИ)
  • Текст добавлен: 6 ноября 2017, 03:30

Текст книги "Песни о Паскале (СИ)"


Автор книги: Олег Деревенец


Жанр:

   

Драматургия


сообщить о нарушении

Текущая страница: 4 (всего у книги 29 страниц)

      else Writeln(’Стойте!’);

Writeln(’Нажмите Enter’); Readln;

end.

Почему после оператора Writeln(’Проходите!’) не видно разделителя – точки с запятой? Потому, что внутри условного оператора разделители не ставят! Другое дело – оператор Writeln(’Стойте!’). Здесь заканчивается условный оператор IF, и точка с запятой уместна – она разделяет операторы. Попробуйте нарушить эту запись и узнать мнение компилятора.

Неполный условный оператор

Что за окном? нет ли дождя? ЕСЛИ дождь идет, ТО прихватите зонтик. В этом кратком рассуждении нет отрицательной ветви, поскольку в ней никаких действий не предусмотрено. В таких случаях отрицательную ветвь отбрасывают и получают неполный условный оператор.

IF <условие> THEN <Оператор>

Блок-схема такого оператора показана на рис. 24.


Рис.24 – Блок-схема неполного условного оператора

Пост номер два

Применим неполный условный оператор ко второй версии электронного часового – программе «P_10_2».

var S, R : string;

begin

Writeln(’Пароль?’); Readln(S);

R:= ’Стойте!’;

if S = ’pascal’

      then R:= ’Проходите!’;

Writeln(R);

Writeln(’Нажмите Enter’); Readln;

end.

Здесь для хранения решения введена переменная R, в которую изначально помещается суровое «Стойте!». После успешной проверки пароля значение переменной меняется на благосклонное «Проходите!», а затем решение выводится на экран.

Откомпилируйте и проверьте оба варианта часового. «Поиграйте» с ошибками компиляции. Если компиляция прошла гладко, внесите ошибки сознательно и исследуйте реакцию компилятора.

Теперь вы познакомились с двумя вариантами условного оператора. Ни один серьезный алгоритм не обходится без них. Скоро вам доведется изобретать весьма хитрые алгоритмы и рисовать блок-схемы для них. Значит, надо привыкать к блок-схемам; на рис. 25 представлены схемы наших программ.


Рис.25 – Блок-схемы программ с полным и неполным условными операторами

Итоги

• Условный оператор изменяет порядок действий в зависимости от некоторого условия; оператор может быть полным или неполным.

• Полный условный оператор состоит из условия IF и двух ветвей: положительной – THEN, и отрицательной – ELSE. В каждую из ветвей можно поместить по одному вложенному оператору.

• Неполный условный оператор состоит из условия IF и положительной ветви THEN.

А слабо?

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

Б) Напишите программу, которая спрашивает, идет ли дождь, и на ответ «да» выводит сообщение «А зонта-то у тебя нет!». Воспользуйтесь неполным условным оператором.

Глава 11

Операторный блок

Электронный часовой из 10-й главы пропускает только знающих пароль. Расширим круг его обязанностей. Пусть часовой, приняв верный пароль, отдаст ещё несколько команд, как то: «Распахнуть ворота! Оркестр, музыку!». А для нарушителей команды будут такими: «Тревога! Задержать его!». Разумеется, что команды будут выводиться на экран, причем каждая – в отдельной строке. Усеченная блок-схема программы показана на рис. 26.


Рис.26 – Блок схема часового, подающего дополнительные команды

Операторные скобки

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

if S = ’pascal’

      then Writeln(’Распахнуть ворота!’);

      Writeln(’Оркестр, музыку!’);

      Writeln(’Проходите!’);

      else Writeln(’Тревога!’);

      Writeln(’Задержать его!’);

Добавьте в программу часового все это и откомпилируйте. Что, не вышло? Тут обнажилась проблема с подряд идущими операторами печати. По правилам языка, они разделяются точками с запятой, не так ли? Но разделители «порежут» на части и условный оператор IF-THEN-ELSE, а это недопустимо! Наткнувшись на показанную выше конструкцию, компилятор заявит вам прямо в глаза о синтаксической ошибке. Ведь в каждой ветви условного оператора допускается лишь по одному вложенному оператору, где выход?

«Вероятно, в Паскале что-то предусмотрено на сей счет» – заподозрите вы. Конечно! Здесь выручит операторный блок, который превращает группу операторов в один, скрывая внутри себя разделители – точки с запятой. Блок организуют знакомой вам парой ключевых слов BEGIN и END. В нашей программе эти слова надо втиснуть в ветви условного оператора так:

if S = ’pascal’

      then begin

      Writeln(’Распахнуть ворота!’);

      Writeln(’Оркестр, музыку!’);

      Writeln(’Проходите!’)

      end

      else begin

      Writeln(’Тревога!’);

      Writeln(’Задержать его!’)

      end;

Как видите, внутри блока BEGIN-END разделители ставят как обычно – для разграничения операторов.

А сколько операторов вместится в блок BEGIN-END? Да сколько угодно! Блок может быть и пустым, – иногда это оправдано. Предположим, вы ещё точно не решили, что будет внутри ветви: один оператор или больше. Тогда вставьте здесь пустой блок BEGIN-END, а затем думайте дальше. Вставка лишних блоков не влияет на программу, но может уберечь от синтаксических и логических ошибок.

И последний вопрос: почему после END нет точки? Ведь мы ставим её в конце программы! Да, но окончание программы – это единственный случай, когда после END ставится точка.

Красиво жить не запретишь

Вероятно, вы заметили, что ветви THEN и ELSE условного оператора расположены с отступом вправо. Что это, требование языка? Ничуть. Вы вправе написать программу даже в одну строку, и компилятор «проглотит» её. Но каково будет разбираться в такой программе вам или вашему приятелю?

Отступы в программе сделаны для удобства чтения. Строгих правил по этой части нет; оформление – дело вкуса. Но сложились традиции, следование которым облегчит жизнь и вам, и тем, кто будет читать ваши программы. Главная идея оформления программ состоит в выделении логических уровней. Что это такое? В данном примере это ветви THEN и ELSE, – они должны быть хорошо видны в тексте. Полезно, также, выделять блоки операторов. Для этого можно поместить слова BEGIN и END друг под другом, а содержимое блока сдвинуть относительно них вправо.

Разбирая примеры, вы со временем научитесь разумно оформлять свои программы, – лучше раз увидеть, чем стократ услышать. Вот, в частности, другой вариант оформления программы «P_11_1», где обе ветви условного оператора прекрасно видны, хотя скобки begin-end и не расположены друг под другом.

var S : string;

begin

      Writeln(’Пароль?’); Readln(S);

      if S = ’pascal’ then begin

      Writeln(’Распахнуть ворота!’);

      Writeln(’Оркестр, музыку!’);

      Writeln(’Проходите!’)

      end else begin

      Writeln(’Тревога!’);

      Writeln(’Задержать его!’)

      end;

      Writeln(’Нажмите Enter’); Readln;

end.


Комментарии

Раз уж мы коснулись оформления, рассмотрим ещё одно средство Паскаля – комментарии, которые служат для пояснения программ. Комментарий – это произвольный текст, заключенный в фигурные скобки {…}, или в круглые скобки со звездочкой (*…*). Вот примеры комментариев.

{ Комментарий в одной строке }

{ Многострочный

комментарий

}

(* Комментарий в скобках со звездочками *)

А как воспринимает их компилятор? Да никак. Найдя начало комментария, компилятор ищет его окончание, а все, что оказалось внутри ограничителей, «пропускает мимо ушей». Поэтому комментарии не оказывают влияния на программу. Есть только одно исключение, о котором я скажу в своё время, повествуя о директивах компилятора. Последующие программы я буду сопровождать комментариями.

Программисты нередко используют комментарии как «шапку-невидимку». О чем я? Иногда – при поиске ошибок – требуется временно исключить часть операторов из программы. Вместо того чтобы удалять, а затем печатать их заново, лучше закомментировать эту часть текста. То есть, заключить ненужные операторы в фигурные скобки, превратив в комментарий. Такой кусок программы легко восстановить, удалив фигурные скобки.

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

      A:= B;       // Копирование переменой – это однострочный комментарий


Итоги

• Операторные скобки BEGIN-END объединяют несколько операторов в один операторный блок. Операторный блок воспринимается как один оператор.

• Форматирование программы – это оформление её с помощью логических отступов. Форматирование не влияет на программу, но облегчает её чтение.

• Комментарии предназначены для включения в программу пояснений. Комментарии пропускаются компилятором и не влияют на программу.

• Комментарии удобны для временного исключения частей программы.

А слабо?

А) Сколько операторов можно поместить в операторном блоке?

Б) Найдите ошибку в этом кусочке программы, проверьте свое решение на компьютере.

      Writeln(’Что дождь? Все ещё идет?’); Readln(S);

      if S = ’ага’ then

      begin

      Writeln(’А зонтик ты так и не купил!’);

      Writeln(’Сколько раз напоминать?’);

      end;

      else begin

      Writeln(’На этот раз тебе повезло!’);

      end;

Глава 12

Цикл с проверкой в конце


Подтянем дисциплину

Продолжим воспитывать нашего часового, он ещё нуждается в этом. Проверяя каждого встречного-поперечного, мы принуждены вновь и вновь запускать свою программу. А все потому, что часовой покидает свой пост без команды, самовольно. Пусть программа проверяет посетителей одного за другим до тех пор, пока мы не скомандуем «отставить!».

Для этого заставим программу «бегать по кругу» так, чтобы она возвращалась к операторам, исполнявшимся ранее. Повторение одних и тех же действий называют циклом. Иногда цикл называют переходом назад. Блок-схема предстоящей программы показана на рис. 27.


Рис.27 – Блок-схема циклического часового

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

Для освобождения часового можно ввести специальную фразу. Например, вместо пароля напечатать фразу «отставить!» или «марш на кухню!». Ещё проще сделать это пустой строкой, которая попадет в переменную S, если в ответ на запрос пароля пользователь, ничего не печатая, нажмет клавишу Enter. Тогда условие завершения программы будет таким.

      if S = ’’ then …

Здесь справа от знака равенства стоят два апострофа, – это пустая строка (между апострофами нет пробела!).

Мы ответили на первый вопрос, но как перейти к началу программы? Не надейтесь на условный оператор, он тут не поможет! Обе его ветви следуют после проверки условия IF, поэтому условный оператор передает управление только вперед.

Нанимаем репетитора

Итак, условный оператор тут не помощник, но Паскаль не оставит вас в беде. Для организации циклов в нём предусмотрены три оператора, с одним из которых мы ознакомимся немедля. Программистам он известен как цикл с проверкой в конце, и записывается двумя ключевыми словами: REPEAT – «повторять» и UNTIL – «вплоть до».

Отчасти «репетитор» похож на операторный блок BEGIN-END, рассмотренный нами в предыдущей главе. Вам надо повторять выполнение ряда операторов? Тогда поставьте слово REPEAT перед первым из них, а проверку условия UNTIL – за последним, и получите следующую конструкцию.

REPEAT

<Оператор 1>;

<Оператор 2>;

...

<Оператор N>

UNTIL условие

По-русски действие оператора можно изъяснить так: ПОВТОРЯТЬ следующие далее операторы, ПОКА условие НЕ соблюдается. На рис. 28 показана блок-схема такой циклической конструкции; здесь операторы 1 и 2 будут исполняться до тех пор, пока НЕ соблюдается условие в конце цикла. При соблюдении условия цикл прекратится, и выполнится оператор 3.

Примечание. Сходство оператора цикла с блоком BEGIN-END состоит в том, что REPEAT-UNTIL тоже скрывает внутри себя разделители операторов – точки с запятой. Стало быть, он тоже формирует единый блок.


Рис.28 – Блок-схема оператора цикла с проверкой в конце

Воспользуемся циклом для очередной версии «киберчасового». За основу возьмем простейшую из предыдущих версий – программу «P_10_1». Поместив внутрь цикла REPEAT-UNTIL все исполняемые там операторы, получим желаемое – программу «P_12_1».

{ P_12_1 – программа-часовой с циклом }

var S : string;

begin

      repeat

      Writeln(’Пароль?’); Readln(S);

      if S = ’pascal’

      then Writeln(’Проходите!’)

      else Writeln(’Стойте!’);

      until S=’’; { окончание цикла, если строка S пуста }

end.

Проверьте наше новое творение. Обратите внимание на комментарии внутри фигурных скобок, – я буду снабжать ими все последующие программы.

Вежливый часовой

Программа работает? Прекрасно! Но одна шероховатость меня удручает. Покидая пост, часовой почему-то поднимает лишний шум: «Стойте!» – кричит он. Кому он это кричит? своему командиру? Безобразие! Пусть при оставлении поста часовой не проверяет пароль. С этой целью добавим ещё один условный оператор, как показано на рис. 29.


Рис.29 – Блок-схема часового с корректным завершением

На этой блок-схеме оператор проверки пароля обведен пунктиром; получив команду о завершении работы, программа должна обойти его. Этому служит ещё один условный оператор, проверяющий, не пуста ли строка S.

      if S <> ’’ then …

Пара знаков «меньше»–«больше» в Паскале означает неравенство. Здесь положительная ветвь THEN будет выполнена, если строка S не будет пустой. Стало быть, это условие по смыслу противоположно условию IF S=’’.

А напоследок программа должна вежливо попрощаться, для чего добавим ещё пару операторов печати. Итак, создайте файл «P_12_2», скопируйте в него предыдущую версию программы и попытайтесь сами внести необходимые изменения, – нет ничего полезней самостоятельной работы! Справившись с задачей, взгляните на мой вариант, он показан ниже. А если не совладаете, тоже посмотрите.

{ P_12_2 – вежливый часовой }

var S : string;

begin

      repeat

      Writeln(’Пароль?’); Readln(S);

      { если строка не пуста, проверяем пароль }

      if S<>’’ then

      if S = ’pascal’

      then Writeln(’Проходите!’)

      else Writeln(’Стойте!’);

      until S=’’;

      Writeln(’До встречи! Нажмите Enter’); Readln;

end.

Я расположил операторы с надлежащими отступами, выделяющими структуру программы. Проверьте, работает ли она?

Досрочный выход из цикла

С какой бы стороны придраться к нашему часовому? Ведь программа делает все, что положено. Но рассмотрим ещё один её вариант. Дело в том, что условные операторы внутри цикла порой загромождают и запутывают его. Это не относится к нашей теперешней программе, но мы ведь только в начале пути… Ждать ли, пока гром грянет? Или подготовиться к нему заранее? Познакомьтесь с процедурой по имени BREAK – «прервать» (боксерам знакомо это слово).

Условие завершения цикла, как вам известно, проверяется в точке UNTIL. Но порой это условие удобней проверить где-то в середине цикла, и тогда цикл лучше прервать досрочно, вызвав процедуру BREAK следующим образом:

      if условие_выхода_из_цикла then Break;

Внимание: вызов процедуры BREAK допустим только внутри циклов!

Посмотрите, как изменится блок-схема с оператором BREAK (рис. 30), здесь оператор принятия решения я заменил пунктирным прямоугольником.


Рис.30 – Блок-схема циклической программы с оператором Break

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

      if S=’’ then break;

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

{ P_12_3 – часовой с досрочным выходом из цикла }

var S : string;

begin

      repeat

      Writeln(’Пароль?’); Readln(S);

      { если строка пуста, то выход из цикла }

      if S=’’ then break;

      if S = ’pascal’

      then Writeln(’Проходите!’)

      else Writeln(’Стойте!’)

      until S=’’;

      Writeln(’До встречи! Нажмите Enter’); Readln;

end.

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

Итоги

• Оператор цикла REPEAT-UNTIL организует многократное повторение операторов, вставленных между этими ключевыми словами.

• Условие выхода из цикла следует за ключевым словом UNTIL, цикл повторяется до тех пор, пока условие НЕ соблюдается.

• Оператор BREAK выполняет досрочный выход из цикла с обходом условия в UNTIL.

А слабо?

А) Сколько операторов можно вставить между REPEAT и UNTIL?

Б) Будет ли проверяться условие в UNTIL при досрочном выходе из цикла?

В) Возьмите за основу программу «P_11_1» и переделайте ее в циклический вариант. Или слабо?

Г) Напишите программу для угадывания слова. Она должна запрашивать от пользователя строки, пока тот не введет слово, предусмотренное в программе.

Глава 13

Правда и кривда

Что приятней, получать подарки или дарить их? Сейчас узнаем: вот вам автомобиль – дарю! Будете в школу на нём гонять. Впрочем, мой подарок не бескорыстен, и взамен я жду вашей помощи.

«Автомобиль – не роскошь, а средство передвижения» – утверждал персонаж книги Ильфа и Петрова. Что бы сказал он сегодня, томясь в унылых пробках? Теперь и вы за рулем, значит, дорожные пробки – наша общая напасть. Так будем бороть её вместе! Ведь все для этого есть, – в каком веке то живем! Что ни автомобиль – то бортовой компьютер, а космос ломится от спутников! Создадим программу для бортового компьютера автомобиля. Компьютер будет принимать сигналы от спутников системы ГЛОНА́СС (это ГЛОба́льная НАвигацио́нная Спу́тниковая Систе́ма) и сообщать о дорожных пробках. К деталям этого проекта обратимся позже, а начнем, как водится, издалека – из космоса.

Есть ли жизнь на Марсе?

Об этом все ещё спорят ученые, не находя ответа. «Спросите что попроще, – скажете, – например, мой возраст». Но если бы здесь отвечал компьютер, то вопрос о Марсе он счел бы простым, а вопрос о возрасте – сложным. Почему?

А потому, что о марсианской жизни можно ответить односложно: «да» или «нет». А сообщая возраст, надо указать какое-то число или дату рождения. Ещё сложнее растолковать компьютеру, как выглядит, к примеру, цветок или бабочка, тут не отделаться одним числом, а тем паче ответом «да» или «нет». Такие вопросы требуют сложного ответа, несущего много информации. Стоп! Я упомянул информацию? Вот о ней – об информации – потолкуем подробней.

Информация и её мерило

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

Получить ответ – это значит получить информацию. А сколько мы при этом её получаем, чем измерить это количество? Математики догадались, что меньше всего информации заключено в односложном ответе: «да» или «нет». Это количество взято за мерило и названо битом (по-английски «BIT»). Крупные единицы информации содержат много битов: байт – восемь битов, 1 Кбайт (читается «кибибайт») – 1024 байта и так далее, – об этом можно прочитать в школьных учебниках. Стало быть, ответ на вопрос «быть или не быть?» содержит всего один бит информации, – компьютер считает такие вопросы простыми. Ответы на сложные вопросы (например, как выглядит то, или это) могут содержать миллионы байтов. В этом легко убедиться по размеру файла с какой-нибудь фотографией или фильмом.

Но вернемся к биту. Природная склонность компьютера к «простым» вопросам и односложным ответам объясняется устройством его электронной памяти, состоящей из битовых ячеек – триггеров. Не вдаваясь в технические детали, скажу лишь, что такая ячейка может находиться в одном из двух устойчивых состояний, которые часто обозначают цифрами «0» и «1». С тем же успехом их можно обозначить иначе, например: «да» и «нет». Или так: «истина» и «ложь», «правда» и «кривда», «крестик» и «нолик». Короче говоря, название – дело вкуса, важно лишь то, что триггер хранит один бит информации. Эта особенность компьютеров отразилась во многих языках программирования, в том числе в Паскале.

Булевы переменные

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

      var A, B, C : Boolean;

Здесь объявлены три переменных булевого типа.

Булевы переменные, подобно триггеру, могут содержать лишь одно из двух значений: TRUE – «истина» или FALSE – «ложь». Это зарезервированные слова Паскаля, и попытка присвоить логическим переменным другие значения будет пресечена компилятором. Вот примеры правильного обращения с булевыми переменными:

      A:= true;

      B:= false;

      C:= B;

А вот грубые ошибки:

      A:= ’true’;

      B:= ’false’;

      C:= ’B’;

Повторяю: TRUE и FALSE – это зарезервированные слова, а не строковые константы, они пишутся без апострофов.

Ввод и вывод булевых данных

Ввод и вывод – это первое и последнее звено в цепочке обработки данных. Прежде, чем обрабатывать данные, надо освоить их ввод и вывод. Рассмотрим, как это делается с булевыми данными.

С выводом проблем нет, поскольку процедура Writeln напечатает их словами «TRUE» и «FALSE». Вот небольшая программа, испытайте её.

var B : Boolean;

begin

      B:= false;       Writeln(B);

      B:= true;       Writeln(B);

end.

Вводить булевы данные чуть сложнее, поскольку процедура Readln, к сожалению, не умеет этого делать. Как быть? «Нормальные герои всегда идут в обход», – поется в песне. Осуществим хитрый манёвр: для ввода булевых значений воспользуемся переменной другого типа, например, строковой, а затем преобразуем введенную строку в булев тип.

Условимся, что значению TRUE будет соответствовать ввод в строковую переменную символа «1», а FALSE – любой другой строки. Тогда булево значение в переменную B можно ввести следующим манером.

var S : String;

      B : Boolean;

begin

      Writeln(’Введите “1” для TRUE и прочее – для FALSE’);

      Readln(S);

      if S=’1’ then B:= true else B:= false;

      Writeln(B); Readln

end.

Просто? Но можно сделать ещё проще, прибегнув к логическому выражению.

Логические выражения

Данные логического типа можно получать в результате не совсем обычных вычислений. В этих вычислениях порой не увидишь ни чисел, ни арифметических действий, – речь идет о логических выражениях. Например, сравнивая две строки, вы задаетесь вопросом, равны ли они? Ответом может быть либо «да», либо «нет», или, выражаясь на языке Паскаль, TRUE или FALSE. Следовательно, сравнение строк, которое мы применяли в условных и циклических операторах, – это логическое выражение. А раз так, то результат сравнения можно присвоить булевой переменной. В приведенном выше примере вместо условного оператора можно записать выражение:

      B := S=’1’;       { равносильно if S=’1’ then B:= true else B:= false }

Здесь справа от знака присваивания стоит логическое выражение S=’1’, и в переменную B попадет TRUE, если S будет содержать строку «1» и FALSE – в любом другом случае.

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

if B

      then... { выполняется, если B=true }

      else... { выполняется, если B=false }

repeat

      { цикл выполняется, пока B=false }

until B

Замечу здесь, что «if B then…» равносильно «if B=TRUE then…».

К чему ещё годны булевы данные? С ними производят логические операции, но к операциям обратимся чуть позже, – пора вернуться к нашей автомобильной задаче.

С высоты птичьего полета

Напомню, что мы работаем над программой для навигатора автомобиля, принимающего сигналы от спутников системы ГЛОНАСС. Из космоса прекрасно видны все улицы и пробки города. Пусть все возможные маршруты от дома до школы известны заранее, а спутник сообщает лишь о том, открыта ли для движения та или иная улица. Если улица открыта, спутник сообщает об этом значением TRUE, а иначе – значением FALSE. Увы, к настоящему спутнику мы пока не подключены, и вводить данные о пробках придется вручную. Результатом работы нашей программы будет сообщение о том, можно ли проехать в школу (TRUE), или нет (FALSE).

Вот первый маршрут. Предположим, путь от дома до школы пролегает по двум улицам так, как показано на рис. 31.


Рис.31 – – Схема первого маршрута

Очевидно, что отразить состояние двух улиц можно двумя булевыми переменными, назовем их A и B. Объявим переменные и введем данные в них.

var A, B : Boolean; S: string;

begin

      Write(’Улица A открыта? ’); Readln(S); A:= S=’1’;

      Write(’Улица B открыта? ’); Readln(S); B:= S=’1’;

Здесь, как мы условились раньше, значение TRUE вводится цифрой «1».

Обратите внимание на новую для вас процедуру Write, – это «младшая сестра» процедуры Writeln. В отличие от «старшей сестры», после вывода сообщения она не переводит курсор на следующую строчку, – это удобно при запросе данных.

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

      S:=’Топай пешком’;

      if A then

      if B then S:=’Поезжай на машине!’;

Исходное значение – «Топай пешком» – заносим в переменную S заранее. Оно изменится тогда, когда обе булевы переменные станут равны TRUE. Согласитесь, это решение из двух условных операторов оказалось несложным. Но до поры до времени. Что, если маршрутов станет много, и каждый будет пролегать через несколько улиц? Программа превратится в нагромождение условных операторов, больше похожее на хаос землетрясения! Страшно? Тогда рассмотрим другой подход. Суть его в том, чтобы выразить решение на обычном человеческом языке, а затем превратить это высказывание в логическое выражение.

Решение нашей задачи можно высказать так: «проехать можно, если открыта улица A И открыта улица B». Обратите внимание на выделенный курсивом союз «И». Чтобы превратить это рассуждение в логическое выражение и записать на Паскале, надо лишь перевести союз «И» на английский язык – это будет «AND», а названия улиц заменить логическими переменными A и B. И вот результат такого перевода.

      if A and B

      then S:=’Поезжай на машине!’

      else S:=’Топай пешком!’;

Вместо двух условных операторов остался один. Готовая программа будет такой.

{ P_13_1 – первый маршрут проезда }

var A, B : Boolean; S: string;

begin

      { ввод данных со «спутника» }

      Write(’Улица A:’); Readln(S); A:= S=’1’;

      Write(’Улица B:’); Readln(S); B:= S=’1’;

      { решение }

      if A and B

      then S:=’Поезжай на машине!’

      else S:=’Топай пешком!’;

      Writeln(S); Readln

end.

Испытайте программу при разных сочетаниях входных данных и проверьте, не врёт ли она?

Теперь рассмотрим другой маршрут, здесь попасть в школу можно по любой из двух улиц (рис. 32).


Рис.32 – Схема проезда, второй вариант

Обычным языком молвим так: «проезд возможен, если открыта улица A ИЛИ открыта улица B». Союз «ИЛИ» тоже припасен в Паскале, по-английски он пишется «OR». В этом случае решение будет таким.

      if A or B

      then S:=’Поезжай на машине!’

      else S:=’Топай пешком!’;

А вот маршрут на рис. 33 более замысловат.


Рис.33 – Схема проезда, третий вариант

Слабо ли вам выразить решение для этого случая? Сказать на обычном языке легко: «проехать можно, если открыта A И открыта B ИЛИ открыта C И открыта D ИЛИ открыта E». Слово «улица» я пропустил. Все, решение готово! Осталось лишь перевести его на язык Паскаль.

      if A and B or C and D or E

      then S:=’Поезжай на машине!’

      else S:=’Топай пешком!’;

Как просто! Здесь опять выделено курсивом логическое выражение. Только теперь оно составлено из булевых переменных и булевых операций AND (И) и OR (ИЛИ). Иногда эти операции называют логическим умножением и логическим сложением. Сходство с арифметикой здесь в том, что каждая логическая операция обладает в выражении своим старшинством: умножение AND выполняется раньше сложения OR. Когда эту последовательность надо изменить, применяют скобки. Пример такого рода показан на рис. 34 (перекресток).


Рис.34 – Схема проезда, четвертый вариант

Сначала скажем словами: «проехать можно, если открыта A ИЛИ открыта B И открыта C ИЛИ открыта D». Переведя на Паскаль буквально, без скобок, получим:

      if A or B and C or D

      then S:=’Поезжай на машине!’

      else S:=’Топай пешком!’;

Поскольку логическое умножение выполняется раньше сложения, Паскаль поймет это так: A or (B and C) or D. Но это не то, что мы хотели! Правильно будет записать наше решение со скобками:

      if (A or B) and (C or D)

      then S:=’Поезжай на машине!’

      else S:=’Топай пешком!’;

Наконец, рассмотрим маршрут на рис. 35, где путь преграждает шлагбаум. Договоримся, что закрытому шлагбауму соответствует значение TRUE (то есть, в сравнении с улицами тут все наоборот).


Рис.35 – Схема проезда, пятый вариант

Рассуждая как обычно, скажем так: «проезд возможен, если НЕ закрыт шлагбаум». Здесь применено логическое отрицание НЕ, что по английски значит «NOT». Решение на Паскале будет таким.

      if not A

      then S:=’Поезжай на машине!’

      else S:=’Топай пешком!’;

В отличие от двух предыдущих операций, логическое отрицание – одноместная операция, ей нужен лишь один операнд. Логическое отрицание имеет наивысший приоритет, и выполняется раньше логического умножения и сложения.

Парад логических операций

Итак, посредством логических операций мы переводим рассуждения с человеческого языка на формальный язык программирования, получая при этом логические (булевы) выражения. Логические данные в Паскале можно сравнивать и выполнять с ними четыре логические операции, три из которых вам уже знакомы. Рассмотрим свойства этих операций.

Логическое отрицание NOT («НЕ»). Имеет наивысший приоритет, то есть, при отсутствии скобок выполняется в первую очередь. Это одноместная операция, поскольку требует лишь одного операнда. По своему действию она напоминает знак «минус» для чисел, поскольку изменяет значение операнда на противоположное. Правила для этой операции таковы.


    Ваша оценка произведения:

Популярные книги за неделю