logo
2012_METODICh_POSOBIE_PASCAL

Лабораторная работа № 10. Использование процедур и функций при обработке массивов.

При выполнении работы необходимо знать:

Теоретический минимум:

При разработке программ можно использовать стандартные, т. е. предоставляемые Turbo Pascal функции. Turbo Pascal позволяет программисту объявить свою собственную функцию и в дальнейшем использовать ее точно так же, как и стандартные функции. Например, можно определить (объявить) функцию вычисления факториала, назвав ее factor. Затем в том месте программы, где нужно вычислить факториал, вместо последовательности инструкции, вычисляющих факториал, написать у:=factor(х);

Объявление функции. Объявление функции в общем виде выглядит так:

Function Имя (параметр1: тип1,… параметрК: типК):Тип;

Var

{здесь объявление внутренних переменных функции}

begin

{здесь инструкции функции}

Имя:=Выражение;

end;

где function – зарезервированное слово языка Turbo Pascal, обозначающее, что далее следуют инструкции, реализующие функцию программиста; Имя – имя функции. Используется для перехода к инструкциям функции ( между begin и end ) из программы, которая вызывает (использует) функцию; параметр – это переменная, значение которой используется для вычисления значения функции.

Отличие параметра от обычной переменной программы состоит в том, что он объявляется не в разделе переменных функции, который начинается словом Var, а в заголовке функции. Конкретное значение параметр получает при вызове функции из основной программы; тип – тип значения, которое функция возвращает в вызвавшую ее программу.

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

В качестве примера приведено объявление функции factor, которая вычисляет факториал числа, полученного в качестве параметра.

Функция программиста для вычисления факториала

Function Factor (n: integer): integer;

var

f: integer {факториал числа n }

i: integer;

begin

f:=1;

for i:=2 to n do

f:=f*i;

Factor:=f;

end;

У функции Factor один параметр – переменная n типа integer. Параметр задает число, факториал которого надо вычислить. Конкретное значение n получит при вызове функции. Возвращает функция вычисленное значение факториала – число типа integer.

Другой пример: в Turbo Pascal нет стандартной функции вычисления кубического корня. Приведем ее возможное определение.

Функция программиста для вычисления кубического корня

function Cub (x:real): real;

var

pr :real; {приближенное значение кубического корня}

begin

pr:=sqrt(x); {первое приближение}

{ в качестве второго приближения выбираем (x:pr):pr }

while abs (pr-x/(pr*pr))>0.001 do

begin

{ новое приближение – среднее арифметическое }

{ удвоенного приближения на прошлом шаге и текущего }

pr:=(2*pr+x/(pr*pr))/3;

end;

Cub:=pr;

end;

Функция Cub реализует алгоритм “ручного” метода приближенного вычисления кубического корня, при котором в качестве первого приближения,”на глаз“, выбирается наиболее подходящее число (в программе – это значение квадратного корня числа, кубический корень которого надо вычислить). Затем число, из которого надо извлечь корень, делится на выбранное приближение, и полученное таким образом значение еще раз делится на выбранное приближение. Если полученное число отличается от выбранного приближения на величину, не большую, чем допустимое значение погрешности, то выбранное приближение принимается за значение корня. Если погрешность превышает допустимое значение, то вычисляется новое приближение как среднее арифметическое удвоенного предыдущего приближения, и процесс вычисления повторяется.

Использование функции.

Если вы собираетесь использовать в программе свою функцию, то в простейшем случае объявление функции следует поместить в текст программы, перед разделом инструкций (обычно объявление функции помещают после раздела Var – раздела объявления).

Инструкции функции будут выполнены, если в одном из выражений программы в качестве операнда будет указано имя этой функции (переход от инструкции основной процедуры программы к инструкциям функции называется вызовом функции или обращением к функции). Если в объявлении функции указаны параметры, то после инструкции вызова функции, которая представляет собой имя функции, в скобках должны быть указаны фактические параметры. Причем количество и тип параметров, задаваемых при вызове функции, должны соответствовать количеству и типу параметров, указанных в заголовке объявления функции. Параметры, задаваемые при обращении к функции, называются фактическими. В качестве фактических параметров обычно используют константы или переменные, реже – выражения.

Следующая программа использует определенную программистом функцию Nod для вычисления наибольшего общего делителя (НОД) двух целых положительных чисел. У функции Nod два параметра – числа, НОД которых надо вычислить. Возвращает функция наибольший общий делитель – значение типа integer. В основе вычисления НОД лежит алгоритм Евклида.

Пример использования функции программиста

program p;

var

c1,c2: integer; {числа НОД которых надо найти }

nd; integer; {наибольший общий делитель}

(функция программиста)

function Nod (a: integer; b: integer;): integer;

