Версия:
Аннотация
Функции: создание, вызов по значению и возврат значения. Локальные переменные, аргументы. Рекурсивный вызов функции.
Функции полезны при необходимости выделения общего, часто используемого кода. Например, можно написать функцию, которая считывает количество чисел в текстовом файле. Далее, копируя текст этой функции, её можно переиспользовать, а не писать код каждый раз заново. При этом код функции уже будет "рабочим т.е. ранее использованным и тем самым проверенным.
Покажем как создать функцию, вычислить и вернуть значение.
Без функции Рассмотрим функцию вычисления абсолютного значения. Для начала рассмотрим в очередной раз как выглядит программа без применения функции, где имеет повторяющийся код.
В данной функции два раза выполняется одни и те же вычисления, а именно – вычисляется абсолютная величина. Такой подход имеет ряд недостатков. Во-первых, разрастается код, что приводит к его нагромождению и, соответственно, к ухудшению его читаемости. Во-вторых, каждая копия живет отдельной жизнью и в случае модификации (устранение ошибок, расширение возможностей) одной копии будет необходимо внести изменения и во все остальные, что существенно повышает вероятность появления очередных ошибок (человек плохо умеет копировать действия).
Добавим функцию Функция позволяет обособить часть кода в именной (в данном случае, my_abs) блок, которому передается список значений (в данном случае, k). Передаются именно значения, а не сами переменные причем в общем случае возможно различных типов (в данном случае, int). Модификация программы при применении функции:
Теперь программа стала лаконичнее и яснее.
Функция создана в строчках 11-16. В строчке 11 описывается по порядку возвращаемый тип (int), имя функции (my_abs) и список входных аргументов ((int k)). Сам код функции (фактически, строчки 13 по 15), описывающий соответствующие действия, называется телом функции. В строчке 15 выполняется возврат из функции, т.е. фактически завершение работы функции, и указывается её возвращаемое значение.
В самой программе функция вызывается в строчках 23 и 26. При вызове указывается название функции (my_abs) и значения соответствующих аргументов. При первом вызове (строчка 23) передается значение переменной a, а при втором (строчка 26) – b. После завершения вызова функция возвращает значение (как это было описано в самой первой заметке) и в данном случае оно сохраняется в те же самые переменные.
Обычно функции возвращают значение, при этом точка возврата не обязательно в конце самой функции (как в предыдущей программе в строчке 15). При грамотном использовании этим понятием можно повысить лаконичность и читаемость кода.
Больше одного return Функция может содержать больше одного return. При правильном использовании это упрощает код, делает его более лаконичным. В согласии с предыдущим, перепишем рассматриваемую функцию.
Без return по умолчанию Предыдущая функция содержала возврат по умолчанию. Но, если убедить компилятор (а он бывает настойчив относительно того, что не все ветвления ведущие к завершению функции рассмотрены), то можно и без выхода по умолчанию обойтись.
Тип возвращаемого значения Он может быть произвольным для конкретной функции, но один и тот же у всех вызовов return. При необходимости и возможности компилятор естественно сделает необходимые преобразование типов.
При вызове функции ей передается список значений от которого она и должна выполнить вычисления.
Больше одного аргумента Естественно, что функция может содержать больше одного аргумента. Например, перепишем предыдущую программу так, что вместо вычисления абсолютного значения, вычисляется минимум двух значений.
В описание функции (строчка 4) теперь указаны два аргумента ((int a, int b)). В согласии с этим, при вызове функции (строчка 20) указываются/передаются два значения (a и b). Возвращаемое значение сохраняется в переменную r.
Без аргументов Интересно, что функция может и не содержать ни одного аргумента. По сути она константная (но есть тонкости!). Фрагмент самой функции:
Важно, что в любой момент можно изменить код, отвечающий за вычисление ПИ. В оставшейся программе не придется больше ничего менять.
Например, в любой момент функцию mypi можно заменить на:
Тип аргументов Аргумент(ы) функции могут иметь произвольный тип.
Функция позволяет в некотором смысле обосабливать код отвечающий за функцию. Во-первых, за счет локальности переменных, в частности, аргументов. Во-вторых, за счет достижения большей лаконичности и четкости кода. Последние позволяет функции тестировать (отлаживать) отдельно друг от друга.
Вызов по значению Как и в самой первой программе самой первой заметке уже было отмечено, что при перед вызовом функции сначала вычисляются значение всех аргументов. Таким образом этот этап отделен он вычислений в самой функции. Поэтом их можно разрабатывать, тестировать и отлаживать отдельно друг от друга.
Далее эти значения присваиваются аргументам функции и передается управление функции. При вызове return производится возврат из функции в точку вызова. Значение возвращенное из функции будет использовано в арифметических действия в точке вызова.
Это позволяет отделить вычисления аргументов от самой сути функции и от использования самого возвращенного значения функции.
Локальность аргументов Имя аргумента в функции никакого отношения не имеет к точке вызова функции. При изменении значения аргумента, значению переменной передаваемой в качестве аргумента не меняется. Совпадение или не совпадение имен аргумента и передаваемой переменной ни на что не влияет.
Локальные переменные Из функции не видны переменные из точке вызова функции. Последние означает невозможность их изменения. Даже при совпадении имен! Напомню, что функции вызываются по значению.
Простая рекурсия Когда функция вызывает сама себя, это называется рекурсией. Например, факториал можно вычислить так:
Упражнение. Напишите соответствующий цикл.
Контрольные упражнения Далее следуют контрольные упражнения.
Упражнение. Напиши программу подчета наибольшего общего делителя как итеративно, так и рекурсивно.
Упражнение. Напиши функция быстрого возведения в степень.
Упражнение. Фибоначи.