- •Программирование и алгоритмические языки
- •Основные понятия процедурного программирования. Области и процедуры
- •Способы обозначения и определения процедур
- •Языки блок-схем
- •Трассировка программы
- •Структурное программирование
- •Программы, как файловые процедуры
- •Итерационные и рекуррентные последовательности
- •Восходящее и нисходящее программирование
- •Язык программирования Pascal
- •Процедурный Паскаль Синтаксис Паскаль-программы
- •Основные операторы
- •Классификация типов Простые (скалярные) типы
- •Стандартные типы
- •Пользовательские скалярные типы данных
- •Алгоритмическое определение булевских операций
- •Стратегия вычисления условий
- •Вычисление кванторов
- •Символьный тип
- •Производные(структурные) типы Массивы
- •Операции над массивами
- •Расширенный синтаксис. Массивы размерности n.
- •Строки. Динамические массивы.
- •Комбинированные типы и записи
- •Оператор присоединения
- •Типизированные файлы.
- •Упорядоченные файлы
- •Поиск в упорядоченном файле
- •Арифметика упорядоченных файлов
- •Дихотомический поиск в упорядоченном массиве
- •Простые алгоритмы сортировки
- •Множества
- •Операции над множествами
- •Решето Эратосфена
- •Подпрограммы. Пользовательские процедуры и функции
- •Синтаксис обращения к процедурам
- •Синтаксис использования или обращения к процедурам.
- •Семантика
- •Правила построения модифицированного тела:
- •Пользовательские процедуры (продолжение)
- •Подпрограммы и функции
- •Описание функции
- •Обращение к функции
Синтаксис использования или обращения к процедурам.
Имя программы (список фактических параметров).
Список фактических параметров, разделённых запятыми, список выражений вида е1,…,еn.
Список фактических параметров, согласованных со списком формальных параметров, согласованных по количеству и типу. Вместо параметров переменных могут стоять переменные, вместо параметров значений можно поставить произвольное выражение того же типа.
Семантика
Прямая подразумеваемая математическая семантика почти тривиальна.
Для нас привычно вход и выход процедуры.
Имена переменных входа называются входными, выхода – выходными.
К паскалевским процедурам используется другое деление: изменяемые значения (имени всех выходов, которые могут быть входными) и значения (чистые входы, выходами не являющиеся).
X:=x+y;
Внутри процедуры могут использоваться вспомогательные объекты (локальные объекты). После установления типового соответствия между определениями процедур семантика обращения к процедуре ясна – это вычисление функции в заданной точке.
Это действительно так, если все результаты процедуры объявлены как var-переменные, все оставшиеся коды объявлены как параметры значения, если все остальные используемые в теле процедуры имена локальны.
Мы не обязаны это делать, что чаще всего мотивируется соображениями эффективности.
Пример. Процедура вычисления максимального среди первых элементов массива.
Type tIndex=1..100;
tVector=array [tIndex] of real;
procedure max;
a: tVector;
n: tIndex;
Var m:real;
Begin
M:=a[i];
For i:=2 to n do
If m>a[i] then m:=a[i] ;
End.
Исключение: файлы мы обязаны объявлять как параметры переменные, даже если по логике задачи это ход, то есть в теле процедуры файл не изменяется.
Как описывать «нестандартную» семантику обращения?
Max(b,10,x);
Понять семантику обращения (то, как оно работает), уметь написать вместо обращения (пользовательского имени) соответствующее ему значение.
Понятно, что этим значением будет тело процедуры, но не в точности оно, поэтому фрагмент программы, эквивалентный обращению, называется модифицированным телом процедуры.
Правила построения модифицированного тела:
Избавление от коллизии имён. При наличии коллизии заменить имена локальных переменных или других объектов с дублированными именами на новые, ещё не использованные в программе.
M:=a[i];
For i:=1 to n do
If m>a[i] then m:=a[i];
Параметры переменные заменяются на имена фактических параметров
Параметры значения вычисляются и копируются.
Пользовательские процедуры (продолжение)
Решение явно не эффективное, используется дополнительная память и тратится время на копирование, что особенно заметно в случае использования значений сложных типов (массив в динамической системе). Заметим, что понятие выражения над сложными типами скорее теоретическое, чем практическое. Возникает «соблазн» отойти от логики (т.е. чисто математического понятия процедуры как оператора), и в целях эффективности использовать особенности его (понятия) реализации. Так, в целях эффективности, можно объявить параметр сложного типа параметром переменной, даже если он по логике – вход. Второй вариант: вообще не включать это значение в список параметров (использовать как глобальное значение).
Procedure Max;
Var a: tVector; n: tIndex;
Var m: real;
max(b,10,x);
x:=b[1];
for I:=1 to n do
if x>b[I] then m:=b[I];
x:=a[1];
for I:=1 to n do
if x>a[I] then m:=b[I];
{max[10,x]}
Этот вариант еще более эффективен, хотя менее удобный – любое обращение вычислят максимум лишь одного массива А , причем неявно. Любое нестандартное использование процедур должно быть тщательно продуманно и обязательно документировано.
Пример (к чему приводят соблазны):
Задача. По заданному массиву А породить массив В , содержащий сначала все положительные, затем все неположительные элементы А.
(рисунок).
Procedure Sort(var a: tVector; var b: tVector);
Var i,k,l: tIndex;
Begin
K:=1; l:=na;
For I:=` to na do
If a[I]>0 then
L[k]:= a[I]
Else begin
B[l]:= a[I];
K:=k+1;
End;
End.
Будет ли корректным обращение sort(c,c)? Синтаксически да (c:tVector), семантически – нет. Значение в массиве С заменяются на новые раньше, чем должны быть использованы старые. Приведи пример.
Второй вариант: использование глобальных значений. Имеет ли оно математический смысл?
Глобальные значения можно понимать как мат. параметр, именованную константу.
Правило полной локализации: не использовать глобальных объектов (подразумевалось в предыдущей лекции).
Правило частичной локализации: при использовании глобальных объектов документировать и не изменять.
Изменение значений глобальных объектов в поле процедуры называется побочным эффектом.