Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lab8.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
189.44 Кб
Скачать

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

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

#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());

}

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

У мові С сама функція не може бути значенням змінної, але можна визначити вказівник на функцію. З ним уже можна оперувати, як зі змінною: передавати його іншим функціям, поміщати в масиви й т.д. Оголошення виду:

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 f 3 ( 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 */

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]