SNK Software
Web Studio Монополия Metaproducts Утилиты Игры
Монополию Web Studio Библиотека
Вебмастер Дельфи Работа на ПК Самоучитель
Для PHP Для Delphi
Веб-дизайн Программирование Компьютеры Девайсы Заметки
SNK Software Индустрия hardware Индустрия software
О студии Портфолио Сопровождение сайтов

Новые материалы

Девайсы:
Сравнительный обзор Nokia Lumia 920 и HTC 8X
Девайсы:
Обзор Nokia Lumia 820 – смартфона на WP8
Вебмастеру:
Настройка Apache, PHP и MySQL для Linux-VPS
Вебмастеру:
VPS на домашнем ПК: настройка сети в VM VirtualBox и Debian
Вебмастеру:
VPS на домашнем ПК: устанавливаем Linux Debian 6
Вебмастеру:
VPS на домашнем ПК: установка VM VirtualBox
Работа на компьютере:
Иные возможности текстового процессора Word
Работа на компьютере:
Вставка объектов
Работа на компьютере:
Таблицы в Word
Работа на компьютере:
Печать и сохранение документов
Работа на компьютере:
Сноски, колонтитулы, оглавление и указатели в Word

Операторы Object Pascal

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

Об управляющих структурах

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

Собственно за переход, в классическом варианте, отвечает небезызвестная инструкция безусловного перехода goto, которая в Pascal используется совместно с метками, декларируемыми в заголовочной части программы при помощи ключевого слова label. Использование инструкции безусловного перехода восходит корнями к тем временам, когда создавались первые высокоуровневые языки программирования, в том числе и Pascal. Она досталась им в наследство от низкоуровневых языков типа Assembler, в которых описание программы создавалось в виде, удобным для машины. Но на сегодня такой подход уже не востребован и вышел из употребления, вместе с безусловным переходом и инструкцией goto.

СОВЕТ
За 10 лет, прошедших с того момента, как я последний раз использовал язык Basic, мне ни разу не довелось ни использовать инструкцию goto в собственных программах, ни встретить ее в миллионах строк просмотренного кода. Вывод: она просто не нужна в Object Pascal, так что старайтесь не использовать goto!

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

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

begin <инструкция 1>; <инструкция 2>; ... <инструкция N>; end;

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

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

Условный оператор if

Пожалуй, самой важной инструкцией для управления выполнением программы является условный оператор if. Именно он отвечает за ветвление, т.е. выполнение (или невыполнение) того или иного варианта кода в зависимости от условий. Оператор if используется совместно с ключевым словом then, а в том случае, когда предусмотрен альтернативный вариант выполнения - еще и с else. В целом синтаксис инструкции получается следующим:

if <условие> then <код> [else <альтернативный код>]

В качестве условия может быть использовано любое выражение, которое может быть приведено к булевскому значению, т.е. к false или true. Как правило, это бывают операции сравнения, например:

if a > 5 then b := 10; if x <> 0 then y := 1 else y :=2;

В первом случае, если переменная a больше 5, то переменной b будет присвоено значение 10, если же a меньше или равно 5, то ничего выполнено не будет и управление будет передано следующему выражению. Во второй строке переменная x проверяется на ненулевое значение, и если x окажется числом, отличным от 0, то переменной y будет присвоено значение 1, в противном случае (если x равно 0) переменной y будет присвоено значение 2.

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

if a > 5 then begin b := 10; c := 20; end;

Как мы уже знаем, в соответствии с правилами синтаксиса Object Pascal, все то, что помещено между ключевыми словами begin и end, равно как и сами эти слова, воспринимаются как 1 оператор. Обратите внимание, что в конце поставлен пустой оператор - точка с запятой. В данном случае по правилам синтаксиса он здесь не обязателен, однако будет хорошим тоном завершать им каждый составной оператор, чтобы выделить тем самым окончание той инструкции, в которой он был применен. В данном случае получается, что мы использовали 2 оператора - составной и пустой, однако нарушения синтаксиса тут нет - компилятор сочтет, что пустой оператор следует уже после условного. Но если бы мы использовали еще и блок else, это привело бы к ошибке синтаксиса, поскольку между then и else допустима лишь 1 инструкция. Поэтому в таком случае точку с запятой следует разместить уже после оператора, следующего за else:

