Функции в С++

До сих пор мы писали программы единым, функционально неделимым, кодом. Алгоритм программы находился в главной функции, причём других функций в программе не было. Мы писали маленькие программы, поэтому не было потребности в объявлении своих функций. Для написания больших программ, опыт показывает, что лучше пользоваться функциями. Программа будет состоять из отдельных фрагментов кода, под отдельным фрагментом кода понимается функция. Отдельным, потому, что работа отдельной функции не зависит от работы какой-нибудь другой. То есть алгоритм в каждой функции функционально достаточен и не зависим от других алгоритмов программы. Однажды написав функцию, её можно будет с лёгкостью переносить в другие программы. Функция (в программировании) — это фрагмент кода или алгоритм, реализованный на каком-то языке программирования, с целью выполнения определённой последовательности операций. Итак, функции позволяют сделать программу модульной, то есть разделить программу на несколько маленьких подпрограмм (функций), которые в совокупности выполняют поставленную задачу. Еще один огромнейший плюс функций в том, что их можно многократно использовать. Данная  возможность позволяет многократно использовать один раз написанный код, что в свою очередь, намного сокращает объем кода программы!

Кроме того, что в С++ предусмотрено объявление своих функций, также можно воспользоваться функциями определёнными в стандартных заголовочных файлах языка программирования С++. Чтобы воспользоваться функцией, определённой в заголовочном файле, нужно его подключить. Например, чтобы воспользоваться функцией, которая возводит некоторое число в степень, нужно подключить заголовочный файл <cmath> и в запустить функцию pow() в теле программы. Разработаем программу, в которой запустим функцию pow().

// inc_func.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
//действие 1 - подключаем заголовочный файл <cmath> который содержит прототипы основных математических функций
#include <cmath>

int main(int argc, char* argv[])
{
    float power = pow(3.14,2); //действие 2 - запуск функции возведения числа в степень
    return 0;
}

// код Code::Blocks

// код Dev-C++

// inc_func.cpp: определяет точку входа для консольного приложения.

//действие 1 - подключаем заголовочный файл <cmath> который содержит прототипы основных математических функций
#include <cmath>

int main(int argc, char* argv[])
{
    float power = pow(3.14,2); //действие 2 - запуск функции возведения числа в степень
    return 0;
}

Подключение заголовочных файлов выполняется так, как показано в строке 5, т. е. объявляется препроцессорная директива #include, после чего внутри знаков <> пишется имя заголовочного файла. Когда подключен заголовочный файл, можно использовать функцию, что, и сделано в строке 9. Функция pow() возводит число 3.14 в квадрат и присваивает полученный результат переменной power, где
pow — имя функции;
числа 3.14 и 2 — аргументы функции;

Всегда после имени функции ставятся круглые скобочки, внутри которых, функции передаются аргументы, и если аргументов несколько, то они отделяются друг от друга запятыми. Аргументы нужны для того, чтобы функции передать информацию. Например, чтобы возвести число 3.14 в квадрат используя функцию pow(), нужно как-то этой функции  сообщить, какое число, и в какую степень его возводить. Вот именно для этого и придуманы аргументы функций, но бывают функции, в которых аргументы не передаются, такие функции вызываются с пустыми круглыми скобочками. Итак, для того, чтобы воспользоваться функцией из стандартного заголовочного файла С++ необходимо выполнить два действия:

  1. Подключить необходимый заголовочный файл;
  2. Запустить нужную функцию.

Кроме вызова функций из стандартных заголовочных файлов, в языке программирования С++ предусмотрена возможность создания собственных функций. В языке программирования С++ есть два типа функций:

  1. Функции, которые не возвращают значений
  2. Функции, возвращающие значение

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

// структура объявления функций не возвращающих значений
void /*имя функции*/(/*параметры функции*/) // заголовок функции
{
// тело функции
}

