Понятие подпрограммы процедуры и функции. Подпрограммы процедуры и подпрограммы функции
Глава 17. Команды вызова процедур
Что такое подпрограмма
Подпрограмма представляет собой самостоятельную компьютерную программу, включенную в состав более сложной программы (по отношению к подпрограмме она выступает в роли основной или вызывающей программы). В любом месте основной программы можно обратиться к подпрограмме (чаще говорят "вызвать подпрограмму"). Ядро процессора при этом должно перейти на адрес первой команды подпрограммы, а после ее завершения вернуться на адрес команды основной программы, следующей за командой вызова подпрограммы.
В пользу применения подпрограмм в технологии программирования чаще всего выдвигаются два довода - экономия места в оперативной памяти и модульность структуры программы. Подпрограмма, в которой закодирован определенный алгоритм, может вызываться многократно, и таким образом экономится место в оперативной памяти, но в этом смысле подпрограмма мало чем отличается от цикла. Важнее другое - подпрограммы позволяют структурно разбить программу решения сложной задачи на более мелкие модули, решающие отдельные подзадачи. Такая модульность структуры большой программы существенно облегчает ее разработку.
Механизм поддержки работы с подпрограммами должен включать два основных типа команд - команду вызова подпрограммы и команду возврата из подпрограммы. Команда вызова подпрограммы должны обеспечить переход на первую команду вызываемой подпрограммы, а команда возврата - переход на команду вызывающей программы, следующую за командой вызова. Команды относятся к категории команд управления ходом выполнения программы.
На рис. 17.1а показан пример использования подпрограммы. В данном примере имеется основная программа, которая размещена в оперативной памяти, начиная с адреса 4000. В основной программе существует вызов подпрограммы PROC1, которая размещена в оперативной памяти, начиная с адреса 4500. Когда в процессе выполнения основной программы ядро процессора дойдет до этой команды, оно прервет выполнение основной программы и перейдет на выполнение подпрограммы PROC1, поместив ее начальный адрес 4500 в счетчик команд. В теле подпрограммы PROC1 есть две команды вызова подпрограммы PROC2, которая размещена в оперативной памяти, начиная с адреса 4800. Дойдя до каждой из этих команд, ядро процессора прекратит выполнять подпрограмму PROC1 и перейдет на выполнение подпрограммы PROC2. Встретив в подпрограмме команду RETURN, ядро процессора вернется в вызывающую программу и продолжит ее выполнение с команды, следующей за командой CALL, которая вызвала переход на только что завершенную подпрограмму. Этот процесс схематически показан на рис. 17.1.6.
Необходимо обратить внимание на следующие моменты:
подпрограмма может быть вызвана из любого места других программных
модулей. Таких вызовов может быть сколько угодно.
одна подпрограмма может быть вызвана из другой, которая, в свою очередь, вызвана третьей. Это называется вложенностью (nesting) вызовов. Глубина вложенности теоретически может быть произвольной.
при выполнении возврата из подпрограммы должен обеспечиваться переход
именно на ту команду вызова, которая запустила завершенный сеанс выполнения подпрограммы.
Рис. 17.1. Вложенный вызов подпрограмм:
а - команды вызова и возврата; б - последовательность выполнения команд
Из всего этого следует, что ядро процессора при выполнении команды вызова подпрограммы должно каким-то образом сохранить адрес возврата (т.е. адрес команды вызывающей программы, следующей за выполняемой командой вызова). Существует три места, где можно было бы сохранить адрес возврата:
регистр процессора;
начальный адрес подпрограммы;
верхняя ячейка стека.
Рассмотрим машинную команду CALL X, которая интерпретируется как "вызов подпрограммы, расположенной по адресу X". Если для хранения адреса возврата использовать регистр Rn, то выполнение команды CALL X должно проходить следующим образом (PC - счетчик команд ядра процессора):
В этой записи D - длина текущей команды. Затем адрес возврата оказывается в регистре Rn, откуда его может извлечь вызванная подпрограмма и сохранить где-либо в оперативной памяти для выполнения в дальнейшем возврата в вызывающую программу.
Если будет принято решение сохранять адрес возврата по начальному адресу вызываемой подпрограммы, то при выполнении команды CALL X ядру процессора нужно будет выполнять следующие операции:
Это довольно удобно, поскольку адрес возврата всегда сохраняется в месте, точно известном подпрограмме (точнее, ее разработчику).
Оба описанных подхода работоспособны и используются на практике. Единственным, но довольно существенным их недостатком является невозможность реализации реентерабельных подпрограмм. Реентерабельность подпрограммы означает, что она может быть вызвана повторно еще до завершения текущего вызова. Например, это происходит, если внутри подпрограммы вызывается другая подпрограмма, которая, в свою очередь, вызывает первую. Реентерабельными должны быть и подпрограммы, реализующие рекурсивные алгоритмы.
Более общим, и более надежным, подходом является использование для хранения адреса возврата стека. Когда ядро процессора выполняет команду вызова подпрограммы, адрес возврата помещается в верхнюю ячейку стека, а когда он выполняет команду возврата, извлекает этот адрес из верхней ячейки стека.
Стеки
Стек - это список элементов данных, обычно слов или байтов, доступ к которым ограничен следующим правилом: элементы этого списка могут добавляться только в его конец и удаляться только из конца. Конец списка называется вершиной стека, а его начало - дном. Такую структуру иногда называют магазином. Представьте себе стопку подносов в столовой. Клиенты берут подносы сверху, работники столовой, добавляя чистые подносы, тоже кладут их на верх стопки. Этот механизм хранения хорошо описывается емкой фразой «последним вошел - первым вышел» (Last In First Out, LIFO), означающей, что элемент данных, помещенный в стек последним, удаляется из него первым. Операцию помещения нового элемента в стек часто называют его проталкиванием (push), а операцию извлечения последнего элемента из стека называют его выталкиванием (pop).
Хранящиеся в оперативной памяти компьютера данные могут быть организованы в виде стека, так чтобы последовательные элементы располагались друг за другом. Предположим, что первый элемент хранится по адресу BOTTOM, а когда в стек помещаются новые элементы, они располагаются в порядке уменьшения последовательных адресов. Таким образом, стек растет в направлении уменьшения адресов, что является весьма распространенной практикой.
На рис. 17.2 показано, как располагается в памяти компьютера стек, элементы которого занимают по одному слову.
На «дне» он содержит числовое значение 43, а на вершине - 28. Для отслеживания адреса вершины стека используется регистр ядра процессора, называемый указателем стека (Stack Pointer, SP). Это может быть один из регистров общего назначения или же регистр, специально предназначенный для этой цели.
Рис. 17.2. Стек слов в оперативной памяти
Если предположить, что оперативная память адресуется побайтно и слово имеет длину 32 разряда, операцию проталкивания в стек можно реализовать так:
Move NEWITEM.(SP),
где команда Subtract вычитает исходный операнд 4 из результирующего операнда, содержащегося в регистре SP, и помещает результат в регистр SP. Эти две команды помещают слово, хранящееся по адресу NEWiTEM, на вершину стека, предварительно уменьшая указатель стека на 4. Операция выталкивания из стека может быть реализована так:
Эти две команды перемещают значение, хранившееся на вершине стека, в другое место оперативной памяти, по адресу ITEM, а затем уменьшают указатель стека на 4, чтобы он указывал на тот элемент, который теперь располагается на вершине стека. Результат выполнения каждой из этих операций для стека, показанного на рис. 17. 2, приведен на рис. 17.3.
![]() |
Рис. 17.3. Результат выполнения операций со стеком
Если в архитектуре поддерживаются режимы автоинкрементной и автодекрементной адресации, для помещения нового элемента в стек достаточно команды
Move NEWITEM,-(SP),
а выталкивание элемента из стека можно выполнить посредством команды
Move (SP)+,ITEM.
Когда стек используется программой, для него обычно выделяется фиксированное количество ячеек оперативной памяти. В этом случае нужно проследить за тем, чтобы программа не пыталась помещать новые элементы в стек, достигший своего максимального размера. Кроме того, она не должна пытаться вытолкнуть элемент из пустого стека, что могло бы произойти в случае логической ошибки.
Предположим, что стек заполняется, начиная с адреса 2000 (BOTTOM) до 1500 и далее. Первоначально в регистр, играющий роль указателя стека, загружается значение 2004. Напомним, что перед помещением в стек нового элемента данных из значения SP каждый раз вычитается 4. Поэтому начальное значение 2004 означает, что первый элемент стека будет иметь адрес 2000. Для предотвращения попыток помещения элемента в полный стек или удаления элемента из пустого стека нужно несколько усложнить реализацию операций проталкивания и выталкивания элемента. Для выполнения каждой из этих операций указаннойвыше команды недостаточно - ее нужно заменить последовательностью команд, приведенной в таблице 17.1.
Команда сравнения Compare src,dst выполняет операцию - и устанавливает флаги условий в соответствии с полученным результатом. Она не изменяет значения ни одного из операндов. Фрагмент а таблицы 17.1 демонстрирует выталкивание элемента из стека, а фрагмент б этой же таблицы - помещение элемента в стек при реализации контроля пустого и полного стека при выполнении операций проталкивания и выталкивания элемента.
Таблица 17.1
| Метка | Команда | Операнды |
Язык G- и М-кодов, как и любой другой язык программирования, позволяет работать с подпрограммами и совершать переходы. Посредством функции подпрограммы основная (главная) управляющая программа может вызывать из памяти другую программу (подпрограмму) и выполнить ее определенное число раз. Если УП содержит часто повторяемое действие или работает по определенному шаблону, то использование подпрограмм позволяет упростить программу обработки и сделать ее гораздо меньшей в размере.
Существуют два вида подпрограмм – внутренние и внешние. Внутренние подпрограммы вызываются при помощи кода М97 и содержатся внутри главной программы. То есть они находятся в одном файле. Внешние подпрограммы вызываются кодом М98 и не содержатся в теле главной программы. В этом случае главная программа и подпрограмма находятся в разных файлах.
Рис. 10.1. Схема внутренней подпрограммы
Внутренняя подпрограмма выполняется, когда СЧПУ встречает код М97. При этом адрес Р указывает на номер кадра, к которому нужно перейти, то есть туда, где начинается внутренняя подпрограмма. Когда СЧПУ находит кадр с кодом окончания подпрограммы М99, то выполнение внутренней подпрограммызавершается и управление передается кадру главной программы, следующему за кадром, вызвавшим завершенную подпрограмму.

