Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Алгоритмизация и языки программирования. Учебно-методический комплекс.pdf
X
- •1. СИЛЛАБУС ДИСЦИПЛИНЫ ДЛЯ СТУДЕНТОВ
- •Тема 1. Понятие алгоритма, свойства, типы, исполнители
- •Структура программы.
- •Имена, ключевые слова и знаки операций
- •Тема 7. Символьные типы данных.
- •Обработка символьных данных.
- •Тема 9. Строки. Строковые процедуры.
- •Функции
- •Тема 11. Множества (Set)
- •Работа с текстовыми файлами
- •Тема 13. Записи
- •Тема 14. Построение изображений на экране
- •Отображение точки на экране
- •Отображение линий на экране
- •Построение прямоугольников на экране
- •Построение многоугольников
- •Построение дуг, эллипсов и окружностей
- •Основная литература
- •Дополнительная литература
- •ГЛОССАРИЙ

Описания двух различных подпрограмм не могут пересекаться:
каждый блок должен быть логически законченным. Однако внутри
любой подпрограммы (она ведь тоже является программой,
помните?) могут быть описаны другие процедуры или функции вложенные. На них распространяются все те же правила объявления
и описания подпрограмм.
Возвращаемые значения
Основное различие между функциями и процедурами состоит в
количестве возвращаемых ими значений.
Любая функция, завершив свою работу, должна вернуть основ-
ной программе (или другой вызвавшей ее подпрограмме) ровно одно
значение, причем его тип нужно явным образом указать уже при
объявлении функции.
Для возвращения результата применяется специальная "переменная", имеющая имя, совпадающее с именем самой функции.
Оператор присваивания значения этой "переменной" обязательно
должен встречаться в теле функции хотя бы один раз.
Например:
function min(a,b: integer): integer;
begin
if a>b then min:= b
else min:= a
end;
Вызов подпрограмм
Любая подпрограмма может быть вызвана не только из основного тела программы, но и из любой другой подпрограммы, объявленной позже нее.
При вызове в подпрограмму передаются фактические параметры или аргументы (в круглых скобках после имени подпрограммы, разделенные запятыми):
<имя_подпрограммы>(<список_аргументов>)
Аргументами могут быть переменные, константы и выражения,
включающие в себя вызовы функций.
Количество и типы передаваемых в подпрограмму аргументов
должны соответствовать количеству и типам ее параметров. Кроме
того, тип каждого аргумента должен обязательно учитывать способ
51

подстановки, указанный для соответствующего параметра (подробнее об этом будет рассказано в разделе "Способы подстановки аргументов"). Если у подпрограммы вообще нет объявленных параметров, то при вызове список передаваемых аргументов будет отсутствовать вместе с обрамляющими его скобками.
Вызов функции не может быть самостоятельным оператором,
потому что возвращаемое значение нужно куда-то записывать. Зато
оно может стать равноправным участником арифметического выражения. Например:
c:= min(a,a*2);
if min(z, min(x,y))= 0 then...;
Процедура же ничего не возвращает явным образом, поэтому ее
вызов является отдельным оператором в программе. Например:
err(res,'Привет!');
Замечание: После того как вызванная подпрограмма завершит
свою работу, управление передается оператору, следующему за
оператором, вызвавшим эту подпрограмму.
В качестве примера рассмотрим процедуру kwad, которая также
служит для печати квадрата в процедуре:
procedure kwad;
var i:integer;
begin
for i:=1 to 3 do write(‘*’);
writeln;
write(‘* *’);
for i:=1 to 3 do write(‘*’);
writeln;
end.
Данный пример ясно показывает, что внутри процедуры также
можно объявлять новые переменные. Так как эти переменные могут
действовать только в самой процедуре, то говорят, что эти
переменные являются локальными. Термин «локальные» объявляет,
что переменные могут использоваться (имеют смысл) только в самой
процедуре.
В процедуре можно также определять метки, константы, типы и
т.д. (и даже новые процедуры). Подобная процедура имеет точно
52

