Тема 5
Определение функции
Определение функции
Определение функции
Формальные параметры и фактические аргументы
Передача аргументов по значению и локальные копии
Передача аргументов по ссылке (параметры-переменные)
Программа Передача аргументов по ссылке
Программа «Определение значений»
Программа «Степени целых чисел»
Автоматические переменные
Статические переменные
Программа Автоматические и статические переменные
Прототипы функций
Прототипы функций
Перегруженные имена функций
Программа «Перегрузка функций»
Аргументы функций по умолчанию
Программа «Перевод числа в заданную систему счисления»
Массивы и функции
Программа «Массивы и функции»
Рекурсия
Программа Вычисление факториала
Таблица Работа рекурсивной функции
Программа «Распечатка числа в обратном порядке»
Программа «Распечатка числа в прямом порядке»
213.50K
Категория: ПрограммированиеПрограммирование

20210211211912

1. Тема 5

Функции

2. Определение функции

Термином функции в языке С++ обозначают подпрограммы. В виде
функций оформляются вычисления, преобразования, другие
действия, которые затем могут быть выполнены неоднократно с
различными аргументами.
При разработки программы возникает необходимость одну и туже
последовательность операторов приводить в тексте несколько раз.
Языки высокого уровня позволяют ввести имя для группы
операторов. После того, как имя введено, в нужных местах
программы вместо последовательности операторов помещается их
групповое имя. Последовательность операторов, для которых
введено имя, представляет собой функцию. Использование в
программе имени функции в качестве оператора называется
обращением к функции. Для того, чтобы ввести имя или
идентификатор для группы операторов, достаточно включить в
программу описание функции.

3. Определение функции

Синтаксис:
Определение функции
тип_результата имя_функции(объявления аргументов)
{ тело функции (объявления и инструкции ) }
Замечания:
1) Отдельные части определения могут отсутствовать, например,
следующая функция ничего не делает:
void dummy() {}
2) Тип результата функции void означает, что функция ничего не
возвращает (является процедурой).
3) Все функции равноправны, то есть функцию нельзя определять
другую функцию.
4) Вычисления в функции завершаются при достижении последней
закрывающей фигурной скобки } или при выполнении инструкции
return. Когда функция завершает работу, управление передается в
вызывающую программу той инструкции, которая следует за вызовом
функции.

4. Определение функции

Синтаксис:
тип_результата имя_функции(объявления аргументов)
{ тело функции (объявления и инструкции ) }
Замечания:
5) Если функция завершается инструкцией
return выр;
то вычисляется выражение выр и его значение передается в вызывающую
программу в точку вызова функции.
6) Значение, возвращаемое функцией, может быть использовано
вызывающей программой или проигнорировано:
cout << sin(M_PI / 6); // Значение, возвр. функцией sin используется
sin(M_PI / 2);
// Значение, возвр. функцией sin игнорируется
7) Функции могут возвращать значения любых типов. Например, следующая
функция возвращает логическое значение true (истина), если ее аргумент a
больше b, иначе значением функции будет false (ложь).
bool greater(int a, int b)
{ return a > b; }

5. Формальные параметры и фактические аргументы

Параметры в скобках называются аргументы функции или формальными
параметрами. При выполнении программы в момент обращения к функции,
формальные параметры заменяются фактическими. Фактической может быть
любая переменная или константа того же типа, который указан при
соответствующем ему формальном параметре. Имена формального и
фактического параметра могут не совпадать.
Программа «Сумма аргументов»
#include <iostream>
#include <cstdlib>
using namespace std;
int sum(int a, int b) //Возвращает сумму аргументов (a,b– формальные параметры)
{ return a + b; }
int main()
{ cout << "3 + 2 = " << sum(3, 2) << endl; // Фактические аргументы – константы
int x = 3, y = 2; // Переменные целого типа
cout << "x + y = " << sum(x, y) << endl; // Фактические аргументы – переменные
system("pause");
return 0; }

6. Передача аргументов по значению и локальные копии

Аргументы передаются в функции по значению. Это реализуется созданием
внутри функции локальных копий фактических аргументов, которые и
используются в вычислениях. Отсюда следует, что фактические аргументы не
могут быть непосредственно изменены внутри функции. Память под формальные
параметры функции выделяется при вызове функции и освобождается при
завершении ее работы.
Программа «Передача аргументов по значению»
#include <iostream>
#include <cstdlib>
using namespace std;
void add(int c)
{ c++; }
int main()
{ int x = 1;
add(x);
cout << "x = " << x << endl;
add(2);
system("pause"); return 0;}

7. Передача аргументов по ссылке (параметры-переменные)