Рис. 10.2. Схема внешней подпрограммы
Внешние подпрограммы работают похожим образом. Когда в главной программе встречается кадр с кодом М98, то вызывается подпрограмма с номером, установленным при помощи Р-адреса. При нахождении кода М99 управление возвращается главной программе, то есть выполняется кадр главной программы, следующий за кадром с М98. Учтите, что внешняя подпрограмма находится в отдельном файле. По сути, внешняя подпрограмма – это отдельная программа с индивидуальным номером, которая при желании может быть выполнена независимо от главной программы. Для вызова подпрограммы необходимо, чтобы она находилась в памяти СЧПУ.
Пример УП с внутренней подпрограммой:
При помощи L-адреса определяется, сколько раз нужно вызвать ту или иную подпрограмму. Если подпрограмму нужно вызвать всего один раз, то L в кадре можно не указывать.
М98 Р1000 L4 – подпрограмма будет вызвана 4 раза.
Большим преимуществом от использования подпрограмм является возможность удобной и эффективной работы с программными массивами и шаблонами. Например, для обработки детали, изображенной на рис. 11.3, мы создадим главную программу и подпрограмму, и вы увидите, насколько удобнее и проще будет работать в этом случае.
Итак, на рис. 10.3 изображена деталь с 4 группами отверстий диаметром 3 мм. Нулевой точкой является верхний левый угол детали. Сначала создадим главную программу, которая будет позиционировать инструмент к каждой группе отверстий. Затем напишем подпрограмму, необходимую для сверления 4 отверстий в одной группе. Учтите, что в подпрограмме используются относительные координаты, а смена инструмента и основные команды находятся в главной программе.

