Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы_по_проге_Берлин / Книги / учебное пособие ОАиП.pdf
Скачиваний:
49
Добавлен:
11.02.2015
Размер:
947 Кб
Скачать

}

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

z=proiz(x,dx,cos);

а для вычисления производной от функции sin(x) в форме z=proiz(x,dx,sin);

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

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <conio.h>

void enter(); void del(); void rew(); void quit(); int menu(void);

void (*options[])(void)={enter, del, rew, quit};

int main(void)

 

{ int i;

 

i=menu();

// выбор режима работы

(* options[i])();

// вызов функции

return 0;

 

}

 

int menu(void)

 

{char ch; do

{printf("1 - ввод");

. . .

printf("4 - выход"); printf("Выберите режим работы"); ch=getch();

printf("\n");

} while(!strchr("1234",ch));

return ch-49; // преобразуем ch в целое число

}

. . .

 

void enter()

void quit()

{ . . .

 

{ . . .

}

 

}

Рекурсия

Функция является рекурсивной, если некоторая инструкция этой функции содержит вызов самой этой функции. Компилятор допускает любое число рекурсивных вызовов. Рекурсивный вызов не создает новую копию функции.

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

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

Хотя компилятор языка СИ не ограничивает число рекурсивных вызовов функций, это число ограничивается ресурсом памяти компьютера. Большое число рекурсивных вызовов функции может привести к переполнению стека, что в свою очередь приведет к ошибочному окончанию работы программы. При разработке рекурсивной функции следует, используя операторы if и return, предусмотреть возможность завершения ее работы. В противном случае возможно "зацикливание" программы.

Примеры программ

Пример . Программа нахождения наибольшего общего делителя двух чисел.

#include <stdio.h> int nod(int, int ); void main()

{int a,b; fflush(stdin);

scanf("%d%d",&a,&b);

printf("НОД чисел %d и %d = %d",a,b,nod(a,b));

}

 

nod(int a,int b)

// рекурсивная функция, вычисляющая

{ int c;

// НОД чисел a и b

if (b>a) c=nod(b,a);

 

else if (b<=0) c=a;

 

else c=nod(b,a%b);

 

return(c);

 

}

Пример . Вычисление факториала n! .

#include<stdio.h>

 

#include<conio.h>

 

int fact1(int);

// прототип первого варианта функции вычисления n!

int fact2(int);

// прототип второго варианта функции вычисления n!

int fact3(int);

// прототип третьего варианта функции вычисления n!

void main(void)

 

{ int n,i;

 

char c;

 

do

 

if(!n) return(1); if (++i<n)
return --i*fact2(n); return n;

{clrscr();

fflush(stdin);

puts("\nВводите число >=0 для вычисления его факт-ла :"); i=scanf("%d",&n);

}while(i<1 || n<0);

printf("\nФакториал числа %d (%d!) = %d

вариант 1",n,n,fact1(n));

printf("\nФакториал числа %d (%d!) = %d

вариант 2",n,n,fact2(n));

printf("\nФакториал числа %d (%d!) = %d

вариант 3",n,n,fact3(n));

getch();

 

}

int fact1(int n) // первый вариант функции вычисления n! { int i;

if (n==1 || n==0) return (1); // выход из рекурсии return fact1(n-1)*n;

}

int fact2(int n) // второй вариант функции вычисления n!

{ static long i; // т.к. i-статическая, то для нее не созда- // ется копии и при возврате через return // для вычисления 0!

// i сохраняет const максимальное значение

}

int fact3(int n) // третий вариант функции вычисления n! {return n ?n*fact3(n-1):1;}

Пример . Программа вывода последовательности Фибоначчи состоящей из 15 членов.

#include<stdio.h> int fibon(int); void main(void)

{int n,i; clrscr();

printf("\nпоследовательность Фибоначчи - "); for(n=0;n<15;n++) printf("%4d",fibon(n));

}

int fibon(int n)

{return ((n==0 || n==1)) ?1:fibon(n-1)+fibon(n-2);}

Пример . Программа перевода чисел из десятичной системы счисления в систему счисления с основанием до 32.

#include <stdio.h> void fc(int);

void fd(double,int);

int ss;

char znak='+'; void main()

{int t; double num;

printf("\nВведите исходное число : "); scanf("%lf",&num);

num<0?znak='-',num*=-1:num; // выделение знака числа printf("\nВведите основание новой с/с"); scanf("%d",&ss);

printf("\nВведите точность для дробной части числа с/с"); scanf("%d",&t);

fc((int)num);

putchar('.'); fd(num-(int)num,t);

}

 

void fc(int num1)

// функция перевода целой части числа

{ int i;

 

if(num1>=ss)

 

{ i=num1%ss;

// получаем остаток от деления на основание

num1/=ss;

// получаем целую часть от деления

fc(num1);

// рекурсивный вызов функции fc

printf("%c",i>9? i-10+'a': i+'0');

}

else printf("%c %c",znak,num1>9? num1-10+'A': num1+'0');

}

void fd(double num,int t) // функция перевода дробной части числа

{static n; int i;

if(num!=0 && n++<t)

{ i=num*=ss; // получаем произведение и выделяем целую частьk printf("%c",i>9? i-10+'a': i+'0');

fd(num-(int)num,t); // рекурсивный вызов fd

}

else printf("%c",num>9? (int)num-10+'A': (int)num+'0');

}

Пример . Программа использующая рекурсивную функцию сортировки массива чисел методом Хоора.

#include<stdio.h>

#include<conio.h>

#define k 7

void hoor(int *,int,int); void swap(int *,int,int);

void main(void)

{int a[k],i,n; do

{clrscr();

fflush(stdin);

puts("\nВводите кол-во чисел"); i=scanf("%d",&n);

} while(i<1 || n>k); for(i=n-1;i<k;i++) a[i]=0;

puts("\nВводите элементы массива "); for(i=0;i<n;i++)

{fflush(stdin);

if (!scanf("%d",&a[i])) i--;

}

clrscr();

printf("\nИсходный массив :"); for(i=0;i<n;i++) printf("%4d",a[i]); hoor(a,0,n-1); printf("\n\nПреобразованный массив :"); for(i=0;i<n;i++) printf("%4d",a[i]); getch();

}

void hoor(int *a,int l,int r)

{ int i,las;

 

if(l>=r) return;

 

swap(a,l,(l+r)/2);

// делящий эл-т переносится в a[l] (a[l]<->a[(l+r)/2])

las=l;

// позиция посл-го эл-та большего чем делящий

for(i=l+1;i<=r;i++)

// деление [l,r] на [l,las-1] и [las+1,r]

if(a[i]<a[l]) swap(a,++las,i);

swap(a,l,las);

 

hoor(a,l,las-1);

// сортировка для [l,las-1]

hoor(a,las+1,r);

// сортировка для [las+1,r]

}

void swap(int *a,int i,int j)

{ int tmp; // функция замены i и j эл-тов в массиве a tmp=a[i];

a[i]=a[j];

a[j]=tmp;

}