Если необходимо изменить фактический аргумент внутри
функции, в нее должен передаваться адрес аргумента или
ссылка на аргумент.
Ссылка (reference) является альтернативным именем объекта.
При объявлении ссылки на переменную некоторого типа после
имени типа ставится знак &.
Ссылку можно передавать в функции в качестве аргумента и
возвращать из функций в качестве результата, при этом аргумент,
передаваемый в функцию по ссылке, можно изменить внутри
функции.
Локальные переменные
Переменные,
объявленные
внутри
функции
являются
локальными. Память под них выделяется в момент вызова
функции и освобождается в момент ее окончания.

8. Программа Передача аргументов по ссылке

#include <iostream>
#include <cstdlib>
using namespace std;
void swap(int& a, int& b) // Обмен значений a и b
{ int tmp = a; // tmp – локальная переменная
a = b;
b = tmp; }
int& max(int& a, int& b) // Возвращает ссылку на максимальное из a и b
{ return a > b ? a : b; }
int main()
{ setlocale(LC_ALL, "Russian");
int x, y;
cout << "Введите два числа: "; cin >> x >> y;
cout << "x = " << x << ", y = " << y << endl;
swap(x, y);
cout << "После обмена: \n" << "x = " << x << ", y = " << y << endl;
max(x, y) = 0;
cout << "Максимальное обнулили: \n" << "x = " << x << ", y = " << y << endl;
system("pause"); return 0; }

9. Программа «Определение значений»

#include <iostream>
#include <cstdlib>
using namespace std;
void f1(int a, int b)
{
int c;
c=2+b;
a=10*c;
b=b+c;
}
int main()
{
int x=3, y=1;
f1(x,y);
cout<<"x="<<x<<" y="<<y<<endl;
f1(3,7);
cout<<"x="<<x<<" y="<<y<<endl;
system("pause");
return 0;
}
#include <iostream>
#include <cstdlib>
using namespace std;
void f2(int a, int r,int& b)
{
a=2*r;
b=a+r;
}
int main()
{
int x=3, y=2,z=3;
f2(x,4,z);
cout<<"x="<<x<<" y="<<y;
cout<<" z="<<z<<endl;
f2(x,y,z);
cout<<"x="<<x<<" y="<<y;
cout<<" z="<<z<<endl;
system("pause");
return 0;
}
#include <iostream>
#include <cstdlib>
using namespace std;
int x=5;
int y=2;
void f3(int a,int& b)
{
a=2*a;
x=b-10;
b=4;
y=b-a;
}
int main()
{
f3(x,y);
cout<<"x="<<x<<" y="<<y<<endl;
f3(x,y);
cout<<"x="<<x<<" y="<<y<<endl;
system("pause");
return 0;
}

10. Программа «Степени целых чисел»

#include <iostream>
#include <locale>
#include <cstdlib>
using namespace std;
// Функция power() возводит base в степень degree
int power(int base, int degree)
{
int i, p = 1;
// p – переменная для степени
for(i = 1; i <= degree; i++)
// degree раз
p = p * base;
// умножаем на base
return p;
// Возвращение вычисленного значения p из функции
}
int main()
// Использование функции power
{ setlocale(LC_ALL, "Russian");
for(int i = 1; i < 10; i++)
{
cout << "2 в степ. " << i << " =\t" << power(2, i)<< "\t";
cout << "-3 в степ. " << i << " =\t" << power(-3, i) << endl;
}
system("pause"); return 0; }

11. Автоматические переменные

Переменные, определенные в теле функции, являются локальными внутри
этой функции и, поэтому, недоступны для других функций. Существуют два
вида локальных переменных: автоматические и статические.
Автоматические переменные создаются только в момент обращения к
функции и исчезают при завершении ее работы. Память под автоматические
переменные выделяется, когда функция начинает работать, и освобождается,
когда функция завершается, поэтому автоматические переменные не
сохраняют своих значений между вызовами функции и должны
устанавливаться заново при каждом новом обращении к функции.
Все переменные внутри функции являются по умолчанию автоматическими,
но можно явно указать на это, используя ключевое слово
auto:
auto int k = 0;
// Автоматическая переменная
Параметры функций создаются заново при каждом вызове функции и
инициализируются значениями фактических аргументов, поэтому они также
являются локальными автоматическими переменными. Параметры функции
можно произвольно изменять внутри функции, причем это никак не влияет
на значения фактических аргументов.

12. Статические переменные

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

13. Программа Автоматические и статические переменные