Рис. 10.3. Использование подпрограмм при обработке повторяющихся элементов позволяет уменьшить размер программы
Обе эти программы необходимо передать в СЧПУ, оператор станка должен вызвать программу О0001 и запустить ее. Главная программа работает с абсолютными координатами и перемещает инструмент последовательно в центр каждой из четырех групп отверстий. Когда СЧПУ встречает кадр с М98 Р1000, то происходит передача управления подпрограмме с номером 01000. В этот момент инструмент уже находится в центре группы отверстий. Переключаемся в режим относительного (инкрементального) программирования и используем постоянный цикл сверления. После завершения сверления четырех отверстий одной группы выключаем цикл сверления командой G80 и переходим в режим абсолютных координат G90, для того чтобы правильно выполнить позиционирование в главной программе. Код М99 передает управление кадру главной программы, который следует за кадром, вызвавшим эту подпрограмму. Затем инструмент перемещается в центр следующей группы отверстий, и снова вызывается подпрограмма 01000. И так далее, пока не просверлим все отверстия и СЧПУ не прочтет код завершения программы М30.
Если бы мы создавали обычную программу обработки, то ее размер был бы значительно больше, так как пришлось бы указывать координаты всех 16 отверстий. Работая в таком формате, легче производить изменения. Например, если из менится диаметр окружности, на которой находятся отверстия группы, то в случае работы с подпрограммой достаточно пересчитать координаты центров четырех отверстий только в подпрограмме.
Из главной программы можно вызвать несколько различных подпрограмм. Более того, из каждой подпрограммы можно вызвать несколько других подпрограмм. Системы ЧПУ могут накладывать ограничения на вложенность и количество выполняемых подпрограмм, поэтому внимательно прочитайте документацию станка и стойки, прежде чем начнете работать с подпрограммами.
| Наименование параметра | Значение |
| Тема статьи: | Подпрограммы |
| Рубрика (тематическая категория) | Программирование |
Методология структурного программирования основывается на использовании подпрограмм и независимых структур данных.
Подпрограмма (англ. subprogram) - поименованная или иным образом идентифицированная часть компьютерной программы, содержащая описание определённого набора действий. Подпрограмма должна быть многократно вызвана из разных частей программы.
Назначение подпрограмм . Подпрограммы изначально появились как средство оптимизации программ по объёму занимаемой памяти - они позволили не повторять в программе идентичные блоки кода, а описывать их однократно и вызывать по мере крайне важно сти. К настоящему времени данная функция подпрограмм стала вспомогательной, главное их назначение - структуризация программы с целью удобства её понимания и сопровождения
Выделение набора действий в подпрограмму и вызов её по мере крайне важно сти позволяет логически выделить целостную подзадачу, имеющую типовое решение. Такое действие имеет ещё одно (помимо экономии памяти) преимущество перед повторением однотипных действий: любое изменение (исправление ошибки, оптимизация, расширение функциональности), сделанное в подпрограмме, автоматически отражается на всех её вызовах, в то время как при дублировании каждое изменение крайне важно вносить в каждое вхождение изменяемого кода.
Даже в тех случаях, когда в подпрограмму выделяется однократно производимый набор действий, это оправдано, так как позволяет сократить размеры целостных блоков кода, составляющих программу, то есть сделать программу более понятной и обозримой.
В простейшем случае (в ассемблерах) подпрограмма представляет собой последовательность команд (операторов), отдельную от основной части программы и имеющую в конце специальную команду выхода из подпрограммы. Обычно подпрограмма имеет имя, по которому её можно вызвать, хотя ряд языков программирования допускает использование и неименованных подпрограмм. В языках высокого уровня описание подпрограммы обычно состоит по меньшей мере из двух частей: заголовка и тела. Заголовок подпрограммы описывает её имя и, возможно, параметры, то есть содержит информацию, необходимую для вызова подпрограммы. Тело - набор операторов, который будет выполнен всякий раз, когда подпрограмма будет вызвана.
Вызов подпрограммы выполняется с помощью команды вызова, включающей в себя имя подпрограммы. В большинстве современных языков программирования команда вызова представляет собой просто имя вызываемой подпрограммы, за которым могут следовать фактические параметры.
Формальные и фактические параметры. Чтобы отличать параметры подпрограммы, описанные в её заголовке и теле, от параметров, указываемых при вызове подпрограммы, первые принято называть формальными параметрами, вторые - фактическими параметрами.
Подпрограмма - ϶ᴛᴏ блок кода между операторами Sub и End Sub или Function и end Function .
Виды подпрограмм . В языках программирования высокого уровня используется два типа подпрограмм: процедуры и функции.
Подпрограмма-процедура Sub и End Sub . Обычно подпрограмму-процедуру принято называть процедурой.
При написании программы нужно учесть одно правило: ʼʼВнутри одной процедуры не должна быть описана другая процедураʼʼ.
Процедура - это любая подпрограмма, которая не является функцией.
Подпрограмма-функция - ϶ᴛᴏ блок кода, заключенный между операторами Function и End Function. Она выполняет какую-то операцию, но при этом обязательно возвращает какое-нибудь значение. Значение возвращается через имя функции.
Функция - это подпрограмма специального вида, которая, кроме получения параметров, выполнения действий и передачи результатов работы через параметры имеет ещё одну возможность - она может возвращать результат. Вызов функции является, с точки зрения языка программирования, выражением, он может использоваться в других выражениях или в качестве правой части присваивания. Подробнее см. в статье Функция (программирование).
Подпрограммы, входящие в состав классов в объектных языках программирования, обычно называются методами . Этим термином называют любые подпрограммы-члены класса, как функции, так и процедуры; когда требуется уточнение, говорят о методах-процедурах или методах-функциях.
6.2.4 Принцип проектирования программ сверху-вниз и снизу–вверх.
Программирование ʼʼсверху внизʼʼ, или нисходящее программирование - ϶ᴛᴏ методика разработки программ, при которой выработка начинается с определения целей решения проблемы, после чего идет последовательная детализация, заканчивающаяся детальной программой. Является противоположной методике программирования ʼʼснизу вверхʼʼ.
При нисходящем проектировании задача анализируется с целью определения возможности разбиения ее на ряд подзадач. Далее каждая из полученных подзадач также анализируется для возможного разбиения на подзадачи. Процесс заканчивается, когда подзадачу невозможно или нецелесообразно далее разбивать на подзадачи.
В данном случае программа конструируется иерархически – сверху вниз: от главной программы к подпрограммам самого нижнего уровня, причем на каждом уровне используются только простые последовательности инструкций, циклы и условные разветвления.
Программирование ʼʼснизу вверхʼʼ, или восходящее программирование - ϶ᴛᴏ методика разработки программ, начинающаяся с разработки подпрограмм (процедур, функций), в то время когда проработка общей схемы не закончилась. Является противоположной методике программирования ʼʼсверху внизʼʼ.
Такая методика является менее предпочтительной по сравнению с нисходящим программированием так как часто приводит к нежелательным результатам, переделкам и увеличению времени разработки.
Программирование ʼʼсверху вниз ʼʼ, или пошаговая детализация. Суть метода состоит в разбиении исходной задачи на последовательность нескольких меньших подзадач. Эти подзадачи, в свою очередь, тоже распадаются на подзадачи и т. д. до тех пор, пока не останутся только элементарные алгоритмы.
Пример.
Размещено на реф.рф
Чтобы написать число 512, сначала пишут цифру 5, затем 1 и, наконец, 2. При этом цифры рисуют, последовательно прорисовывая линии, из которых они состоят. Принтер напечатает это число точками.
При разработке программы пошагово, методом ʼʼсверху вниз ʼʼ сначала пишется текст основной программы, в котором, вместо каждого связного логического фрагмента текста͵ вставляется вызов подпрограммы, которая будет выполнять данный фрагмент. Вместо настоящих, работающих подпрограмм, в программу вставляются ʼʼзаглушкиʼʼ, которые ничего не делают. Полученная программа проверяется и отлаживается. После того, как программист убедится, что подпрограммы вызываются в правильной последовательности (то есть общая структура программы верна), подпрограммы-заглушки последовательно заменяются на реально работающие, причём выработка каждой подпрограммы ведётся тем же методом, что и основной программы. Разработка заканчивается тогда, когда не останется ни одной ʼʼзатычкиʼʼ, которая не была бы удалена. Такая последовательность гарантирует, что на каждом этапе разработки программист одновременно имеет дело с обозримым и понятным ему множеством фрагментов, и должна быть уверен, что общая структура всех более высоких уровней программы верна. При сопровождении и внесении изменений в программу выясняется, в какие именно процедуры нужно внести изменения, и они вносятся, не затрагивая части программы, непосредственно не связанные с ними. Это позволяет гарантировать, что при внесении изменений и исправлении ошибок не выйдет из строя какая-то часть программы, находящаяся в данный момент вне зоны внимания программиста.
В теории и практике программирования наиболее популярны стратегии ʼʼсверху внизʼʼ и ʼʼснизу вверхʼʼ. Такие полярные варианты взаимодействия процессов проектирования и реализации оказываются применимыми только для программ небольшого или среднего размера. Создание же крупной программы обычно связано с поиском разумного компромисса между этими вариантами. Существует и еще одно решение – программирование ʼʼвширьʼʼ.
Программирование ʼʼвширьʼʼ - ориентиром провозглашается набор однородных модулей. В одной программе должна быть выявлено несколько однородных наборов. После того как однородные модули выявлены, приступают к непосредственному программированию, ĸᴏᴛᴏᴩᴏᴇ, собственно, и разбивается на этапы. На первом этапе создается лишь минимальное число представителей каждого из выделенных однородных наборов. В случае если поиск однородности проводился достаточно энергично, то обычно оказывается, что объём работ первого этапа реализации сравнительно невелик.
Подпрограммы - понятие и виды. Классификация и особенности категории "Подпрограммы" 2017, 2018.
Вызов подпрограммы процедуры Sub Синтаксис процедуры типа Sub Процедура типа Sub [ Public | Private] Sub имя [(параметры)] [операторы внутри процедуры] End Sub Public - процедура доступна для всех других процедур модулей проекта. По умолчанию... .
В целях структуризации программ, облегчения их разработки, отладки и понимания большие программы принято разбивать на отдельные модули, логически связанные друг с другом и достаточно автономные. Идея структурного программирования заключается в том, что структура... .
Лабораторная работа № 3. В целях структуризации программ, облегчения их разработки, отладки и понимания большие программы принято разбивать на отдельные модули, логически связанные друг с другом и достаточно автономные. Идея структурного программирования... .
При вызове процедуры или функции передают в них некоторые переменные путем замены формальных параметров на фактические. (Фактические параметры берутся при вызове ф-ции. Формальные параметры берутся из задач.) Внутри процедуры этим переменным может быть присвоено... .
Begin Var s:real; s1: integer;{Ввод числовых данных} s:=StrToFloat(Edit1.Text); s1:=StrToInt(InputBox("Ввод данных","Введите s","")); {Вывод числовых данных} Edit2.Text:=FloatToStr(s); Label1.Caption:=IntToStr(s1); ShowMessage(FloatToStr(s)) End; Для вывода чисел по формату используются: - Процедура Str(F[:Width[:Decimals]], S), которая... .
Вызов подпрограммы на С не отличается от вызова подпрограммы на ассемблере. Однако при вызове С/С++-функции следует учитывать, что она работает в соответствии с рассмотренными положениями функционирования среды выполнения. Поэтому, если вложенная asm-процедура в... .
Хорошим стилем программирования считается описание прототипа ассемблерной функции для определения аргументов функции и интерфейса между программой на С и подпрограммой на ассемблере. Run-time модель выполнения определяет некоторые регистры как рабочие (Scratch), а... .
Begin Uses Uses End. Begin . . .//код проектаРабота с модулем: 1. Создать консольное приложение командой Файл => Новый => Другое => Console Application. 2. Cохранить проект в папке KR командой Файл => Сохранить проект как..=> Blank. 3.... .
Программное обеспечение USB Библиотечные подпрограммы разработаны для использования с компоновщиком. Нет необходимости создавать дополнительные включаемые файлы. Подпрограммы предлагаются упакованными в следующие файлы: USB_CH9 .ASM - обработка всех команд в... .
При решении новых задач можно попытаться воспользоваться ранее написанными программами. Алгоритм, ранее разработанный и целиком используемый в составе других алгоритмов, называется вспомогательным. Применение вспомогательных алгоритмов позволяет разбить задачу на части, структурировать ее.
Вся программа условно может быть разделена на две части: основную и вспомогательную. В основной части производится простейшая обработка информации, организуется обращение к разным вспомогательным модулям (подпрограммам).
Вспомогательный алгоритм тоже может вызывать другие вспомогательные, длина такой цепочки вызовов теоретически не ограничена. Здесь и далее следующие пары слов используются как синонимы: алгоритм и программа, вспомогательный алгоритм и подпрограмма, команда и оператор, программа и модуль. Вспомогательными и основными алгоритмы являются не сами по себе, а по отношению друг к другу.
При использовании вспомогательных алгоритмов необходимо учитывать способ передачи значений исходных данных для них и получения результата от них. Аргументы вспомогательного алгоритма - это переменные, в которых должны быть помещены исходные данные для решения соответствующей подзадачи. Результаты вспомогательного алгоритма - это также переменные, где содержаться результаты решения этих подзадач, а также результатом может быть конкретное действие, которое совершает компьютер под действием подпрограммы.
Подпрограммы могут быть двух видов: подпрограмма без параметров и подпрограмма с параметрами. Обращение к подпрограмме может быть организовано из любого места основной программы или другой подпрограммы сколько угодно раз.
При работе с подпрограммами важными являются понятия формальных и фактических параметров. Формальные параметры - это идентификаторы входных данных для подпрограммы. Если формальные параметры получают конкретные значения, то они называются фактическими. Формальные параметры могут получить конкретные значения только в той программе, где производится обращение к данному модулю-подпрограмме. Тип и порядок записи фактических параметров должны быть такими же, как и формальных параметров. В противном случае результат работы программы будет непредсказуемым. Из этого следует, что фактические параметры используются при обращении к подпрограмме из основной, а формальные параметры - только в самом модуле.
Подпрограмма с параметрами используется для записи многократно повторяющихся действий при разных исходных данных. Подпрограммы с параметрами можно разделить на два типа: подпрограммы-функции и просто подпрограммы с параметрами (их называют процедурами).
При составлении подпрограмм с параметрами надо соблюдать следующие правила:
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.
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);
While M <> N Do
If M >
Write("Введите числители и знаменатели дробей:");
ReadLn(A, B, C, D);
E:= A * D - B * C;
If E = 0 Then WriteLn(E)
Nod(Abs(E), F, G);
WriteLn("Ответ: ", E, "/", F)
Как видно из примера, объявление и тело подпрограмм находится в разделе описаний. В заголовке подпрограммы содержится список формальных параметров с указанием их типа, которые условно можно разделить на входные и выходные (перед ними стоит служебное Var). При обращении к процедуре указывается ее имя и список фактических параметров. Формальные и фактические параметры должны соответствовать по количеству и по типу.
Вызов процедуры осуществляется следующим образом:
<Идентификатор (имя) процедуры>(<список фактических параметров>);
Например,
Nod(Abs(E), F, G);
По способу передачи фактических значений в подпрограмму в Turbo Pascal 7.0 выделяют параметры-переменные, параметры-значения, параметры-константы и массивы открытого типа, строки открытого типа, параметры-процедуры, параметры-функции (подробности - в литературе).
Функция (в отличие от процедуры) всегда возвращает единственное значение.
Покажем, как изменится подпрограмма из примера, если ее записать в виде функции.
Function Nod(M, N: Integer) : Integer;
While M <> N Do
If M > N Then M:= M - N Else N:= N - M;
Итак, после списка параметров указывается тип значения функции, а в теле функции хотя бы один раз встречается присваивание переменной, имя которой совпадает с именем функции, соотответствующего значения.
Вызов функции будет следующим:
G:= Nod(Abs(E), F);
Вообще, вызов функции может присутствовать в выражении, стоящем: в правой части оператора присваивания, в процедуре вывода, в качестве фактического параметра в вызове другой подпрограммы и т.д.
При решении задач целесообразно проанализировать условие, записать решение в крупных блоках (не являющихся операторами Pascal), детализировать каждый из блоков (записав в виде блоков, возможно, по-прежнему не операторов Pascal), и т.д., продолжать до тех пор, пока каждый из блоков не будет реализован с помощью операторов языка.
Пример 2. Дано натуральное число n. Переставить местами первую и последнюю цифры этого числа.
If Impossible(N)
Then WriteLn("Невозможно переставить цифры, возникнет переполнение")
WriteLn("Ответ: ", N)
Можно заметить, что необходимо детализировать логическую функцию Impossible, которая диагностирует, возможна ли перестановка, и процедуру Change, которая эту перестановку (в случае, если она возможна) выполняет.
Function Impossible(N: Integer) : Boolean;
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)
Здесь необходимо детализировать функцию Number, возвращающую количество цифр в записи натурального числа (т.к. функция Impossible содержит ее вызов, то в разделе описаний функция Number должна ей предшествовать).
Function Number(N: Integer) : Integer;
Var Vsp: Integer;
While N > 0 Do
Vsp:= Vsp + 1; N:= N Div 10
Наконец, последняя процедура.
Procedure Change(Var N: Integer);
Var Kol, P, S, R: Integer;
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
Возможны также подпрограммы, которые вызывают сами себя. Они называются рекурсивными. Создание таких подпрограмм является красивым приемом программирования, но не всегда целесообразно из-за чрезмерного расхода памяти ЭВМ.
Пример 3. Найти максимальную цифру в записи данного натурального числа.
Program MaxDigit;
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.
Более подробно о рекурсии говорится в следующей статье.
| Подпрограммы. Практикум. Практическая работа № 3.5 "Программирование с использованием подпрограмм"
Уроки 45 - 47
Подпрограммы
Практикум
Практическая работа № 3.5
"Программирование с использованием подпрограмм"
![]() |
![]() |
|
![]() |
![]() |
![]() |
Вспомогательные алгоритмы и подпрограммы
Еще одним важнейшим методологическим приемом структурного программирования является декомпозиция решаемой задачи на подзадачи - более простые, с точки зрения программирования, части исходной задачи. Алгоритмы решения таких подзадач называются вспомогательными алгоритмами .
В языках программирования вспомогательные алгоритмы называются подпрограммами. В Паскале различаются две разновидности подпрограмм: процедуры и функции. Рассмотрим этот вопрос на примере следующей задачи: даны два натуральных числа а и b . Требуется определить наибольший общий делитель трех величин: а + b, а 2 + b 2 , а b.
Запишем это так: НОД(а + b, а 2 + b 2 , а b).
Идея решения состоит в следующем математическом факте: если х, у, z - три натуральных числа, то НОД(х, y, z ) = НОД(НОД(х, у ), z ). Иначе говоря, нужно найти НОД двух величин, а затем НОД полученного значения и третьего числа (попробуйте это доказать).
Очевидно, что вспомогательным алгоритмом для решения поставленной задачи является алгоритм получения наибольшего общего делителя двух чисел. Эта задача решается с помощью алгоритма Евклида, который подробно обсуждался в 9 классе. Напомним, что идея алгоритма Евклида основана на следующей формуле:
Приведем алгоритм решения поставленной задачи на учебном Алгоритмическом языке. Алгоритм состоит из процедуры «Евклид» и основного алгоритма «Задача», в котором присутствуют два обращения к процедуре:
Здесь М, N и К являются формальными параметрами процедуры. М и N - параметры-аргументы, К - параметр-результат.
Процедуры в Паскале. Основное отличие процедур в Паскале от процедур в Алгоритмическом языке (АЯ) состоит в том, что процедуры в Паскале описываются в разделе описания подпрограмм, а в АЯ процедура является внешней по отношению к вызывающей программе. Теперь посмотрим, как решение поставленной задачи программируется на Паскале.
В данном примере обмен аргументами и результатами между основной программой и процедурой производится через параметры . Описание процедуры на Паскале имеет следующий формат:
Procedure <имя процедуры> [(список формальных параметров)]; <блок>
Квадратные скобки указывают на то, что список формальных параметров может отсутствовать, т. е. возможна процедура без параметров. Параметры могут быть параметрами-переменными и параметрами-значениями. Параметры-переменные записываются следующим образом:
Var <список переменных>: <тип>
Параметры-значения указываются так:
<список переменных>: <тип>
Чаще всего аргументы представляются как параметры-значения (хотя могут быть и параметрами-переменными). А для передачи результатов используются параметры-переменные. Процедура в качестве результата может передавать в вызывающую программу множество значений (в частном случае - одно), а может и ни одного. Теперь рассмотрим правила обращения к процедуре. Обращение к процедуре производится в форме оператора процедуры :
<имя процедуры>[(список фактических параметров)]
Если описана процедура с формальными параметрами, то обращение к ней производится оператором процедуры с фактическими параметрами. Правила соответствия между формальными и фактическими параметрами: соответствие по количеству , соответствие по последовательности и соответствие по типам .
Взаимодействие формальных и фактических параметров через параметры-переменные называется передачей по ссылке: при обращении к процедуре ей передается ссылка на переменную, заданную в качестве фактического параметра. Эта ссылка и используется процедурой для доступа к этой переменной.
Другой вариант взаимодействия формальных и фактических параметров называется передачей по значению: вычисляется значение фактического параметра (выражения), и это значение присваивается соответствующему формальному параметру.
В рассмотренном нами примере формальные параметры М и N являются параметрами-значениями. Это аргументы процедуры. При обращении к ней первый раз им соответствуют значения выражений А + В и abs(A - В) ; второй раз - С и А*В . Параметр К является параметром-переменной. В ней получается результат работы процедуры. В обоих обращениях к процедуре соответствующим фактическим параметром является переменная С . Через эту переменную основная программа получает результат.
Теперь рассмотрим другой вариант программы, решающей ту же задачу. В ней используется процедура без параметров.
Чтобы разобраться в этом примере, требуется объяснить новое для нас понятие: область действия описания .
Областью действия описания любого программного объекта (переменной, типа, константы и т. д.) является тот блок, на который это описание распространяется. Если данный блок вложен в другой (подпрограмма), то присутствующие во вложенном блоке описания являются локальными . Они действуют только в пределах внутреннего блока. Описания же, расположенные во внешнем блоке, называются глобальными по отношению к внутреннему блоку. Если глобально описанный объект используется во внутреннем блоке, то на него распространяется внешнее (глобальное) описание.
В программе NOD1 переменные М, N, К являются локальными внутри процедуры; переменные А, В, С - глобальные. Однако внутри процедуры переменные А, В, С не используются. Связь между внешним блоком и процедурой осуществляется через параметры.
В программе N0D2 все переменные являются глобальными. В процедуре Evklid нет ни одной локальной переменной (нет и параметров). Переменные М и N , используемые в процедуре, получают свои значения через оператор присваивания в основном блоке программы и изменяют значения в подпрограмме. Результат получается в глобальной переменной К , значение которой выводится на экран. Здесь обмен значениями между основной программой и процедурой производится через глобальные переменные .
Использование механизма передачи через параметры делает процедуру более универсальной, независимой от основной программы. Однако в некоторых случаях оказывается удобнее использовать передачу через глобальные переменные. Чаще такое бывает с процедурами, работающими с большими объемами информации. В этой ситуации глобальное взаимодействие экономит память компьютера.
Функции. Теперь выясним, что такое подпрограмма - функция. Обычно функция используется в том случае, когда результатом работы подпрограммы должна быть скалярная (простая) величина. Тип результата называется типом функции . Формат описания функции следующий:
Как и у процедуры, у функции в списке формальных параметров могут присутствовать параметры-переменные и параметры-значения. Всё это - аргументы функции . Параметры вообще могут отсутствовать, если аргументы передаются глобально.
Программа решения рассмотренной выше задачи с использованием функции будет выглядеть следующим образом:
Из примера видно, что тело функции отличается от тела процедуры только тем, что в функции результат присваивается идентификатору функции : Evklid:=M .
Обращение к функции является операндом в выражении. Оно записывается в следующей форме:
<имя функции> (<список фактических лараметров>)
Правила соответствия между формальными и фактическими параметрами все те же. Сравнивая приведенные выше программы, можно сделать вывод, что программа N0D3 имеет определенные преимущества перед другими. Функция позволяет получить результат путем выполнения одного оператора присваивания. Здесь также иллюстрируется возможность того, что фактическим аргументом при обращении к функции может быть эта же функция.
По правилам стандарта Паскаля, возврат в вызывающую программу из подпрограммы происходит, когда выполнение подпрограммы доходит до ее конца (последний End ). Однако в современных версиях Паскаля есть средство, позволяющее выйти из подпрограммы в любом ее месте. Это оператор-процедура Exit . Например, функцию определения большего из двух данных вещественных чисел можно описать так:
Модифицированный алгоритм Евклида. Подпрограмму алгоритма Евклида можно составить иначе, если воспользоваться операцией mod (получение остатка от деления), имеющейся в Паскале. Идея алгоритма исходит из справедливости следующих равенств:
В таком случае функцию Evklid можно переписать так:
Вопросы и задания
1. Для чего используются подпрограммы?
2. В чем различие между процедурами и функциями?
3. Какие существуют способы передачи данных между подпрограммой и вызывающей ее программой?
4. Составьте программу вычисления площади кольца по значениям внутреннего и внешнего радиусов, используя подпрограмму вычисления площади круга (два варианта: с процедурой и с функцией).
5. Составьте программу сложения двух простых дробей. Результат должен быть несократимой дробью. Используйте подпрограмму вычисления НОД по алгоритму Евклида. Простая дробь задается двумя целыми числами: числителем и знаменателем.
6. По координатам вершин треугольника вычислите его периметр, используя подпрограмму вычисления длины отрезка между двумя точками.
7. Даны три целых числа. Определите, у которого из них больше сумма цифр. Подсчет суммы цифр организуйте через подпрограмму.
Практикум
Работа 3.5. Программирование с использованием подпрограмм
Задание 1
Для решения всех задач сделать два варианта программы: с реализацией указанной подпрограммы в виде функции и в виде процедуры.
Уровень 1
1. Составить программу нахождения наибольшего общего делителя (НОД) и наименьшего общего кратного (НОК) двух натуральных чисел

Использовать подпрограмму алгоритма Евклида для определения НОД.
2. Вычислить площадь правильного шестиугольника со стороной а , используя подпрограмму вычисления площади треугольника.
3. Даны две дроби - (А, В, С, D - натуральные числа).
Составить программу деления дроби на дробь. Ответ должен быть несократимой дробью. Использовать подпрограмму алгоритма Евклида для определения НОД.
4. Даны две дроби - (А, В, С, D - натуральные числа).
Составить программу умножения дроби на дробь. Ответ должен быть несократимой дробью. Использовать подпрограмму алгоритма Евклида для определения НОД.
5. Даны две дроби - (А, В, С, D - натуральные числа).
Составить программу вычитания из первой дроби второй. Ответ должен быть несократимой дробью. Использовать подпрограмму алгоритма Евклида для определения НОД.
6. Написать программу вычисления суммы - для заданного числа n . Результат представить в виде несократимой дроби (р, q - натуральные). Использовать подпрограммы алгоритма Евклида для определения НОД и сложения двух простых дробей.
7. Даны числа X, Y, Z, Т
- длины сторон четырехугольника. Вычислить его площадь, если угол между сторонами длиной X
и Y
- прямой. Использовать две подпрограммы для вычисления площадей: прямоугольного треугольника и прямоугольника.
Задание 2
Для всех задач выделить подзадачи, решения которых могут быть реализованы через подпрограммы. Выбрать наиболее удобный вариант подпрограммы: функцию или процедуру. Составить программу решения задачи.
Уровень 2
1. Дано простое число. Найти следующее за ним простое число.
2. Для заданного натурального числа п найти наименьший нечетный натуральный делитель k (k ≠ 1) .
3. Заменить данное натуральное число на число, которое получается из исходного записью его цифр в обратном порядке (например, дано число 156, нужно получить 651).
4. Найти все натуральные числа, не превосходящие заданного п, которые делятся на каждую из своих цифр.
5. Имеется часть катушки с автобусными билетами. Номер билета шестизначный. Составить программу, определяющую количество счастливых билетов на катушке, если меньший номер билета - N , больший - М (билет является счастливым, если сумма первых трех его цифр равна сумме последних трех).
6. Из заданного числа вычли сумму его цифр. Из результата вновь вычли сумму его цифр и т. д. Через сколько таких действий получится нуль?
7. На отрезке (2 10 < N < 2 31 ) найти количество чисел, составленных из цифр а, b, с .
8. Найти все натуральные n-значные числа, цифры в которых образуют строго возрастающую последовательность (например, 1234,5789).
Уровень 3
9. Два простых числа называются «близнецами», если они отличаются друг от друга на 2 (например, 41 и 43). Напечатать все пары «близнецов» из отрезка , где n - заданное натуральное число, большее 2.
10. Дано четное число n > 2. Проверить для него гипотезу Гольдбаха: каждое четное п представляется в виде суммы двух простых чисел.
11. Составить программу разложения данного натурального числа на простые множители. Например, 200 = 2 3 . 5 2 .
12. Дано натуральное число n. Найти все меньшие п числа Мерсенна. (Простое число называется числом Мерсенна, если оно может быть представлено в виде 2 p - 1, где р - тоже простое число. Например, 31 = 2 5 - 1 - число Мерсенна.)
13. Два натуральных числа называются «дружественными», если каждое из них равно сумме всех делителей (кроме его самого) другого (например, числа 220 и 284). Найти все пары «дружественных» чисел, которые не больше данного числа N .
14. Натуральное число, в записи которого n цифр, называется числом Армстронга, если сумма его цифр, возведенная в степень n , равна самому числу. Найти все числа Армстронга от 1 до k .
15. Найти все простые натуральные числа, не превосходящие n , двоичная запись которых представляет собой палиндром, т. е. читается одинаково слева направо и справа налево.
16. Составить программу для нахождения чисел из интервала [М, N] , имеющих наибольшее количество делителей.
17 Дано натуральное число n > 1. Определить длину периода десятичной записи дроби 1/n.
Популярное
- Универсальная консоль отчетов (8
- Услуга конференц связь мтс отключить
- Музыка (Yandex music downloader)
- Новостной и аналитический портал "время электроники"
- Премиум шаблон Tempera. Супер тема wordpress. Вниманию пользователей Mantra, Nirvana, Parabola, Tempera: плагин Cryout Serious Theme Settings Случайные записи из рубрики
- Мощность: сколько ватт нужно АС
- Россию покроет «умная пыль Умная пыль нанотехнологии
- Обзор тарифов линейки «Просто супер» от МТС-Украина
- LG Spirit - Технические характеристики
- "Неполадки подключения или неверный код MMI "














