Функции в программировании совсем незначительно отличаются от функций в математике. И там, и там нам нужен аргумент и возращаемое значение. Но не всё так просто.

Также существуют процедуры - блоки кода, не возращающие никакого значения, также могут не принимать аргументы.

Общий вид функции таков:

 <тип> <имя функции> (<аргументы>)
 {
  <тело функции>
 }

Процедуры

Процедуры в языке 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.

Стиль программирования, является не требованием, а пожеланием, потому что чистый, структурированный код улучшает его понимание другими людьми, и способствует более продуктивной работе. Поэтому в сообществе программистов были приняты некоторые соглашения касательно правил написания кода.