#include <iostream>
#include <cstdlib>
using namespace std;
int fauto ()
{
// Автоматическая локальная переменная k
int k = 0;
// инициализируется при каждом вызове функции
return ++k;
// Изменение локальной автоматической переменной
}
int fstat ()
{
// Статическая локальная переменная k инициализируется
static int k = 0;
// только при первом вызове функции
return ++k;
// Изменение локальной статической переменной
}
int main()
{ for(int i = 0; i < 10; i++)
// 10 раз вызываем fauto()
cout << fauto() << " ";
cout << endl;
for(int i = 0; i < 10; i++)
// 10 раз вызываем fstat()
cout << fstat() << " ";
cout << endl; system("pause"); return 0; }

14. Прототипы функций

Прототипом называется предварительное объявление функции.
Синтаксис:
тип-результата имя-функции(объявления аргументов);
Он состоит из заголовка функции и точки с запятой.
Пример (функция возведения в степень):
int power(int base, int degree);
// Прототип функции power()
Замечание: имена аргументов в объявлении (прототипе) функции можно не
указывать, так как важен лишь их тип:
int power(int , int);
После объявления функцию можно вызывать из других функций, расположенных
ниже по тексту программы, причем, вызовы должны быть согласованы с
прототипом. Компилятор проверяет соответствие типов фактических и
формальных параметров, и, если они не согласованы, выдает ошибку. Если
обращение к функции соответствует ее прототипу, будет сгенерирован
правильный код вызова функции, так как объявление сообщает компилятору все
необходимое: имя функции, количество и типы аргументов, тип возвращаемого
значения.
Замечание: компилятору достаточно объявления функции, но редактор связей должен
иметь код функции, поэтому объявленная функция должна быть где-то определена.

15. Прототипы функций

#include <iostream>
#include <locale>
#include <cstdlib>
using namespace std;
int power(int, int);
int main()
{ setlocale(LC_ALL, "Russian");
cout << "2 в степ. 10 = " <<power(2, 10) <<endl<< "2 в степ. -1 = ";
cout<<power(2, -1) <<endl;
system("pause");
return 0; }
int power(int base, int degree)
// Определение функции power()
{
// base - обснование степени, degree - показатель степени
if(degree < 0) {
cerr << "\nОтрицательный показатель недопустим\n";
system("pause");
exit(1); }
int p = 1;
while(degree-- > 0)
// base возводится
p *= base;
// в степень degree
return p; }
// Возвращение вычисленной степени

16. Перегруженные имена функций

Если функции делают примерно одинаковую работу над
объектами разных типов, удобно давать им одинаковые
имена. Использование одного имени для операции,
выполняемой над различными типами, называется
перегрузкой.
Компилятор различает функции с одинаковыми именами
по количеству и типам аргументов. При выборе
подходящей функции из нескольких перегруженных
компилятор ищет ту, которая имеет наилучшее
соответствие типов формальных и фактических
параметров.
Пусть в программе требуется вычислять абсолютную
величину переменных типа int и типа float. Для этого
можно написать две функции с одинаковыми именами.

17. Программа «Перегрузка функций»

#include <iostream>
#include <cstdlib>
using namespace std;
int module(int n)
{// module: возвращает абсолютную
//величину целого n
if(n < 0)
return -n;
return n;
}
float module(float x)
{// module: возвращает абсолютную
//величину плавающего x
if(x < 0)
return -x;
return x;
}
// double module(int n)
// {return n >= 0 ? n : -n;}
// Ошибка, отличие от int module(int n)
// только в типе возвращаемого значения
int main()
{
// Работаем с int
cout << "module(-3) = " << module(-3) << endl;
// Работаем с double
// В следующей строке неоднозначность выбора
//перегруженной функции
// К какому типу перевести double -3.14?
//(int или float)
// cout << "module(-3.14) = " << module(-3.14) <<
endl;
// Явное преобразование типа для вызова
//перегруженной функции
cout << "module(-3.14) = " << module(float(-3.14)) <<
endl;
system("pause");
return 0;
}

18. Аргументы функций по умолчанию

У функций общего назначения часто больше аргументов, чем требуется
в простых случаях. Значения некоторых значений могут быть заданы
при объявлении функции (аргументы функций по умолчанию).
В случае, если при вызове функции количество передаваемых
значений в функцию меньше общего числа параметров, то последние
параметры инициализируются значениями по умолчанию.
Замечания:
1) Аргументы по умолчанию можно задавать только в конце списка
аргументов, например,
int f(int, int = 0, char = 0);
// Правильно
int g(int = 0, int = 0, char);
// Ошибка
2) Аргументы по умолчанию указывают один раз в объявлении
функции. Если определение функции идет после объявления значения
аргументов по умолчанию не повторяются:
int f(int i, int j, char c)
// Определение функции. Значения по
{…}
// умолчанию для j и c заданы в объявлении

19. Программа «Перевод числа в заданную систему счисления»