Строка 2 начинается с зарезервированного слова void — это тип данных, который не может хранить какие-либо данные. Тип данных void говорит о том, что данная функция не возвращает никаких значений. void никак по-другому не используется и нужен только для того, чтобы компилятор мог определить тип функции. После зарезервированного слова void пишется имя функции. Сразу за именем функции ставятся две круглые скобочки, открывающаяся и закрывающаяся. Если нужно функции передавать какие-то данные, то внутри круглых скобочек объявляются параметры функции, они отделяются друг от друга запятыми. Строка 2 называется заголовком функции. После заголовка функции пишутся две фигурные скобочки, внутри которых находится алгоритм, называемый телом функции. Разработаем программу, в которой объявим функцию нахождения факториала, причём функция не должна возвращать значение.

// struct_func.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
using namespace std;

// объявление функции нахождения n!
void faktorial(int numb)// заголовок функции
{
    int rezult = 1; // инициализируем переменную rezult значением 1
    for (int i = 1; i <= numb; i++) // цикл вычисления значения n!
        rezult *= i; // накапливаем произведение в переменной rezult 
    cout << numb << "! = " << rezult << endl; // печать значения n!
}

int main(int argc, char* argv[])
{
    int digit; // переменная для хранения значения n!
    cout << "Enter number: ";
    cin >> digit;
    faktorial(digit);// запуск функции нахождения факториала
    system("pause");
    return 0;
}

// код Code::Blocks

// код Dev-C++

// struct_func.cpp: определяет точку входа для консольного приложения.

#include <iostream>
using namespace std;

// объявление функции нахождения n!
void faktorial(int numb)// заголовок функции
{
    int rezult = 1; // инициализируем переменную rezult значением 1
    for (int i = 1; i <= numb; i++) // цикл вычисления значения n!
        rezult *= i; // накапливаем произведение в переменной rezult
    cout << numb << "! = " << rezult << endl; // печать значения n!
}

int main(int argc, char* argv[])
{
    int digit; // переменная для хранения значения n!
    cout << "Enter number: ";
    cin >> digit;
    faktorial(digit);// запуск функции нахождения факториала
    return 0;
}

После того, как были подключены все необходимые заголовочные файлы, можно объявлять функцию нахождения факториала.Под объявлением функции подразумевается выбор имени функции, определение параметров функции и написание алгоритма, который является телом функции. После выполнения этих действий функцию можно использовать в программе. Так как функция не должна возвращать значение, то тип возвращаемых данных должен быть void. Имя функции — faktorial, внутри круглых скобочек объявлена переменная numb типа int. Эта переменная является параметром функции faktorial(). Таким образом, все объявления в строке 8 в совокупности составляют заголовок функции. Строки 9 — 14 составляют тело функции faktorial(). Внутри тела в строке 10 объявлена переменная rezult, которая будет хранить результат нахождения n! После чего, в строках 11-12 Объявлен оператор цикла for для нахождения факториала. В строке 13 объявлен оператор cout, с помощью которого значение факториала будет печататься на экране. Теперь, когда функция объявлена можно воспользоваться ею. В строке 21 запускается функция faktorial(digit), внутри скобочек функции передаётся аргумент, т. е. значение, содержащееся в переменной digit. Результат работы программы (см. Рисунок 1).

CppStudio.com
Enter number: 5
5! = 120
Для продолжения нажмите любую клавишу . . .

Рисунок 1 — Функции в С++

Итак, после запуска программы, было введена цифра 5, и программа вычислила, что значение 120 это 5!.

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

// структура объявления функций возвращающих значения
/*возвращаемый тип данных*/ /*имя функции*/(/*параметры функции*/) // заголовок функции
{
// тело функции
 return /*возвращаемое значение*/;
}

Структура объявления функций осталась почти неизменной, за исключением двух строк. В заголовке функции сначала нужно определять возвращаемый тип данных, это может быть тип данных int, если необходимо возвратить целое число или тип данных float — для чисел с плавающей точкой. В общем, любой другой тип данных, всё зависит от того, что функция должна вернуть. Так как функция должна вернуть значение, то для этого должен быть предусмотрен специальный механизм, как в строке 5. C помощью зарезервированного слова return  можно вернуть значение, по завершении работы функции. Всё, что нужно, так это указать переменную, содержащую нужное значение, или некоторое значение, после оператора return. Тип данных возвращаемого значения в строке 5 должен совпадать с типом данных в строке 2. Переделаем программу нахождения факториала так, чтобы функция faktorial() возвращала значение факториала.