такую же структуру, как и программы, которые мы до сих пор
описывали.
Процедуры с параметрами-значениями
Представьте себе, что нам нужно воспроизвести рисунок, на
котором должны быть нарисованы друг под другом квадраты и
размеры квадратов должны быть разными. Для этого случая было бы
очень удобно, если бы в процедуре можно было задавать, например,
размер напечатанного квадрата.
Паскаль дает такую возможность задавать параметры, принимающие определенные значения в процедуре – «параметры-зна-
чения».
Когда в качестве параметров задаются переменные, которые
должны подвергаться определенной обработке, тогда речь идет о
«параметрах-переменных» (или о параметрах, вызываемых по имени
переменной).
Уточним еще раз, заголовок процедуры имеет вид:
procedure <имя >(<описание формальных параметров)>;
Формальные параметры – переменные, используемые внутри
процедуры и принимающие различные начальные и конечные
значения для каждого вызова процедуры. Описание формальных
параметров имеет вид:
var <список_формальных_параметров>: <имя_типа>;
Список формальных параметров может состоять из одного
параметра или нескольких параметров, отделенных друг от друга
запятой.
Поскольку внутри подпрограммы параметры рассматриваются
как переменные с начальным значением, то имена локальных
переменных, описываемые в разделе var (внутреннем для подпрограммы), не могут совпадать с именами параметров этой же подпрограммы.
Глобальные объекты - это типы данных, константы и пере-
менные, объявленные в начале программы до объявления любых
подпрограмм. Эти объекты будут видны во всей программе, в том
числе и во всех ее подпрограммах. Глобальные объекты существуют
на протяжении всего времени работы программы.
53

Локальные объекты объявляются внутри какой-нибудь подпрограммы и "видны" только этой подпрограмме и тем подпрограммам,
которые были объявлены как внутренние для нее. Локальные объек-
ты не существуют, пока не вызвана подпрограмма, в которой они
объявлены, а также после завершения ее работы.
Список параметров может и вовсе отсутствовать:
procedure proc1;
function func1: boolean;
В этом случае подпрограмма не получает никаких переменных
"извне". Упомянутый в начале лекции песенный припев как раз и
является примером подпрограммы, в которую не передается никаких
данных при вызове.
Однако отсутствие параметров и, как следствие, передаваемых
извне значений вовсе не означает, что при каждом вызове подпрограмма будет выполнять абсолютно одинаковые действия. Поскольку
глобальные переменные видны изнутри любой подпрограммы, их
значения могут неявно изменять внутреннее состояние подпрограмм.
Если способ подстановки и тип нескольких параметров совпадают, описание этих параметров можно объединить:
[<способ_подстановки>]<имя1>,...,<имяN>: <тип>;
В заголовке подпрограммы можно указывать только простые (не
составные) типы данных. Следовательно, попытка записать
procedure proc2(a: array[1..100]of char);
вызовет ошибку уже на этапе компиляции. Для того чтобы
обойти это ограничение, составной тип данных нужно описать в
разделе type, а при объявлении подпрограммы воспользоваться
именем этого типа:
type arr = array[1..100] of char;
procedure proc2(a: arr);
Параметр-переменная
Описание
В списке параметров подпрограммы перед параметромпеременной ставится служебное слово var. Например, процедура
proc3 имеет три параметра-переменные и один параметр-значение:
procedure proc3(var x,y:real; var k:integer; flag:boolean);
54

При вызове подпрограммы параметру-переменной может соответствовать только аргумент-переменная; константы и выражения
запрещены. Кроме того, тип аргумента и тип параметра-переменной
должны быть эквивалентными.
Механизм передачи значения
В отличие от параметра-значения, для параметра-переменной не
создается копии при вызове подпрограммы. Вместо этого в работе
подпрограммы участвует та самая переменная, которая послужила
аргументом. Понятно, что если ее значение изменится в процессе
работы подпрограммы, то это изменение сохранится и после того, как
будет уничтожен контекст подпрограммы. Понятно опять же и
ограничение на аргументы, которые должны соответствовать параметрам-переменным: ни константа, ни выражение не смогут сохранить изменения, внесенные в процессе работы подпрограммы.
Итак, параметры-переменные и служат теми посредниками,
которые позволяют получать результаты работы процедур, а также
увеличивать количество результатов, возвращаемых функциями.
Замечание: Для экономии памяти в параметр-переменную мож-
но передавать и такую переменную, изменять значение которой не
требуется. Скажем, если нужно передать в качестве аргумента массив,
то лучше не создавать его копию, как это будет сделано при использовании параметра-значения, а использовать параметр-переменную.
Параметр-константа
Описание
В списке параметров подпрограммы перед параметром-константой ставится служебное слово const. Например, процедура proc4
имеет один параметр-переменную и один параметр-константу:
procedure proc4(var k:integer; const flag:boolean);
При вызове подпрограммы параметру-константе может соответствовать аргумент, являющийся выражением, переменной или константой. Во время выполнения подпрограммы соответствующая пере-
менная считается обычной константой. Ограничением является то,
что при вызове другой подпрограммы из тела текущего параметраконстанте не может быть подставлен в качестве аргумента в параметр-переменную.
55

