Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lekcii_1_10 / Лекция 07.docx
Скачиваний:
52
Добавлен:
21.05.2015
Размер:
328.19 Кб
Скачать

Функции

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

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

В языке программирования С++ есть два типа функций:

  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;

}

Так как функция не должна возвращать значение, то тип возвращаемых данных должен быть void. Имя функции - faktorial, внутри круглых скобочек объявлена переменная numb типа int. Эта переменная является параметром функции faktorial().

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

// структура объявления функций возвращающих значения

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

{

// тело функции

 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;

}

//Tabs

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

Мы рассмотрели два типа функций, причём объявление функций выполняли в области программы, после подключения заголовочных файлов, но до начала функции 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()

 

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

 

*/

Область объявления функций переместилась в самый конец программы, после 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; // функция возвращает ложное значение

}

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

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

  2. создание файлов  типа *.cpp и *.h.

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

1

2

3

4

5

// код файла 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; // функция возвращает ложное значение

}

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

// 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;

}

мы разбили программу на три файла:

  • файл проекта: func_palendrom.cpp

  • заголовочный файл palendrom.h

  • исполняемый файл palendrom.cpp

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

Передача указателей и массивов в качестве аргументов

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

Вызов функций с указателями

В C++ разрешается передавать функции указатели. Для этого достаточно объявить параметр типа указатель. Рассмотрим пример.

// Передача функции указателя.

#include <iostream>

using namespace std;

void f (int *j);

int main()

{

 int i;

 int *p;

 p = &i; // Указатель p теперь содержит адрес переменной i.

 f(p);

 cout << i; // Переменная i теперь содержит число 100.

 return 0;

}

void f (int *j)

{

 *j = 100; // Переменной, адресуемой указателем j, присваивается число 100.

}

Как видите, в этой программе функция f() принимает один параметр: указатель на целочисленное значение. В функции main() указателю р присваивается адрес переменной i. Затем из функции main() вызывается функция f(), а указатель р передается ей в качестве аргумента. После того как параметр-указатель j получит значение аргумента р, он (так же, как и р) будет указывать на переменную i, определенную в функции main(). Таким образом, при выполнении операции присваивания

*j = 100;

переменная i получает значение 100. Поэтому программа отобразит на экране число 100. В общем случае приведенная здесь функция f() присваивает число 100 переменной, адрес которой был передан этой функции в качестве аргумента.

В предыдущем примере необязательно было использовать переменную р. Вместо нее при вызове функции f() достаточно использовать переменную i, предварив ее оператором "&" (при этом, как вы знаете, генерируется адрес переменной i). После внесения оговоренного изменения предыдущая программа приобретает такой вид.

// Передача указателя функции -- исправленная версия.

#include <iostream>

using namespace std;

void f (int *j);

int main()

{

 int i;

 f(&i);

 cout << i;

 return 0;

}

void f (int * j)

{

 *j = 100; // Переменной, адресуемой указателем j, присваивается число 100.

}

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

Соседние файлы в папке lekcii_1_10