var

r: integer; {остаток от деления числа a на b}

begin

while (a mod b)<>0 do

begin

r:= a mod b; {остаток от деления}

a:=b;

b:=r;

end;

nod:=b;

end;

{основная программа}

begin

writeln (‘Вычисление наибольшего общего делителя (НОД)’)

Write (‘Введите в одной строке два целых положительных числа через пробел’);

Readln (c1, c2);

nd:=Nod (c1, c2);

Writeln(‘НОД чисел ’, c1, ’ и ’, c2,’ это ’,nd);

end;

Процедуры.

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

В Turbo Pascal процедурой называется имеющая имя последовательность инструкций, предназначенная для решения определенной задачи.

Основная программа и определенная программистом процедура взаимодействуют следующим образом (рис. 10). Если во время работы основной программы встречается инструкция вызова процедуры, то выполнение инструкции основной программы приостанавливается и выполняются инструкции процедуры. После того, как будут выполнены все инструкции процедуры, продолжается выполнение основной программы с той инструкции, которая следует за инструкцией вызова процедуры.

Рис.10. Взаимодействие основной программы и процедуры программиста

Объявление процедуры. В общем виде объявление процедуры программиста выглядит так:

procedure Имя (var параметр1:тип1;var параметр1:тип1;…; var параметрК:типК; )

var

{здесь объявление внутренних переменных процедуры}

begin

{здесь инструкция процедуры}

end;

где procedure – зарезервированное слово языка Pascal, обозначающее, что далее следует объявление процедуры программиста; Имя – имя процедуры, используется для вызова инструкций, находящихся между begin и end, реализующих процедуру; параметр1 – переменная, которая используется в инструкциях процедуры. Параметры используются для передачи в процедуру информации, а так же для передачи информации из процедуры в вызвавшую ее программу.

Указанные в объявлении процедуры параметры являются формальными параметрами. Слово var стоящее перед именем параметра, не является обязательным. Однако если оно стоит, то это означает, что при вызове процедуры параметром должна быть переменная основной программы, при этом изменение параметра внутри процедуры приведет к изменению значения переменной основной программы, указанной в качестве фактического параметра при вызове процедуры.

Ниже приведено объявление процедуры Line, которая выводит на экран строку символов. У процедуры два параметра: первый (n) задает длину выводимой строки (количество символов), второй (с) – символ, которым рисуется строка.

procedure Line (n:integer;c:char);

var

i:integer;

begin

for i:=1 to n do Write(c);

Writeln;

end;

Использование процедуры.

Инструкция вызова процедуры в общем виде выглядит так:

Имя {Список Параметров};

где Имя – имя вызываемой процедуры; Список Параметров – разделенные запятыми фактические параметры, в качестве которых, в зависимости от описания параметров в объявлении процедуры, могут быть использованы константа, переменная или выражение. Например, инструкции вызова приведенной выше процедуры Line могут быть такими:

Line (30,’-‘); Line (n+2,’*‘); Line (n,ch);

Следующая программа выводит таблицу квадратных корней. Для оформления таблицы используется процедура программиста Line.

Пример использования процедуры программиста

program Tabsqrt;

var

i: integer;

procedure Line (n:integer;c:char); {процедура программиста}

var

i: integer;

begin

for i:=1 to n do write(c);

Writeln;

end;

begin {основная программа}

Writeln(‘Таблица квадратных корней’);

Line (14,’=‘);

Writeln (‘число корень’);

Line (14,’=‘);

for i:=1 to 5 do begin

Writeln (i:5, ’ ‘,Sqrt(i):6:3);

Line (14,’-‘);

end;

end.

Ниже приведен результат работы программы:

Таблица квадратных корней

==============

число корень

==============

1 1,000

------------------------

2 1,414

------------------------

3 1,732

------------------------

4 2,000

-----------------------

5 2,236

----------------------

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

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

Параметр-переменная и параметр-значение.

Программист имеет дело с параметрами при описании и при использовании процедур и функций. Различают формальные и фактические параметры.

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

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

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

В следующей программе для вычисления площади круга и длинны окружности по значению радиуса используется процедура программиста SqLeOkr.

Пример использования процедуры программиста

program sqring;

var

{переменные основной процедуры}

r,l,s:real; {радиус, длинна окружности и площадь круга}

{процедура программиста}

procedure SqLeOkr (r:real; var s:real; var l:real);

{r - радиус,s - площадь круга, l - длинна окружности }

const

pi=3.14159;

begin

s:=pi*r*r;

l:=2*pi*r;

end;

{основная процедура}

begin

Writeln (‘Вычисление длинны окружности и площади круга:’);

Write (‘Задайте радиус и нажмите <Enter>’);