if a > 5 then begin b := 10; c := 20; end else begin b := 20; c := 15; end;

В тех случаях, когда требуется предусмотреть 3 или более вариантов исполнения, используют вложение операторов if друг в друга. Например, если требуется выполнить один вариант когда, когда некая переменная x меньше нуля, другой - если x равна 0, и третий - если x больше нуля, то синтаксис операторов может быть следующим:

if x < 0 then <вариант для x<0> else if x = 0 then <вариант для x=0> else <вариант для x>0>;

В данном случае использован вложенный оператор if, который выполняется в случае, когда переменная x не меньше 0. Он проверяет, не является ли значением x число 0, и если нет, то, учитывая, что x явно не меньше, чем 0 (это условие к моменту выполнения вложенного оператора if уже проверено внешним, т.е. первым в данном выражении оператором if), значит значение x больше 0.

Оператор выбора case

Условный оператор удобен в тех случаях, когда необходимо проверить 1-2-3 варианта. При большем числе получается слишком громоздкая и неудобная для восприятия конструкция из множества вложенных инструкций. Скажем, если требуется проверить 5 значений переменной x, то получим такую конструкцию:

if x = 1 then ; else if x = 2 then ; else if x = 3 then ; else if x = 4 then ; else if x = 5 then ;

Очевидно, что код получается слишком громоздким, и малоэффективным. В таких случаях на помощь приходит семафор - оператор множественного выбора case. Он состоит из выражения, являющегося селектором, списка вариантов, представленного константами или значениями, и необязательной части else. Таким образом, формат оператора case таков:

case [выражение-селектор] of   <значение 1>: <код для значения 1>;   <значение 2>: <код для значения 2>;   ...   <значение N>: <код для значения N>;   [else <код для непредусмотренных явно значений>;] end

Единственным ограничением семафора, в сравнении с условным оператором, является то, что в качестве селектора могут выступать лишь данные порядкового типа, скажем, целым числом или же символом. Впрочем, для подавляющего числа случаев этого достаточно. Например, приведенный выше вариант кода с 4 вложенными условными операторами, при помощи case можно оформить так:

case x of 1: ; 2: ; 3: ; 4: ; 5: ; end;

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

Инструкция выбора выполняется следующим образом: вначале, при необходимости, вычисляется значение селектора, затем производится последовательный обход вариантов на предмет совпадения с селектором. В случае совпадения, выполняется инструкция, предусмотренная для этого варианта, после чего выполнение оператора выбора заканчивается. Если же ни один из перечисленных вариантов не совпал со значением селектора (для нашего случая - если x меньше 1 или больше 5), то либо оператор завершается без каких-либо действий, либо, при наличии блока else, выполняются заданные в нем инструкции.

В качестве констант выбора могут выступать не только единичные значения, но и их список, разделенный запятыми, или же диапазоны, определенные границами из 2 констант, разделенных двумя точками. В таком случае мы можем объединить логически связанные значения в группы, для которых следует выполнить один и тот же код. Например, таким образом можно получить название времени года в зависимости от порядкового номера месяца (листинг 4.1).

Листинг 4.1. Использование оператора case

var month: integer; season: string; ... case month of 1,2,12: season := "зима"; 3..5: season := "весна"; 6..8: season := "лето"; 9..11: season := "осень"; else season := "других не знаем!"; end;

В данном случае, если переменная month имеет значения 1, 2 или 12, то переменной season присваивается значение "зима", если же значение переменной month окажется в диапазоне от 3 до 5 (включительно), то season получит значение "весна", и т.д.

Оператор цикла for

