Обращение к процедуре производится по имени с указанием фактических параметров, согласованных с формальными параметрами, или без их указания. Возврат из подпрограммы в основную программу происходит к оператору, стоящему следующим за ее вызовом.
Пример программы для вычисления второй и четвертой степеней числа:
PROGRAM PROS;
VAR X, Y, A, A2, A4: INTEGER;
A2 — A 2 , A4 — A 4 , глобальные переменные>
PROCEDURE STEP24;
BEGIN
WRITELN(A: 5, A2: 5, A4: 6);
END;
BEGIN
WRITELN(‘Число; квадрат; куб’);
END.
Любой из формальных параметров процедуры может быть либо параметром-значением, либо параметром-переменной. Формальному параметру-значению (обычно для задания исходных данных) может соответствовать фактический параметр — константа, переменная или выражение. Параметру переменной может соответствовать только переменная. Обычно параметры-переменные используются для передачи результатов в вызывающую программу. Параметрам-переменным в заголовке функции должно предшествовать слово VAR.
Подпрограмма
Пример: PROCEDURE P(Y, X: REAL; VAR Z1, Z2: REAL);
где Y, X — параметры-значения, Z1, Z2 — параметры-переменные.
Передачу результатов можно проводить и через глобальные переменные. Однако злоупотребление глобальными переменными делает программу запутанной и сложной в отладке. В связи с этим рекомендуется там, где это возможно передавать результаты с помощью параметров-переменных. С другой стороны, нежелательно описание всех формальных параметров параметрами-переменными.
Чем меньше параметров объявлено параметрами-переменными и чем меньше используется глобальных переменных, тем меньше возможность получения непредвиденных программистом побочных эффектов в программе.
При наличии одноименных переменных в программе и подпрограмме в подпрограмме будут доступны только локальные переменные.
Передача в подпрограмму массивов и строк
Передача одиночных элементов массивов при вызове подпрограммы не отличается от передачи в неё простых переменных. При передаче всего массива рекомендуется предварительно определить его тип, поскольку он не является стандартным. Например:
TYPE ATYPE = ARRAY[1..10] OF REAL;
PROCEDURE R(A: ATYPE);
Такое описание возможно в связи с тем, что в списке формальных параметров могут использоваться не только стандартные, но и ранее описанные типы.
Однако объявить процедуру можно и следующим образом:
PROCEDURE R(A: ARRAY[1..10] OF REAL);
Передача в подпрограмму строки осуществляется аналогичным образом, поскольку строка является фактически массивом из её символов.
Пример описания и передачи строковых переменных:
TYPE INTYPE = STRING[10];
FUNCTION R(A: INTYPE): ONTYPE;
Рекурсия в программе
Рекурсия — это способ организации вычислительного процесса, при котором подпрограмма в ходе выполнения своих операторов обращается сама к себе.
Вызов подпрограммы «М98»
Пример. Пусть задано целое положительное число, выведите на экран дисплея цифры числа в обратном порядке.
PROGRAM REKURS;
PROCEDURE REVERS(M: INTEGER);
BEGIN
IF (M DIV 10) < >0 THEN REVERS(M DIV 10);
END;
В ходе выполнения программы процедура рекурсивно обращается сама к себе и выводит на экран при каждом обращении очередную цифру.
Рекурсия может быть прямой или косвенной. В первом случае модуль подпрограммы содержит оператор вызова этой же подпрограммы. Во втором случае один модуль (например, А) вызывается из другого модуля (например, В), а модуль В – из А. Поскольку по правилам языка каждый идентификатор перед объявлением должен быть описан, то необходимо выполнить опережающее описание подпрограммы В. Для этого объявляется заголовок процедуры В, за которым следует служебные слово FORWARD. Теперь из процедуры А можно обращаться к процедуре В. Например:
PROCEDURE B(I: BYTE); FORWARD;
PROCEDURE A(J: BYTE);
PROCEDURE B(I: BYTE);
Вложенные подпрограммы
В разделе описаний любой подпрограммы могут встречаться описания других подпрограмм, тогда говорят, что одна подпрограмма вложена в другую.
Любые идентификаторы для описания переменных, констант, типов, а также процедур и функций, описанные внутри подпрограммы, локализуются только в ней и называются локальными для данного блока (подпрограммы). Такой блок подпрограммы вместе с выделенными в нем модулями называется областью действия этих локальных имен. Локальные имена не являются формальными параметрами.
Переменные, описанные в разделе описания основной программы, называются глобальными. Область действия глобальных переменных — основная программа и ее подпрограммы.
Имена называются нелокальными, если они описаны не в самой подпрограмме, а в охватывающем ее блоке (или во внешней подпрограмме).
Все имена в пределах подпрограммы должны быть уникальными и не могут совпадать с именем самой подпрограммы. При входе в подпрограмму низшего уровня становятся доступными не только объявленные в ней имена, но и сохраняется доступ ко всем именам внешних уровней.
Рекомендуется описывать имена в том блоке, где они используются, если это возможно. Если один и тот же объект (переменная или константа) используется в двух и более блоках, то их описание необходимо сделать в самом верхнем блоке, который содержит все остальные. Если переменная, используемая в подпрограмме должна сохранять свое значение до следующего вызова этой подпрограммы, то она описывается во внешнем блоке, содержащем данную подпрограмму.
Процедуры EXIT и HALT
Процедура EXIT; осуществляет выход из программного модуля — подпрограммы или основной программы. Из подпрограммы управление передается этой процедурой в вызывающую программу к следующему за ее вызовом оператору. В программе EXIT приводит к завершению ее работы.
Процедура HALT(Cod); прекращает выполнение программы, вызывает в случае необходимости подпрограмму завершения и осуществляет выход в операционную систему. Cod — необязательный параметр, определяющий код завершения программы.
7.10. Пример и задания с подпрограммой-процедурой
Пример. Ввести два массива A [1..3], B [1..4] с помощью процедуры » ввод». Вычислить средние арифметическое и геометрическое значения элементов каждого из них, используя подпрограмму-процедуру.
Для решения задачи pазpаботана СА (pис. 15), состоящая из основной программы (а) и двух процедур: одной — для ввода элементов массива (б), другой – для определения средних арифметического и геометрического значений в массиве (в), а также написана пpогpамма для реализации алгоритма:
Program lr7;
mass = array[1..5] of integer;
ka, kb: byte;
Sr, Sg: real;
PROCEDURE VVOD ( Var d: mass; Var k: byte );
Begin
writeln(‘ введите число элементов’);
writeln(‘ введите массив из ‘, k, ‘ элементов’);
FOR i: =1 to k do read(d[i]);
end;
PROCEDURE SARR (k: byte; f: mass; var s, p: real);
begin
for i: =1 to k do begin
s: = s+f [i]; p: =p*f[i]
End;
BEGIN
writeln( ‘ SrA= ’, Sr: 5: 2, ‘ SgA= ’, Sg: 5: 2);
writeln( ‘ SrB= ’, Sr: 5: 2, ‘ SgB= ’, Sg: 5: 2);
END.
Задания для самостоятельного выполнения
Задание 1
Написать и отладить программу для п. 6.4 с выделением алгоритма обработки или формирования массива. Организовать вызов процедуры с параметрами-массивами для двух наборов исходных данных. (Для ускорения отладки массив можно задать типизированной константой).
Задание 2
1. Даны массивы A [1..6], B [1..6], C [1..6]. Получить A*B, B*С, A*C. Вычисление произведения массивов оформить процедурой.
2. Даны массивы A [1..5], B [1..6]. Получить новые массивы путем сдвига элементов в массиве А на один разряд, а в массиве В — на два разряда вправо, освободившиеся слева элементы обнулить. Сдвиг элементов в массиве оформить подпрограммой.
3. Даны два одномерных массива А [1..6] и C [1..6]. Получить A 2 , С 2 , А*С. Перемножение массивов выполнить в подпрограмме.
4. Даны две матрицы целых чисел S [1..3, 0..2], K [1..3, 0..2], в которых имеется по два одинаковых числа. Найти и распечатать их значение и индексы.
5. Вычислить значение функции Z = x1+e x 2 , где x1, x2 – корни уравнения Aix 2 +Bix + Ci = 0, i = 1, 2. N. Коэффициенты уравнения заданы в массивах A [1..N], B [1..N], C [1..N]. Для вычисления корней использовать процедуру.
6. Составить процедуру для перемножения двух квадратных матриц, с помощью которой вычислить вторую, третью и четвертую степени матрицы M [1..5, 1..5].
7. Даны массивы A [1..6], B [1..6], C [1..6]. Преобразовать их, каждому элементу массива присваивая значение соседнего с ним справа. Последнему элементу присвоить значение первого.
8. По заданным вещественным массивам A [1..6], B [1..6] и С [1..6] вычислить (minAi)/maxAi + (maxCi)/min(Ci) + max(B+C)i /min(B+C)i.
9. Даны массивы A [1..6], B [1..8]. Выбрать из них положительные элементы и записать соответственно в массивы A1 [1..k] и B1 [1..n], где k < 6, n < 8; из отрицательных элементов сформировать массивы A2 [1..6-k], B2 [1..8-n].
10. Даны массивы A [1..6], B [1..6], C [1..6]. Переставить элементы в них таким образом, чтобы слева подряд были записаны отрицательные, а справа положительные элементы.
11. Даны две целые квадратные матрицы четного порядка. Элементы массивов с четными номерами строки и столбца заменить нулем (стереть). Напечатать полученные массивы.
12. Даны одномерные массивы A [1..6], B [1..8], C [1..10]. Записать их в виде матриц AA [1..3, 1..2], BB [1..2, 2..4], CC [1..5, 1..2].
13. Даны две целые квадратные матрицы шестого порядка. Распечатать элементы главных диагоналей каждой из них и определить симметричность каждой матрицы относительно главной диагонали.
14. По заданным 10 элементам вещественных массивов A, B и С вычислить
15. Даны две матрицы целых чисел V (-1..2, 0..3) W [1..3, 0..2]. Сформировать из них одномерные массивы VV и WW, записывая элементы построчно.
16. Дана матрица чисел H [1..5, 1..6]. Переставить столбцы матрицы таким образом, чтобы элементы первой строки матрицы были расположены в порядке возрастания их модулей. Перестановку двух столбцов матрицы реализовать процедурой.
17. Дана матрица чисел G [1..4, 1..6]. Переставить элементы в матрице так, чтобы элементы каждого столбца матрицы были расположены в порядке возрастания их модулей. Перестановку элементов в столбце реализовать процедурой.
18. Даны массивы A [1..6], B [1..6], C [1..6]. Упорядочить элементы в них в порядке убывания их модулей.
19. Даны две матрицы целых чисел V [1..2, 1..3], W [1..3, 1..2]. Найти общие суммы элементов строк и столбцов, результаты сформировать в виде двух массивов.
20. Даны две целые квадратные матрицы шестого порядка. Определить, можно ли отражением относительно главной и побочной диагоналей преобразовать одну в другую.
ОБРАБОТКА СИМВОЛЬНЫХ ДАННЫХ
Символьный тип
Символьный тип — это тип данных, состоящих из одного символа (знака, буквы, цифры). Традиционная запись символьного значения представляет собой символ, заключенный в апострофы (‘ж’). В Pascal ABC имеются альтернативные способы представления символов [1]. Значениями символьного типа является множество всех символов компьютера.
Каждому символу приписывается целое число в диапазоне 0.. 255, которое служит кодом его внутреннего представления. Связь между символом и кодом устанавливается функцией ORD:
Переменные символьного типа объявляются в блоке VAR ключевым словом CHAR. Пример.
BEGIN C1: = ‘A’; C2: = ‘B’; C3: = chr(43); …
Для кодирования символов используется код ASCII (AMERICAN STANDART CODE FOR INFORMATION INTERCHANGE — Американский стандартный код для обмена информацией). Код ASCII имеет 7 бит, которые позволяют кодировать в стандарте основные 128 символов, включающие латинские пpописные и стpочные буквы, цифpы, pазделители и pяд служебных символов
(с кодами 0..31). Служебные символы в тексте считаются пробельными и в операциях ввода-вывода имеют самостоятельное значение (табл. 7).
В Pascal ABC применяется восьмибитовый код, содержащий 256 символов. Кодировка символов с номерами [128..255] зависит от типа ПК и включает буквы русского алфавита, а также графические символы [3–5].
К символам типа char применимы операции присваивания и все операции логических отношений: , < =, >=, =, < >.
Примеры ‘A’ = ‘A’ (TRUE);
Служебные символы
Символ | Код | Назначение |
BEL HT LT VT FF CR SUB ESC | Звонок Табуляция горизонтальная Перевод строки с сохранением текущей позиции Табуляция вертикальная Прогон страницы Возврат каретки Конец файла Конец работы |
Символьный тип имеет следующие встроенные функции:
ORD(С ) — возвращает код типа byte для символа С: char;
CHR( b) — возвращает символ по коду аргумента b: byte;
UPCASE(c) — переводит в верхний регистр только букву латинского алфавита, оставляя любой другой символ без изменения, и возвращает символ c: char;
PRED(C) — возвращает символ, предшествующий С: char в таблице кодов;
SUCC(C) — возвращает символ, следующий за С: char в таблице кодов.
Пример. Напечатать прописными только латинские буквы из двух заданных. Зададим буквы константами и применим функцию UpCase:
c1: = UPCASE( ‘f’ );
c2: = UPCASE( ‘ф’ );
writeln(c1, ‘ ‘, c2, #7 )
Символы также можно описывать указанием в функции CHR кода символа или с признаком # перед кодом. Например, считаются эквивалентными следующие записи:
Задания для символьных данных
1. Дана строка из 20 символов. Вывести из нее на печать только строчные буквы латинского алфавита.
2. Вывести на печать все строчные, а затем все прописные буквы русского и латинского алфавитов.
3. В заданной строке подсчитать частоту появления букв «a», «b».
4. Дан текст из 60 литер. Напечатать только строчные русские буквы, входящие в этот текст.
5. Дана последовательность символов, содержащая символ «я». Определить порядковый номер символа «я» в последовательности.
6. Дана последовательность символов. Определить в ней символ, который по алфавиту предшествует другим.
7. Напечатать в алфавитном порядке все различные строчные буквы, входящие в заданный текст из 100 литер.
8. Определить, является ли заданная последовательность символов в строке симметричной: читается одинаково слева направо и справа налево.
9. Напечатать текст, образованный символами с порядковыми номерами 56, 89, 84 и 69, и текст с изменением регистра.
10. Даны две строки с1 и с2, содержащие до 5 цифр каждая. Преобразовать их к данным целого типа, используя процедуру VAL, вычислить арифметическое выражение с3 = (с1-с2)/(с1+с2).
11. Вычислить суммы кодов всех букв, входящих в слова SUM и ALFA. Сравнить слова и определить, какое из них больше.
12. Напечатать заданный текст с удалением из него всех букв b, непосредственно перед которыми находится буква с.
13. Имеется символьная переменная d, присвоить логической переменной T значение true, если значение d – цифра, и значение false в противном случае.
14. Если в заданный текст входит каждая из букв слова key, тогда напечатать «yes», иначе – «no».
15. Написать программу, которая предварительно запрашивает ваше имя, а затем приветствует вас по имени.
16. Ввести вещественное число, преобразовать его в строку. Подсчитать количество разрядов в целой и дробной частях. Найти представление числа в виде мантиссы (по модулю меньшее единицы) и порядка.
17. Ввести строку, состоящую из нулей, единиц и десятичной точки. Преобразовать ее в десятичное число.
ОБРАБОТКА СТРОК ТЕКСТА
Строковый тип
Строковый тип (String) используется для обработки текстовой информации. Строка-константа — это произвольная последовательность символов, заключённая в апострофы. Отдельный символ совместим по типу с элементом типа CHAR.
Для обработки текстовой информации используется тип динамических строк. Строка представляет собой цепочку символов. В программе строковая переменная может быть описана в блоках Type или Var. Например:
TYPE stroka: string[100];
VAR st: string;
Максимальная длина строки — 255 символов. Строка имеет структуру, подобную одномерному массиву. Поэтому строка st1 трактуется как
st1: array[0..N] of char.
Отличие между строкой типа string и массивом состоит в том, что строка имеет переменную длину (количество символов) и нулевой элемент строки st[0] содержит информацию о длине строки. Длина строки может быть изменена путем заполнения строки новым элементом или путем изменения ее нулевого элемента. Текущая длина строки может быть определена значением ORD(st[0]).
Строки можно присваивать и сравнивать. Операции отношения >, =, < =, < >для строк выполняются посимвольно слева направо с учетом внутренней кодировки символов. Строки считаются одинаковыми, если они имеют одинаковую длину и одинаковые символы. Например:
К строкам применима операция сцепления (+) или конкатенации, например:
Если количество символов превышает максимально допустимую длину, то » лишние» символы справа отбрасываются.
Отдельный элемент строки совместим с типом char.
Пример:
stt: string[2]; c: char;
Источник: lektsia.com
Подпрограммы (процедуры и функции). Рекурсия
При решении новых задач можно попытаться воспользоваться ранее написанными программами. Алгоритм, ранее разработанный и целиком используемый в составе других алгоритмов, называется вспомогательным. Применение вспомогательных алгоритмов позволяет разбить задачу на части, структурировать ее.
Вся программа условно может быть разделена на две части: основную и вспомогательную. В основной части производится простейшая обработка информации, организуется обращение к разным вспомогательным модулям (подпрограммам).
Вспомогательный алгоритм тоже может вызывать другие вспомогательные, длина такой цепочки вызовов теоретически не ограничена. Здесь и далее следующие пары слов используются как синонимы: алгоритм и программа, вспомогательный алгоритм и подпрограмма, команда и оператор, программа и модуль. Вспомогательными и основными алгоритмы являются не сами по себе, а по отношению друг к другу.
При использовании вспомогательных алгоритмов необходимо учитывать способ передачи значений исходных данных для них и получения результата от них. Аргументы вспомогательного алгоритма — это переменные, в которых должны быть помещены исходные данные для решения соответствующей подзадачи. Результаты вспомогательного алгоритма — это также переменные, где содержаться результаты решения этих подзадач, а также результатом может быть конкретное действие, которое совершает компьютер под действием подпрограммы.
Подпрограммы могут быть двух видов: подпрограмма без параметров и подпрограмма с параметрами. Обращение к подпрограмме может быть организовано из любого места основной программы или другой подпрограммы сколько угодно раз.
При работе с подпрограммами важными являются понятия формальных и фактических параметров. Формальные параметры — это идентификаторы входных данных для подпрограммы. Если формальные параметры получают конкретные значения, то они называются фактическими.
Формальные параметры могут получить конкретные значения только в той программе, где производится обращение к данному модулю-подпрограмме. Тип и порядок записи фактических параметров должны быть такими же, как и формальных параметров. В противном случае результат работы программы будет непредсказуемым. Из этого следует, что фактические параметры используются при обращении к подпрограмме из основной, а формальные параметры — только в самом модуле.
Подпрограмма с параметрами используется для записи многократно повторяющихся действий при разных исходных данных. Подпрограммы с параметрами можно разделить на два типа: подпрограммы-функции и просто подпрограммы с параметрами (их называют процедурами).
При составлении подпрограмм с параметрами надо соблюдать следующие правила:
1) каждая подпрограмма имеет свое имя и список формальных параметров;
2) процедура из основной программы вызывается командой вызова, которая по форме ничем не отличается от вызова команды исполнителя. Результат присваивается одной или нескольким переменным, которые находятся в списке формальных параметров. Но результатом могут быть, конечно, не только значения переменных, но какое либо действие, выполненное ЭВМ.
Пример 1. Используем алгоритм нахождения наибольшего общего делителя двух натуральных чисел в качестве вспомогательного при решении задачи: составить программу вычитания дробей (a, b, c, d — натуральные числа). Результат представить в виде обыкновенной несократимой дроби.
1) Ввести натуральные числа M, N.
2) Если M=N, перейти к п. 5, иначе к следующему пункту.
3) Если M>N, то M:=M-N, иначе N:=N-M.
4) Перейти к п. 2.
5) Передать значение M в основную программу.
6) Конец подпрограммы.
1) Ввести значения A, B, C, D.
4) Если E=0, вывести значение E и перейти к п. 9, иначе перейти к следующему пункту.
5) M:=|E|, N:=F, перейти к подпрограмме вычисления НОД.
7) E и F нацело разделить на G.
8) Вывести значения E и F на печать.
9) Конец программы.
Var A, B, C, D, G, E, F : Integer;
Procedure Nod(M, N : Integer; Var K : Integer);
If M > N Then M := M — N Else N := N — M;
Write(‘Введите числители и знаменатели дробей:’);
If E = 0 Then WriteLn(E)
WriteLn(‘ Ответ : ‘, E, ‘/’, F)
Как видно из примера, объявление и тело подпрограмм находится в разделе описаний. В заголовке подпрограммы содержится список формальных параметров с указанием их типа, которые условно можно разделить на входные и выходные (перед ними стоит служебное Var). При обращении к процедуре указывается ее имя и список фактических параметров. Формальные и фактические параметры должны соответствовать по количеству и по типу.
Вызов процедуры осуществляется следующим образом:
По способу передачи фактических значений в подпрограмму в Turbo Pascal 7.0 выделяют параметры-переменные, параметры-значения, параметры-константы и массивы открытого типа, строки открытого типа, параметры-процедуры, параметры-функции (подробности — в литературе).
Функция (в отличие от процедуры) всегда возвращает единственное значение.
Покажем, как изменится подпрограмма из примера, если ее записать в виде функции.
Function Nod(M, N : Integer) : Integer;
If M > N Then M := M — N Else N := N — M;
Итак, после списка параметров указывается тип значения функции, а в теле функции хотя бы один раз встречается присваивание переменной, имя которой совпадает с именем функции, соотответствующего значения.
Вызов функции будет следующим:
Вообще, вызов функции может присутствовать в выражении, стоящем: в правой части оператора присваивания, в процедуре вывода, в качестве фактического параметра в вызове другой подпрограммы и т.д.
При решении задач целесообразно проанализировать условие, записать решение в крупных блоках (не являющихся операторами Pascal), детализировать каждый из блоков (записав в виде блоков, возможно, по-прежнему не операторов Pascal), и т.д., продолжать до тех пор, пока каждый из блоков не будет реализован с помощью операторов языка.
Пример 2. Дано натуральное число n. Переставить местами первую и последнюю цифры этого числа.
Write(‘Введите натуральное число: ‘);
Then WriteLn(‘Невозможно переставить цифры, возникнет переполнение’)
WriteLn(‘ Ответ : ‘, N)
Можно заметить, что необходимо детализировать логическую функцию Impossible, которая диагностирует, возможна ли перестановка, и процедуру Change, которая эту перестановку (в случае, если она возможна) выполняет.
Function Impossible(N : Integer) : Boolean;
Then Impossible := False
Else Impossible := (N Mod 10 > 3) Or
(N Mod 10 = 3) And
(N Mod 10000 Div 10 * 10 + N Div 10000 > MaxInt Mod 10000)
Здесь необходимо детализировать функцию Number, возвращающую количество цифр в записи натурального числа (т.к. функция Impossible содержит ее вызов, то в разделе описаний функция Number должна ей предшествовать).
Function Number(N : Integer) : Integer;
Var Vsp : Integer;
Vsp := Vsp + 1; N := N Div 10
Наконец, последняя процедура.
Procedure Change(Var N : Integer);
Var Kol, P, S, R : Integer;
S := N Div Round(Exp((Kol — 1) * Ln(10)))
R := N Mod Round(Exp((Kol — 1) * Ln(10))) Div 10;
N := P * Round(Exp((Kol — 1) * Ln(10))) + R * 10 + S
Возможны также подпрограммы, которые вызывают сами себя. Они называются рекурсивными. Создание таких подпрограмм является красивым приемом программирования, но не всегда целесообразно из-за чрезмерного расхода памяти ЭВМ.
Пример 3. Найти максимальную цифру в записи данного натурального числа.
Type NaturLong = 1..(High(LongInt));
Function Maximum(N : LongInt) : Digit;
Then Maximum := N
Else If N Mod 10 > Maximum(N Div 10)
Then Maximum := N mod 10
Else Maximum := Maximum(N Div 10)
Write(‘Введите натуральное число: ‘);
WriteLn(‘ Максимальная цифра равна ‘, Maximum(A))
При создании функции Maximum было использовано следующее соображение: если число состоит из одной цифры, то она является максимальной, иначе если последняя цифра не является максимальной, то ее следует искать среди других цифр числа. При написании рекурсивного алгоритма следует позаботиться о граничном условии, когда цепочка рекурсивных вызовов обрывается и начинается ее обратное «раскручивание». В нашем примере это условие N < 10.
Более подробно о рекурсии говорится в следующей статье .
Контрольные вопросы и задания
Какие алгоритмы называют вспомогательными?
какое количество вспомогательных алгоритмов может присутствовать в основном алгоритме?
Можно ли вспомогательные алгоритмы, написанные для решения данной задачи, использовать при решении других задач, где их применение было бы целесообразно?
Какие параметры называют формальными? фактическими?
Какое соответствие должно соблюдаться между формальными и фактическими параметрами?
Может ли фактических параметров процедуры (функции) быть больше, чем формальных? А меньше?
Существуют ли подпрограммы без параметров?
Существуют ли ограничения на число параметров подпрограмм? Если нет, то чем же всё-таки ограничивается это количество в Turbo Pascal?
В каком разделе объявляются и реализуются подпрограммы в Turbo Pascal?
Какие виды формальных параметров существуют? Чем они отличаются друг от друга?
В чём состоит отличие процедур и функций?
В каких случаях целесообразно использовать функции?
Почему, если в функции используются параметры-переменные, необходимо преобразовать её в процедуру?
Какого типа может быть значение функции?
Расскажите о методе последовательной детализации при разработке программ.
Какие подпрограммы называют рекурсивными?
Что такое граничное условие при организации рекурсивной подпрограммы?
Список литературы
Для подготовки данной работы были использованы материалы с сайта http://www.comp-science.narod.ru/
Дата добавления: 28.07.2003
База рефератов на портале KM.RU существует с 1999 года. Она пополнялась не только готовыми рефератами, докладами, курсовыми, но и авторскими публикациями, чтобы учащиеся могли использовать их и цитировать при самостоятельном написании работ.
Это популяризирует авторские исследования и научные изыскания, что и является целью работы истинного ученого или публициста. Таким образом, наша база — электронная библиотека, созданная в помощь студентам и школьникам.
Источник: www.km.ru
Подпрограммы (процедуры и функции). Рекурсия
При решении новых задач можно попытаться воспользоваться ранее написанными программами. Алгоритм, ранее разработанный и целиком используемый в составе других алгоритмов, называется вспомогательным. Применение вспомогательных алгоритмов позволяет разбить задачу на части, структурировать ее.
Вся программа условно может быть разделена на две части: основную и вспомогательную. В основной части производится простейшая обработка информации, организуется обращение к разным вспомогательным модулям (подпрограммам).
Вспомогательный алгоритм тоже может вызывать другие вспомогательные, длина такой цепочки вызовов теоретически не ограничена. Здесь и далее следующие пары слов используются как синонимы: алгоритм и программа, вспомогательный алгоритм и подпрограмма, команда и оператор, программа и модуль. Вспомогательными и основными алгоритмы являются не сами по себе, а по отношению друг к другу.
При использовании вспомогательных алгоритмов необходимо учитывать способ передачи значений исходных данных для них и получения результата от них. Аргументы вспомогательного алгоритма — это переменные, в которых должны быть помещены исходные данные для решения соответствующей подзадачи. Результаты вспомогательного алгоритма — это также переменные, где содержаться результаты решения этих подзадач, а также результатом может быть конкретное действие, которое совершает компьютер под действием подпрограммы.
Подпрограммы могут быть двух видов: подпрограмма без параметров и подпрограмма с параметрами. Обращение к подпрограмме может быть организовано из любого места основной программы или другой подпрограммы сколько угодно раз.
При работе с подпрограммами важными являются понятия формальных и фактических параметров. Формальные параметры — это идентификаторы входных данных для подпрограммы. Если формальные параметры получают конкретные значения, то они называются фактическими.
Формальные параметры могут получить конкретные значения только в той программе, где производится обращение к данному модулю-подпрограмме. Тип и порядок записи фактических параметров должны быть такими же, как и формальных параметров. В противном случае результат работы программы будет непредсказуемым. Из этого следует, что фактические параметры используются при обращении к подпрограмме из основной, а формальные параметры — только в самом модуле.
Подпрограмма с параметрами используется для записи многократно повторяющихся действий при разных исходных данных. Подпрограммы с параметрами можно разделить на два типа: подпрограммы-функции и просто подпрограммы с параметрами (их называют процедурами).
При составлении подпрограмм с параметрами надо соблюдать следующие правила:
1) каждая подпрограмма имеет свое имя и список формальных параметров;
2) процедура из основной программы вызывается командой вызова, которая по форме ничем не отличается от вызова команды исполнителя. Результат присваивается одной или нескольким переменным, которые находятся в списке формальных параметров. Но результатом могут быть, конечно, не только значения переменных, но какое либо действие, выполненное ЭВМ.
Пример 1. Используем алгоритм нахождения наибольшего общего делителя двух натуральных чисел в качестве вспомогательного при решении задачи: составить программу вычитания дробей (a, b, c, d — натуральные числа). Результат представить в виде обыкновенной несократимой дроби.
1) Ввести натуральные числа M, N.
2) Если M=N, перейти к п. 5, иначе к следующему пункту.
3) Если M>N, то M:=M-N, иначе N:=N-M.
4) Перейти к п. 2.
5) Передать значение M в основную программу.
6) Конец подпрограммы.
1) Ввести значения A, B, C, D.
2) E:=A*D — B*C.
3) F:= B*D.
4) Если E=0, вывести значение E и перейти к п. 9, иначе перейти к следующему пункту.
5) M:=|E|, N:=F, перейти к подпрограмме вычисления НОД.
6) G := M.
7) E и F нацело разделить на G.
8) Вывести значения E и F на печать.
9) Конец программы.
Program Sub;
Var A, B, C, D, G, E, F : Integer;
Procedure Nod(M, N : Integer; Var K : Integer);
Begin
While M <> N Do
If M > N Then M := M — N Else N := N — M;
K := M
End;
Begin
Write(‘Введите числители и знаменатели дробей:’);
ReadLn(A, B, C, D);
E := A * D — B * C;
F := B * D;
If E = 0 Then WriteLn(E)
Else
Begin
Nod(Abs(E), F, G);
E := E Div G;
F := F Div G;
WriteLn(‘Ответ: ‘, E, ‘/’, F)
End
End.
Как видно из примера, объявление и тело подпрограмм находится в разделе описаний. В заголовке подпрограммы содержится список формальных параметров с указанием их типа, которые условно можно разделить на входные и выходные (перед ними стоит служебное Var). При обращении к процедуре указывается ее имя и список фактических параметров. Формальные и фактические параметры должны соответствовать по количеству и по типу.
Вызов процедуры осуществляется следующим образом:
По способу передачи фактических значений в подпрограмму в Turbo Pascal 7.0 выделяют параметры-переменные, параметры-значения, параметры-константы и массивы открытого типа, строки открытого типа, параметры-процедуры, параметры-функции (подробности — в литературе).
Функция (в отличие от процедуры) всегда возвращает единственное значение.
Покажем, как изменится подпрограмма из примера, если ее записать в виде функции.
Function Nod(M, N : Integer) : Integer;
Begin
While M <> N Do
If M > N Then M := M — N Else N := N — M;
Nod := M
End;
Итак, после списка параметров указывается тип значения функции, а в теле функции хотя бы один раз встречается присваивание переменной, имя которой совпадает с именем функции, соотответствующего значения.
Вызов функции будет следующим:
Вообще, вызов функции может присутствовать в выражении, стоящем: в правой части оператора присваивания, в процедуре вывода, в качестве фактического параметра в вызове другой подпрограммы и т.д.
При решении задач целесообразно проанализировать условие, записать решение в крупных блоках (не являющихся операторами Pascal), детализировать каждый из блоков (записав в виде блоков, возможно, по-прежнему не операторов Pascal), и т.д., продолжать до тех пор, пока каждый из блоков не будет реализован с помощью операторов языка.
Пример 2. Дано натуральное число n. Переставить местами первую и последнюю цифры этого числа.
Program Integ;
Var N : Integer;
Begin
Write(‘Введите натуральное число: ‘);
ReadLn(N);
If Impossible(N)
Then WriteLn(‘Невозможно переставить цифры, возникнет переполнение’)
Else Begin
Change(N);
WriteLn(‘Ответ: ‘, N)
End;
End.
Можно заметить, что необходимо детализировать логическую функцию Impossible, которая диагностирует, возможна ли перестановка, и процедуру Change, которая эту перестановку (в случае, если она возможна) выполняет.
Function Impossible(N : Integer) : Boolean;
Begin
If Number(N) < 5
Then Impossible := False
Else Impossible := (N Mod 10 > 3) Or
(N Mod 10 = 3) And
(N Mod 10000 Div 10 * 10 + N Div 10000 > MaxInt Mod 10000)
End;
Здесь необходимо детализировать функцию Number, возвращающую количество цифр в записи натурального числа (т.к. функция Impossible содержит ее вызов, то в разделе описаний функция Number должна ей предшествовать).
Function Number(N : Integer) : Integer;
Var Vsp : Integer;
Begin
Vsp := 0;
While N > 0 Do
Begin
Vsp := Vsp + 1; N := N Div 10
End;
Number := Vsp
End;
Наконец, последняя процедура.
Procedure Change(Var N : Integer);
Var Kol, P, S, R : Integer;
Begin
Kol := Number(N);
P := N Mod 10;
If Kol > 1 Then
S := N Div Round(Exp((Kol — 1) * Ln(10)))
Else S := 0;
R := N Mod Round(Exp((Kol — 1) * Ln(10))) Div 10;
N := P * Round(Exp((Kol — 1) * Ln(10))) + R * 10 + S
End;
Возможны также подпрограммы, которые вызывают сами себя. Они называются рекурсивными. Создание таких подпрограмм является красивым приемом программирования, но не всегда целесообразно из-за чрезмерного расхода памяти ЭВМ.
Пример 3. Найти максимальную цифру в записи данного натурального числа.
Program MaxDigit;
Type NaturLong = 1..(High(LongInt));
Digit = 0..9;
Var A : LongInt;
Function Maximum(N : LongInt) : Digit;
Begin
If N < 10
Then Maximum := N
Else If N Mod 10 > Maximum(N Div 10)
Then Maximum := N mod 10
Else Maximum := Maximum(N Div 10)
End;
Begin
Write(‘Введите натуральное число: ‘);
ReadLn(A);
WriteLn(‘Максимальная цифра равна ‘, Maximum(A))
End.
При создании функции Maximum было использовано следующее соображение: если число состоит из одной цифры, то она является максимальной, иначе если последняя цифра не является максимальной, то ее следует искать среди других цифр числа. При написании рекурсивного алгоритма следует позаботиться о граничном условии, когда цепочка рекурсивных вызовов обрывается и начинается ее обратное «раскручивание». В нашем примере это условие N < 10.
Более подробно поговорим о рекурсии, о её механизме несколько позднее.
Источник: www.examen.ru