Для типов данных здесь не обязательно строгое совпадение
program prim1;
end.
program prim2;
end.
(эквивалентность), достаточно и совместимости по присваиванию.
Механизм передачи значения
В некоторых источниках можно встретить утверждение о том,
что для параметра-константы, как и для параметра-переменной, не
создается копии в момент вызова подпрограммы. Однако выполнение
простейшей проверки доказывает обратное: физические адреса
переменной а и параметра с различаются. Следовательно, в памяти
эти переменные занимают разные позиции, а не одну, как было бы в
случае параметра-переменной. Вы можете убедиться в этом само-
стоятельно, запустив данную программу в трех разных вариантах
(для параметра-значения, параметра-переменной и параметра-константы), а затем сравнить результаты.
Функции
Выше мы уже говорили о том, что функция подобно процедуре
может восприниматься как отдельная программа. Однако резуль-
татом выполнения функции всегда будет определенное число. Это
почти единственная разница между процедурой и функцией.
Чтобы выявить соответствие и различие, ниже приводятся два
примера одного типа. В этих программах демонстрируется обычное
сложение. В одной программе используется процедура, в другой
функция.
var a : integer;
procedure sum(b,c: integer;
var k:integer);
begin
k:=b+c;
end;
var a : integer;
function sum(b,c: integer):
integer;
begin
sum:=b+c;
end;
begin
sum(12,3, a);
writeln(‘sum=’,a);
begin
a:=sum(12,3);
writeln(‘sum=’,a);
56

Обратите внимание на то, что результат процедуры присваивается переменной.
Мы вызываем процедуру с помощью выражения sum(12,3,a).
Таким образом, результат выполнения процедуры присваивается
переменной а. Описанный способ всегда используется для присвоения результата глобальной переменной (переменная a объявлена
вне процедуры).
В программе с функцией целой переменной a присваивается
результат вычисления функции sum(12,3): a:=sum(12,3).
Сравните это выражение с выражениями, где используются
стандартные функции, например, a:=sqr(2).
Мы видим, что имя функции всегда стоит справа от знака
равенства и непосредственно после имени записывается в скобках
значение аргумента функции. Слева от знака равенства стоит переменная, которой в конечном итоге присваивается значение функции.
Вам будет понятно, что с помощью выражения a:=sum(12,3) целой
переменной a присваивается сумма целочисленных значений 12 и 3.
Обратите внимание на заголовок функции.
Сходство между процедурой и функцией заключается в том, что
в обоих случаях используется блок структура, при которой могут
быть объявлены новые переменные, метки и т.д.
Различие состоит в том, что значение у функции всегда должно
рассчитываться. Тип этого значения должен объявляться в заголовке.
Кроме того, у функции, по крайней мере, 1 раз должно встречаться
имя функции, стоящее слева от оператора присваивания и выражения, вычисляющего конечное значение.
Параметр-значение
Описание
В списке параметров подпрограммы перед параметром-значением служебное слово отсутствует. Например, функция func3 имеет
три параметра-значения:
function func3(x:real; k:integer; flag:boolean):real;
При вызове подпрограммы параметру-значению может соот-
ветствовать аргумент, являющийся выражением, переменной или
константой, например:
dlina:= func3(shirina/2, min(a shl 1,ord('y')), true)+0.5;
57

