Пример построения функции




#include <iostream>

using namespace std;

 

void function_name ()

{

cout << "Hello, world" << endl;

}

 

int main ()

{

function_name(); // Вызов функции

return 0;

}

Перед вами тривиальная программа, Hello, world, только реализованная с использованием функций.

Если мы хотим вывести «Hello, world» где-то еще, нам просто нужно вызвать соответствующую функцию. В данном случае это делается так: function_name();. Вызов функции имеет вид имени функции с последующими круглыми скобками. Эти скобки могут быть пустыми, если функция не имеет аргументов. Если же аргументы в самой функции есть, их необходимо указать в круглых скобках.

Функции в C++ могут не возвращать никаких значений (как в примере) и могут возвращать какое-либо значение. Если функция не возвращает ничего, то это функция типа void.

Синтаксис функции, которая не возвращает значений:

Имя функции следует давать придерживаясь правил для имен переменных. Единственное – желательно чтобы оно содержало глагол, так как функция выполняет действие. Например если она считает среднее арифметическое можно дать название calculateAverage, если выводит что-то на экран – showText. Имя должно говорить за себя, чтобы не пришлось оставлять лишние комментарии в коде.

Параметры (или аргументы функции) – это данные, которые функция принимает и обрабатывает в теле. Если функции не нужно ничего принимать для обработки, круглые скобки оставляют пустыми. Согласно правилам High Integrity C++ Coding Standard желательно не определять функции с больш и м количеством параметров (больше 6).

Рассмотрим пару примеров с функциями, которые принимают параметры и не возвращают значений.

Принимает один параметр:

  #include <iostream> using namespace std;   void printQuestion(int questionCount);   int main() { setlocale(LC_ALL, "rus");   printQuestion(7); cout << endl << endl;   return 0; }   void printQuestion(int questionCount) { for (int i = 0; i < questionCount; i++) { cout << '?'; } }

В 10-й строке кода функция получает параметр – целое число 7. С ним (с этим числом) произойдет то, что описано в определении функции – строки 16 – 22. А именно – это число подставится в заголовок цикла for. Выражение i < questionCount станет равнозначным i < 7. В итоге мы увидим на экране 7 знаков вопроса.

Принимает три параметра:

  #include <iostream> using namespace std;   void printOurSymbol(int symbCount, int lineCount, char ourSymbol);   int main() { setlocale(LC_ALL, "rus");   printOurSymbol(7, 5, '@'); cout << endl << endl;   return 0; }   void printOurSymbol(int symbCount, int lineCount, char ourSymbol) { for (int i = 0; i < lineCount; i++) { for (int j = 0; j < symbCount; j++) { cout << ourSymbol; } cout << endl; } }

Синтаксис функции, которая возвращает значение:

Такие функции отличаются тем, что необходимо указать тип значения, которое вернет функция в результате своей работы. Сам возврат значения в программу оформляется оператором return и это значение программа получит в том месте, где функция была вызвана. return может возвращать переменную, константу или результат выражения (например: return variable1 -variable2;). В теле функции могут находиться несколько операторов return. Тогда, работа функции завершится, если сработает какой-то один из этих операторов. Например:

  #include <iostream> using namespace std;   int calculateSomeDigits(int d1, int d2, char ch);   int main() { setlocale(LC_ALL, "rus");   int digit1 = 0; int digit2 = 0; int res = 0; char chVar = 0;   cout << "1-е число: "; cin >> digit1; cout << "2-е число: "; cin >> digit2; cout << "Операция(+ или -): "; cin >> chVar;   res = calculateSomeDigits(digit1, digit2, chVar); cout << "res = " << res << endl;   return 0; }   int calculateSomeDigits(int d1, int d2, char ch) { if (ch == '+') return d1 + d2; if (ch == '-') return d1 - d2; }

Определение функции располагается в строках 28 – 34. Если пользователь введет +, сработает блок if в строке 30, а в нём соответственно сработает return d1 + d2;. После этого код функции уже не будет обрабатываться дальше. Компилятор вернется к выполнению main -функции.

