Создание заголовочного файла
Прототипы функций
Рекурсивные и нерекурсивные функции
Существует важный класс функций, называемых рекурсивными. Функция называется рекурсивной, если она вызывает сама себя. Хотя любую рекурсивную программу можно переписать без использования рекурсии, в ряде случаев рекурсивная версия функции имеет более простой вид, особенно в тех случаях, когда вычисляемое значение или объект, используемый в функции, определяется рекурсивно.
Рассмотрим функцию, вычисляющую факториал. Факториал числа N обозначается через N! и равен произведению 1*2*3*4*…*N; по определению также полагается 0!=1. Очевидная реализация такой функции следующая:
int factorial(int n) {
int result = 1;
for (int i=1; i<=n; i++) {
result *= i;
}
return result;
}
Заметим теперь, что факториал можно задать двумя формулами: 0!=1 и N!=N*(N-1)! В данном случае значение задается только для минимального N, т.е. для 0, а для остальных значения функция определяется через предыдущее значение N. Например, 6!=6*5! Используя данные соотношения функцию вычисления факториала можно модифицировать:
|
|
int factorial(int n) {
if (n==0) {
return 1;
} else {
return n*factorial(n-1);
}
}
Можно воспользоваться и оператором?:
int factorial(int n) {
return n==0? 1: n*factorial(n-1);
}
Обратите внимание на то, что такая реализация не использует цикл, зато она вызывает сама себя: n*factorial(n-1).
Описание функции состоит из двух частей: объявление и реализация. Прототип функции сообщает компилятору, что такая функция есть, и ее реализация находится где-то ниже.
float average(float x, float y, float z);
int main() {
cout << average(1.2,3.4,5.6);
}
float average(float x, float y, float z) {
return (x+y+z)/3;
}
Мы уже сталкивались с заголовочными файлами, когда подключали библиотеку stdio.h для работы с функциями ввода/вывода или библиотеку stdlib.h для работы с функцией rand() для генерации псевдослучайных чисел. Эти функции были кем-то реализованы, и любой программист может их использовать. Другими словами, функция написана один раз, а использована она может быть использована много раз и в разных программах.
По аналогии с этими библиотеками можно создать и свою библиотеку, куда поместить часто используемые функции. Для этого нужно выполнить следующие действия:
- создать файл с расширением.h;
- поместить в него необходимые функции;
- подключить файл в программе;
- вызвать требующуюся функцию.
Существенным недостатком многих программ, написанных начинающими (да и не только начинающими) программистами, является их непонятность. Одна из рекомендаций по созданию понятных функций заключается в том, чтобы ее текст помещался на экране; это существенно облегчает чтение кода. Рассмотрим несколько типичных приемов, позволяющих значительно сократить размер функций.
|
|
Рассмотрим функцию, которая проверяет, является ли число четным:
bool isEven(int n) {
if (n%2==0) {
return true;
} else {
return false;
}
}
Обратите внимание на то, что, если убрать ветку else, то работа функции не изменится, поскольку оператор return останавливает работу функции:
bool isEven(int n) {
if (n%2==0) {
return true;
}
return false;
}
Еще сократить код можно при помощи оператора?::
bool isEven(int n) {
return n%2==0? true: false;
}
Однако оптимальный вариант выглядит так:
bool isEven(int n) {
return n%2 == 0;
}
Посмотрите, какой длинной программа была в начале, и какой компактной она стала в конце!
Рассмотрим еще один пример лаконичной записи функции, определяющей максимум из двух чисел. Очевидный способ следующий:
int max(int m, int n) {
if (m>n) {
return m;
} else {
return n;
}
}
Сократить код можно так:
int max(int m,int n) {
return m>n? m: n;
}
Еще один пример, использующий то, что оператор return прерывает работу функции, – это поиск элемента в массиве. Он может быть реализован так:
int indexOf(int element) {
for (int i=0; i<n; i++) {
if (numbers[i]==element) {
return i;
}
}
return -1;
}
Возвращение функцией индекса -1 является общепринятым способом сообщить, что элемент не найден.