МАРК РЕГНЕРУС ДОСЛІДЖЕННЯ: Наскільки відрізняються діти, які виросли в одностатевих союзах
РЕЗОЛЮЦІЯ: Громадського обговорення навчальної програми статевого виховання ЧОМУ ФОНД ОЛЕНИ ПІНЧУК І МОЗ УКРАЇНИ ПРОПАГУЮТЬ "СЕКСУАЛЬНІ УРОКИ" ЕКЗИСТЕНЦІЙНО-ПСИХОЛОГІЧНІ ОСНОВИ ПОРУШЕННЯ СТАТЕВОЇ ІДЕНТИЧНОСТІ ПІДЛІТКІВ Батьківський, громадянський рух в Україні закликає МОН зупинити тотальну сексуалізацію дітей і підлітків Відкрите звернення Міністру освіти й науки України - Гриневич Лілії Михайлівні Представництво українського жіноцтва в ООН: низький рівень культури спілкування в соціальних мережах Гендерна антидискримінаційна експертиза може зробити нас моральними рабами ЛІВИЙ МАРКСИЗМ У НОВИХ ПІДРУЧНИКАХ ДЛЯ ШКОЛЯРІВ ВІДКРИТА ЗАЯВА на підтримку позиції Ганни Турчинової та права кожної людини на свободу думки, світогляду та вираження поглядів Контакти
Тлумачний словник |
|
|||||||
Вказівники на функції. Масиви вказівників на функціїПриклади програм з використанням рекурсії
Приклад: не оголошуючи масиву, ввести групу даних і вивести їх у зворотному порядку.
#include <iostream.h> //Рекурсивна функція void rec() { int i; cin >> i; if(i!=0) rec (); else cout << "Вивід чисел: " << endl; cout << i; } • void main(} { cout << "Введіть числа. Ознака закінчення вводу - 0 : " << endl; rec (); }
/* Результат виконання програми: Введіть числа . Ознака закінчення вводу -0 : 3 2 4 1 5 6 7 9 8 0 Вивід чисел: 0 8 9 7 6 5 1 4 2 3 */
/* Приклад: не оголошуючи масиву довгих цілих чисел, ввести групу даних, вивести їх у зворотному порядку разом з їхніми порядковими номерами. */
#include <iostream.h> void rec (int num) /* Рекурсивна функція */ { int i; cin >> i; if (i!=0) rec(num + l) ; else cout << "Вивід чисел:" << endl; cout << ",Число, "<< i << ", порядковий .номер " << num << "\n"; } void main () {cout << “Введіть числа. Ознака закінчення вводу - 0: " << endl; гес (0) ; }
/* Результат виконання програми: Введіть числа. Ознака закінчення вводу - 0: 1 2 3 4 5 6 7 8 9 0
Вивід чисел: Число 0, порядковий номер 10 Число 9, порядковий номер 9 Число 8, порядковий номер 8 Число 7, порядковий номер 7 Число 6, порядковий номер 6 Число 5, порядковий номер 5 Число 4, порядковий номер 4 Число 3, порядковий номер 3 Число 2, порядковий номер 2 Число 1, порядковий номер 1 */
/* Приклад: використовуючи рекурсивний виклик функції main(), обчислити суму елементів масиву цілого типу. Масив не оголошувати. Останній -елемент масиву - 0. У файлу з вихідним модулем повинне бути розширення .с */
#include<stdio.h> #include <iostream.h> int main() { int i; cin >> i ; if(i) { i+=main (); cout << " s= " << i; } return i; ' - }
/* Другий варіант: сума обчислюється у функції, результат виводиться в main () */
int fun() { int i; scanf (“%d”,&i); if (i) i+ = fun (); return i; } void main () { printf (“%d”, fun()); }
У мові С сама функція не може бути значенням змінної, але можна визначити вказівник на функцію. З ним уже можна оперувати, як зі змінною: передавати його іншим функціям, поміщати в масиви й т.д. Оголошення виду:
int ( *fl ) ( );
говорить про те, що fl - вказівник на функцію, що повертає ціле значення. Перша пара дужок необхідна, без них
int *f 1 ( ); /* це не вказівник на функцію */
означало б, що fl -функція, що повертає вказівник на ціле значення. Після оголошення вказівник а на функцію в програмі можна використовувати оператори виду:
y = ( *fl ) ( . . .); або y = f1(...);
Вказівник на функцію - такий тип змінної, котрій можна присвоювати адреси точки входу у функцію, тобто адресу першої виконуваної команди. Ця змінна надалі може використовуватися для виклику функції замість її імені. Визначення вказівника на функцію має наступний загальний вид:
тип_результату (* ім'я вказівника на функцію) (список типів параметрів) ;
Наприклад:
double (*fd) ( int, int ); /* fd - вказівник на функцію, що повертає результат типу double і приймає два параметри типу int. */ int ( *find ) ( int, float * ) ; / find - вказівник на функцію. Функція повертає результат типу int і приймає два параметри: число типу int і вказівник на число типу float.*/
char* ( * comp ) ( const char *sl, const char *s2 ) ; /* comp - вказівник на функцію, що повертає результат вказівник на char і приймаючу як параметри два вказівники на char.*/
При визначенні вказівника на функцію дозволяється одночасно із вказівкою типу параметрів задавати і їхні імена.
Нехай є прототипи функцій піднесення числа типу int у третю, п'яту і сьому степінь і які повертають результат типу int (звичайно, все це легко реалізувати й в одній функції):
int f3 ( int ); int f5 ( int ) ; int f7 ( int ); і є вказівник на функцію наведеного вище виду:
int ( *fst ) ( int );
Тоді оператор fst = f3; присвоїть вказівнику fst адресу входу у функцію f3, fst = f5; - адресу входу у функцію f5 і, відповідно, fst = f7; - адресу входу у функцію f7. Після цього викликати кожну з функцій (f3, f5, f7) можна будь-яким оператором, записаним нижче (наприклад, f3):
f3 ( a ); // звертання до функції, використовуючи її ім'я. (*fst ) ( а ); // виклик функції через вказівник. fst( a ); // виклик функції також через вказівник.
Останній варіант також правильний, тому що f3, fst - це адреси входу у функцію. Однак виклик ( *fst ) ( а ) явно показує, що використовується вказівник на функцію, а не викликається функція з ім'ям fst, якщо бачити тільки один оператор fst ( a );. У ряді задач, що використовують математичні методи, вказівник на функцію необхідно передавати як параметр у функцію, що реалізує відповідний метод. Наприклад, для обчислення значення інтеграла треба знати ім'я функції, у якій обчислюється значення підінтегрального виразу; для пошуку екстремума деякої цільової функції треба знати ім'я цієї функції і т.п.
Для ілюстрації розглянемо простий приклад. Нехай потрібно обчислити наступні вирази: y = 4 * 4 * 4 + 7 * 7 * 7 і . y = 3*3*3*3*3 + 9*9*9*9*9. За умовою задачі, сума елементів обчислюється в окремій функції, з якої повинна викликатися і функція піднесення числа до степеня.
#include <stdio.h> #include <conio.h> int f3( int x ) // Піднесення числа в третю степінь { return x * x * x; } int f5( int x ) // Піднесення числа в п’яту степінь int х2 = х * х; return х2 * х2 * х; }• void main( ) { int ( *fst ) ( int ); // Вказівник на функцію int sum (int , int, int ( *fst ) ( int ) ); // Прототип функції sum fst = f3; // fst адреса входу в f3 printf(" 4 ^ 3 + 7 ^ 3 = %d \n ", sum( 4, 7, fst ) ); fst = f5; // fst = адреса входу у f5 printf(" 3 ^ 5 + 9 ^ 5 = %d\n ,", sum( 3, 9, fst ) ) ; } int sum( int m, int n, int ( *fp ) ( int ) ) // Реалізація функції sum { int yl, y2; yl = ( *fp ) ( m ); // Виклик або f3, або f5 y2 = ( *fp ) ( n ); // Виклик або f3, або f5 return y+y2; }
/*Є й інші варіанти реалізації функції sum. */ int sum( int m, int n, int ( *fst ) ( int ) ) { return fst( m ) + fst( n ) ; }
Вказівники на функцію широко застосовуються в програмуванні: - багато бібліотечних функцій як аргумент одержують вказівник на функцію; - використання вказівників на функцію як аргументів дозволяє розробляти універсальні функції, наприклад функції чисельного рішення рівнянь, чисельного інтегрування й диференціювання; - масиви вказівників на функції використовуються для організації меню.
Вказівники на функції можуть бути компонентами структур. Як і звичайні змінні, вказівники на функції можуть об’єднуватися в масиви. Наприклад, визначити й проініціалізувати масив вказівників на функції можна в такий спосіб:
/* Опис прототипів функцій, точки входів яких будуть елементами масиву вказівників на функції. */
float funcl( float ); float func2 ( float ) ; float func3( float ); float func4( float ) ; float func5( float ) ; // Масив вказівників на функції float ( *fparray [5] ) (float ) = { funcl, func2, func3, func4, func5 } ;
Доступ до елементів масиву fparray виконується, як до звичайних елементів масиву.
Наприклад: float х = 1; cout << fparray[0] ( х) ; // або cout << (*fparray[0] ) ( х) ;
При організації меню можна використовувати вказівники на масиви функцій. Кожному пункту меню ставиться у відповідність його реалізуюча функція, вказівник на яку поміщається в масив. Після того як користувач зробив вибір, за відповідним індексом вибирається функція, що реалізує цей пункт меню.
Одним з прикладів, де можуть використовуватись вказівники на функції, є обчислення коренів трансцендентних рівнянь. Розглянемо цей випадок на прикладі найпростішого методу половинного ділення.
Нехай відомо, що на відрізку [a,b] рівняння має один корінь, тобто в точках a і b значення функції мають різні знаки. Якщо | а - b |<e (де е - точність обчислень), то [а, b] можна вважати коренем, наприклад х = а (необхідна точність досягнута). Інакше за наближене значення кореня візьмемо середину відрізка . Якщо , то корінь знайдений. Інакше вибираємо той з відрізків ([a , ], [, b]), на кінцях якого значення функції мають різні знаки, і застосовуємо до нього ті ж міркування.
// Функція вимагає під’єднання бібліотечного модуля <math.h>
int hdiv(double ( *f ) ( double),double a ,double b, double *x, double e) { double y; int n=0; /* n - кількість ітерацій */ while ( fabs ( a-b ) > e ) { *x - ( a + b ) / 2; n++; y = f ( *x ); if( y == 0 ) break; if( f(a) *y < 0) b = *x; else a = *x; } *x = ( a + b ) / 2; return n; }
Розглянемо наступний приклад з використанням вказівників на функції.
/* Приклад. Визначити масив вказівників на функції. Вводити цифру, яка визначатиме, яку функцію необхідно виконати: 0 – знайти мінімальне число, 1 – знайти максимальне число, 2- обрахувати суму, 3- обрахувати різницю, 4 – добуток, 5 – частку, 9 – завершити роботу. Виконати відповідну функцію, використовуючи вказівник на неї */
#include <stdio.h> #include <conio.h> void main (void) { int min (int, int); /* - minimum is found */ int max (int, int); /* - maximum is found */ int plus(int, int); /* - sum is found */ int minus (int, int); /* difference is found */ int mul (int, int); /* - product is found */ int div (int, int); /* - quotient is found */ // array of pointers int (*y[10]) (int, int) = { min, max, plus, minus, mul, div}; // names of operations char *str[ ] = {“min”, “max”, “plus”, “minus”, “mul”, “div”}; int m, n; char i;
while (l) { puts (“Input the operation: \n”); puts (“0 – to find minimum \n”); puts (“1 – to find maximum \n”); puts (“2 – to find sum \n”); puts (“3 – to find difference \n”); puts (“4 – to find product \n”); puts (“5 – to find quotient \n”); puts (“9 – exit \n”);
scanf(“%d”, &i); if ( i == 9 ) return; if ( i < 0 || i > 5 )
{ puts (“Incorrect operation code \n”); continue; } puts (“Input the operands (m, n): \n”); scanf(“%d%d”, &m, &n);
// Call the function by the pointer – element of array
printf (“%s= %d \n”, str[i],(*y[i]) (m, n) );
// or in the following way printf (“%s= %d \n”, str[i], y[i], (m, n) ); } }
// description of functions
int min (int m, int n) {return ( m < n ) ? m: n; } int max (int m, int n) {return ( m > n ) ? m: n; } int plus (int m, int n) {return m + n ; } int minus (int m, int n) {return m - n; } int mul (int m, int n) {return m * n; } int div (int m, int n) { if ( n) return m / n; return 32767; /* n value is equal to 0 */ }
Читайте також:
|
||||||||
|