Как передать функцию в функцию c
Перейти к содержимому

Как передать функцию в функцию c

  • автор:

Как передать функцию в функцию c

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

#include int add(int, int); int subtract(int, int); int operation(int(*)(int, int), int, int); // первый параметр — указатель на функцию int main() < int a; int b; int result = operation(add, a, b); std::cout int add(int x, int y) < return x + y; >int subtract(int x, int y) < return x - y; >int operation(int(*op)(int, int), int a, int b)

В данном случае первый параметр функции operation — int (*op)(int, int) — представляет указатель на функцию, которая возвращает значение типа int и принимает два параметра типа int . Результатом функции является вызов той функции, на которую указывает указатель.

Определению указателя соответствуют две функции: add и subtract, поэтому их адрес можно передать в вызов функции operation: operation(add, a, b); .

Результат работы программы:

result: 16 result: 4

Функция, передаваемая другой функции в качестве аргумента, называется функцией обратного вызова или коллбек (callback). А функция, которая принимает другую функцию в качестве аргумента, является функцией высшего порядка. Таким образом, в примере выше функция operation представляет функцию высокого порядка, а функции add и subtract — функции обратного вызова.

Рассмотрим другой пример — определим функцию, которая может принимать в качестве параметра некоторое условие и вычислять все элементы массива, которые соответствуют этому условию:

#include // функции, которые представляют условия bool isEven(int); // если число четное bool isPositive(int); // если число положительное // Функция для определения элементов массива, которые соответствуют некоторому условию // функция принимает условие — bool(*)(int) // массив — int[] // размер массива — unsigned void action(bool(*)(int), int[], unsigned); int main() < int numbers[]< -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 >; const unsigned n < std::size(numbers)>; // находим длину массива std::cout bool isEven(int x) < return x % 2 == 0; >bool isPositive(int x) < return x >0; > void action(bool(*condition)(int), int numbers[], unsigned n) < // перебираем массив for (unsigned i<>; i < n; i++) < // если число (numbers[i] соответствует условию condition if (condition(numbers[i])) < std::cout > std::cout

Функция action в качестве первого параметра принимает некоторую функцию, которая задает условие, которому должны соответствовать элементы массива. Это условие представляет указатель bool (*condition)(int) . То есть это некоторая функцию, которая принимает целое число и в зависимости от того, соответствует оно условию или нет, возвращает значение типа bool ( true , если число из массива соответствует условию, и false , если не соответствует). На момент определения функции action точное условие может быть неизвестно.

В текущей программе условия представлены двумя функциями. Функция isEven() возвращает true, если число четное, и false, если число нечетное. А функция isPositive() возвращает true, если число положительное, и false, если отрицательное.

Второй параметр функции action — массив чисел int, для которых вызываем условие. А третий параметр — размер массива. Если число соотвествует условию, то выводим это число на консоль

void action(bool(*condition)(int), int numbers[], unsigned n) < // перебираем массив for (unsigned i<>; i < n; i++) < // если число (numbers[i] соответствует условию condition if (condition(numbers[i]))

При вызове функции action() в нее можно передать нужное условие:

action(isEven, nums, n); action(isPositive, numbers, n);

В итоге программа выведет на экран числа из массива nums, которые соответствуют переданному условию:

Even numbers: -4 -2 0 2 4 Positive numbers: 1 2 3 4 5

Как передать функцию в функцию c

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

#include int add(int x, int y) < return x+y; >int subtract(int x, int y) < return x-y; >int operation(int (*op)(int, int), int a, int b) < return op(a, b); >int main(void)

Здесь в функции operation первый параметр — указатель int (*op)(int, int) представляет функцию, которая возвращает значение типа int и принимает два параметра типа int . Результатом функции является вызов той функции, на которую указывает указатель.

Определению указателя соответствуют две функции: add и subtract, поэтому их адрес можно передать в вызов функции operation: operation(add, a, b); .

Другой пример — функция, которая может принимать в качестве параметра некоторое условие:

#include int isEven(int x) < return x%2==0; >int isPositive(int x) < return x>0; > void action(int (*condition)(int), int numbers[], int n) < for(int i=0; i> > int main(void) < int nums[] = ; int n = sizeof(nums)/sizeof(nums[0]); printf("Even numbers: "); action(isEven, nums, n); printf("\nPositive numbers: "); action(isPositive, nums, n); return 0; >

Первый параметр функции action — указатель int (*condition)(int) представляет функцию, которая принимает целое число и в зависимости от того, соответствует оно условию или нет, возвращает 1 (если соответствует) или 0. На момент определения функции action точное условие может быть неизвестно.