Для написания практически любой программы, помимо операторов условия, требуются операторы цикла, и в Object Pascal, они, разумеется, есть. Прежде всего, это оператор цикла с параметром - for. Такой тип цикла обычно применяют в тех случаях, когда количество возможных повторов известно заранее. Он имеет 2 варианта написания: один - для цикла с приращением, и другой - для цикла с уменьшением:

for <параметр> := <выражение 1> to <выражение 2> do <тело цикла>; for <параметр> := <выражение 1> downto <выражение 2> do <тело цикла>;

В первом случае (с использованием цикла for-to) при каждом проходе цикла, называемом итерацией, значение параметра увеличивается на 1, а во втором (for-downto) - уменьшается на 1. При этом в качестве начального значения используется "выражение 1", а в качестве конечного - "выражение 2". Разумеется, если для цикла to значение первого выражения изначально будет больше значения второго, или наоборот, меньше (для цикла downto), то цикл не будет выполнен ни разу. Практическое применение циклов крайне разнообразно. Если привести наиболее общий пример из программирования, то цикл - идеальный способ заполнения массива. Например, если требуется организовать цикл для заполнения массива из 10 числовых значений последовательно возрастающими числами, то можно записать:

for i := 0 to 9 do MyArray[i]=i;

В данном случае элементам массива MyArray последовательно назначаются значения от 0 до 9.

ПРИМЕЧАНИЕ
Сами массивы будут рассмотрены несколько позже, в главе, посвященной структурным типам данных.

Теперь рассмотрим цикл for с отрицательным приращением на примере вычисления математического факториала (последовательное произведение всех целых чисел от 1 до самого числа). Для этого нам понадобится следующий цикл:

var num, rez: integer; ... rez := 1; for num := num downto 1 do rez := rez * num;

Здесь нам потребовалась небольшая подготовительная работа: определена переменная rez, в которой будет храниться вычисляемое значение, и ей присвоено значение 1. В качестве числа, для которого вычисляется факториал, выступает переменная num, она же используется для самого цикла в качестве счетчика. Поскольку нам надо будет прекратить выполнение цикла, после того, как счетчик (num) достигнет значения 1, то именно это значение и указано в качестве конечного условия.

В итоге, если переменной num присвоить значение 5, то после прохождения цикла переменная rez получит значение 120. Хотя в результате работы такого цикла получится выполнение как бы наоборот (т.е. не вместо 1*2*3*4*5, на самом деле выполняется 5*4*3*2*1), это никак не помешает получить верный результат.

Наконец, в качестве тела цикла, как и в случае с уже рассмотренными операторами, может использоваться составной оператор. Кроме того, циклы могут быть вложены один в другой, при этом важно лишь следить за тем, где заканчивается вложенный цикл и начинается внешний. Для этого полезно следить за правильным оформлением программы, в частности, использовать отступы, в качестве которых можно использовать либо знак табуляции, либо пробелы, в последнем случае их желательно ставить не менее 2 (листинг 4.2).

Листинг 4.2. Вложенные циклы и форматирование кода

for x := 5 to 10 do begin z := x; for y := 10 to 20 do begin z := z + x * y; writeln(z); end; // конец вложенного цикла writeln(x); end; // конец внешнего цикла

При использовании циклов с параметром важно помнить, что изменение значения параметра в теле цикла недопустимо.

Операторы циклов while и repeat

Помимо классического цикла с параметром, в Object Pascal предусмотрено еще 2 вида циклов - с предусловием и с постусловием. В качестве цикла с предусловием выступает оператор while. Он имеет следующий синтаксис:

while <Условие> do <тело цикла>

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

while false do ; В то же время, при помощи оператора while удобно делать бесконечный цикл. В бесконечных циклах весь контроль возлагается на операторы, помещаемые в тело цикла: while true do begin <инструкции> end;

ПРИМЕЧАНИЕ
Очевидно, что цикл с условием, которое изначально истинно и никак не изменяется, будет выполняться вечно. Таким образом, в теле цикла следует предусмотреть возможность его прерывания иным способом.

В отличие от while, цикл с постусловием, задаваемый при помощи оператора repeat, всегда выполняется хотя бы 1 раз, поскольку проверку на соответствие условию он проходит после того, как будет выполнено его тело:

repeat <тело цикла> until <условие>

Важно так же отметить, что в цикле с постусловием ключевые слова repeat и until образуют как бы составной оператор. Иначе говоря, если в цикле while при необходимости использовать более одной инструкции следует использовать составной оператор, то для цикла repeat этого не требуется:

repeat x := x + 1; y := x * 2; until y < 1000;

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

Операторы break и continue

Мы уже поднимали вопрос бесконечного цикла и возможного зацикливания программы, чреватого ее зависанием. Чтобы иметь возможность обработки подобных ситуаций, а так же сделать сами циклы более гибкими, используют специальные операторы - break и continue. Оператор break позволяет завершить цикл досрочно, а оператор continue - выполнить только часть операторов в теле цикла, перейдя к его следующей итерации.

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

while true do begin a := b * c; if a > 1000 then break; b := b + 1; // в случае если a > 1000, эта строка выполнена не будет end; Еще одним полезным применением досрочного выхода является его использования в качестве дополнительного параметра. Например, если нам нужен цикл, который должен прерваться по 1 из 2 условий, то для второй проверки мы можем использовать условный оператор if совместно с break: repeat i := i + 1; if i > 100 then break; y := y - 1; until y < 50;

Здесь мы определили цикл, который будет завершен либо после того, как значение переменной y достигнет 50 (что задано в самом условии цикла), либо если значение переменно x превысит указанное в условии if значение 100 - здесь как раз будет задействован оператор break.

Иногда бывает необходимо перейти к следующему шагу цикла досрочно, пропустив часть операторов. Для этих целей используют оператор continue. В отличие от break, этот оператор не завершает цикл, а заставляет программу досрочно перейти к новой проверке условия цикла. Рассмотрим эту ситуацию на примере. Допустим, что нам надо получить список чисел, на которые число 100 делится без остатка:

for i := 1 to 100 do begin if 100 mod i <> 0 then continue; writeln(i); end;

Для этого мы определили цикл, в котором при каждой итерации делитель, в качестве которого выступает счетчик цикла, увеличивается на единицу. В самом теле цикла использован условный оператор, в котором условием выступает выражение, в котором производится операция "остаток от деления" и ее результат сравнивается с 0. Таким образом, если дано условие истинно (т.е. если остаток равен нулю), то интерпретатор переходит к следующему оператору в теле цикла, который выводит нужное нам число, в противном случае выполняется оператор continue и начинается новый шаг цикла.

Операторы в действии

Таким образом, мы рассмотрели практически все операторы языка Object Pascal, включая 3 типа стандартных циклов. Еще один цикл - for-in, появившийся в Delphi 2005, является частным случаем цикла for-to и позволяет без лишних усилий создавать циклы для данных порядкового типа. Тем не менее, останавливаться на возможностях языка, появившихся после Delphi 7, мы здесь не будем. Рассмотрим лучше практическое применение изученных операторов для реализации алгоритмов, для чего вновь обратимся к игре "угадай число".

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

Помимо них, нам потребуются несколько стандартных функций Object Pascal - для вывода информационных сообщений, для ввода пользователем значений, а так же для "загадывания" числа. Ввод и вывод в консольных программах осуществляется при помощи функций read и write, соответственно. А для генерации псевдослучайных чисел используют процедуру randomize и функцию random.

ПРИМЕЧАНИЕ
Несколько позже мы подробно ознакомимся с тем, что такое процедуры и функции, и чем они различаются. Пока же достаточно просто принять к сведению, что перечисленные здесь функции будут делать в данном случае.

Итак, для начала запустите Delphi и создайте новое приложение командной строки (File New Other New/Console Application). После того, как Delphi создаст новый проект, сразу сохраните его под каким-либо осмысленным именем, попутно выбрав для него подходящее место на диске. Назовем эту программу "Ugadaika" и помести ее в одноименный каталог на диске C:.