// struct_func.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
using namespace std;

// объявление функции нахождения n!
int faktorial(int numb)// заголовок функции
{
    int rezult = 1; // инициализируем переменную rezult значением 1
    for (int i = 1; i <= numb; i++) // цикл вычисления значения n!
        rezult *= i; // накапливаем произведение в переменной rezult 
    return rezult; // передаём значение факториала в главную функцию
}

int main(int argc, char* argv[])
{
    int digit; // переменная для хранения значения n!
    cout << "Enter number: ";
    cin >> digit;
    cout << digit << "! = " << faktorial(digit) << endl;// запуск функции нахождения факториала
    system("pause");
    return 0;
}

// код Code::Blocks

// код Dev-C++

// struct_func.cpp: определяет точку входа для консольного приложения.

#include <iostream>
using namespace std;

// объявление функции нахождения n!
int faktorial(int numb)// заголовок функции
{
    int rezult = 1; // инициализируем переменную rezult значением 1
    for (int i = 1; i <= numb; i++) // цикл вычисления значения n!
        rezult *= i; // накапливаем произведение в переменной rezult
    return rezult; // передаём значение факториала в главную функцию
}

int main(int argc, char* argv[])
{
    int digit; // переменная для хранения значения n!
    cout << "Enter number: ";
    cin >> digit;
    cout << digit << "! = " << faktorial(digit) << endl;// запуск функции нахождения факториала
    return 0;
}


Теперь функция faktorial() имеет возвращаемый тип данных — int, так как n! — это целое число.   В строке 13 объявлен оператор return, который возвращает значение, содержащееся в переменной rezult. В строке 21 выполняем запуск функции faktorial(), возвращаемое значение которой отправляем в поток вывода с помощью оператора cout. Можно было бы написать так int fakt = faktorial(digit); — переменной типа int присваиваем возвращаемое значение функции faktorial(), после чего в переменной fakt будет храниться значение n!. Результат работы программы не изменился (см. Рисунок 2).

CppStudio.com
Enter number: 5
5! = 120
Для продолжения нажмите любую клавишу . . .

Рисунок 2 — Функции в С++

Мы рассмотрели два типа функций, причём объявление функций выполняли в области программы, после подключения заголовочных файлов, но до начала функции main(). Существует несколько способов объявления функций (см. Рисунок 3).

Функции в С++

Рисунок 3 — Функции в С++

На рисунке 3 показаны 4 способа объявления функций в языке программирования С++. Рассмотрим структуры объявления функций в одном файле, с главной функцией. Функции можно объявлять в двух областях, до начала функции main(), после функции main(). До сих пор мы объявляли функции  в одном файле, перед функцией main() — это самый простой из способов.

// struct_func.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
/*область 1 - объявление функций до начала main()

место для объявления функций 
функциям объявленным в этой области не нужны прототипы

*/
int main(int argc, char* argv[])
{

 return 0;
}

Если функции объявлять в области 1, перед главной функцией, то прототипы для этих функций не нужны. Хорошему стилю программирования соответствует способ объявления функций после main(). Рассмотрим структуру такого объявления функций.

// struct_func.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"

// место для объявления прототипов функций

int main(int argc, char* argv[])
{

 return 0;
}

/*область 2 - объявление функций после main()

место для объявления функций 

*/

// код Code::Blocks

// код Dev-C++

// struct_func.cpp: определяет точку входа для консольного приложения.

// место для объявления прототипов функций

int main(int argc, char* argv[])
{

 return 0;
}

/*область 2 - объявление функций после main()

место для объявления функций 

*/

Область объявления функций переместилась в самый конец программы, после main(). Что касается самого способа объявления функций , то он не поменялся. Но так как функции объявлены после main(), использовать их не получится, ведь порядок объявлений изменился и функция main() просто не будет видеть функции объявленные после. Так вот для того, чтобы эти функции можно было увидеть в main() существует понятие прототипа. Прототип функции — это заголовок функции, который объявляется перед функцией main(). И если объявить прототип функции, тогда функцию можно будет увидеть в main().

// синтаксис объявления прототипа
/*тип возвращаемых данных функции*/ /*имя функции*/(/*параметры функции*/);

Структура объявления прототипа очень схожа со структурой объявления функции. Разработаем программу, которая определяет, является ли введённое пятизначное число палиндромом. Палиндром — это число или текст, который читается одинаково как слева, так и справа: 93939; 49094; 11311.

// palindrom_func.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
using namespace std;

bool palindrom5(int); // прототип функции нахождения палиндрома пятизначных чисел

int main(int argc, char* argv[])
{
    cout << "Enter 5zn-e chislo: "; // введите пятизначное число
    int in_number, out_number; // переменные для хранения введённого пятизначного числа
    cin >> in_number;
    out_number = in_number; // в переменную out_number сохраняем введённое число

    if (palindrom5(in_number)) // если функция вернёт true, то условие истинно, иначе функция вернёт false - ложно 
        cout << "Number " << out_number << " - palendrom" << endl;
    else
        cout<<"This is not palendrom"<<endl;
    system("pause");
    return 0;
}
bool palindrom5(int number) // функция нахождения палиндрома пятизначных чисел
{
    int balance1, balance2, balance4, balance5; // переменные хранящие промежуточные результаты
    balance1 = number % 10; // переменной balance1 присвоили первый разряд пятизначного числа
    number = number / 10;   // уменьшаем введённое число на один разряд

    balance2 = number % 10; // переменной balance2 присвоили второй разряд
    number = number / 100;  // уменьшаем введённое число на два разряда

    balance4 = number % 10; // переменной balance4 присвоили четвёртый разряд
    number = number / 10;   // уменьшаем введённое число на один разряд

    balance5 = number % 10; // переменной balance5 присвоили пятый разряд
    if ((balance1 == balance5) && (balance2 == balance4)) 
        return true;  // функция возвращает истинное значение
    else
        return false; // функция возвращает ложное значение
}

// код Code::Blocks

// код Dev-C++

// palindrom_func.cpp: определяет точку входа для консольного приложения.

#include <iostream>
using namespace std;

bool palindrom5(int); // прототип функции нахождения палиндрома пятизначных чисел

int main(int argc, char* argv[])
{
    cout << "Enter 5zn-e chislo: "; // введите пятизначное число
    int in_number, out_number; // переменные для хранения введённого пятизначного числа
    cin >> in_number;
    out_number = in_number; // в переменную out_number сохраняем введённое число

    if (palindrom5(in_number)) // если функция вернёт true, то условие истинно, иначе функция вернёт false - ложно
        cout << "Number " << out_number << " - palendrom" << endl;
    else
        cout<<"This is not palendrom"<<endl;
    return 0;
}
bool palindrom5(int number) // функция нахождения палиндрома пятизначных чисел
{
    int balance1, balance2, balance4, balance5; // переменные хранящие промежуточные результаты
    balance1 = number % 10; // переменной balance1 присвоили первый разряд пятизначного числа
    number = number / 10;   // уменьшаем введённое число на один разряд

    balance2 = number % 10; // переменной balance2 присвоили второй разряд
    number = number / 100;  // уменьшаем введённое число на два разряда

    balance4 = number % 10; // переменной balance4 присвоили четвёртый разряд
    number = number / 10;   // уменьшаем введённое число на один разряд

    balance5 = number % 10; // переменной balance5 присвоили пятый разряд
    if ((balance1 == balance5) && (balance2 == balance4))
        return true;  // функция возвращает истинное значение
    else
        return false; // функция возвращает ложное значение
}