В текущей программе условия представлены двумя функциями. Функция isEven() возвращает 1, если число четное, и 0, если число нечетное. А функция isPositive() возвращает 1, если число положительное, и 0, если отрицательное.

При вызове функции action() в нее можно передать нужное условие: action(isEven, nums, n); . В итоге программа выведет на экран числа из массива nums, которые соответствуют переданному условию:

Even numbers: -4 -2 0 2 4 Positive numbers: 1 2 3 4 5

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

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

Например, нам надо выбрать и выполнить одну из трех арифметических операций

#include int add(int x, int y) < return x + y; >int subtract(int x, int y) < return x - y; >int multiply(int x, int y) < return x * y; >// int choice - выбранный пункт int (*select(int choice))(int, int) < // возвращаем нужную функцию switch (choice) < case 2: return subtract; case 3: return multiply; default: return add; >> int main(void) < int (*operation)(int, int); // указатель на выбранную функцию operation = select(1); // получаем указатель на функцию add - сложение int result = operation(6, 4); // выполняем функцию printf("result: %d \n", result); // result: 10 return 0; >

В данной программе мы предполагаем, что пользователь должен выбрать для выполнения одну из трех функций: add, subtract, multiply, каждая из которых представляет определенное действие.

Все выбираемые функции имеют один и тот же прототип вида:

int action(int, int);

То есть возвращают значение типа int и принимают два параметра типа int .

Сам выбор происходит в функции select() . Она возвращает указатель на функцию — по сути выбранную функцию. Посмотрим на ее заголовок:

int (*select(int choice))(int, int)

Если рассматривать по компонентам, то заголовок выглядит следующим образом:

тип_указателя_на_функцию (*select(параметры_функции))(параметры_указателя_на_функцию)

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

Далее в скобках идет название самой функции и ее параметры — (*select(int choice)) . То есть функция select , которая возвращает указатель на функцию, принимает один параметр — choice — условный номер арифметической функции.

Зтаем идут типы параметров функции, указатель на которую возвращается: (int, int)

То есть в итоге функция select() имеет один параметр choice , который представляет тип int , и возвращает указатель на функцию, которая имеет прототип int action(int, int) .

В самой функции select() в зависимости от значения параметра choice возвращаем определенную функцию:

switch (choice)

В функции main сначала определяем указатель, который соответствует прототипу арифметических функций add, subtract, multiply:

int (*operation)(int, int);

Далее в этот указатель получаем результат из функции select , передав в нее номер функции:

operation = select(1);

По номеру 1 функция select возвращает функцию add . Соответственно переменная-указатель operation будет хранить адрес функции add.

Далее вызываем функцию, на которую указавает указатель, передвая ей два числа для ее параметров:

int result = operation(6, 4); // выполняем функцию

Подобным образом можно получить и другие функции:

int main(void) < int (*operation)(int, int) = select(2); // получаем указатель на функцию subtract printf("result: %d \n", operation(6, 4)); // result: 2 operation = select(3); // получаем указатель на функцию multiply printf("result: %d \n", operation(6, 4)); // result: 24 return 0; >

Для хранения всех действий в функции select определен массив указателей на функции actions:

int (*actions[])() = ;

С помощью введенного с клавиатуры числа определяем номер нужного действия, которое надо выполнить. Если номер меньше 1 или больше 3, то возвращается константа NULL.

В главной функции main() в бесконечном цикле вызываем функцию select, получая в качестве результата указатель на функцию:

action = select();

И если указатель не равен NULL, то после этого мы сможем вызвать функцию по указателю и получить ее результат:

actionNumber = action();

Консольный вывод работы программы:

Select action (1, 2, 3): 1 Action 1 selected action 1 Select action (1, 2, 3): 3 Action 3 selected action 3 Select action (1, 2, 3): 4 End

Функции. Передача аргументов по значению и по ссылке

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

При изучении работы функций важно понимать, что такое локальная и что такое глобальная переменные. В языке программирования C глобальные (внешние) переменные объявляются вне какой-либо функции. С их помощью удобно организовывать обмен данными между функциями, однако это считается дурным тоном, т.к. легко запутывает программу. Локальные переменные в языке программирования C называют автоматическими. Область действия автоматических переменных распространяется только на ту функцию, в которой они были объявлены. Параметры функции также являются локальными переменными.

Структурная организация файла программы на языке C, содержащего несколько функций, может выглядеть немного по-разному. Так как выполнение начинается с main() , то ей должны быть известны спецификации (имена, количество и тип параметров, тип возвращаемого значения) всех функций, которые из нее вызываются. Отсюда следует, что объявляться функции должны до того, как будут вызваны. А вот определение функции уже может следовать и до и после main() . Рассмотрим такую программу:

