Функции и процедуры
Функции в программировании совсем незначительно отличаются от функций в математике. И там, и там нам нужен аргумент и возращаемое значение. Но не всё так просто.
Также существуют процедуры - блоки кода, не возращающие никакого значения, также могут не принимать аргументы.
Общий вид функции таков:
<тип> <имя функции> (<аргументы>)
{
<тело функции>
}
Процедуры
Процедуры в языке C++ имеют тип void. Создадим процедуру, печатающую приветствие:
void hello()
{
cout << "Hello!";
}
Вызываем данную процедуру в главной функции main:
int main()
{
hello();
return 0;
}
Теперь создадим процедуру, которая будет печатать приветствие заданное число раз.
void hello(int n)
{
for (int i = 0; i < n; i++)
cout << "Hello!" << endl;
}
n - аргумент данной процедуры.
В функции main вызываем процедуру и указываем в скобках параметры:
int main()
{
hello(5);
return 0;
}
Таким образом, процедура hello печатает приветствии на экран 5 раз.
Функции
Функция, в отличие от процедуры, должна иметь тип возвращаемого значения. Например, нам потребовалась функция возведения в квадрат:
int sqr(int x)
{
return x * x; // возвращаем
}
Здесь int - это тип возвращаемого значения, а return - это сам возврат.
В функции main:
int main()
{
cout << sqr(13);
return 0;
}
Данный код возвел 13 в квадрат.
Также можем придумать что-то интересное:
bool is_zero(int n)
{
if (n == 0)
return true;
else
return false;
}
Аргументы функции
В качестве аргумента мы можем использовать значение по умолчанию:
long double energy(long double m, long double c = 10e+8)
{
return m * c * c;
}
Данная функция вычисляет энергию по известному закону: \(E = mc^2\).
В качестве аргументов функции иогут выступать любые типы данных, в том числе и определенные пользователем.
- Перадача массива в функцию. Допустим, что перед нами поставили задачу: написать функцию, которая примет массив как аргумент и вернет среднее арифметическое его элементов. Чтобы передать массив в функцию, нужно передать указатель на первый элемент массива и размер самого массива. Вот так реализуется наша функция:
double average(int arr[], int size) // int arr[] <=> int * arr
{
double sum = 0;
for (int i = 0; i < size; i++)
sum += arr[i];
return sum / size;
}
int main()
{
int arr[] = { 1,3,8,16,2,32 }; // 6 элементов
cout << average(arr, 6);
return 0;
}
Рекурсия
Важным понятием в программировании является рекурсия. Рекурсия - это когда функция вызывает сама себя. Классическим примером рекурсии является факториал, когда значение умножениется на значение функции, уменьшенное на единицу, и так до 1. В данном случае 1 - базовый случай рекурсии. Базовый случай - это значение, которое должно остановить рекурсию. Если базовый случай отсутствует, мы получим бесконечную рекурсию.
Вычисление факториала:
int factorial(int n)
{
if (n == 0 || n == 1) // базовый случай
return 1;
else
return n * factorial(n - 1); // обращение к самой себе
}
Встроенные в язык функции
Вы наверняка уже встречались с функциями, встроенными в C++. Рассмотрим самые полезные и важные:
// возможно потребуется подключение <cmath>
sqrt(n); // квадратный корень
pow(n, 2.0); // <=> n^2
abs(n); // модуль
sin(n); asin(n); // тригонометрические функции
log(n); // логарифм
round(n); // математическое округление
ceil(n); // округление в большую сторону
floor(n); // округление в меньшую сторону
trunc(n); // отбрасывание дробной части числа
exp(x); // экспонента
Рандом
rand() - это функция псевдослучайных чисел. Почему псевдослучайных? Потому, что при каждом запуске она будет генерировать одни и те же значения. Для того, чтобы пользоваться рандомом, подключаем библиотеку
Заполним массив псевдослучайными числами при помощи rand():
int arr[100];
for (int i = 0; i < 10; i++)
arr[i] = rand();
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
Как можем заметить, при каждом запуске числа не меняются. Что же делать?
Выход есть! Используем высококачественный генератор случайных чисел - mt19937 rndm. Этот генератор основан на вихре Марсенна. Чтобы его использовать нам нужно зерно генерации. В качестве зерна можем использовать время, для этого подключаем
int arr[100];
mt19937 rndm;
rndm.seed(time(0)); // устанавливаем зерно
for (int i = 0; i < 10; i++)
arr[i] = rndm();
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
Теперь уже больше походит на генерацию случайных чисел!
Стиль программирования и функции
Кака правило, оформление кода выше (когда функция пишется сразу после прототипа) подходит для маленьких проектов. Однако на практике такой подход не применяется. В больших проектах сначала пишется прототип функции - объявление функции без тела:
int sum(int a, int b); // прототип функции sum
Уже после главной функции мы пишем полную функцию с телом:
int sum(int a, int b)
{
return a + b;
}
Таким образом весь наш файл main.cpp выглядит следующим образом:
#include <iostream>
using namespace std;
int sum(int a, int b);
int main()
{
cout << sum(2,2);
return 0;
}
int sum(int a, int b)
{
return a + b;
}
В дальнейшем, когда мы будем пробовать писать собственные классы, мы будем все объявления хранить в заголовочном файле, а определения в другом файле. Таким образом, наш проект будет состоять из трех файлов: Header.h, Definition.cpp и main.cpp.
Стиль программирования, является не требованием, а пожеланием, потому что чистый, структурированный код улучшает его понимание другими людьми, и способствует более продуктивной работе. Поэтому в сообществе программистов были приняты некоторые соглашения касательно правил написания кода.