Вы наверное заметили, что в предыдущем коде названия параметров в прототипе и в самом определении функции отличаются от имен переменных, которые передаются в функцию из main. Дело в следующем – параметры в определении и прототипе функции формальные. Когда мы передаем переменные в виде параметров, функция будет работать не с оригиналами переменных, а с их точными копиями. Эти копии создаются в оперативной памяти в момент вызова функции. Она работает с этими копиями, а по завершении работы, копии уничтожаются. Так что в прототипах вы можете использовать точные имена переменных, но функция в любом случае будет работать не напрямую с ними, а с их копиями. То есть сами переменные она не может изменить. Когда в следующих уроках вы познакомитесь с указателями и ссылками – узнаете, как можно изменить значения передаваемых переменных в теле функции.

Еще немного о прототипе: прочитав его до main, компилятор получает сведения о том, какой тип возвращаемого значения будет у функции (или она вообще не возвращает значения – имеет тип void) и о том, какие параметры будут в неё переданы, в каком количестве и в какой последовательности.

Прототип int calculateSomeDigits(int d1, int d2, char ch); говорит компилятору, что функция вернет на место её вызова целое число и о том, что при вызове в нее должно быть передано два целых числа и один символ. При вызове функции, мы должны передать ей столько параметров сколько указано в её заголовке при определении.

Передавать параметры необходимо в том же порядке, как они определены в круглых скобках за именем функции. Иначе возникнут ошибки при компиляции либо программа будет работать некорректно.

Синтаксис прототипа функции:

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

Имена переменных-параметров в прототипе можно не указывать. Следующий прототип равнозначен тому, что выше.

На мой взгляд, все же лучше объявлять прототипы функций с указанием имён параметров. Особенно если параметров несколько и они имеют одинаковый тип. Для читаемости и понимания программы так будет лучше.

 

Оператор return используется для возвращения вычисляемого функцией значения.

Рассмотрим пример функции, возвращающей значение на примере проверки пароля.

#include <iostream>

#include <string>

 

using namespace std;

 

string check_pass (string password)

{

string valid_pass = "qwerty123";

string error_message;

if (password == valid_pass) {

error_message = "Доступ разрешен.";

} else {

error_message = "Неверный пароль!";

}

return error_message;

}

 

int main ()

{

string user_pass;

cout << "Введите пароль: ";

getline (cin, user_pass);

string error_msg = check_pass (user_pass);

cout << error_msg << endl;

return 0;

}

В данном случае функция check_pass имеет тип string, следовательно она будет возвращать только значение типа string, иными словами говоря строку. Давайте рассмотрим алгоритм работы этой программы.

Самой первой выполняется функция main(), которая должна присутствовать в каждой программе. Теперь мы объявляем переменную user_pass типа string, затем выводим пользователю сообщение «Введите пароль», который после ввода попадает в строку user_pass. А вот дальше начинает работать наша собственная функция check_pass().

В качестве аргумента этой функции передается строка, введенная пользователем.

Аргумент функции — это, если сказать простым языком переменные или константы вызывающей функции, которые будет использовать вызываемая функция.

При объявлении функций создается формальный параметр, имя которого может отличаться от параметра, передаваемого при вызове этой функции. Но типы формальных параметров и передаваемых функии аргументов в большинстве случаев должны быть аналогичны.

После того, как произошел вызов функции check_pass(), начинает работать данная функция. Если функцию нигде не вызвать, то этот код будет проигнорирован программой. Итак, мы передали в качестве аргумента строку, которую ввел пользователь.

Теперь эта строка в полном распоряжении функции (хочу обратить Ваше внимание на то, что переменные и константы, объявленные в разных функциях независимы друг от друга, они даже могут иметь одинаковые имена. В следующих уроках я расскажу о том, что такое область видимости, локальные и глобальные переменные).

Теперь мы проверяем, правильный ли пароль ввел пользователь или нет. если пользователь ввел правильный пароль, присваиваем переменной error_message соответствующее значение. если нет, то сообщение об ошибке.

