К операторам, позволяющим из нескольких возможных вариантов выполнения программы (ветвей) выбрать только один, относятся if и case.
Оператор if выбирает между двумя вариантами развития событий:
if <условие> then <один_оператор> [else <один_оператор>];
Обратите внимание, что перед словом else (когда оно присутствует, конечно же) символ ";" не ставится - ведь это разорвало бы оператор на две части.
Условный оператор if работает следующим образом:
else. Если же else-ветвь отсутствует, то не выполняется ничего.Что же произойдет, если написать несколько вложенных операторов if?
В случае, когда каждый оператор if имеет собственную else-ветвь, все будет в порядке. А вот если некоторые из них этой ветви не имеют, может возникнуть ошибка. Компилятор языка else относится к самому ближнему оператору if. Таким образом, если написать
if i>0 then if s>2 then s:= 1 else s:= -1;
подразумевая, что else-ветвь относится к внешнему оператору if, то компилятор все равно воспримет эту запись как
if i>0 then if s>2
then s:= 1
else s:= -1
else;
Ясно, что таким образом правильного результата получить не удастся.
Для того чтобы избежать подобных ошибок, стоит всегда (или по крайней мере при наличии нескольких вложенных условных операторов) указывать оба ключевых слова, даже если одна из ветвей будет пустовать. Так вы застрахуетесь от одной из частых "ошибок по невнимательности", которые очень сложно найти в процессе отладки программы.
Итак, исходный вариант нужно переписать следующим образом:
if i>0 then if s>2
then s:=1
else
else s:=-1;
либо так:
if i>0 then begin if s>2
then s:=1
end
else s:=-1;
Вообще же, если есть возможность переписать несколько вложенных условных операторов как один оператор
Оператор case позволяет сделать выбор между несколькими вариантами:
case <переключатель> of <список_констант> : <один_оператор>; [<список_констант> : <один_оператор>;] [<список_констант> : <один_оператор>;] [else <один_оператор>;] end;
Замечание: Обратите внимание, что после else двоеточие не ставится.
Существуют дополнительные правила, относящиеся к структуре этого оператора:
Пример
case symbol(* :char *) of
'a'..'z', 'A'..'Z' : writeln('Это латинская буква');
'а'..'я', 'А'..'Я' : writeln('Это русская буква');
'0'..'9' : writeln('Это цифра');
' ',#10,#13,#26 : writeln('Это пробельный символ');
else writeln('Это служебный символ');
end;
Выполнение оператора case происходит следующим образом:
end, которое закрывает всю конструкцию case.else. Если else-ветви нет, то не выполняется ничего.В качестве примера, иллюстрирующего использование операторов
sgn(x) = -1, если x < 0; sgn(x) = 0, если x = 0; sgn(x) = 1, если x > 0.
Реализовать эту функцию для случая, когда х вещественное, можно следующими способами (при условии, что x:real; sgn: -1..1;):
if x=0 then sgn:= 0; if x<0 then sgn:= -1; if x>0 then sgn:= 1;Это так называемая реализация "в лоб". Здесь нет никаких хитростей и никаких попыток оптимизации: даже если сработает первый вариант, второй и третий все равно будут проверены, невзирая на то, что результат уже получен.
if x=0 then sgn:= 0 else if x<0 then sgn:= -1 else sgn:= 1;Этот вариант свободен от излишних проверок в случае, если значение переменной не положительно.Эту реализацию следует признать более эффективной, чем предыдущая
if x=0 then sgn:=0 else sgn:=x/abs(x);Еще одна попытка сократить текст программы. Здесь используется стандартная функция
if x=0 then sgn:=0 else sgn:=round(x/abs(x));И действительно, исправленный вариант будет выдавать верный результат.
case x=0 of true: sgn:=0; false: sgn:=round(x/abs(x)); end;А вот еще один (правда, несколько неестественный) способ с использованием
true и false фигурируют в качестве меток выбора.Конечно же, мы перебрали далеко не все возможные способы реализации функции sgn(x) (ведь сколько людей, столько и способов выражать свои мысли - хоть в литературе, хоть в программировании). Однако уже на этом простеньком примере видно, что способов запрограммировать желаемое всегда больше, чем один, и вряд ли самое простое решение будет и оптимальным.
Теперь мы приступаем к изучению массива - наиболее широко используемого
Для того чтобы задать массив, необходимо в разделе
Общий вид описания (одномерного) массива:
array[<тип_индексов>of <тип_компонент>; ] Напоминаем, что жирная квадратная скобка является обязательным элементом синтаксиса.
Чаще всего это трактуется так:
array[<левая_граница>..<правая_граница>] of <тип_компонент>;
Например, одномерный (
var a1: array [1..10] of integer;
Нумерация компонент массива не обязана начинаться с 1 или с 0 - вы можете описывать массив, пронумерованный любыми целыми числами. Необходимо лишь, чтобы номер последней компоненты был больше, чем номер первой:
var a1: array [-5..4] of integer;
Собственно говоря, нумеровать компоненты массива можно
не только целыми числами. Любой
type char = 'a','c'..'z'; (- отсутствует символ "b")
var a1: array[char] of integer; - 256 компонент
a2: array [char] of integer; - 256 целых компонент
a3: array [shortint] of real; - 256 вещественных компонент
Общий размер массива не должен превосходить 65 520 байт. Следовательно, попытка задать массив a4:array[integer]of byte ; не увенчается успехом, поскольку longint в данном случае лучше и вовсе не вспоминать.
Тип компонент массива может быть любым:
var a4: array[10..20] of real; - массив из компонент простого типа
a5: array[0..100] of record1; - массив из
a6: array[-10..10] of ^string; - массив из
a7: array[-1..1] of file; - массив из имен файловых
a8: array[1..100] of array[1..100] of char;
-
Для краткости и удобства
var a9: array[1..10,1..20] of real;
-
- четырехмерный массив 2 х 3 х 256 х 21
Общее ограничение на размер массива - не более 65 520 байт - сохраняется и для многомерных массивов. Количество компонент многомерного массива вычисляется как произведение всех его "измерений". Таким образом, в массиве а9 содержится 200 компонент, а в массиве а10 - 32 256 компонент.
Если ваша программа должна обрабатывать
var m,n: integer;
a: array[1..m,1..n] of real;
придется отбросить.
Если на этапе написания программы ничего нельзя сказать о предполагаемом размере входных данных, то не остается ничего другого, как воспользоваться техникой динамически распределяемой памяти (см. лекцию 10).
Предположим, однако, что вам известны максимальные границы, в которые могут попасть индексы обрабатываемого массива. Скажем, N и М заведомо не могут превосходить 100. Тогда можно выделить место под наибольший возможный массив, а реально работать только с малой его частью:
const nnn=100;
var a: array[1..nnn,1..nnn] of real;
m,n: integer;
Массивы относятся к структурам прямого доступа. Это означает, что возможно напрямую (не перебирая предварительно все предшествующие компоненты) обратиться к любой интересующей нас компоненте массива.
Доступ к компонентам линейного массива осуществляется
<имя_массива>[<индекс_компоненты>]
а многомерного - так:
<имя_массива>[<индекс>,_,<индекс>]
Правила употребления
Примеры использования компонент массива:
a2['z']:= a2['z']+1; a3[-10]:= 2.5; a3[i+j]:= a9[i,j]; a10[x>0,sgn(x),'!',abs(k*5)]:= 0;
Для того чтобы не вводить массивы вручную во время отладки программы (особенно если они имеют большую размерность), можно пользоваться не только
Если массив линейный (вектор), то начальные значения для компонент этого вектора задаются через запятую, а сам вектор заключается в круглые скобки.
Исключение составляют только массивы, компонентами которых являются величины
Примеры задания массивов типизированными константами:
type
const a: array[-1..1] of byte = (0,0,0); {линейный}
b: {двумерный}
s: array[0..9] of char = '0123456789';
Замечание: Невозможно задать неименованную или нетипизированную константу, относящуюся к типу данных array.
Для того чтобы обработать несколько однотипных элементов, совершить несколько одинаковых действий и т.п., разумно воспользоваться
Замечание: Алгоритмы, построенные только с использованием циклов, называются
В случае когда количество однотипных действий заранее известно (например, необходимо обработать все компоненты массива), стоит отдать предпочтение циклу с параметром ( for ).
Общий вид оператора for-to:
for i:= first to last do <оператор>;
Счетчик i (переменная), нижняя граница first (переменная, константа или выражение) и верхняя граница last (переменная, константа или выражение) должны относиться к эквивалентным
Цикл for-to работает следующим образом:
last;first;i<=last;<оператор> ;i увеличивается на единицу;i не станет строго больше, чем last; как только это произошло, выполнение цикла прекращается, а управление передается следующему за ним оператору.Из этой последовательности действий можно понять, какое количество раз отработает цикл for-to в каждом из трех случаев:
first < last: цикл будет работать last-first+1 раз;first = last: цикл отработает ровно один раз;first > last: цикл вообще не будет работать.После окончания работы цикла переменная-счетчик может потерять свое i=last+1. Поэтому попытки использовать переменную-счетчик сразу после завершения цикла (без присваивания ей какого-либо нового значения) могут привести к непредсказуемому поведению программы при отладке.
Существует аналогичный
for i:= first downto last do <оператор>;
Счетчик i (переменная), верхняя граница first (переменная, константа или выражение) и нижняя граница last (переменная, константа или выражение) должны иметь эквивалентные порядковые типы. Если тип нижней или верхней границы не эквивалентен типу счетчика, а лишь совместим с ним, то осуществляется неявное
Цикл for-downto работает следующим образом:
i присваивается значение first ;i>=last ;<оператор> ;i уменьшается на единицу;i не станет меньше, чем last ; как только это произошло, выполнение цикла прекращается, а управление передается следующему за ним оператору.Если при этом
first < last, то цикл вообще не будет работать;first = last, то цикл отработает один раз;first > last, то цикл будет работать first-last+1 раз.Замечание о неопределенности значения счетчика после окончания работы цикла справедливо и в этом случае.
Если заранее неизвестно, сколько раз необходимо выполнить
Общий вид этих операторов таков:
while <условие_1> do <оператор>; repeat <операторы> until <условие_2>;
Условие окончания цикла может быть выражено переменной, константой или выражением, имеющим
Замечание: Обратите внимание, что на каждой итерации циклы for и while выполняют только по одному оператору (либо группу операторов, заключенную в позволяет выполнить сразу несколько операторов: ключевые слова и until сами служат операторными скобками.
Так же, как циклы for-to и for-downto, циклы while и можно назвать в некотором смысле противоположными друг другу.
Последовательности действий при выполнении этих циклов таковы:
| Для while: | Для |
|---|---|
| 1. Проверяется, истинно ли <условие_1>. | 1. Выполняются <операторы>. |
| 2. Если это так, то выполняется <оператор>. | 2. Проверяется, ложно ли <условие_2> |
| 3. Пункты 1 и 2 выполняются до тех пор, пока <условие_1> не станет ложным. | 3. Пункты 1 и 2 выполняются до тех пор, пока <условие_2> не станет истинным. |
Таким образом, если <условие_1> изначально ложно, то цикл while не выполнится ни разу. Если же <условие_2> изначально истинно, то цикл выполнится один раз.
Существует
break прерывает работу всего цикла и передает управление на следующий за ним оператор.
continue прерывает работу текущей итерации цикла и передает управление следующей итерации (цикл ) или на предшествующую ей проверку (циклы for-to, for-downto, while ).
Замечание: При прерывании работы циклов for-to и for-downto с помощью функции break переменная цикла (счетчик) сохраняет свое текущее значение, не "портится".
Возвращаясь к сказанному об операторе
Дело в том, что процедуры break и continue прерывают только один цикл - тот, в теле которого они содержатся. Поэтому в упомянутой выше ситуации пришлось бы заметно усложнить текст программы, вводя много дополнительных прерываний. А один
Сравните, например, два программно-эквивалентных отрывка:
write('Матрица '); write('Матрица ');
for i:=1 to n do for i:=1 to n do
begin for j:=1 to m do
flag:=false; if a[i,j]>a[i,i]
for j:=1 to m do then begin
if a[i,j]>a[i,i] write('не ');
then begin flag:=true; goto 1;
write('не '); end;
break; 1: writeln('обладает
end свойством
if flag then break; диагонального
end; преобладания.');
writeln('обладает свойством
диагонального
преобладания.');
Задача. Вычислить
Алгоритм. Метод последовательных приближений, которым мы воспользуемся для решения этой задачи, состоит в многократном вычислении интеграла со все возрастающей точностью, - до тех пор, пока два последовательных результата не станут различаться менее чем на заданное число (скажем,
Вычислять одно текущее значение для интеграла мы будем с помощью
На нашем рисунке изображена функция f(x) = x2 (на отрезке [1,2]). Каждая из криволинейных трапеций будет урезана (сверху) до прямоугольника: высотой каждого из них послужит значение функции на левом конце участка. График станет "ступенчатым".
Реализация
step:= 1; h:= b-a; s_nov:= f(a)*h; repeat s_star:= s_nov; s_nov:= 0; step:= step*2; h:= h/2; for i:= 1 to step do s_nov:= s_nov+f(a+(step-1)*h); s_nov:= s_nov*h; until abs(s_nov - s_star)<= eps; writeln(s_nov);
Задача. Распечатать
Алгоритм. Понятно, что если весь массив мы вытянем в одну строчку (или, того хуже, в один столбик), то хороших слов в свой адрес мы от пользователя не дождемся. Именно поэтому нам нужно вывести массив построчно, отражая его структуру.
Реализация
for i:= 1 to n do begin for j:= 1 to m do write(a[i,j]:4); writeln; end;
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.