Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Подбельский Фомин_Программирование на языке СИ_...doc
Скачиваний:
356
Добавлен:
10.08.2019
Размер:
53.81 Mб
Скачать

Указатели на функции как параметры

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

Параметры функции rectangle( ): pf - указатель на функцию с параметром типа double, возвращающую значение типа double. Это указатель на функцию, вычисляющую значение подынтегральной функции при заданном значении аргумента. Параметры a, b - пределы интегрирования. Число интервалов разбиения отрезка интегрирования фиксировано: N=20. Пусть текст функции под именем rect.c сохранен в каталоге пользователя.

Предложим, что функция rectangle( ) должна быть использована для вычисления приближенных значений интегралов (Абрамов С.А., Зима Е.В. Начала информатики. - М.: Наука, 1989.- С. 83):

Программа для решения этой задачи может иметь следующий вид:

Комментарии к тексту программы могут быть следующими. Директива #include "rect.c" включает на этапе препроцессорной обработки в программу определение функции rectangle(). Предполагается, как упомянуто выше, что текст этого определения находится в файле rect.c. В языке Си, как говорилось в главе 3, существует соглашение об обозначении имен включаемых файлов. Если имя файла заключено в угловые скобки '< >', то считается, что это один из файлов стандартной библиотеки компилятора. Например, файл <math.h> содержит средства связи с библиотечными математическими функциями. Файл, название которого помещено в кавычках " ", воспринимается как файл из текущего каталога. Именно там в этом примере препроцессор начинает разыскивать файл rect.c.

Определения функций ratio( ) и cos4_2(), позволяющих вычислять значения подынтегральных выражений по заданному значению аргумента, ничем не примечательны. Их прототипы соответствуют требованиям спецификации первого параметра функции rectangle( ):

double имя (double)

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

Указатель на функцию как возвращаемое функцией значение.

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

Рассмотрим программу, демонстрирующую особенности такой организации меню.

В программе определены три функции: первые две функции f 1 ( ) и f2( ) с прототипом вида

int f (void);

(пустой список параметров, возвращается значение типа int) и третья функция menu() с прототипом

int (*menu(void)) (void);

которая возвращает значение указателя на функции с пустыми списками параметров, возвращающие значения типа int.

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

В основной программе определен указатель г, который может принимать значения адресов функций f1( ) и f2( ). В бесконечном цикле выполняются обращения к функции menu( ), и если результат равен NULL, то программа печатает "The End" и завершает выполнение. В противном случае вызов

обеспечивает исполнение той из функций fl() или f2(), адрес которой является значением указателя r. Текст программы*:

* Исходный вариант программы предложен С.М. Лавреневым.

Результаты выполнения программы:

В функции menu() определен массив menu_items[ ] указателей на функции. В качестве инициализирующих значений в списке использованы имена функций f1( ) и f2():

int (* menu_items[ ] ) ( ) = {fl, f2};

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

typedef int (*Menu_action) (void);

Menu_action menujtems [ ] = {fl, f2};

Здесь typedef вводит обозначение Menu_action для типа "указатель на функции с пустым списком параметров, возвращающие значения типа int".