#include // объявление функции float median (int a, int b); int main () { int num1 = 18, num2 = 35; float result; printf("%10.1f\n", median(num1, num2)); result = median(121, 346); printf("%10.1f\n", result); printf("%10.1f\n", median(1032, 1896)); } // определение функции float median (int n1, int n2) { float m; m = (float) (n1 + n2) / 2; return m; }

В данном случае в начале программы объявляется функция median() . Объявляются тип возвращаемого ею значения ( float ), количество и типы параметров ( int a, int b ). Обратите внимание, когда объявляются переменные, то их можно группировать: int a, b; . Однако с параметрами функций так делать нельзя, для каждого параметра тип указывается отдельно: (inta, int b) .

Далее идет функция main() , а после нее — определение median() . Имена переменных-параметров в объявлении функции никакой роли не играют (их вообще можно опустить, например, float median (int, int); ). Поэтому когда функция определяется, то имена параметров могут быть другими, однако тип и количество должны строго совпадать с объявлением.

Функция median() возвращает число типа float . Оператор return возвращает результат выполнения переданного ему выражения; после return функция завершает свое выполнение, даже если далее тело функции имеет продолжение. Функция median() вычисляет среднее значение от двух целых чисел. В выражении (float) (n1 + n2) / 2 сначала вычисляется сумма двух целых чисел, результат преобразуется в вещественное число и только после этого делится на 2. Иначе мы бы делили целое на целое и получили целое (в таком случае дробная часть просто усекается).

В теле main() функция median() вызывается три раза. Результат выполнения функции не обязательно должен быть присвоен переменной.

Вышеописанную программу можно было бы записать так:

#include float median (int n1, int n2) { float m; m = (float) (n1 + n2) / 2; return m; } int main () { int num1 = 18, num2 = 35; float result; printf("%10.1f\n", median(num1, num2)); result = median(121, 346); printf("%10.1f\n", result); printf("%10.1f\n", median(1032, 1896)); }

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

Напишите функцию, возводящую куб числа, переданного ей в качестве аргумента. Вызовите эту функцию с разными аргументами.

Статические переменные

В языке программирования C существуют так называемые статические переменные. Они могут быть как глобальными, так и локальными. Перед именем статической переменной пишется ключевое слово static .

Внешние статические переменные, в отличие от обычных глобальных переменных, нельзя использовать из других файлов в случае программы, состоящей не из одного файла. Они глобальны только для функций того файла, в котором объявлены. Это своего рода сокрытие данных, по принципу «не выставлять наружу ничего лишнего, чтобы ‘что-нибудь’ нечаянно не могло ‘испортить’ данные».

Статические переменные, объявленные внутри функций имеют такую же область действия, как автоматические. Однако в отличие от автоматических, значения локальных статических переменных не теряются, а сохраняются между вызовами функции:

#include int hello(); int main() { printf(" - %d-й вызов\n", hello()); printf(" - %d-й вызов\n", hello()); printf(" - %d-й вызов\n", hello()); } int hello () { static count = 1; printf("Hello world!"); return count++; }
Hello world! - 1-й вызов Hello world! - 2-й вызов Hello world! - 3-й вызов

В этом примере в функции hello() производится подсчет ее вызовов.

Передача аргументов по ссылке

В первом примере этого урока мы передавали в функцию аргументы по значению. Это значит, что когда функция вызывается, ей передаются в качестве фактических параметров (аргументов) не указанные переменные, а копии значений этих переменных. Сами переменные к этим копиям уже никакого отношения не имеют. В вызываемой функции эти значения присваиваются переменным-параметрам, которые, как известно, локальны. Отсюда следует, что изменение переданных значений никакого влияния на переменные, переданные в функцию при вызове, не оказывают. В примере выше даже если бы в функции median() менялись значения переменных n1 и n2, то никакого влияния сей факт на переменные num1 и num2 не оказал.

Однако можно организовать изменение локальной переменной одной функции с помощью другой функции. Сделать это можно, передав в функцию адрес переменной или указатель на нее. На самом деле в этом случае также передается копия значения. Но какого значения?! Это адрес на область памяти. На один и тот же участок памяти может существовать множество ссылок, и с помощью каждой из них можно поменять находящееся там значение. Рассмотрим пример:

#include void multi (int *px, int y); int main () { int x = 34, y = 6; multi(&x, 367); multi(&y, 91); printf("%d %d\n", x, y); } void multi (int *base, int pow) { while (pow >= 10) { *base = *base * 10; pow = pow / 10; } }

Функция multi() ничего не возвращает, что подчеркнуто с помощью ключевого слова void . Принимает эта функция адрес, который присваивается локальной переменной-указателю, и целое число. В теле функции происходит изменение значения по адресу, содержащемуся в указателе. Но по сути это адрес переменной x из фукнции main() , а значит меняется и ее значение.