После этой проверки мы возвращаем переменную error_message. На этом работа нашей функции закончена. А теперь, в функции main(), то значение, которое возвратила наша функция мы присваиваем переменной error_msg и выводим это значение (строку) на экран терминала.

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

#include <iostream>

#include <string>

 

using namespace std;

 

bool password_is_valid (string password)

{

string valid_pass = "qwerty123";

if (valid_pass == password)

return true;

Else

return false;

}

 

void get_pass ()

{

string user_pass;

cout << "Введите пароль: ";

getline(cin, user_pass);

if (!password_is_valid(user_pass)) {

cout << "Неверный пароль!" << endl;

get_pass (); // Здесь делаем рекурсию

} else {

cout << "Доступ разрешен." << endl;

}

}

 

int main ()

{

get_pass ();

return 0;

}

 

Задачи

1. Объявить два целочисленных массива с разными размерами и написать функцию, которая заполняет их элементы значениями и показывает на экран. Функция должна принимать два параметра – массив и его размер.

2. Необходимо создать двумерный массив 5 х 5. Далее написать функцию, которая заполнит его случайными числами от 30 до 60. Создать еще две функции, которые находят максимальный и минимальный элементы этого двумерного массива. (О генерации случайных чисел есть отдельная статья)

3. Написать игру в которой имитируется бросание кубиков компьютером и пользователем. В игре 2 кубика и на каждом из них может выпасть от 1 до 6 очков. Реализовать определение программой первого ходящего. Каждый делает по четыре броска. После бросков показать, нарисованные символами кубики и количество очков, выпавших на них. После пары бросков (бросок компьютера + бросок пользователя) выводить на экран промежуточный результат – количество набранных очков игроком и компьютером. В конце сообщить о том, кто выиграл по итогам всех бросков.


 

Рекурсия в C++ на примере

Вычисления факториала

 

Сначала определимся, что из себя представляет рекурсивная функция. Рекурсивной называется функция, которая возвращает значение самой себя, рассмотрим пример рекурсивной функции на примере программы, вычисляющей факториал целого числа

Для начала напишем главную функцию программы и определим заголовочные файлы:

#include <iostream>using namespace std; int main (){ int N; setlocale(0,""); // Включаем кириллицу cout << "Введите число для вычисления факториала: "; cin >> N; cout << "Факториал для числа " << N << " = " << fact(N) << endl << endl; // fact(N) - функция для вычисления факториала. return 0;}

А теперь приступим к написанию самой функции:

long double fact (int N){ if (N < 0) // если пользователь ввел отрицательное число return 0; // возвращаем ноль if (N == 0) // если пользователь ввел ноль, return 1; // возвращаем факториал от нуля - не удивляетесь, но это 1 =) else // Во всех остальных случаях return N * fact (N - 1); // делаем рекурсию. }

Наша окончательная версия программы будет выглядеть так:

#include <iostream>using namespace std; long double fact (int N){ if (N < 0) // если пользователь ввел отрицательное число return 0; // возвращаем ноль if (N == 0) // если пользователь ввел ноль, return 1; // возвращаем факториал от нуля - не удивляетесь, но это 1 =) else // Во всех остальных случаях return N * fact (N - 1); // делаем рекурсию. } int main (){ int N; setlocale(0,""); // Включаем кириллицу cout << "Введите число для вычисления факториала: "; cin >> N; cout << "Факториал для числа " << N << " = " << fact(N) << endl << endl; // fact(N) - функция для вычисления факториала. return 0;}

Для удобства использования данной функции, ее можно поместить в отдельный заголовочный файл, к примеру — fact.h, а затем подключить этот файл в главный файл программы:

Fact.h

long double fact (int N){ if (N < 0) // если пользователь ввел отрицательное число return 0; // возвращаем ноль if (N == 0) // если пользователь ввел ноль, return 1; // возвращаем факториал от нуля - не удивляетесь, но это 1 =) else // Во всех остальных случаях return N * fact (N - 1); // делаем рекурсию. }

В таком случае нам будет необходимо добавить в главных файл программы строчку, подключающую функцию.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2021-04-24 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: