Что такое имя функции в программировании. Операторы организации циклов. Чистые и Грязные функции

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

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

Существует множество встроенных в язык программирования функций. С некоторыми такими в Python мы уже сталкивались. Это print(), input(), int(), float(), str(), type(). Код их тела нам не виден, он где-то "спрятан внутри языка". Нам же предоставляется только интерфейс – имя функции.

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

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

i = 0 while i < 3 : a = int (input () ) b = int (input () ) print (a+b) i += 1

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

print () a = int (input () ) b = int (input () ) print ("Всего" , a+b, "шт." ) print () a = int (input () ) b = int (input () ) print ("Всего" , a+b, "шт." )

Пример исполнения программы:

Сколько бананов и ананасов для обезьян? 15 5 Всего 20 шт. Сколько жуков и червей для ежей? 50 12 Всего 62 шт. Сколько рыб и моллюсков для выдр? 16 8 Всего 24 шт.

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

Определение функции. Оператор def

В языке программирования Python функции определяются с помощью оператора def. Рассмотрим код:

def countFood() : a = int (input () ) b = int (input () ) print ("Всего" , a+b, "шт." )

Это пример определения функции. Как и другие сложные инструкции вроде условного оператора и циклов функция состоит из заголовка и тела. Заголовок оканчивается двоеточием и переходом на новую строку. Тело имеет отступ.

Ключевое слово def сообщает интерпретатору, что перед ним определение функции. За def следует имя функции. Оно может быть любым, также как и всякий идентификатор, например, переменная. В программировании весьма желательно давать всему осмысленные имена. Так в данном случае функция названа "посчитатьЕду" в переводе на русский.

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

После двоеточия следует тело, содержащее инструкции, которые выполняются при вызове функции. Следует различать определение функции и ее вызов. В программном коде они не рядом и не вместе. Можно определить функцию, но ни разу ее не вызвать. Нельзя вызвать функцию, которая не была определена. Определив функцию, но ни разу не вызвав ее, вы никогда не выполните ее тела.

Вызов функции

Рассмотрим полную версию программы с функцией:

def countFood() : a = int (input () ) b = int (input () ) print ("Всего" , a+b, "шт." ) print ("Сколько бананов и ананасов для обезьян?" ) countFood() print ("Сколько жуков и червей для ежей?" ) countFood() print ("Сколько рыб и моллюсков для выдр?" ) countFood()

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

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

В языке Python определение функции должно предшествовать ее вызовам. Это связано с тем, что интерпретатор читает код строка за строкой и о том, что находится ниже по течению, ему еще неизвестно. Поэтому если вызов функции предшествует ее определению, то возникает ошибка (выбрасывается исключение NameError):

print ("Сколько бананов и ананасов для обезьян?" ) countFood() print ("Сколько жуков и червей для ежей?" ) countFood() print ("Сколько рыб и моллюсков для выдр?" ) countFood() def countFood() : a = int (input () ) b = int (input () ) print ("Всего" , a+b, "шт." )

Результат:

Сколько бананов и ананасов для обезьян? Traceback (most recent call last ) : File "test.py" , line 2 , in < module> countFood() NameError: name "countFood" is not defined

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

Функции придают программе структуру

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

Пусть надо написать программу, вычисляющую площади разных фигур. Пользователь указывает, площадь какой фигуры он хочет вычислить. После этого вводит исходные данные. Например, длину и ширину в случае прямоугольника. Чтобы разделить поток выполнения на несколько ветвей, следует использовать оператор if-elif-else:

figure = input () if figure == "1" : a = float (input ("Ширина: " ) ) b = float (input ("Высота: " ) ) print ("Площадь: %.2f" % (a*b) ) elif figure == "2" : a = float (input ("Основание: " ) ) h = float (input ("Высота: " ) ) print ("Площадь: %.2f" % (0.5 * a * h) ) elif figure == "3" : r = float (input ("Радиус: " ) ) print ("Площадь: %.2f" % (3.14 * r**2 ) ) else : print ("Ошибка ввода" )

Здесь нет никаких функций, и все прекрасно. Но напишем вариант с функциями:

def rectangle() : a = float (input ("Ширина: " ) ) b = float (input ("Высота: " ) ) print ("Площадь: %.2f" % (a*b) ) def triangle() : a = float (input ("Основание: " ) ) h = float (input ("Высота: " ) ) print ("Площадь: %.2f" % (0.5 * a * h) ) def circle() : r = float (input ("Радиус: " ) ) print ("Площадь: %.2f" % (3.14 * r**2 ) ) figure = input ("1-прямоугольник, 2-треугольник, 3-круг: " ) if figure == "1" : rectangle() elif figure == "2" : triangle() elif figure == "3" : circle() else : print ("Ошибка ввода" )

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

Если нам когда-нибудь захочется вычислять площадь треугольника по формуле Герона, а не через высоту, то не придется искать код во всей программе (представьте, что она состоит из тысяч строк кода как реальные программы). Мы пойдем к месту определения функций и изменим тело одной из них.

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

Практическая работа

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

Основная ветка программы, не считая заголовков функций, состоит из одной строки кода. Это вызов функции test(). В ней запрашивается на ввод целое число. Если оно положительное, то вызывается функция positive(), тело которой содержит команду вывода на экран слова "Положительное". Если число отрицательное, то вызывается функция negative(), ее тело содержит выражение вывода на экран слова "Отрицательное".

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

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

Начнем с оператора цикла с предусловием . Данный оператор имеет вид:

While do .

При выполнении этого оператора вначале вычисляется значение логического выражения. Если это значение истинно, выполняется оператор. Затем значение выражения проверяется вновь, и все повторяется до тех пор, пока выражение не примет значение «ложь». Каждое выполнение цикла иногда называют итерацией цикла. Если выражение принимает значение «ложь» при первой же проверке, то оператор не выполняется вообще.

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

Цикл с постусловием имеет вид:

Repeat…until…

Здесь вначале выполняется оператор statement(утверждение), и только затем вычисляется значение логического выражения. Именно поэтому такой цикл называют циклом с постусловием. Процесс повторяется, пока выражение имеет значение «ложь». Как только его значение становится истинным, выполнение цикла прекращается. Оператор может быть любым, в том числе и составным оператором:

Оператор_1;

Оператор_2;

…………….

Оператор_N;

Until

В цикле repeat...until проверка выполняется в последнюю очередь, и тело цикла в любом случае выполняется хотя бы один раз.

Операторы цикла со счетчиком: for...to...do и for…downto …do.

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

For параметр цикла:= начальное значение to конечное значение do ;

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

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

Вариант for…downto...do... цикла for аналогичен циклу for..to…do за исключением того, что в нем управляющая переменная на каждом шаге выполнения не увеличивается, а уменьшается на единицу:

for j:- downto do .

Подводя итоги, для применения циклов можно сформулировать следующие рекомендации:

Используйте цикл for в том случае, когда точно знаете, сколько раз должно быть выполнено тело цикла. В противном случае обратитесь к циклам repeat или while.

· Используйте while, если хотите, чтобы проверка была произведена прежде, чем будет выполняться тело цикла.

· Иногда бывает удобно проводить проверку на возможный выход из цикла где-нибудь в его середине, а не в начале или конце.

Такой выход из цикла обеспечивается процедурой Break, которая прерывает выполнение самого внутреннего вложенного цикла, будь то for, while или repeat. Указанный модуль подключается к программе автоматически, если в этом есть необходимость.

While true do begin

If then Break

; end

Следует также упомянуть процедуру Continue, которая прерывает выполнение тела самого внутреннего цикла for, while или repeat и передает управление на его заголовок, так что начинается выполнение очередной итерации цикла.

Шаг цикла for всегда постоянный и равен интервалу между двумя ближайшими значениями типа параметра цикла.

Var {описание параметров цикла}

i: integer(целочисленный тип);

c: char(символьный тип);

1. Begin {вывод на печать целых чисел от 1 до 10}

For i:=1 to 10 do writeln (i);{шаг цикла равен 1}

2. {вывод на печать чисел от 10 до -10}

For 10 down to -10 {шаг цикла равен -1}

3. {вывод на печать латинских символов от A до R}

{параметр цикла изменяется от A до R в алфавитном порядке}

For c:=‘A’ to ‘R’ do writeln (c);

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

Пример: Вычисление суммы от 1 до n.

var s,n,i: integer;

writeln (‘Введите n’);

for i:=1 to n do s:=s+i;

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

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

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

Функция, создаваемая разработчиком, должна иметь определение, а ее применение в программе называют вызовом функции. Например, в JavaScript и РНР (а также в большинстве других языков) такое определение начинается с ключевого слова function , за которым следуют имя функции, пара круглых скобок, внутри которых можно указать список параметров, а затем блок кода, заключенный в фигурные скобки:

Funсtion имя_функции(список_парамeтров) { блок кода }

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

Для вызова функции в том или ином месте программы указывают следующее выражение:

Имя_функции(список_параметров)

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

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

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

Результат работы функции

Если вызывающей программе ничего не требуется получить от вызванной функции, то программист может определить эту функцию как ничего не возвращающую. Это разрешается в JavaScript и РНР, но может быть недопустимо в других языках. Если даже практически не важно, что именно возвращает функция, все равно желательно определить для нее некоторое возвращаемое значение. В таких случаях, часто указывают, например, пустое значение, обозначаемое как null . Возможны и другие варианты. Кроме того, функции, возвращающие какие-то значения, можно использовать в выражениях с операторами (например, арифметическими), а также в качестве параметров других функций. Если функция ничего не возвращает, то ее применение в выражениях с операторами обычно чревато сообщениями об ошибках.

Чтобы функция что-то возвращала, необходимо записать в ее теле специальный оператор возврата:

