![](/user_photo/2706_HbeT2.jpg)
- •1.1. Элементы языка программирования
- •Основные правила записи программы:
- •1.2. Алфавит языка
- •1.3. Лексемы
- •1.4. Концепция данных
- •2.2. Операции
- •2.2.1. Арифметические операции
- •2.2.2. Операции присваивания
- •2.2.3. Операции отношения
- •2.2.4. Логические операции
- •2.2.5. Поразрядные операции
- •2.2.6. Вычисление выражений
- •3. Структурное программирование
- •3.1. Общая характеристика операторов
- •3.2. Оператор-выражение
- •3.3. Условный оператор
- •3.4. Составной оператор
- •3.5. Операторы для программирования циклов
- •3.5.1. Оператор цикла for
- •3.5.2. Оператор цикла while
- •3.5.3. Оператор цикла do while
- •3.5.4. Оператор break
- •3.5.5. Оператор continue
- •3.6. Оператор goto
- •3.7. Пустой оператор
- •3.8. Оператор switch
- •3.9. Оператор return
- •4. Массивы
- •4.1. Объявление массива
- •4.2. Обращение к элементам массива
- •4.3. Типовые алгоритмы работы с массивами
- •4.4. Многомерные массивы
- •5. Строки
- •5.1. Объявление строки
- •5.2. Посимвольная обработка строк
- •5.3. Ввод строк
- •5.4. Библиотечные функции для работы с текстом
- •6. Указатели
- •6.1. Объявление указателей
- •6.2. Операции над указателями
- •6.3. Связь между указателями и массивами
- •6.4. Функция strtok для выделения лексем из текста
- •6.5. Динамические массивы
- •7. Структуры и объединения
- •7.1. Объявление структуры
- •Компонент структуры может быть любого типа, кроме типа объявляемой структуры.
- •7.2. Операции над структурами
- •7.3. Объявление объединения
- •8. Модульное программирование
- •8.1. Нисходящее проектирование и программирование
- •8.2. Определение и вызов функции
- •8.3. Место определения функции в программе
- •8.4. Обмен данными между функциями
- •8.4.1. Использование глобальных переменных
- •8.4.2. Использование аппарата формальных и фактических параметров
- •8.4.3. Передача массивов в функцию
- •8.5. Перегрузка функции
- •8.6. Шаблон функции
- •8.7. Рекурсивные функции
- •8.8. Функции с параметрами по умолчанию
- •8.9. Передача в функцию другой функции
- •9. Работа с файлами
- •9.1. Текстовые и двоичные файлы
- •9.2. Объявление файловых переменных
- •9.3. Чтение текстового файла
- •9.4. Создание текстового файла
- •9.5. Изменение данных в текстовом файле
- •9.6. Вывод в двоичный файл
- •9.7. Чтение данных из двоичного файла
- •9.8. Изменение данных двоичного файла
- •9.9. Организация файла с произвольным доступом
- •10. Данные с динамической структурой
- •10.1. Линейный список
- •10.1.1. Специальные типы линейных списков
- •10.1.2. Реализация линейного списка с помощью массива
- •10.1.3. Реализация линейного списка с помощью связанного однонаправленного списка
- •10.1.4. Реализация линейного списка с помощью связанного двунаправленного списка
- •10.2. Деревья
- •10.2.1. Основная терминология
- •10.2.2. Реализация двоичных деревьев поиска Для реализации дерева поиска используются массивы и связанные указателями элементы [3, 4].
- •10.2.3. Сбалансированные деревья
- •Основные достоинства в-дерева:
- •10.3. Графы
- •10.3.1. Определения
- •10.3.2. Реализация графа с помощью списков смежности
- •10.3.3. Реализация графа с помощью матрицы смежности
- •10.3.4. Поиск кратчайших путей. Алгоритм Дейкстры
- •10.3.5. Матрица достижимости. Алгоритм Уоршалла
8.7. Рекурсивные функции
Рекурсивная функция – это функция, которая вызывает сама себя. Такой вызов функции может произойти, если функция, выполнение которой еще не закончилось, вызывается снова. Существуют классы алгоритмов, запись которых с помощью рекурсивных функций является более компактной.
Пример программы с рекурсивной функцией, которая вычисляет n-число Фибоначчи. Последовательность чисел Фибоначчи: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …начинается с 0 и 1, а каждое следующее число является суммой двух предыдущих чисел. Числа этой последовательности обозначаются через Fn и формально определяются следующим образом:
F0=0, F1=1, Fn=Fn-1+Fn-2, n>=2
В пределе отношение Fn/Fn-1стремится к значению 1.618033… Это значение называется золотым сеченим или божественной пропорцией. Принято считать, что объекты, содержащие в себе золотое сечение, воспринимаются людьми как наиболее гармоничные.
#include <iostream.h>
#include <conio.h>
//Рекурсивная функция вычисления n-го числа Фибоначчи
int fib(int n)
{
if (n==0 || n==1) //ветвь выхода из рекурсии
return n;
return fib(n-1)+fib(n-2); //рекурсивный вызов
}
void main()
{
int n;
cout<<"n? ";
cin>>n;
cout<<"fib="<<fib(n);
cout<< “f=”<<fib(n);
getch(); }
Любую рекурсивную функцию можно заменить нерекурсивным вариантом. Нерекурсивный вариант функции вычисления числа Фибоначчи может быть таким:
int fib (int n)
{int fnew, fold, foldold; //3 последовательных числа Фибоначчи
if (n==0 || n==1)
return n;
foldold=0; fold=1;
for (int i=2; i<=n; i++)
{
fnew=fold+foldold;
foldold=fold;
fold=fnew;
}
return fnew;
}
Недостатки рекурсивных функций:
Увеличение памяти на повторные вызовы функции и многократное размещение в стеке формальных параметров и локальных переменных рекурсивной функции.
Расход времени на многократное выполнение команд вызова функции.
Переполнение стека программы, при большом количестве рекурсивных вызовов.
8.8. Функции с параметрами по умолчанию
В С++ для того, чтобы упростить вызов функции с наиболее часто используемыми входными значениями, в заголовке функции используются параметры по умолчанию. Параметр по умолчанию – это значение, которое используется в качестве аргумента функции, если при вызове функции аргумент не указан. Для задания в функции параметра по умолчанию, надо в заголовке функции объявить формальный параметр с начальным значением. Функция может иметь несколько параметров умолчания, но они должны находиться в конце списка формальных параметров.
Пример программы, в которой используется функция поиска позиции первого вхождения заданного числа в массив, начиная с некоторой начальной позиции. Так как наиболее часто требуется найти первое вхождение заданного числа в массив, то в заголовке функции используется параметр умолчания, задающий значение начальной позиции поиска вхождения равное нулю.
#include <iostream.h>
#include <conio.h>
//Функция поиска первого вхождения значения х в массив из
//n целых чисел начиная с позиции p
int pos (int a[], int n, int x, int p=0);
void main()
{
int a[100], n, x, p;
int number; //номер первого числа массива со значением х (или -1)
cout<<"n? "; cin>>n;
cout<<”a: ”;
for (int i=0; i<n; i++)
cin>>a[i];
cout<<"x? "; cin>>x;
number= pos(b,n,x); //по умолчанию поиск начинается с 0-позиции
if (number==-1)
cout<<”No”<<endl;
else
cout<<"number_0="<<number<<endl;
number=pos(b,n,x,3); // поиск начинается с 3-позиции
if (number==-1)
cout<<”No”<<endl;
else
cout<<"number_3="<<number;
getch();
}
int pos (int a[], int n, int x, int p)
{for (int i=p; i<n; i++)
if(a[i]==x)
return i; //возврат номера элемента
return -1; //возврат признака отсутствия вхождения элемента
}
Тесты:
а: 8 9 5 2 1 9 10, n=7, x=9, p=0 результат: number=1
а: 8 9 5 2 1 9 10, n=7, x=9, p=3 результат: number=5
а: 8 9 5 2 1 9 10, n=7, x=4, p=0 результат: number =-1
В программе функция pos вызывалась два раза: первый раз с 3 аргументами (использовалось значение умолчания), второй – с 4 аргументами.
Ограничения на использование параметров по умолчанию:
параметры со значениями по умолчанию должны быть последними в списке формальных параметров;
если параметров по умолчанию несколько, то при вызове можно не указывать все параметры умолчания или только последние из них;
инициализация параметров по умолчанию должна выполняться в первом заголовке функции (в прототипе или в определении функции) и только один раз.