Передача функций

В этом разделе рассмотрим передачу в качестве аргумента имени функции.

Этот специфический вид аргумента позволяет придать программе универсальность.

Пример. Найти y=min(f(x)), где {xi}, i=1...n. Существует множество методов нахождения экстремума функции многих переменных, практически не зависящих от вида функции, минимум которой отыскивается.

Сопряжение, т.е. имя функции со списком аргументов, min_fun(x, n, dx, eps, f) практически одинаково для различных методов. Здесь вектор (одномерный массив) x является одновременно и входным параметром (начальное приближение), и выходным (найденная точка минимума); n – число координат; dx – начальный шаг поиска; eps – точность нахождения минимума; f – имя минимизируемой функции.

Передаваемое значение является адресом функции. Следовательно, соответствующий параметр – указатель на функцию. Это специфический объект, характерный только для языков Cи С++.

Формат объявления: [<тип>](*<имя>)();

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

float f1(float [ ]), min_fun(float [ ], int, float, float, float(*)( )), z;

..........................

z=min_fun(s, l, delta_x, epsilon, f1);

Вызываемая процедура:

float min_fun(float x[ ], int n, float dx, float eps, float(*f)( )){

..........................

}

Следует раличать записи:

[<тип>] *f(void); и [<тип>](*f)(void);

Первая – прототип функции без параметров, возвращающей указатель на <тип>, вторая – прототип указателя на функцию, возвращающей значение данного типа.


Пример. Вычислить и напечатать таблицу функции: Интеграл вычислять методом трапеций.

/* Вычислить таблицу y=f(alfa) */

void main(void){

double f1(double), // Подинтегральная функция

y, // Значение интеграла

alfa, // Параметр

trap(double, double, int, double(*)( )); // Метод трапеций /

for(alfa=2; alfa<3.05; alfa+=.1){

y=trap(.15, alfa, 20, f1);

printf("%10cальфа=%.1lf интеграл=%.6lf\n", ' ', alfa, y);

}

} // End main

/* Интегрирование методом трапеций */

double trap( double a, // Нижний предел интегрирования

double b, // Верхний --------------------

int k, // Число элементарных интервалов

double (*f)( )){ // Подинтегральная функция

double dx, // Размер элементарного интервала

t;

int i;

dx=(b-a )/k;

t=((*f)(a)+(*f)(b))/2;

for(i=1; i<k; i++){

t += (*f)(a+i*dx);

}

return dx*t;

} /* End trap */

/* Подинтегральная функция */

double f1(double x){

return exp(x)*cos(pow(x, 3));//Без прототипов все эти функции возвращают // int

} /* End f1 */