В строке 7 объявлен прототип функции нахождения палиндрома пятизначных чисел. Обратите внимание на то, что прототип полностью должен совпадать с заголовком функции, но некоторые отличия все же есть. Например, то, что в прототипе имена параметров перечислять не надо, достаточно объявить их типы данных. В конце объявления прототипа всегда нужно ставить точку с запятой. В остальном объявление прототипа совпадает с объявлением заголовка одной функции. Прототип необходимо объявлять для каждой функции отдельно. Переменная out_number служит для временного хранения введённого числа. В строке 16 в условии оператора выбора if выполняется запуск функции palindrom5(). Аргументом для неё является переменная in_number. функция вернёт значение типа bool, и если функция вернёт true, то условие будет истинно, в противном случае — ложно. Можно было бы сначала присвоить значение, возвращаемое функцией, некоторой переменной, а потом эту переменную подставить в условие оператора выбора if, но это бы увеличило код программы на одну строку. В строках 23 — 40 объявлена функция palindrom5(), с одним параметром, через который функции передаётся пятизначное число. Переменные balance1balance2, balance4, balance5 объявлены в строке 25, и необходимы для хранения разрядов пятизначного числа: первого, второго, четвёртого, пятого (нумерация — справа на лево). В строках 26, 29, 32, 35 выполняется одна и та же операция — остаток от деления. Операция остаток от деления отсекает по одному разряду справа налево и сохраняет их в переменные balance1balance2, balance4, balance5 соответственно. Причём операция остаток от деления чередуется с операцией  обычного деления. Операция деления выполняется в строках 27, 30, 33, и уменьшает введённое пятизначное число за шаг на один разряд. В строке 30 операция деления уменьшает введённое число сразу на два разряда, потому, что число пятизначное и средний разряд нас не интересует, он может быть любым. В строках 36 — 39 объявлен оператор выбора if, который сравнивает разряды пятизначного числа, и если они, соответствующим образом, равны, то функция вернёт значение true, иначе — false. Результат работы программы (см. Рисунок 4).

CppStudio.com
Enter 5zn-e chislo: 12321
Number 12321 - palendrom
Для продолжения нажмите любую клавишу . . .

Рисунок 4 — Функции в С++

До сих пор мы объявляли функции в одном файле, с основной программой, то есть там, где находится функция main(). В С++ существует возможность поместить объявления функций в отдельный файл, тогда необходимо будет подключать файл с функциями, как в случае с подключением стандартных заголовочных файлов. Есть два способа:

  1. создание файла типа *.cpp, в котором объявляются функции;
  2. создание файлов  типа *.cpp и *.h.

К хорошему стилю программирования относится второй способ. Таким образом, если объявлять функции в другом файле, то делать это согласно способу два. Переделаем программу нахождения палиндрома так, чтобы объявление функции palindrom5() находилось в отдельном файле *.cpp. Файл *.h нужен для того, чтобы скрыть реализацию функций, т. е. в файле *.h будут содержаться прототипы функций. С помощью обозревателя решений MVS создаём файл типа *.h и называем его palendrom.

// код файла palendrom.h
#ifndef palendrom
#define palendrom
bool palindrom5(int); // прототип функции нахождения палиндрома пятизначных чисел
#endif

Директивы в строках 2,3,5 необходимо всегда объявлять в файлах с прототипами функций, причём прототипы функций всегда объявляются в файлах типа *.h. После директив записанных в строках 2,3, но до директивы #endif объявляются прототипы функций. В строке 4 объявлен прототип функции palindrom5(). Объявление данной функции находится в файле palendrom.cpp, который предварительно тоже был создан с помощью обозревателя решений MVS.

// содержимое файла palendrom.cpp
#include "stdafx.h"
#include "palendrom.h"
bool palindrom5(int number) // функция нахождения палиндрома пятизначных чисел
{
    int balance1, balance2, balance4, balance5; // переменные хранящие промежуточные результаты
    balance1 = number % 10; // переменной balance1 присвоили первый остаток
    number = number / 10;   // уменьшаем введённое число на один разряд

    balance2 = number % 10; // переменной balance2 присвоили второй остаток
    number = number / 100;  // уменьшаем введённое число на два разряда

    balance4 = number % 10; // переменной balance4 присвоили четвёртый остаток
    number = number / 10;   // уменьшаем введённое число на один разряд

    balance5 = number % 10; // переменной balance5 присвоили пятый остаток
    if ((balance1 == balance5) && (balance2 == balance4)) 
        return true;  // функция возвращает истинное значение
    else
        return false; // функция возвращает ложное значение
}

