Содержание:
Процедуры в Паскале
Подпрограмма — это фрагмент кода, который имеет свое имя и создается в случае необходимости выполнять этот код несколько (много) раз. Подпрограмма описывается единожды перед началом основной программы (до begin). Компилятор пропускает данный фрагмент кода, пока в основной программе не встретит «вызов» подпрограммы, который выглядит как обращение к ней по имени (возможно, имени с аргументами, указанными в скобках).
Во многих языках программирования подпрограммы существуют только в виде функций. Однако в Паскале подпрограмма — и функция и процедура. Разница между ними станет очевидна в данном уроке.
Итак, рассмотрим синтаксис объявления и описания процедуры в Паскале
var …;{область объявления глобальных переменных} procedure название (параметры); {начало процедуры} var …;{объявление локальных переменных} begin … {тело процедуры} end;{конец процедуры} begin … {основная программа} end.
1 2 3 4 5 6 7 8 9 10 11 | procedure pr; var i:integer; begin for i:=1 to 60 do begin {тело подпрограммы} write('*'); writeln; end; end; {конец подпрограммы} begin pr; {вызов процедуры} end. |
В данном примере работы с процедурой в Паскале очевидно, что компилятор пропустит блок описания процедуры и дойдет до основной программы (9 строка кода). И только после того, как встретится вызов процедуры (10 строка), компилятор перейдет к ее выполнению, вернувшись к строке 1.
Процедуры с параметрами. Фактические и формальные параметры
Рассмотрим пример необходимости использования процедуры.
Построить фигуру
Особенность: Три похожие фигуры.
Алгоритм решения:
- выделить одинаковые или похожие действия (три фигуры);
- найти в них общее (размеры, форма, угол поворота) и отличия (координаты, цвет);
- отличия записать в виде неизвестных переменных, они будут параметрами процедуры.
Решение на паскале:
Процедура:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | uses GraphABC; procedure Tr( x, y: integer; color:system.Drawing.Color); begin MoveTo(x, y); LineTo(x, y-60); LineTo(x+100, y); LineTo(x, y); FloodFill(x+20, y-20,color); end; begin SetPenColor(clBlack); Tr(100, 100, clBlue); Tr(200, 100, clGreen); Tr(200, 160, clRed); end. |
Рассмотрим синтаксис объявления и описания процедуры с параметрами в Паскале.
var …;{область объявления глобальных переменных} procedure pr(параметр1, параметр2: integer; параметр3:char); {начало процедуры} var …;{объявление локальных переменных} begin … {тело процедуры} end;{конец процедуры} begin … {основная программа} pr (параметр1, параметр2, параметр3); {вызов процедуры} end.
Параметры процедуры (в некоторых языках они называются аргументами) указываются в скобках после ее имени (в объявлении).
В данном примере в качестве введенного символа будем использовать параметр процедуры. Формальный параметр процедуры указывается в скобках при ее описании. Обязательно необходимо указать тип формального параметра через двоеточие.
Фактический параметр — это то значение, которое указывается в скобках при вызове процедуры. Фактическим параметром может быть конкретное значение (литерал: число, символ, строка…) либо переменная, которые компилятор подставит вместо формального параметра. Поэтому тип данных у формального и фактического параметра процедуры должен быть одинаковым.
| Pascal | PascalABC.NET | ||||
|
|
В данном примере при вызове процедуры компилятор заменит формальный параметр a фактическим параметром s, т.е. тем символом, который будет введен с клавиатуры. Оба параметра имеют тип данных char.
- число фактических параметров должно быть равно числу формальных параметров;
- соответствующие фактические и формальные параметры должны совпадать по порядку следования и по типу данных.
Процедуры с параметрами. Параметр по ссылке
(передача параметра по ссылке)
- способ:
- способ:
| Pascal | PascalABC.NET | ||||
|
|
В примере параметры a и b служат для хранения в них сравниваемых чисел, а параметр по ссылке max — для сохранения в ней максимального из двух чисел. Параметр по значению — параметр, принимаемый по значению, или выходной параметр передает свое значение в основную программу (фактическому параметру m), т.е. возвращает значение. Тогда как параметры по ссылке — параметры, принимаемые по ссылке, (входные параметры), наоборот, принимают значения из основной программы (из фактических параметров x и y). Для параметра по ссылке (max) используются те ячейки памяти, которые отведены под соответствующий параметр при вызове процедуры (ячейка m), именно поэтому такой параметр называется параметром, передаваемым по ссылке.
Таким образом, сформулируем понятия:
Если в качестве формального параметра указана обычная переменная с указанием ее типа, то такой параметр есть параметр, передаваемый по значению, или входной параметр (
aиbв примере). Тип данных формального параметра-значения должен соответствовать типу данных его фактического параметра (aиbдолжны попарно соответствовать типу данныхxиy).Если перед именем формального параметра в объявлении процедуры стоит служебное слово var, то такой параметр называется параметром, передаваемым по ссылке, или выходным параметром (
maxв примере). Для него используются те ячейки памяти, которые отведены под соответствующий параметр при вызове процедуры (m). А передача такого параметра называется передачей по ссылке (ссылка на ту же ячейку в памяти). Фактический параметр, соответствующий параметру-переменной, может быть только переменной (не константой, не литералом и не выражением).
| Pascal | PascalABC.NET | ||||
|
|
Используя данный способ решения задачи, мы обошлись без третьего параметра. Для этого в процедуре мы использовали еще одну локальную переменную c. Процедура меняет значения переменных a и b таким образом, чтобы b всегда была максимальной. Поэтому в 15 строке программы в качестве максимальной выводится второй параметр (y), соответствующий формальному параметру b.
- Необходимо определить наибольший общий делитель двух введенных чисел, используя цикл.
- Необходимо определить наибольший общий делитель двух введенных чисел, используя процедуру (два параметра по значению, один параметр по ссылке).
- Вводятся a и b (например, 18 и 24)
- В цикле повторяем действия:
- Если а < b, то меняем переменные местами (1 шаг: a=24, b=18; 2 шаг: a=18, b=6)
- Переменной a присваиваем остаток от деления a на b (1 шаг: a=6, b=18; 2 шаг: a=0, b=6)
- Когда остаток равен 0, выводится результат (значения переменной b) (b=6)
Алгоритм решения поиска НОД:
| числа | a и b | остаток | результат | |
| 1 | a=18, b=24 24>18 |
если b>a → swap(a,b) a=24, b=18 |
24/18 = 1(6) | a=6, b=18 |
| 2 | a=6, b=18 18>6 |
если b>a → swap(a,b) a=18, b=6 |
18/6 =3(0) | a=0, b=6 6 |
| 128 и 56 | ||||
| 1 | a=128,b=56 a>b |
нет a=128,b=56 |
128/56=2(16) | a=16,b=56 |
| 2 | a=16,b=56 b>a |
если b>a → swap(a,b) a=56, b=16 |
56/16=3(8) | a=8,b=16 |
| 3 | a=8,b=16 b>a |
если b>a → swap(a,b) a=16,b=8 |
16/8=2(0) | a=0, b=8 8 |
Для формирования элементов массива и подсчета суммы и среднего арифметического использовать одну процедуру (среднее арифметическое и сумму оформить как параметры-переменные).
В задачах на Паскале часто встречается необходимость заполнить массив данными и затем вывести значения на экран. Почему бы не автоматизировать данную задачу заполнения и вывода массива — т.е. оформить при помощи процедур, а в дальнейшем использовать данные процедуры при надобности.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const n = 10; var i:integer; a, b: array[1..n] of integer; procedure arr_out (k:integer; arr: array[1..n] of integer); var i: byte; begin write ('вывод массива: '); for i := 1 to k do write (arr[i]:4); writeln; end; begin for i:=1 to n do a[i]:=random(10); arr_out (n, a); end. |
Пояснение:
Тело основной программы:
— формирование элементов массива (с функцией random).
— вызов процедуры с двумя параметрами: количество элементов, массив.
Тело процедуры:
— вывод элементов массива с использованием параметров
Продолжим нашу задачу:
random 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const n = 10; var a, b: array[1..n] of integer; procedure arr_rand (k:integer; var arr: array[1..n] of integer); var i: byte; begin write ('Заполнение массива случайными числами '); randomize; for i := 1 to k do arr[i]:=random(100); end; begin arr_rand (n, a); end. |
Передача аргументов по значению и по ссылке
-
Рассмотрим более подробно два этих понятия:
- Передача по значению: Значение фактического параметра копируется в соответствующий формальный параметр. Изменение формального параметра не ведет к изменению фактического параметра
- Передача по ссылке: Оба параметра и формальный и фактический ссылаются на одно и то же расположение в памяти, поэтому все изменения в теле процедуры отражаются и на фактическом параметре.
- Изменение формального параметра изменяет и фактический параметр тоже:
1 2 3 4 5 6 7 8 9 10 | procedure p(a: integer); begin a := 666; // изменяется только формальный параметр! end; begin var x := 555; p(x); Print(x); // 555 end. |
1 2 3 4 5 6 7 8 9 10 | procedure p(var a: integer); begin a := 666; end; begin var x := 555; p(x); Print(x); // 666 – фактический параметр изменился тоже! end. |
Если тело процедуры состоит только из одного оператора, PascalABC.NET позволяет использовать при описании сокращенный синтаксис, без ключевых слов begin и end:
1 2 3 4 5 6 | ## procedure SqrtX(x: real) := print(sqrt(x)); // основная программа begin SqrtX(9); //3 end; |
Самостоятельная работа
Общее задание 2: Описать процедуру Mean(X, Y, AMean, GMean), вычисляющую:
- среднее арифметическое
AMean = (X+Y)/2 - и среднее геометрическое
GMean = √X*Yдвух положительных вещественных чиселXиY.
X и Y — входные параметры, AMean и GMean — выходные параметры вещественного типа.
В основной программе: Для заданных A, B, C, D найти среднее арифметическое и среднее геометрическое для пар (A, B), (A, C), (A, D), используя созданную процедуру.
1 вариант: для 5 одномерных массивов определять произведение элементов каждого массива, используя процедуру с двумя параметрами — число элементов массива и параметр по ссылке — для вывода произведения.
2 вариант: для 5 одномерных массивов определять минимальный элемент каждого массива, используя процедуру с двумя параметрами — число элементов массива и параметр по ссылке — для вывода минимального элемента.
* сложное С помощью процедуры формировать случайным образом одномерные массивы из 10 элементов (значения от -20 до +20). Вызывать процедуру до тех пор, пока среди значений не появится ноль.




