
Программирование 1
.pdf
7.9 Рекурсивные вызовы функции
Рекурсией называют способ организации подпрограммы, при котором она прямо или косвенно вызывает сама себя. Соответственно различают прямую и косвенную рекурсию.
При прямой рекурсии подпрограмма вызывает себя из своего раздела операторов. Схематично это можно представить на рисунке 7.1.
А |
Рисунок 7.1 – Прямая рекурсия
При косвенной рекурсии подпрограмма вызывает подпрограмму, которая прямо или косвенно вызывает первую. Схематично это можно представить на рисунке 7.2.
А |
B |
C |
|
Рисунок 7.2 – Косвенная рекурсия |
|
Любая функция в программе на языке СИ может быть вызвана рекурсивно, т.е. она может вызывать саму себя. Компилятор допускает любое число рекурсивных вызовов. При каждом вызове для формальных параметров и переменных с классом памяти auto и register выделяется новая область памяти, так что их значения из предыдущих вызовов не теряются, но в каждый момент времени доступны только значения текущего вызова.
Переменные, объявленные с классом памяти static, не требуют выделения новой области памяти при каждом рекурсивном вызове функции и их значения доступны в течение всего времени выполнения программы.
Классический пример рекурсии - это математическое определение факториала n! :
n! = 1 при n=0; n*(n-1)! при n>1 .
Функция, вычисляющая факториал, будет иметь следующий вид: long fakt(int n)
{
return ( (n==1) ? 1 : n*fakt(n-1) );
61
}
Хотя компилятор языка СИ не ограничивает число рекурсивных вызовов функций, это число ограничивается ресурсом памяти компьютера и при слишком большом числе рекурсивных вызовов может произойти переполнение стека.
7.10 Примеры составления функций
Пример 1. Написать функцию, которая вычисляет объем цилиндра. Параметрами функции должны быть радиус и высота цилиндра.
#include <stdio.h> #include <conio.h> #include <math.h>
float veil(float h, float r) {return(M_PI*r*r*h);} void main ()
{
float r,h; float v;
puts("Вычисление объема цилиндра"); printf("Введите высоту и радиус основания ->"); scanf ("%f%f", &h, &r) ;
v = veil(h, r);
printf("Объем цилиндра %3.2f\n", v); printf("Для завершения нажмите <Enter>"); getch();
}
Пример 2. Написать функцию, которая возвращает максимальное из двух целых чисел, полученных в качестве аргумента.
int max(int a, int b) {if (a > b) return(a); else return(b);
}
Пример 3. Написать функцию, которая сравнивает два целых числа и возвращает результат сравнения в виде одного из знаков: >, < или =.
#include <stdio.h> #include <conio.h>
char compare(int a, int b)
{
char res;
if (a > b) res = '>';
else if (a < b) res = '<'; else res = '=';
62
return(res);
}
void main()
{
int xl,x2; // сравниваемые числа char res; // результат Сравнения puts("Введите два целых числа и нажмите <Enter>"); printf("->");
scanf("%i%i", &xl, &x2);
res = compare(xl,x2); // вызов функции программиста printf("%i %c %i\n", xl, res, x2);
puts("\nДля завершения работы программы нажмите <Enter>"); getch();
}
Пример 4. Написать функцию, обеспечивающую решение квадратного уравнения. Параметрами функции должны быть коэффициенты и корни уравнения. Значение, возвращаемое функцией, должно передавать в вызывающую программу информацию о наличии корней уравнения: 2 — два разных корня, 1 — корни одинаковые, 0 — уравнение не имеет решения. Кроме того, функция должна проверять корректность исходных данных. Если исходные данные неверные, то функция должна возвращать -1.
#include "stdio.h" #include "conio.h" #include "math.h"
int kvadur(float a, float b, float с, float *xl, float *x2)
//значение функции - количество корней
//или -1, если неверные исходные данные
{
float d; // дискриминант if (a == 0) return(-1);
d = b*b-4*a*c;
if (d < 0) return(0); // уравнение не имеет решения
*xl = (-b+sqrt(d))/(2*a); *х2 = (-b-sqrt(d))/(2*a); if (*xl != *х2) return(2); else return(1);
}
void main()
{
float a,b,c; // коэффициенты уравнения float xl,x2; // корни уравнения
int n; // кол-во корней
puts("\nРешение квадратного уравнения");
puts("Введите в одной строке коэффициенты и нажмите <Enter>"); printf("->");
63
scanf("%f%f%f", &a, &b, &c); switch (kvadur(a,b,c,&xl,&x2))
{
case -1: puts("Ошибка исходных данных."); break; case 0: puts("Уравнение не имеет решения.");break; case 1: printf("Корни одинаковые: x=%3.2f", xl) ;break; case 2: printf("xl=%3.2f x2=%3.2f", xl, x2);
}
puts("\n Для завершения работы нажмите <Enter>"); getch();
}
64