// код Code::Blocks

// код Dev-C++

// содержимое файла palendrom.cpp

#include "palendrom.h"
bool palindrom5(int number) // функция нахождения палиндрома пятизначных чисел
{
    int balance1, balance2, balance4, balance5; // переменные хранящие промежуточные результаты
    balance1 = number % 10; // переменной balance1 присвоили первый остаток
    number = number / 10;   // уменьшаем введённое число на один разряд

    balance2 = number % 10; // переменной balance2 присвоили второй остаток
    number = number / 100;  // уменьшаем введённое число на два разряда

    balance4 = number % 10; // переменной balance4 присвоили четвёртый остаток
    number = number / 10;   // уменьшаем введённое число на один разряд

    balance5 = number % 10; // переменной balance5 присвоили пятый остаток
    if ((balance1 == balance5) && (balance2 == balance4))
        return true;  // функция возвращает истинное значение
    else
        return false; // функция возвращает ложное значение
}

В файле palendrom.cpp находится объявление функции palindrom5(). Так как файл palendrom.cpp является исполняемым файлом (*.cpp — исполняемые файлы), то в нём обязательно нужно подключить контейнер "stdafx.h", как в строке 2. Чтобы связать файл, где объявлена функция palindrom5() и файл с её прототипом, подключим заголовочный файл (файл с прототипом), это сделано в строке 3. Обратите внимание на то, что при подключении созданного нами файла используются двойные кавычки, а не знаки больше, меньше. Осталось только запустить функцию palindrom5() в главном исполняемом файлеfunc_palendrom.cpp.

// func_palendrom.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
// подключение заголовочного файла, с прототипом функции palindrom5()
#include "palendrom.h"
using namespace std;

int main(int argc, char* argv[])
{
    cout << "Enter 5zn-e chislo: "; // введите пятизначное число
    int in_number, out_number; // переменные для хранения введённого пятизначного числа
    cin >> in_number;
    out_number = in_number; // в переменную out_number сохраняем введённое число

    if (palindrom5(in_number)) // если функция вернёт true, то условие истинно, иначе функция вернёт false - ложно 
        cout << "Number " << out_number << " - palendrom" << endl;
    else
        cout<<"This is not palendrom"<<endl;
    system("pause");
    return 0;
}

// код Code::Blocks

// код Dev-C++

// func_palendrom.cpp: определяет точку входа для консольного приложения.

#include <iostream>
// подключение заголовочного файла, с прототипом функции palindrom5()
#include "palendrom.h"
using namespace std;

int main(int argc, char* argv[])
{
    cout << "Enter 5zn-e chislo: "; // введите пятизначное число
    int in_number, out_number; // переменные для хранения введённого пятизначного числа
    cin >> in_number;
    out_number = in_number; // в переменную out_number сохраняем введённое число

    if (palindrom5(in_number)) // если функция вернёт true, то условие истинно, иначе функция вернёт false - ложно 
        cout << "Number " << out_number << " - palendrom" << endl;
    else
        cout<<"This is not palendrom"<<endl;
    return 0;
}

В строке 6 мы подключили файл с прототипом функции palindrom5(), после чего можно использовать эту функцию. Итак, мы разбили программу на три файла:

  • файл проекта: func_palendrom.cpp
  • заголовочный файл palendrom.h
  • исполняемый файл palendrom.cpp

Файл проекта связываем с заголовочным файлом, а заголовочный файл связываем с исполняемым файлом, в таком случае файл проекта увидит функцию palindrom5() и сможет её запустить.

Автор: admin
Дата: 25.08.2012
Поделиться:

Комментарии

  1. lnikaFax

    Первый заработок за 60 минут. Законно и без рисков!

  2. Сергей Цысь

    Как можно присвоить результат функции переменной в основной функции?
    Для примера: одна функция при двукратном вызове вернула два результата.
    Как их возможно сравнить?
    Как эти результаты присвоить переменным в основной функции.?

  3. mpavelFax

    Официальное трудоустройство, работа на дому.

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.