Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабораторный практикум

.pdf
Скачиваний:
48
Добавлен:
15.06.2021
Размер:
3 Mб
Скачать

Общий вид записи функции:

тип_возвращаемого_значения имя_функции (формальный_параметр_1, формальный_параметр_2, …)

{

операторы;

return возвращаемое_значение;

}

Вызов функции:

переменная=имя_функции(список_фактически_ параметров);

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

Приведем пример функции с параметром-константой:

#include <iostream> using namespace std; int IsSign(double a)

{

if (a>0) return 1;

else

if (a == 0) return 0;

else

return -1;

}

void main()

{

setlocale(LC_CTYPE, "Russian"); int n, m;

cout << "n="; cin >> n;

m = IsSign(n); switch (m)

{

case -1:cout << "Отрицательное" <<

103

endl; break;

case 0:cout << "Нуль" << endl; break; case 1:cout << "Положительное" <<

endl; break;

}

}

По я сн е н ия к пр о гр ам м е . В функцию IsSign передается па- раметр-константа а, который анализируется относительно нуля, - больше ли его значение нуля, равно нулю или значение является отрицательным. При разных значениях переданного параметра возвращается значение 1, 0 или 1. В основной функции значение для анализа вводится с клавиатуры в переменную n, и это фактическое значение передается при вызове функции IsSign, результат вычисления функции заносится в переменную m. Далее, в зависимости от значения m, на экран выводится соответствующая информация, является ли введенное число положительным, отрицательным или это нуль. Результат выполнения программы приведен на рис.1.

Рис.1. Результат выполнения программы с использованием параметра-значения

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

Указатель - это переменная, которая содержит адрес другой переменной. Иными словами, переменная типа указатель указывает на некоторое значение, имеющееся в памяти компьютера.

Описание указателя:

тип *идентификатор

Например:

int *p;

104

Выделим память в динамической области с помощью функции new, которая возвращает адрес выделенного участка памяти. Занесем в переменную-указатель p значение этого адреса:

int *p; p=new int;

*p= 5;

Схематично взаимосвязь ячеек памяти можно представить так: p

* –5

Иными словами, переменная p содержит адрес ячейки, в которой находится значение, равное 5.

Без использования оператора new эту же схему можно реализовать, используя оператор получения адреса &:

int *p, c= 5; p=&c;

Говоря другими словами, имеется две переменные, в одной из них (в с) хранится значение, равное 5, а в другой ( в р) находится адрес переменной с.

Ссылка - это другое имя (псевдоним) уже имеющегося данного имени. Обозначается ссылка следующим образом:

тип & идентификатор

Пример использования ссылки:

int c=-5; int &a=c;

Переменные a и с - это имена одного и того же данного со значением 5. Изменение значения с, влечет за собой изменение значения а.

Одним из применений указателей и ссылок является использование их в качестве параметров-переменных.

Приведем пример функции с параметром-переменной:

#include <iostream> using namespace std;

void exgange(int &a, int &b)

105

{

int s = a; a = b;

b = s;

}

void main()

{

setlocale(LC_CTYPE, "Russian"); int n, m;

cout << "n="; cin >> n; cout << "m="; cin >> m; exgange(n, m);

cout<<"После обмена n="<<n<<" m="<< m << endl;

}

По я сн е н ия к пр о гр ам м е . В функции exgange осуществляется обмен значений между переменными a и b, поэтому параметры a и b передаются по ссылке, и внутри функции эти параметры меняют свои значения. Функция возвращает значения через параметры, поэтому оператор return здесь не используется, а тип возвращаемого значения равен void. В основной функции вводятся значения в переменные m и n, а после вызова функции exgange значения m и n становятся другими (m присвоено значение, которое раньше имела переменная n, и наоборот). Результат выполнения данной программы представлен на рис.2.

Рис.2. Результат работы программы с использованием параметра-переменной

Приведем примеры функций с параметрами-массивами. Отметим, что массивы в качестве параметров являются параметрами-

106

переменными, поскольку передается адрес первого (с индексом 0) элемента массива. Рассмотрим пример функции формирования одномерного массива с помощью датчика случайных чисел:

void input(int a[])

{

for(int i=0;i<n;i++)a[i]=rand()/100-100;

}

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

Функция для вывода на экран значений одномерного массива:

void output (int a[])

{

cout<<"Output matr>"<<endl; for(int i=0;i<n;i++)

cout<<setw(6)<<a[i];

cout<<endl;

}

Функции ввода и вывода одномерного массива с использованием указателя:

void input(int *a)

{

for(int i=0;i<n;i++)a[i]=rand()/100-100;

}

void output (int *a)

{

cout<<"Output matr>"<<endl; for(int i=0;i<n;i++)

cout<<setw(6)<<a[i]; cout<<endl; }

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

Немного сложнее выглядят заголовки функций, которые в качестве параметров используют матрицы. Запись void input(int a[][]) является неверной, поскольку компьютер должен знать точное количе-

107

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

const int n=6, m=4; void input( int a[][m])

{

for(int i=0;i<n;i++) for(int j=0;j<m;j++)

a[i][j]=rand()/100-100;

}

В заголовке данной функции явно задается количество столбцов, а количество строк матрицы опущено. Запись void input(int a[n][m]) будет также правильной.

Функция вывода значений матрицы на экран:

void output ( int a[][m])

{

cout<<"Output matr>"<<endl; for(int i=0;i<n;i++)

{

for(int j=0;j<m;j++) cout<<setw(6)<<a[i][j];

cout<<endl;

}

}

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

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

int** rezerv(int n, int m)

{

int **a = new int*[n]; for (int i = 0; i<n; i++)

a[i] = new int[m]; return a;

}

108

В данной функции параметры n и m - это количество строк и количество столбцов создаваемой матрицы. Переменная а указывает на одномерный массив указателей, каждый элемент которого в свою очередь указывает на одномерный массив. Схема взаимосвязей указателей представлена на рис.3.

а

 

*

*

*

*

 

 

 

 

 

 

a11

a12

a1

a21

a22

a2

an1

an2

an

Рис.3. Схема взаимосвязей указателей при динамическом резервировании памяти для элементов матрицы

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

Функция формирования значений матрицы:

void input(int **a, int n, int m)

{

for (int i = 0; i<n; i++)

for (int j = 0; j<m; j++)

a[i][j] = rand() / 100 - 100;

}

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

Аналогичным образом можно представить и функцию вывода значений матрицы на экран:

void output(int **a, int n, int m)

{

109

cout << "Output matr>" << endl; for (int i = 0; i<n; i++)

{

for (int j = 0; j<m; j++)

cout << setw(6) << a[i][j]; cout << endl;

}

}

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

void dispose(int **a, int n, int m)

{

for (int i = 0; i<n; i++) delete [] a[i];

delete[] a;

}

Приведем основную функцию, использующую вышеописанные функции:

void main()

{

const int n = 6, m = 4; int **f;

f = rezerv(n, m); input(f, n, m); output(f, n, m); dispose(f, n, m);

}

Примеры программирования

Пример 1. Для матрицы F, сформировать одномерный массив K из количества положительных элементов каждого столбца матрицы.

Решение. Формирование матрицы одномерного массива, а также вывод матрицы и одномерного массива на экран оформим с помощью функций.

Текст программы:

#include <iostream> #include <iomanip> using namespace std; typedef int matr[5][5];

110

typedef int mas[5];

// Функция формирования матрицы void input(matr a, int n, int m)

{

for (int i = 0; i<n; i++)

for (int j = 0; j<m; j++)

a[i][j] = rand() / 100 - 100;

}

//Функция вывода значений матрицы на экран void output(matr a, int n, int m)

{

cout << "Матрица" << endl; for (int i = 0; i<n; i++)

{

for (int j = 0; j<m; j++)

cout << setw(6) << a[i][j]; cout << endl;

}

}

// Функция формирования одномерного массива void form(matr a, mas b, int n, int m)

{

int kol;

for (int j = 0; j<m; j++)

{

kol = 0;

for (int i = 0; i<n; i++) if (a[i][j]>0)kol++;

b[j] = kol;

}

}

//Функция вывода значений одномерного массива //на экран

void output_mas(mas a, int m)

{

cout << "Массив" << endl; for (int i = 0; i<m; i++)

cout << setw(6) << a[i]; cout << endl;

}

int main()

{

setlocale(LC_CTYPE, "Russian"); matr f;

111

mas k;

input(f, 5, 5); output(f, 5, 5); form(f, k, 5, 5); output_mas(k, 5);

}

По я сн е н ия к пр о гр ам м е . В данной программе использован оператор typedef, позволяющий определить свой собственный тип и затем применять его в программе наравне со стандартными типами данных. Так, в программе было определено два типа - matr и mas, которые использовались в заголовках функций и при объявлении фактических данных в основной функции. Результат выполнения программы приведен на рис.4.

Рис.4. Результат выполнения программы к примеру 1

Пример 2. Для целочисленных матриц А и В 10 10 сформировать одномерные массивы P и Q, состоящие из числа элементов каждой строки матрицы, кратных пяти, и найти наибольшие из них.

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

Текст программы:

#include <iostream> #include <iomanip> #include <time.h>

112