const
n = 10;
var
i:integer;
a, b: array[1..n] of integer;
procedure arr_out (k:integer; arr: array[1..n] of integer);
var i: byte;
begin
write (‘вывод массива: ‘);
for i := 1 to k do
write (arr[i]:4);
writeln;
end;
begin
for i:=1 to n do
a[i]:=random(10);
arr_out (n, a);
end.
На этот код, программа пишет: «Тип параметра или возвращаемого значения не может быть описанием записи или описанием массива с границами»
Да, массив передавать в процедуру параметром только через новый тип данных нужно:
const
n = 10;
type arrInt=array[1..n] of integer;
var
i:integer;
a: arrInt;
procedure arr_out (k:integer; arr: arrInt);
var i: byte;
begin
write (‘вывод массива: ‘);
for i := 1 to k do
write (arr[i]:4);
writeln;
end;
begin
for i:=1 to n do
a[i]:=random(10);
arr_out (n, a);
end.
Подскажите как реализовать данную программу в Паскаль?
program podschet_chisel_1;
var n, k1, k2: integer;
begin
k1:=0;
k2:=0;
repeat
write (‘Введите целое число>>’);
readln (n);
if n>0 then k1:=k1+1;
if n<0 then k2:=k2+1;
until n=0;
writeln (‘Введено:’) ;
writeln (‘положительных чисел — ‘, k1);
writeln (‘отрицательных чисел — ‘, k2)
end.
Что мы пишем в результате?
Спасибо