Return \возвращаемое значение\;

Приведу пример:

Оклад = 10000; Процент = 15; Выплата = Оклад + Премия(Оклад, Процент); function Премия (Оклад, Процент) { return Оклад * Процент / 100; }

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

Данный программный код написан на вымышленном (абстрактном) языке. Я хотел сказать, что рассмотренный пример иллюстрирует принцип применения функции, а потому не важно, какой именно язык выбрать. Главное, что все изложенное ранее должно позволить вам понять данный код. Тем не менее, признаюсь, что приведенный мной пример написан и на языке JavaScript. Напишите в обычном текстовом редакторе, например, в Блокноте Windows следующие строки:

Оклад = 10000; function Премия(Оклад, Процент) { return Оклад * Процент / 100; } alert("Выплата = " + Выплата);

Это HTML-код с внедренным в него сценарием на JavaScript. Код сценария заключен между тегами и отличается от рассмотренного ранее только встроенной функцией alert () для вывода сообщений в диалоговом окне. Сохраните данный код в файле с расширением htm или html, а затем откройте его в Web-браузере, например, Microsoft Internet Explorer или Mozilla Firefox. В результате появится диалоговое окно с сообщением "Выплата =11500".

Назначение

Появление в 1960-х годах в языках (например, ALGOL и FORTRAN) функций позволило писать программы, более ясные в структурном отношении и компактные по объему кода. В идеале основная программа могла состоять из одних только вызовов функций, перемежаемых, возможно, операторами управления (условными переходами и/или циклами). Разрабатывать и отлаживать такие программы стало и быстрее и легче. Программист при желании мог писать программы, широко используя вызовы функций, тела которых еще не написаны.

Чтобы такая программа как-то работала без зависаний и выдачи системных сообщений об ошибках, вместо настоящего кода функции можно было временно поставить так называемые заглушки, например, выво­ды специальных сообщений программиста, например, "работает функция mуfunc".

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

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

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

Приведение типов

Возможно, вы заметили одно странное обстоятельство: функции аlert() в качестве параметра передается выражение в виде суммы разнотипных данных (символьного и числового значения):

"Выплата = " + Выплата

Здесь "Выплата =" - символьная строка, а Выплата - переменная числового типа. Ведь ранее упоминалось, что типы данных для того и придуманы, чтобы выполнять операции над однотипными данными. Тем не менее, сообщений об ошибках не было, а результат оказался правильным!

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

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

Методы окружения

Также может вызвать недоумение функция alert() , которая использовалась для вывода на экран диалогового окна с некоторым сообщением. А откуда она взялась? В сценарии же нет ее определения.

Если быть точным, то alert() - не функция языка JavaScript, а метод объекта window , который принадлежит объектной модели браузера. Методами называют внутренние функции объектов. Иначе говоря, этот метод, как и множество других объектов браузера и загруженного в него документа, составляют внешнее окружение сценария на JavaScript. К объектам этого окружения можно обратиться из сценария, т. е. прочитать и даже изменить значения их свойств. Тем самым обеспечивается возможность управлять внешним видом и информационным содержанием Web-страницы.

Разумеется, модель того, с чем требуется иметь дело посредством языка программирования, необходимо знать. Но это особая тема. Сейчас же мы рассматриваем языки программирования, причем с высоты "птичьего полета", и до поры не будем слишком приближаться к "земле".

Цель работы: 1) изучить правила описания функций; 2) приобрести навыки использования функций при написании программ на языкеC++.

Теоретические сведения

Основным модулем программ в языке С++ является функция.

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

Каждая программа на языке С++ обязательно содержит функцию с именем main (главная), которая является телом программы. Для всех остальных функций, если они присутствуют в программе, следует объявлять прототипы - схематические записи, которые сообщают компилятору имя и форму каждой функции в программе.

Синтаксис для прототипа функций с параметрами:

тип_возвращаемого_значения имя_функции (список_параметров_с_указанием_типов);

Функции в С++ бывают стандартные (библиотечные) и программируемые пользователем.

Стандартные функции

Описания стандартных функций находятся в файлах, включаемых в программу с помощью директивы #include. Такие файлы называют заголовочными; они имеют расширение h.

Обращение к имени функции в основной программе называется вызовом функции.

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

y = sin (x); //функция вычисления синуса

Определение функции

В общем виде функции определяются следующим образом:

тип_возвращаемого_значения имя_функции (тип имя_параметра,...,тип имя_параметра)

тело_функции

Программируемые функции

Функции, которые программист создает сам, упрощают процесс написания программ, поскольку они:

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

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

Пример 9 .1. Создадим функцию, которая печатает 65 символов "*" в ряд. Чтобы эта функция выполнялась в некотором контексте, она включена в программу печати фирменного бланка. Программа состоит из функций: main() и stars().

// Фирменный бланк

#include

const int Limit=65;

void stars(void); // прототип функции stars()

cout