Для типов данных здесь не обязательно строгое совпадение
(эквивалентность), достаточно и совместимости по присваиванию.
Механизм передачи значения
В области памяти, выделяемой для работы вызываемой
подпрограммы, создается переменная с именем <имя_подпро-
граммы>.<имя_параметра>, и в эту переменную записывается
значение переданного в соответствующий параметр аргумента.
Дальнейшие действия, производимые подпрограммой, выполняются
именно над этой новой переменной. Значение же входного аргумента
не затрагивается. Следовательно, после окончания работы подпрограммы, когда весь ее временный контекст будет уничтожен, значение аргумента останется точно таким же, каким оно было на
момент вызова подпрограммы.
В качестве примера рассмотрим последовательность действий,
выполняемых при передаче аргументов 1+а/2, а и true в описанную
выше функцию func3. Пусть а - переменная, имеющая тип byte, тогда
значение выражения 1+a/2 будет иметь тип real, а true и вовсе
является константой (неименованной).
Итак, при вызове func3(1+a/2,a,true) будут выполнены следующие действия:
1) создать временные переменные func3.x, func3.k, func3.flag;
2) вычислить значение выражения 1+а/2 и записать его в
переменную func3.x;
3) записать в переменную func3.k значение переменной а;
4) записать в переменную func3.flag значение константы true;
5) произвести действия, описанные в теле функции;
6) уничтожить все временные переменные, в том числе func3.x,
func3.k, func3.flag.
Уже видно, что значения аргументов не изменятся.
Замечание: При использовании параметров-значений в контексте подпрограммы создаются хотя и временные, но вполне
полноценные копии входных аргументов. Поэтому нежелательно
передавать в параметры-значения "большие" аргументы (например,
массивы): они будут занимать много лишней памяти.
58

Тема 11. Множества (Set)
Еще один структурированный тип данных - это множество (set).
В нем может содержаться не более 256 элементов. Важное отличие
множества от остальных структурированных типов состоит в том, что
его элементы не являются упорядоченными.
Описание множеств
В разделе var множества описываются следующим образом:
var <имя_множества>: set of <тип_элементов_множества>;
Элементы могут принадлежать к любому порядковому типу,
размер которого не превышает 1 байт (256 элементов). Например:
var s1: set of char; {множество из 256-ти элементов}
s2: set of 'a'..'z','A'..'Z'; {множество из 52-х элементов}
s3: set of 0..10; {множество из 11-ти элементов}
s4: set of boolean; {множество из 2-х элементов}
Множество-константа
Неименованная константа
Множество можно задать неименованной константой прямо в
тексте программы. Для этого необходимо заключить список
элементов создаваемого множества в квадратные скобки:
[<список_элементов>]
Список элементов может быть задан перечислением элементов нового множества через запятую, интервалом или объединением этих двух способов. Элементы и границы интервалов могут
быть переменными, константами и выражениями. Если левая грани-
ца интервала окажется больше правой, результатом будет пустое
множество.
Примеры конструирования и использования различных множеств:
Нетипизированная константа
if c in ['a','e','i','o','u']
then writeln('Гласная буква');
if set1 < [k*2+1..n,13] then set1:=[];
59

Множество - это структурированный тип данных, поэтому его
1) Пересечение двух множеств s1 и s2:
s:=s1*s2;
2) Объединение двух множеств s1 и s2:
s:=s1+s2;
3) Разность двух множеств s1 и s2 (все элементы, которые
множеству s2):
s:=s1-s2;
4) Проверка принадлежности элемента el множеству s
(результат этой операции имеет тип boolean):
el in s
5) Обозначение для пустого множества:
[]
6) Создание множества из списка элементов:
s:=[e1,_,eN];
7) Проверка двух множеств на равенство или строгое
s1 = s2
s1 < s2
невозможно задать нетипизированной константой.
Типизированная константа
Задать множество как типизированную константу можно в
разделе const:
<имя_константы>:set of <тип_элементов> =[<список_элементов>];
Например:
type cipher = set of '0'..'9';
const odds: cipher = ['1','3','5','7','9'];
vowels: set of 'a'..'z' = ['a','o','e','u','i'];
Операции с множествами
Все теоретико-множественные операции реализованы и в языке
Pascal:
принадлежат множеству s1 и одновременно не принадлежат
включение (результат этих операций имеет тип boolean):
s1 > s2
Не существует никакой процедуры, позволяющей распечатать
содержимое множества. Это приходится делать следующим образом:
{s: set of type1; k: type1}
for k:= min_type1 to max_type1
do if k in s then write(k);
Представление множеств массивами
Одно из основных неудобств при работе с множествами - это
ограничение размера всего лишь 256-ю элементами. Мы приведем
здесь два очень похожих способа представления больших множеств
массивами. Единственным условием является наличие некоторого
внутреннего порядка среди представляемых элементов: без этого
невозможно будет их перенумеровать.
60
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