Теперь можно приступать к написанию кода. Поскольку программа должна начинаться с деклараций переменных, то с них и начнем. Нам понадобятся 2 переменных: одна - для хранения загаданного числа, и вторая - для получения ответа пользователя. Назовем их a и b и поместим объявление перед ключевым словом begin. Таким образом, в самом начале работы программа примет такой вид, как показано на примере листинга 4.3.

Листинг 4.3. Программа "угадай-ка" в самом начале разработки

program ugadaika; {$APPTYPE CONSOLE} uses SysUtils; var a,b: integer; begin end.

Теперь можно приступать к написанию основного кода, который, как мы знаем, должен располагаться между begin и end. Начинаться он должен с загадывания числа. Для этого поместим в начало программы (начиная со строки, следующей за begin), следующий код:

randomize; // инициализация генератора псевдослучайных чисел a := random(100)+1; // присваивание переменной a значения от 1 до 100

Далее следует подготовиться к циклу отгадывания, для чего надо, во-первых, установить переменную b в заведомо неподходящее значение (скажем, в 0), а во-вторых - вывести пользователю сообщение, в котором пояснить, чего ему надо делать:

b:=0; write(Input a number between 1 to 100 and hit Enter);

Здесь мы использовали английские символы по той причине, что кодовые номера символов кириллицы для DOS и Windows различаются. Соответственно, чтобы опустить здесь процедуры перекодировки символов, мы пошли по пути наименьшего сопротивления и ограничились латиницей.

Следующим этапом будет создание самого цикла. Мы уже определили условие его выполнения - до тех пор, пока число не отгадано, т.е. пока a не равно b. Соответственно, выглядеть он будет так:

while (a<>b) do

Кроме того, поскольку в цикле будет явно больше 1 оператора, сразу определим составной оператор, добавив begin и end. В результате общий вид программы на текущем этапе получится таким, как показано на листинге 4.4.

Листинг 4.4. "Угадай-ка" с основными блоками

program ugadaika; {$APPTYPE CONSOLE} uses SysUtils; var a,b: integer; begin randomize; a := random(100)+1; b := 0; write(Input a number between 1 to 100 and hit Enter); while (a<>b) do begin end; end.

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

write(#13+#10+?:);

Использованные здесь символы #13 (возврат каретки) и #10 (новая строка) переносят точку ввода на одну строку вниз для лучшего эстетического восприятия. Теперь дадим пользователю возможность ввести свой вариант ответа, воспользовавшись функцией read:

read(b); // введенное число будет помещено в переменную b

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

if (b>a) then write(Too much!);

Теперь составим условие для противоположного случая:

if (b<a) then write(Too small!);

Вот, в общем-то, и все! Остается после завершения цикла предусмотреть вывод сообщения о том, что число отгадано, для чего вновь воспользуемся функцией write, а заодно - функцией sleep, чтобы предотвратить преждевременное закрытие окна:

write(Cool! You win!); sleep(2000); // пауза в 2 секунды

В итоге мы получим вполне работоспособную программу, полный исходный код которой приведен в листинге 4.5, а на CD он находится в Demo\Part1\Ugadaika.

Листинг 4.5. Полный исходный код игры

program ugadaika; {$APPTYPE CONSOLE} uses SysUtils; var a,b: integer; begin randomize; a := random(100)+1; b := 0; write(Input a number between 1 to 100 and hit Enter); while (a<gt;b) do begin write(#13+#10+'?:'); read(b); if (b>a) then write(Too much!); if (b<a) then write(Too small!); end; write(Cool! You win!); sleep(2000); end.

Избранное

SNK GSCP
SNK GSCP - новая библиотека для PHP 5!
Web Studio
Web Studio и Visual Workshop
Библиотека:
Стандарты на web-технологии
Монополия
Монополия v. 2.0.2
Загрузки:
скачать программы
Продукция:
программы и книги
Техподдержка / Связаться с нами
Copyright © 1999-2013 SNK. Все права защищены.
При использовании материалов с сайта ссылка на источник обязательна.
Рейтинг@Mail.ru