Когда multi() вызывается в main() , то в качестве первого параметра мы должны передать адрес, а не значение. Поэтому, например, вызов multi(x, 786) привел бы к ошибке, а вызов multi(&x, 786) — правильный, т.к. мы берем адрес переменной x и передаем его в функцию. При этом ничего не мешает объявить в main() указатель и передавать именно его (в данном случае сама переменная p содержит адрес):

int x = 34, y = 6; int *p; p = &x; multi(p, 367); p = &y; multi(p, 367); printf("%d %d\n", x, y);

Кроме того, следует знать, что функция может возвращать адрес.

Важно понять механизм так называемой передачи аргументов по ссылке, т.к. это понимание пригодится при изучении массивов и строк. Использовать указатели при работе с простыми типами данных не стоит. Лучше возвращать из функции значение, чем менять локальные переменные одной функции с помощью кода другой функции. Функции должны быть достаточно автономными.

  1. Перепишите код первого примера этого урока так, чтобы в нем использовался указатель; а код примера с функцией multi() , наоборот, избавьте от указателей.
  2. Напишите программу, в которой помимо функции main() были бы еще две функции: в одной вычислялся факториал переданного числа, в другой — находился n-ый элемент ряда Фибоначчи (n — параметр функции). Вызовите эти функции с разными аргументами.
  3. Придумайте и напишите программу, в которой из функции main() вызывается другая функция, а из последней вызывается еще одна функция.

Курс с решением части задач:
pdf-версия

Как ввести функцию с клавиатуры и передать ее в качестве аргумента в другую функцию?

Как передать функцию из класса в другую функцию (в качестве параметра)?
У меня есть такой класс: Class a < static public function sum($a, $b) < return $a+$b; >.

Как передать функцию в качестве аргумента?
Как передать функцию в функцию, выполняющую усреднение значения через интегрирование. Так как.

Как передать функции указатель на функцию в качестве аргумента?
как передать функции указатель на функцию в качестве аргумента?

Нюансы работы с массивами: как правильно передать массив в функцию в качестве аргумента?
Здравствуйте. Начал недавно изучать с++ и с по книге. там есть пример и возник небольшой вопрос к.

как передать функции в качестве аргумента указатель на функцию описанной в другом классе?
Есть два класса A и B в классе A есть две функции funcA_1 и funcA_2 в классе B — funcB в.

Эксперт С++

8737 / 4315 / 960
Регистрация: 15.11.2014
Сообщений: 9,760

ЦитатаСообщение от Bao77 Посмотреть сообщение

Как ввести функцию с клавиатуры и передать ее в качестве аргумента в другую функцию?
из племени тумба-юбма
2445 / 1772 / 414
Регистрация: 29.11.2015
Сообщений: 8,605
Записей в блоге: 15

hoggy, сдается мне, что ТС нужно нечто другое ))
Возможно он хочет ввести имя функции, и чтоб это имя передалось в качестве аргумента

1704 / 1104 / 337
Регистрация: 25.01.2019
Сообщений: 2,907

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#include #include #include double foo(double x) { return x * x; } double bar(double x) { return x * -2.; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ double a(double (*foo)(double), double x) { return foo(x); } templatetypename T> double b(T foo, double x) { return foo(x); } #include double c(std::functiondouble(double)> foo, double x) { return foo(x); } int main() { std::cout  (foo, 3.14)  <"\n"; std::cout  ([](double x){ return x * x; }, 2.71)  <"\n"; std::cout  (foo, 3.14)  <"\n"; std::cout  ([](double x){ return x * x; }, 2.71)  <"\n"; std::cout  (foo, 3.14)  <"\n"; std::cout  ([](double x){ return x * x; }, 2.71)  <"\n"; std::mapstd::string, std::functiondouble(double)>> func_house; func_house["foo"] = foo; func_house["bar"] = bar; func_house["lambda"] = [](double x)->double{ return x + 100.; }; std::string str; std::getline(std::cin, str); if(func_house.find(str) != func_house.end()) std::cout  (func_house[str], 110); return 0; }

87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Ввести с клавиатуры 3 словосочетания и передать их по порядку в функцию. Используя функцию удалить
Ввести с клавиатуры 3 словосочетания и передать их по порядку в функцию. Используя функцию удалить.

Функция, которая в качестве аргумента принимает другую функцию (не встроенную, built-in)
Чтобы лучше разобраться в типах параметров функций Инна создала inspect_function (), которая в.

Можно ли в качестве параметра функции передать другую функцию?
В ниже представленной программе функция returnMax находит в массиве максимальный элемент и.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *