Студопедия
Новини освіти і науки:
МАРК РЕГНЕРУС ДОСЛІДЖЕННЯ: Наскільки відрізняються діти, які виросли в одностатевих союзах


РЕЗОЛЮЦІЯ: Громадського обговорення навчальної програми статевого виховання


ЧОМУ ФОНД ОЛЕНИ ПІНЧУК І МОЗ УКРАЇНИ ПРОПАГУЮТЬ "СЕКСУАЛЬНІ УРОКИ"


ЕКЗИСТЕНЦІЙНО-ПСИХОЛОГІЧНІ ОСНОВИ ПОРУШЕННЯ СТАТЕВОЇ ІДЕНТИЧНОСТІ ПІДЛІТКІВ


Батьківський, громадянський рух в Україні закликає МОН зупинити тотальну сексуалізацію дітей і підлітків


Відкрите звернення Міністру освіти й науки України - Гриневич Лілії Михайлівні


Представництво українського жіноцтва в ООН: низький рівень культури спілкування в соціальних мережах


Гендерна антидискримінаційна експертиза може зробити нас моральними рабами


ЛІВИЙ МАРКСИЗМ У НОВИХ ПІДРУЧНИКАХ ДЛЯ ШКОЛЯРІВ


ВІДКРИТА ЗАЯВА на підтримку позиції Ганни Турчинової та права кожної людини на свободу думки, світогляду та вираження поглядів



Вказівники на функції. Масиви вказівників на функції

Приклади програм з використанням рекурсії

 

Приклад: не оголошуючи масиву, ввести групу даних і вивести їх у зворотному порядку.

 

#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 */

}

 


Читайте також:

  1. Адвокатура в Україні: основні завдання і функції
  2. Алгоритм знаходження ДДНФ (ДКНФ) для даної булевої функції
  3. Але відмінні від значення функції в точці або значення не існує, то точка називається точкою усувного розриву функції .
  4. Аналіз коефіцієнтів цільової функції
  5. АРХІВНІ ДОВІДНИКИ В СИСТЕМІ НДА: ФУНКЦІЇ ТА СТРУКТУРА
  6. Асимптоти графіка функції
  7. Базальні ядра, їх функції, симптоми ураження
  8. Базові функції, логічні функції
  9. Банки як провідні суб’єкти фінансового посередництва. Функції банків.
  10. Банківська система та її основні функції
  11. Банківська система та її структура. Функції Центрального банку.
  12. Банківська система: сутність, принципи побудови та функції. особливості побудови банківської системи в Україн




Переглядів: 5723

<== попередня сторінка | наступна сторінка ==>
Рекурсивні функції | Вказівники типу near і far

Не знайшли потрібну інформацію? Скористайтесь пошуком google:

  

© studopedia.com.ua При використанні або копіюванні матеріалів пряме посилання на сайт обов'язкове.


Генерація сторінки за: 0.014 сек.