#include <iostream>
#include <cstdlib>
#include <locale>
#include <math.h>
using namespace std;
int fun(int n, int osn=10)
{
int s=0,i=0;
while (n>0)
{
s=(n%osn)*pow(10.0,i)+s;
i++;
n=n/osn;
}
return s;
}
int main()
{
setlocale(LC_ALL, "Russian");
int n,osn;
cout << "Введите число в десятичной системе счисления"<<
endl;
cin>>n;
cout << "Введите основание новой системе счисления"<< endl;
cin>>osn;
cout << "Число "<<n<<" в системе счисления с основанием 10 ";
cout<<"равно "<<fun(n)<< endl;
cout << "Число "<<n<<" в системе счисления с основанием 10 ";
cout<<"равно "<<fun(n,10)<< endl;
cout << "Число "<<n<<" в системе счисления с основанием ";
cout<<osn<<" равно "<<fun(n,osn)<< endl;
system("pause");
return 0;
}

20. Массивы и функции

В С++ имена массивов являются адресами их первого
элемента, то есть элемента с индексом 0. При
передаче массива внутрь функции передаётся его
базовый адрес, сами элементы массива не
копируются.
Замечания:
1) В С++ можно передавать массивы, размер которых
не фиксирован в объявлении функции. Это позволяет
работать с массивами и строками переменной длины.
2) Внутри функции можно изменять объекты массива.

21. Программа «Массивы и функции»

Функция возвращает сумму элементов массива, после этого заменяя все
отрицательные элементы их абсолютными значениями
#include <iostream>
#include <cstdlib>
#include <locale>
using namespace std;
int absolut(int mas[], int n)
{
int sum=0;
for (int i=0;i<n; i++)
{
sum+=mas[i];
if (mas[i]<0)
mas[i]=-mas[i];
}
return sum;
}
int main()
{
setlocale(LC_ALL, "Russian");
int n;
int mas[20];
cout << "Введите количество элементов"<< endl;
cin>>n;
for(int i=0;i<n;i++)
{
cout << "mas["<<i<<"]=";
cin>>mas[i];
}
cout<<"Сумма элементов равна "<<absolut(mas,n)<<endl;
cout<<"преобразованный массив: ";
for(int i=0;i<n;i++)
cout <<mas[i]<<" ";
cout<<endl;
system("pause");
return 0;
}

22. Рекурсия

В языке C++ функции могут быть рекурсивными, то есть вызывать
сами себя.
Пример (вычисления факториала неотрицательного целого
числа):
Эта формула показывает, как, зная значение факториала для
меньшего числа n – 1, вычислить факториал для следующего
числа n, что позволяет сводить задачу к вычислению факториала
все более меньшего числа. Также задан предельный случай n = 0.

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

#include <iostream>
#include <locale>
#include <cstdlib>
int main()
using namespace std;
{
setlocale(LC_ALL, "Russian");
int factorial(int n)
int k;
{
do{
int f;
// Значение факториала
cout << "Введите целое число >= 0: ";
if (n == 0)
cin >> k;
f = 1;
}while(k < 0);
int fct = factorial(k);
else
// Рекурсивный вызов функции factorial() cout << "factorial(" << k << ") = " << fct << endl;
system("pause");
f = factorial(n - 1) * n;
return 0;
return f;
}
}
Замечание (модернизированная версия):
int factorial(int n)
{ if (n == 0)
return 1;
else
return factorial(n - 1) * n; }
// Рекурсивный вызов factorial()

24. Таблица Работа рекурсивной функции

25. Программа «Распечатка числа в обратном порядке»

#include <iostream>
#include <cstdlib>
#include <locale>
using namespace std;
void print1(int n)
{ if(n>0)
{cout<<n%10;
// Выводим последнюю цифру
print1(n/10);
// Вызов функции от числа без последней цифры
}
}
int main()
{ setlocale(LC_ALL, "Russian");
int n;
cout << "Введите число"<< endl; cin>>n;
cout << "Преобразованное число ";
print1(n);
cout<<endl;
system("pause"); return 0; }

26. Программа «Распечатка числа в прямом порядке»


Программа «Распечатка числа в прямом
порядке»
#include <iostream>
#include <cstdlib>
#include <locale>
using namespace std;
void print1(int n)
{ if(n>0)
{print1(n/10);
// Вызов функции от числа без последней цифры
cout<<n%10;
// Выводим последнюю цифру
}
}
int main()
{ setlocale(LC_ALL, "Russian");
int n;
cout << "Введите число"<< endl; cin>>n;
cout << "Распечатанное число ";
print1(n);
cout<<endl;
system("pause"); return 0; }
English     Русский Правила