В этом разделе рассмотрим передачу в качестве аргумента имени функции.
Этот специфический вид аргумента позволяет придать программе универсальность.
Пример. Найти 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 */