Лекция № 8

Тема: «Функции в программах на С++»

 

План

1. Описание функций, возвращающих значения

2. Описание функций, не возвращающих значения

3. Передача массивов как параметров в функцию

4. Передача структур как параметров в функцию

5. Функции без параметров

 

1. Описание функций, возвращающих значения

Использование подпрограмм позволяет упростить создание сложных программ за счет разбиения программы на простые части кода. Язык С++ поддерживает использование подпрограмм и дает разработчику множество инструментов для работы с подпрограммами.

Все подпрограммы в С++ называются функциями. Однако функции делят на два основных вида:

 

Независимо от вида функции ее создание всегда соответствует стандартному набору действий:

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

Создание прототипа функции

Прототип такой функции записывается в виде:

 

тип_результата имя_функции (аргументы);

 

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

Имя функции – любое имя, подчиняющееся правилам именования в языке С++.

Аргументы – список переменных и их типов, необходимых для работы функции (исходные данные). Если несколько аргументов имеют одинаковый тип, то каждый аргумент описывают отдельно.

 

Например: пусть функция подсчитывает сумму двух вещественных чисел. В этом случае прототип функции может иметь вид:

 

float sum (float a, float b);

 

Так как исходные данные вещественные, то и результат будет вещественным. Поэтому тип функции указан float. Для работы функции необходимы две исходные переменные (a,b). Несмотря на то, что они имеют одинаковый тип, каждая переменная описана отдельно.

 

Например: пусть функция находит максимальное значение из трех целых чисел. Прототип функции может иметь вид:

 

int max(int a, int b, int c);

 

Тип функции int, так как максимальное из целых чисел будет также целым числом. Каждая переменная-аргумент описана отдельно.

Замечание: необходимо напомнить, что прототипы всех функций указываются до вызова главной программы int main().

Вызов функции в главной программе

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

Если функция возвращает значение, то ее можно вызывать в операторе присваивания, операторе вывода или в выражении.

Реализация функции

После завершения главной программы приводят реализацию функции. Реализация имеет вид:

 

заголовок функции

{

описание переменных;

операторы;

return результат;

}

 

Заголовок функции повторяет ее прототип, приведенный вверху программы.

Описание переменных и операторы используются только при необходимости. В простейших функциях этих элементов может не быть.

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

 

return результат;

 

Для лучшего понимания приведем несколько примеров.

 

Пример. Найти значение функции:

 

y=max(3a,3+b)-min(a-7,2b)

 

Для решения задачи создадим две функции: нахождение максимального и минимального значения из двух чисел.

 

//подключаем заголовочные файлы

#include <iostream.h>

 

//прототип функции

//нахождения максимального значения

float max(float a, float b);

//прототип функции

//нахождения минимального значения

float min(float a, float b);

 

//главная программа

int main()

{

system("chcp 1251>nul");

//описываем переменные

float x,y,rez;

//вводим исходные данные

cout<<"Введите исходные значения(x,y): ";

cin>>x>>y;

//вычисляем выражение с помощью функций

rez=max(3*x,3+y)-min(x-7,2*y);

//задаем точность вывода

cout.precision(3);

//выводим результат

cout<<"Значение функции="<<rez;

//делаем паузу для просмотра

system("pause");

//конец главной программы

return 0;

}

 

//реализация функции  

//нахождения максимального значения

float max(float a, float b)

{

if (a>b)

     return a;

else

     return b;

}

 

//реализация функции

//нахождения минимального значения

float min(float a, float b)

{

if (a<b)

     return a;

else

     return b;

}

 

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

Рассмотрим этот же пример, но функции вызовем не в выражении, а в операторе вывода:

 

//подключаем заголовочные файлы

#include <iostream.h>

 

//прототип функции

//нахождения максимального значения

float max(float a, float b);

//прототип функции

//нахождения минимального значения

float min(float a, float b);

 

//главная программа

int main()

{

system("chcp 1251>nul");

//описываем переменные

float x,y;

//вводим исходные данные

cout<<"Введите исходные значения(x,y): ";

cin>>x>>y;

cout.precision(3);

//выводим результат

cout<<"Значение функции="<< max(3*x,3+y)-min(x-7,2*y);

//делаем паузу для просмотра

system("pause");

//конец главной программы

return 0;

}

 

//реализация функции

//нахождения максимального значения

float max(float a, float b)

{

if (a>b)

     return a;

else

     return b;

}

 

//реализация функции

//нахождения минимального значения

float min(float a, float b)

{

if (a<b)

     return a;

else

     return b;

}

 

Такой подход позволил сократить текст программы и сэкономить часть памяти, которая была бы отведена под переменную rez. (начало)

 

2. Описание функций, не возвращающих значения

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

 

void имя_функции(аргументы);

 

 

return;

 

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

 

//подключаем заголовочные файлы

#include <iostream.h>

#include <math.h>

 

//прототип функции

//вывода переменной с точность n

void print (float a, int n);

 

//главная программа

int main()

{

system("chcp 1251>nul");

//описываем переменные

float x,rez;

//вводим исходные данные

cout<<"Введите исходное значение(x): ";

cin>>x;

//вычисляем выражение

rez=sqrt(x);

//печатаем с помощью функции ответ

//с точность 2 знака

print(rez,2);

//делаем паузу для просмотра

system("pause");

//конец главной программы

return 0;

}

 

//реализация функции вывода

void print (float a, int n)

{

//задаем точность вывода n знаков

cout.precision(n);

//выводим переменную a на экран

cout<<"Значение функции="<<a<<"\n";

return;

}

 

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

 

//подключаем заголовочные файлы

#include <iostream.h>

#include <math.h>

 

//прототип функции

//вывода переменной с точность n

void print (float a, int n);

 

//главная программа

int main()

{

system("chcp 1251>nul");

//описываем переменную

float x;

//вводим исходные данные

cout<<"Введите исходное значение(x): ";

cin>>x;

//вычисляем выражение с помощью функции

//печатаем на экране с точностью 2 знака

print(sqrt(x),2);

//делаем паузу для просмотра

system("pause");

//конец главной программы

return 0;

}

 

//реализация функции вывода

void print (float a, int n)

{

//задаем точность вывода n знаков

cout.precision(n);

//выводим переменную a на экран

cout<<"Значение функции="<<a<<"\n";

return;

} (начало)

 

3. Передача массивов как параметров в функцию

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

Например, пусть массив вещественных чисел mas состоит из n элементов. Прототип функции для формирования массива может иметь вид:

 

void formmas (float mas[], int n);

 

Как видно из описания, массив mas указан без размера, а его размер n указан как отдельный параметр функции.

Рассмотрим пример обработки массива с помощью функции.

 

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

Функции ввода и вывода не подсчитывают результат, поэтом их тип void. Функция нахождения суммы подсчитывает значение типа float.

 

//подключаем заголовочные файлы

#include <iostream.h>

#include <stdlib.h>

 

//прототип функции формирования массива

void formmas (float m[], int n);

//прототип функции вывода массива

void vivodmas (float m[], int n);

//прототип функции нахождения суммы

float summas (float m[], int n);

 

//главная программа

int main()

{

system("chcp 1251>nul");

//описываем переменную для размера массива

int m;

//описываем массив

float *mas;

//вводим число элементов в массиве

cout<<"Введите количество элементов в массиве: ";

cin>>m;

//создаем массив из m элементов

mas=new float [m];

//вызываем функцию формирования массива

formmas(mas,m);

cout<<"Исходный массив:\n";

//вызываем функцию вывода массива на экран

vivodmas(mas,m);

//в операторе вывода вызываем функцию

//нахождения суммы элементов

cout<<"Сумма положительных элементов="<<summas(mas,m);

//делаем паузу для просмотра

system("pause");

//конец основной программы

return 0;

}

 

//реализация функции формирования массива

void formmas (float m[], int n)

{

//описываем концы отрезка

float a,b;

//описываем счетчик цикла

int i;

//вводим концы отрезка

cout<<"Введите концы отрезка (a,b): ";

cin>>a>>b;

//в цикле заполняем массив

//случайными числами на отрезке

for (i=0; i<=n-1; i++)

m[i]=(b-a)*rand()/32767+a;

//завершаем функцию

return;

}

 

//реализация функции вывода массива

void vivodmas (float m[], int n)

{

//описываем счетчик цикла

int i;

//задаем точность вывода 4 знака

cout.precision(4);

//в цикле выдаем массив в строку

//через пробел

for (i=0; i<=n-1; i++)

cout<<m[i]<<" ";

//переводим курсор на новую строку

cout<<"\n";

//завершаем функцию

return;

}

 

//реализация функции нахождения

//суммы элементов

float summas (float m[], int n)

{

//описываем счетчик цикла

int i;

//описываем переменную для суммы

float sum=0;

//в цикле считаем сумму положительных элементов

for (i=0; i<=n-1; i++)

if (m[i]>0)

sum+mas[i];

//завершаем функцию и передаем

//в главную программу найденную сумму

return sum;

} (начало)

 

4. Передача структур как параметров в функцию

Если аргументом функции является структура, то это также накладывает некоторые особенности на реализацию такой функции:

 

тип-структура * переменная

 

 

переменная->поле

 

Пример. Пусть объект «студент» обладает свойствами: фамилия, имя, год рождения, средний балл. Составить функции для ввода данных о студенте и выводе введенной информации на экран.

 

//подключаем заголовочные файлы

#include <iostream.h>

 

//описываем структур «студент»

struct student

{

//фамилия, имя

char fam[15], imya[10];

//год рождения

int god;

//средний балл

float srbal;

};

 

//прототип функции ввода структуры

void vvodstud (student * a);

//прототип функции вывода структуры

void vivodstud (student * a);

 

//главная программа

int main()

{

system("chcp 1251>nul");

//описываем переменную-структуру

student st;

//вызываем функцию ввода структуры

vvodstud(&st);

//вызываем функцию вывода структуры

vivodstud(&st);

//делаем паузу для просмотра

system("pause");

//конец главной программы

return 0;

}

 

//реализация функции ввода структуры

void vvodstud (student * a)

{

//вводим данные о студенте

cout<<"Введите данные о студенте:\n";

cout<<"-фамилия: ";          cin.getline(a->fam,15);

cout<<"-имя: ";              cin.getline(a->imya,10);

cout<<"-год рождения: ";    cin>>a->god;

cout<<"-средний балл: ";    cin>>a->srbal;

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

return;

}

 

//реализация функции вывода структуры

void vivodstud (student * a)

{

//выводим структуру

cout<<"Данные о студенте:\n";

cout<<"-фамилия: "<<a->fam<<"\n";

cout<<"-имя: "<<a->imya<<"\n";

cout<<"-год рождения: "<<a->god<<"\n";

cout<<"-средний балл: "<<a->srbal<<"\n";

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

return;

} (начало)

 

5. Функции без параметров

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

Например, в конце каждой программы приходится делать паузу для просмотра результата и выдавать сообщение:

 

cout<<"Для продолжения нажмите любую клавишу…";

system("pause");

 

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

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

 

//подключаем заголовочные файлы

#include <iostream.h>

 

//описываем прототип функции без параметров

void pauza();

 

//начало главной программы

int main()

{

system("chcp 1251>nul");

//описываем переменные

float a,b;

//вводим значения переменных

cout<<”Введите значения двух чисел (a,b): ”;

cin>>a>>b;

//выводим сумму переменных

cout<<”Сумма чисел равна: ”<<a+b;

//вызываем функцию для создания паузы

pauza();

//конец главной программы

return 0;

}

 

//реализация функции для создания паузы

void pauza()

{

//выдаем текст-подсказку

cout<<"Для продолжения нажмите любую клавишу...";

//ждем нажатия любой клавиши

system("pause");

//завершаем работу функции

return 0;

}