Конспект урока "Процедуры и функции" 11 класс

1
Урок 18 Процедуры и функции
Цель: дать учащимся представление о подпрограммах и возможностях их
использования. Показать на примерах механизм реализации подпрограмм с
помощью процедур
ПЛАН
I. Повторение материала.
П. Изучение нового материала.
III. Итог урока.
VI. Домашнее задание.
Ход урока
Повторение материала.
1. Какова структура программы?
2. Обязателен ли заголовок программы?
3. Какие разделы описаний вы знаете?
4. С чего начинается раздел констант?
5. Как описать переменные?
6. С чего начинается основная часть программы? Как ее закончить?
II. Изучение нового материала.
При создании программы для решения сложной задачи программисты
выполняют разделение этой задачи на подзадачи, подзадачи - на еще
меньшие подзадачи и так далее, до легко программируемых элементарных
задач. Со временем у каждого программиста через некоторое время
появляется большой набор собственных заготовок, неординарных решений и
т. д., которые он хотел бы использовать во всех своих творениях.
Язык программирования Turbo Pascal позволяет разделять программу на
отдельные части, которые называются подпрограммами. Сам термин
подпрограмма говорит о том, что она подобна и подчинена основной
программе. Подпрограммы решают три важные задачи, значительно
облегчающие программирование:
- избавляют от необходимости многократно повторять в тексте
2
программы аналогичные фрагменты, т. е. сократить объем программы;
- улучшают структуру программы, облегчая понимание при разборе;
. - уменьшают вероятность появления ошибок, повышают устойчивость к
ошибкам программирования и непредвиденным последствиям при
модификации.
Таким образом, подпрограмма - это повторяющаяся группа операторов,
оформленная в виде самостоятельной программной единицы. Она
записывается однократно, а в соответствующих местах программы
обеспечивается лишь обращение к ней по имени.
Сформулируем общие принципы выделения подпрограмм:
- если вы в программе вынуждены переписывать одни и те же
последовательности команд, то стоит эту последовательность команд
оформить в виде подпрограммы;
- иногда слишком много мелочей закрывают главное. Стоит перенести в
подпрограмму подробности, заслоняющие основной смысл программы;
- слишком длинную программу полезно разбить на составные части -
подобно тому, как книгу разбивают на главы. При этом основная программа
становится похожей на оглавление;
- при решении задачи могут возникать слишком сложные подзадачи.
Целесообразней отладить их отдельно в небольших программах. Добавление
этих программ в основную задачу будет легким, если они оформлены как
подпрограммы;
- все, что вы сделали хорошо в одной программе, вам захочется
перенести в новые программы. Для повторного использования
частей кода лучше сразу выделять в программе полезные вам подзадачи в
виде отдельных подпрограмм.
Подпрограммы могут быть стандартными, определенными сисемой Turbo
Pascal, и собственными, т. е. созданными отдельным пользователем.
В Turbo Pascalе механизм подпрограмм реализуется в виде ПРОЦЕДУР и
ФУНКЦИЙ, которые вводятся в программу с помощью своего описания, но
3
их структура такая же, как и структура программы. Они различаются
назначением и способом их использования.
Описание процедуры.
Оператор процедуры.
Процедуры предназначены для выполнения некоторой последовательности
действий. Любая процедура начинается с заголовка, который является ее
обязательной частью (в отличие от заголовка программы). Он состоит из
служебного слова Procedure , за которым следует имя процедуры, а в круглых
скобках - список формальных параметров. После заголовка могут идти те же
разделы, что и в программе.
Таким образом, общий вид будет
следующим:
Procedure<uмя>(формальные параметры);
Список формальных параметров может отсутствовать.
Объявление переменных
описательная часть
begin
тело процедуры
end.
Результат выполнения процедуры - это одно или несколько значений. Оно
(или они) передается в основную программу как значение ее параметра. При
вызове процедуры ее формальные параметры заменяются фактическими в
порядке их следования.
Фактические параметры - это параметры, которые передаются процедуре при
обращении к ней.
Внимание: число и тип формальных и фактических параметров должны
совпадать с точностью до их следования.
Формальные параметры - это переменные, фиктивно присутствующие в
процедуре и определяющие тип и место подстановки фактических
параметров, над которыми производятся действия.
4
Все формальные параметры делятся на два вида: параметры-переменные и
параметры-значения.
Параметры-переменные в Turbo Pascal 7.0 — это те формальные параметры,
перед которыми стоит служебное слово Var. Они передаются по ссылке
(передается адрес фактического параметра) тогда, когда необходимо
передать некоторые новые значения в точку вызова процедуры из
программы, то есть когда нужно, чтобы изменения в теле процедуры
значений формальных параметров приводило к изменению соответствующих
фактических параметров, таким образом они и получают новое значение.
Параметры-значения — перед ними слово var не ставится, и идет передача по
значению, то есть передается.- только копия значения этих параметров,
внутри процедуры можно производить любые действия с данными
формальными параметрами (допустимые для его типа), но их любые
изменения никак не отражаются на значениях соответствующих
фактических параметров, то есть какими они были до вызова процедуры,
то такими же и останутся после завершения ее работы.
Областью действия переменной (идентификатора) называется часть
программы, где она может быть использована. Область действия переменных
определяется местом их объявления. В программе все переменные делятся на
глобальные и локальные. Глобальные переменные - это те переменные,
которые объявлены в описании основной части, и их могут использовать
любые процедуры и функции данной программы. Переменные, описанные
внутри подпрограммы, называются локальными и могут быть использованы
только внутри данной подпрограммы. Локальные переменные могут быть
описаны как в заголовке программы, так и в разделе описания переменных.
При совпадении имен глобальных и локальных переменных, локальные
определения в пределах своего действия отменяют действия локальных, и эти
переменные никак не связаны между собой.
Возникает вопрос, какова роль локальных переменных, нельзя ли все
переменные описать как глобальные? Подпрограмма должна быть, по
5
возможности, независима от основной программы, поэтому все переменные,
нужные только в пределах подпрограммы, должны описываться как
локальные. Общение основной программы с подпрограммой должно, как
правило, идти через список параметров подпрограммы, что придает ей
необходимую гибкость.
Локальность или глобальность - понятия относительные. Программа с
вложенными в нее подпрограммами представляет собой иерархическое
дерево. Объект, локальный по отношению к более высокому уровню
иерархии, ведет себя как глобальный по отношению к объектам более
низкого уровня.
Программу можно изобразить в виде блоков (подпрограмм), каждый блок -
это дом с зеркальными стеклами в окнах. Изнутри через них видно все, что
находится снаружи, внутрь заглянуть нельзя.
Пример 1.
Составить процедуру сложения двух чисел, вводимых с клавиатуры.
uses crt;
var a,b,s:real;
procedure summa (x,y:real;var
s:real);
begin
s:=x+y;
writeln('s=',s:3;l,'\a:3:l,'
',b:3:l);
end;
begin
clrscr;
writeln('a=b=') ;readln(a,b);
summa(a,b,s);
writeln('s=',s:3:l,' a:3:l,'\b:3:l);
readln;
6
end.
Обратите внимание на значения А и В в процедурах и в основной программе.
Объясните различие.
Вызов подпрограммы происходит при каждом употреблении ее имени в
основной программе. При вызове подпрограммы начинают выполняться
команды, заданные в ней. Подпрограмма завершается, если выполнены все ее
процедуры до завершающего слова End или по специальной команде выхода
из подпрограммы Exit. После выхода из подпрограммы основная программа
возвращается к командам, следующим за обращением к этой подпрограмме.
Процедура вызывается как оператор, состоящий из имени процедуры. В
круглых скобках передаются фактические параметры. В нашем примере
фактические параметры а, в и s передают свои значения соответственно
формальным параметрам X,Y,S . После завершения работы процедуры
переменные А и В имеют те же значения, что и при вызове, a S получает
новое значение.
Передача параметров является очень важной для процедур и функций. Это
процесс, благодаря которому передается информация.
Пусть а=3 и в=4. Когда в программе встречается оператор summa((a), (b),S)
или summa (a,b,s), то ЭВМ выполняет следующие действия:
- выделяет память для переменных, описанных в процедуре;
- присваивает формальным параметрам значения фактических: х:=а (х=3),
у:=в (у=4), s:=s;
- выполняет операторы процедуры, то есть найдет сумму;
- полученное значение присвоит переменной S, а переменные А и В остаются
прежними, после этого переходит к выполнению следующих действий
программы в точке вызова, то есть выполняется следующий оператор,
стоящий за обращением процедуры.
Пример 2.
Составить процедуру нахождения максимального из четырех
7
действительных чисел, вводимых с клавиатуры. Используйте процедуру для
нахождения максимального значения для двух чисел.
uses crt;
var a,b,s,c,d:real;
procedure maxim (x,y:real;var s.real);
begin
if x<y then s:=y else s:=x;
end;
begin
clrscr;
writeln('a=b=') ;readln(a,b);
writeln('c-d=') ;readln(c,d);
В переменную S заносим большее из двух чисел А и В.
maxim(a,b,s);
В переменную S заносим большее из двух чисел С и S.
maxim(c,s,s);
В переменную S заносим большее из двух чисел D и S.
maxim(d,s,s);}
writeln('max=',s:3:l);
readln;
end.
Для нахождения максимального значения для четырех чисел добавим
следующие строки. Они выделены в предыдущей программе жирным
шрифтом
Пример 3.
Составить программу, которая будет находить а
ь
, то есть в-ю степень числа
А, где А и В- это целые числа и В>0, вводимые с клавиатуры.
uses crt;
var a, b:integer;
s:longint;
8
procedure stepen (x,у: integer;var
s:Longint);
var i: integer;
begin
s:=l;
for i:=l to y do
s:=s*x;
end;
begin
clrscr;
writeln('a=b=') ;readln(a, b);
Вызов процедуры
нахождения степени числа
A.
stepen(a,b,s);
writeln('s=',s);
readln;
end.
Описание функции.
Функции предназначены для того, чтобы вычислять только одно значение,
поэтому ее первое отличие состоит в том, что процедура может иметь новые
значения у нескольких параметров, а функция только одно (оно и будет ее
результатом).
Второе отличие заключается в заголовке функции. Он состоит из слова
Function, за которым идет имя функции, затем в круглых скобках идет список
формальных параметров, после чего через двоеточие записывается тип
результата функции. Остальное как в процедуре. Кроме того:
В теле функции обязательно должен быть хотя бы один оператор
присвоения, где в левой части стоит имя функции, а в правой -ее значение.
Иначе значение не будет определено.
Таким образом, общий вид такой:
Function <имя>
9
(<список форм. параметров>):
<тип результата> ;
Эта часть заголовка может отсутствовать.
Описательная часть.
begin
Тело функции.
мя>: =<значение>;
end.
Пример 2.
Написать функцию, подсчитывающую количество цифр целого числа.
Используя ее, определить, в каком из двух данных чисел больше цифр.
Для решения задачи вспомним, как подсчитать количество цифр?
Для этого можно выделять последнюю цифру до тех пор, пока число не
станет равным нулю. При этом каждый раз надо увеличивать счетчик на 1
(начальное значение счетчика - 0). Тогда можно описать такую функцию:
function zifr (x.longint):integer;
var k: integer;
begin
k:=0;
while x<>0 do
begin
к:=к+1;
x:=x div 10
end;
zifr: =k;
end.
В заголовке функции указано ее имя - Zifr. Ей передается только один
параметр - число, количество цифр которого надо найти. Результат - тоже
целое число. В разделе переменных описана переменная к - это счетчик
цифр. В теле функции с помощью цикла While и выполняются указанные
10
выше действия (увеличение значения счетчика и "удаление" последней
цифры).
Еще раз заметим, что память для переменной к, которая является локальной,
выделяется только тогда, когда начинает свою работу функция. После
завершения ее работы эта часть памяти снова освобождается и значение к
будет не определено.
uses crt;
var nl,n2:longint;
kl,k2:byte;
function zifr (x.longint):integer;
var k.integer;
begin
k:=0;
while x<>0 do begin
inc(k);
x:=x div 10;
end;
zifr:=k;
end;
begin
clrscr;
writeln('nl=n2=');readln(nl,n2);
kl:= zifr(nl);
k2:= zifr(n2);
ifkl =k2 then writeln ('Одинаково') else ifkl>k2 then writeln(' nl>n2')
else writeln(' n2>nl');
readln;
end.
Урок 19. Рекурсия
Цель: дать учащимся представление о рекурсии и возможностях ее
11
использования.
ПЛАН
1. Проверка домашнего задания.
2. Изучение нового материала.
3. Итог урока. Домашнее задание.
Ход у р о к а
I. Проверка домашнего задания.
1. Как описывается функция?
2. Каковы отличия функции от процедуры?
3. Чем отличаются друг от друга формальные и фактические параметры?
4. Что такое область действия переменной?
5. Чем отличаются друг от друга глобальные и локальные параметры?
П. Изучение нового материала.
Подпрограммы в Turbo Pascal и могут обращаться к самим себе. Такое
обращение называется рекурсией. Объект, который частично определяется
через самого себя, называется - рекурсивным. Рекурсивные определения как
мощный аналитический аппарат используются во многих областях науки,
особенно в математике. Для того, чтобы не было бесконечного обращения
подпрограммы к самой себе, требуется наличие некоторого условия (ус-
ловного оператора) в тексте программы, по достижении которого дальнейшее
обращение не происходит. Таким образом, рекурсивное программирование
может включаться только в одну из ветвей условного оператора,
присутствующего в подпрограмме.
Некоторые задачи являются рекурсивными по своему определению, поэтому
рекурсивные алгоритмы - это точные копии с соответствующего
определения.
Пример 1.
Вычисление факториала натурального числа.
Как правило, N! факториал определяют как произведение первых N чисел:
N1=1 -2-3- ... N, (так называемое итеративное определение). Такое
12
произведение, конечно, можно легко вычислить с помощью оператора цикла,
однако существует и другое определение факториала (рекурсивное):
Для того, чтобы вычислить N!, надо знать значение (N-1)! и умножить его на
N, при этом 1!=1.
Для вычисления факториала опишем функцию, которая будет вычислять его
значение. Ей будет передаваться целое число, поэтому у нее есть только один
параметр. Результат выполнения -тоже целое число. Например, можно
описать такую функцию:
Function factorial (n: integer): longin t;
begin
if n=l then factorial: =1
else factorial: =n*factorial (n-l);
end.
Найдем 3!. Как же будет вычисляться факториал этого числа? Первый вызов
этой функции будет из основной программы (Например, а:= factorial(3)), где
переменной а присваиваем значение 3!). Надо заметить, что при каждом
обращении к функции будет появляться свой набор локальных переменных
со своими значениями, в данном случае - переменная n, для которых выделя-
ется память. А после завершения работы эта часть памяти освобождается и
переменные удаляются.
Так как N<>1, то пойдем по ветке Else и функции Factorial присваиваем
значение n*Factorial(n-l), то есть надо умножить 3 на значение функции
Factorial(2). Поэтому обращаемся второй раз к этой же функции, но передаем
ее новое значение параметра -2. Так делаем до тех пор, пока не передадим
значение, равное 1. Тогда N=1, а поэтому значение функции Factorials 1.
Таким образом, N=1 - это условие, по которому процесс входа в следующую
рекурсию заканчивается. Идет возвращение в точку вызова и подстановка в
оператор присвоения значения вычисленной функции. То есть возвращаемся
в предыдущую функцию для п=2: Factorial:=n*Factorial(n-l), значит,
Factorial:=2*l, следовательно, Factorial(2)=2. И возвращаемся дальше n=3:
13
Factorials n*Factorial(n-l), значит, Factorial—3*2*1, следовательно,
Factorial(3)=6.. Таким образом, получаем значение Factorial(3)=6, это
значение и присвоим переменной а.
uses crt;
var п: integer; a.longint;
function factorial (n: integer): longint;
begin
if n=l then factorial :=1
else factorial :=n*factorial (n-'l);
end;
begin
clrscr;
writeln('n=');readln(n);
a:=factorial (n);
writeln('a=',a);
readln;
end.
Пример 2.
Нахождение НОД (наибольшего общего делителя) двух натуральных чисел.
Решение.
Есть несколько способов нахождения этого значения. Одним из них является
алгоритм Евклида. Рассмотрим еще один из вариантов его реализации.
Пусть есть два целых числа а и Ь.
Если а=Ь, то НОД(а,Ь)=а.
Если а>Ь, то НОД(а,Ь)=НОД(а-Ь,Ь).
Если а<Ь, то НОД(а,Ь)=НОД(а,Ь-а).
Рассмотрим на примере. Найдем наибольший общий делитель чисел 22 и 16.
а
Б
22
16
6
16
6
10
6
4
14
2
4
2
2
Таким образом, можно составить следующую функцию и программу:
uses crt;
var a,b:longint;
function nod (a,b:longint):longint;
begin
if a=b then nod: =a else if a>b then nod:=nod(a - b,b)
else nod:=nod(a,b- a)
end;
begin
clrscr;
writeln('a-b=') ;
readln(a, b);
a:=nod(a,b);
writeln('nod= \a);
readln;
end.
Пример 3.
Перевод натурального числа из десятичной системы счисления в двоичную.
Для решения этой задачи рассмотрим сначала, как перевести число из
десятичной системы счисления в двоичную. Пусть есть число 39, которое и
надо представить в двоичной системе. Для этого разделим его на 2, получим
целую часть и остаток от деления. Целую часть снова делим на 2 и получаем
целую часть и остаток. Так делаем до тех пор, пока целую часть можно
делить на 2 (то есть пока она не станет равной 1).
Теперь, начиная с этой единицы, выписываем в обратном порядке все
остатки от деления, это и будет запись числа 39 в двоичной системе
счисления: 39ю=100111
2
.
Таким образом можно переводить любое натуральное число из десятичной
системы счисления в двоичную, а также и другие системы (например,
15
восьмеричную или шестеричную).
uses crt;
var n.longint;
procedure REC (n:longint);
begin
if n>l then rec(n div 2);
writefn (mod 2);
end;
begin
clrscr;
writeln('n - ');
readln(n);
rec(n);
readln;
end.
Результат на экране: 100111.
Первая цифра (1) выводится на экран из последнего вызова, следующая
цифра (0) - из предпоследнего и так далее, последняя (1) - из первого. Таким
образом, вывод очередной цифры происходит перед тем, как выйти из
данной функции.
Домашнее задание;
1. Повторить понятие процедур и функций.
2. Выучить конспект.
3. Написать программу нахождения факториала числа при помощи
рекурсивной функции.