Readln (‘r’);

l:=0; s:=0;

SqLeOkr (r,s,l);

{переменные программы – фактические параметры процедуры}

Writeln (‘Радиус окружности:’,r:6:3’);

Writeln (‘Длина: ’, l:6:3, ’ Площадь: ‘, s:7:3);

end.

Локальные и глобальные переменные.

Программа на языке Pascal состоит из основной программы и, возможно, процедур и функций программиста. Каждая из них содержит раздел объявления переменных. Переменные, объявленные в основной программе, доступны всем инструкциям программы, в том числе и инструкциям процедур и функций программиста. Такие переменные называются глобальными.

Переменные, объявленные в процедуре или функции программиста, называются локальными. Локальные переменные доступны только инструкциям той программы (процедуры или функции), в которой они объединены.

program p;

var

x: integer; {глобальная переменная}

procedure p1;

var

y: integer; {локальная переменная}

begin

{здесь можно использовать переменные x и y}

end;

begin

{здесь можно использовать только переменную x}

{попытка использовать y приведет к сообщению об ошибке}

end.

В приведенном примере в процедуре p1 можно использовать переменную у, так как она объявлена в процедуре, и переменную х, так как она объявлена в основной программе и является по отношению к процедуре p1 глобальной переменной. В основной программе можно использовать переменную х. Переменная у в основной программе недоступна, так как она локальная.

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

program p;

var

i:integer;

procedure proc;

var

i:integer;

begin

i:=100;

end;

begin

i:=1;

proc;

writeln(i);

end.

на экран будет выведено число 1, так как процедура proc изменяет только значение локальной переменной i, которое после завершения процедуры уничтожается.

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

program p;

var

name:string[10]; {переменная основной программы}

procedure GetName;

begin

Write(‘Ваше имя’);

Readln(name);

end;

begin {инструкции основной программы}

GetName

Writeln(name);

end.

В результате выполнения приведенной программы на экран будет выведена введенная с клавиатуры строка, так как процедура GetName меняет значение глобальной переменной.

Процедура или функция?

Процедура и функция – это два способа оформления программы или фрагмента программы, предназначенного для решения общей части задачи. Одну и ту же программу можно оформить как процедуру или функцию.

procedure SoprPar (r1,r2,r3:real; var sr:real);

begin

sr:=(r1+r2+r3)/(r1*r2*r3);

end;

function SoprPar (r1,r2,r3:real ):real;

var

sr:real;

begin

sr:=(r1+r2+r3)/(r1*r2*r3);

SoprPar:=sr;

end;

Очевидно, что оформление подпрограммы в виде функции в данном случае более предпочтительно, так как целью вычисления является получение только одного значения. Кроме того, инструкция вычисления сопротивления цепи sr:= SoprPar (r1,r2,r3); выглядит более естественно по сравнению с инструкцией вызова процедуры SoprPar (r1,r2,r3, sr);.

Возникает вопрос, каким критерием пользоваться при выборе способа оформления подпрограммы?

Ответ можно сформулировать в виде следующего правила:

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

Задача 10.

Заданы три одномерных числовых массива одинаковой размерности. Определить количество положительных элементов в каждом массиве. В том из них, где это количество окажется больше всего, подкрасить зеленым цветом положительные элементы.

Решение:

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

Алгоритм основной программы к задаче 10:

Текст программы к задаче 10.

Program Ex_10;

Uses Crt;

Type Mas=Array[1..15] of integer;

Var A, B, C:Mas;

i, j: integer;

Procedure Vvod (Var y:Mas);

Begin

For i:=1 to 15 do

Y[i]:=random(101)-50;

End;

Procedure Vivod (Var Y: Mas);

Begin

For i:=1 to 15 do begin

Write(Y[i]:4);

End;

Writeln;

End;

Function Kol (Var Y: Mas): integer;

Var k:integer;

Begin

k:=0;

For i:=1 to 15 do

If Y[i]>0 then k:=k+1;

Kol:=k;

End;

Procedure Okras (Var Y: Mas);

Begin

For i:=1 to 15 do begin

If Y[i]>0 then TextColor(2)

else TextColor(7);

Write(Y[i]:4);

End;

End;

Begin

ClrScr;

Randomize;

Vvod(A); Vvod(B); Vvod(C);

Vivod(A); Vivod(B); Vivod(C);

k1:=Kol(A);

k2:=Kol(B);

k3:=Kol(C);

Writeln (‘k1=’,k1,’ k2=’,k2,’ k3=’,k3);

if (k1>k2) and (k1>k3) then Okras(A);

if (k2>k1) and (k2>k3) then Okras(B);

if (k3>k1) and (k3>k2) then Okras(C);

Readln;

End.