Передача массивов в качестве аргументов функции

Стандартные функции

Описания стандартных функций находятся в файлах, включаемых в программу с помощью директивы #include. Такие файлы называют заголовочными; они имеют расширение h.

Обращение к имени функции в основной программе называется вызовом функции.

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

y = sin (x); //функция вычисления синуса

Определение функции

В общем виде функции определяются следующим образом:

тип_возвращаемого_значения имя_функции (тип имя_параметра,...,тип имя_параметра)

{

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

}

Программируемые функции

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

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

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

Пример 9.1.Создадим функцию, которая печатает 65 символов "*" в ряд. Чтобы эта функция выполнялась в некотором контексте, она включена в программу печати фирменного бланка. Программа состоит из функций: main() и stars().

// Фирменный бланк

#include <iostream.h>

const int Limit=65;

void stars(void); // прототип функции stars()

void main()

{ stars();

cout<<"Moscow Institute of Electronic Engineering"<<endl;

stars();

}

// Определение функции stars()

void stars()

{ int count;

for (count=1; count<=Limit; count++)

putchar ('*');

putchar ('\n');

}

Мы рассмотрели пример простейшей функции, не имеющей аргументов и не возвращающей никаких значений.

Параметры функций

Рассмотрим на примере использование параметров функции.

Пример 9.2.Напишем функцию space(), в качестве аргумента которой будет число пробелов, которое должна напечатать эта функция.

#define address " Zelenograd"

#define name " Moscow Institute Electronic Engineering "

#define department " Informatics and Programming"

const int LIMIT=65;

#include <iostream.h>

void stars();

void space(int number);

void main()

{ int spaces;

stars();

space(25);

cout<<address<<endl;

spaces=(LIMIT - strlen(name))/2; // Вычислить, сколько

// нужно пробелов

space(spaces);

cout<<name<<endl;

space((LIMIT - strlen(department))/2); // аргумент – выражение

cout<<department<<endl;

stars();

}

//Определение функции stars()

void stars()

{ int count;

for (count=1; count<=LIMIT; count++)

putchar ('*');

putchar ('\n');

}

//Определение функции space()

void space(int number)

{ int count;

for (count=1; count <=number; count++)

putchar (' ');

}

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

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

void printnum (int i, int j)

{ cout<<"Координаты точек”<< i << j <<endl; }

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

Возвращение значений с помощью оператора return

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

Пример 9.3.

int abs(int x); // прототип функции abs();

void main()

{ int а=10, b=0, c= -22;

int d, e, f;

d= abs(a);

e= abs(b);

f= abs(c);

cout<<d<<e<<f<<endl;

}

int abs(int x) // функция, вычисляющая абсолютное

// значение числа

{ int y;

y= (x<0) ? –x :x;

return y; // возвращает значение у вызывающей программе

}

Запись y= (x<0) ? –x :x эквивалентна записи

if (x<0) y= –x;

else y= x;

Другая версия функции abs(x):

int abs(int x)

{ if (x<0) return –x;

return x;

}

Третья версия функции abs(x):

int abs(int x)

{ if (x<0) return –x;

return x;

cout<<"А вот эти строки не напечатаются никогда и ни за что";

cout <<endl;

cout<<"так как этому препятствует наличие оператора return.";

cout <<endl;

}

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

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

В языке C, если указание типа отсутствует, то по умолчанию считается, что функция имеет тип int. В языке C++ такое умолчание приводит к трудно обнаруживаемым ошибкам, поэтому надежнее явно указывать тип функции.

Если функция не возвращает никакого результата посредством выполнения оператора return выражение, то тип возвращаемого ею значения определяется как void (в том числе и для функции main ()). Иными словами, тип функции не определен.

Запрещается в C++ определять функции внутри других функций.

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

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

Рассмотренные выше функции содержали объявления переменных внутри определения функции. Такие переменные называются локальными и доступны только в пределах функции, в которой они определены. В следующем примере переменная var1 доступна только внутри функции func(), а var2 активна только в main().

Пример 9.4.

#include <iostrem.h>

void func(void)

{ int var1=11; //локальная переменная var1

cout<<"var1="<<var1<<endl;

}

int main(void)

{ int var2=22; //локальная переменная var2

cout<<"var2="<<var2<<endl;

func();

cout<<"var1="<<var1<<endl; //приведет к возникновению

//ошибки

return 0; // 'Undefined symbol var1'

}

Переменная, объявленная вне любой из функций, называется глобальной переменной и доступна в области от точки ее объявления до конца файла. Чтобы сделать var1 доступной как в func(), так и в main(), следует описать эту переменную в начале файла.

Пример 9.5.

#include <iostream.h>

int var1=11; // глобальная переменная var1

void func(void)

{ cout<<"var1="<<var1<<endl;

}

int main(void)

{ int var2=22;

cout<<"var2="<<var2<<endl;

func(); //на экран будут выданы

cout<<"var1="<<var1<<endl; //два одинаковых значения.

return 0;

}

Параметры функций

Передача массивов в качестве аргументов функции

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

double SumOfData(double data[max]);

Еще лучше объявить

double SumOfData(double data[ ], int n);

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

Сама функция SumOfData() может содержать, например, обычный цикл while, суммирующий элементы массива, а функция return возвращает результат:

double SumOfData(double data[ ], int n)

{ double sum=0;

while (n>0)

sum += data [--n];

return sum;

}

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

Пусть ROWS - количество строк, COLS - количество столбцов. Объявим функцию с массивом в качестве параметра:

void AnyFn(int data[ROWS][COLS]);

или

void AnyFn(int data[ ][COLS]);

Можно передать параметр, определяющий количество строк:

void AnyFn(int data[ ][COLS], int numRows);

где numRows сообщает функции число строк в массиве data.

Пример 9.6. Передача функции многомерных массивов

#include <iostream.h>

#include <iomanip.h>

#include <stdlib.h>

const int COLS=8;

void FillArray(int data[ ][COLS], int numRows);

void DisplayTable(int data[ ][COLS], int numRows);

int data1[7][COLS];

int data2[4][COLS];

void main()

{ randomize(); // инициализация генератора случайных чисел

FillArray(data1, 7);

DisplayTable(data1, 7);

FillArray(data2,4);

DisplayTable(data2,4);

}

void FillArray(int data[ ][COLS], int numRows)

{ int r, c;

for (r=0; r<numRows; r++)

for (c=0; c<COLS; c++)

data[r][c]= rand(50); // rand() - генератор случайных чисел

}

void DisplayTable(int data[ ][COLS], int numRows)

{ int r, c;

for (r=0; r<numRows; r++)

{ cout<<endl;

for (c=0; c<COLS; c++)

cout<<setw(5)<<data[r][c]);

}

cout<<endl;

}

Понятие об указателях

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

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

При работе с указателями используются два оператора:

"&" - унарный оператор определения адреса переменной,

"*" - унарный оператор раскрытия ссылки.

Записывая функцию С++, которая передает параметр в виде массива, можно объявить этот параметр как указатель на базовый тип массива.

Общий синтаксис для прототипа функции с параметром в виде указателя на массив:

возвращаемый_тип имя_функции (базовый_тип*, другие_типы_параметров);

Общий синтаксис для определения этой функции:

возвращаемый_тип имя_функции (базовый_тип *массив_параметр, другие_параметры)

{

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

}

Напишем функцию, использующую массивы, а затем перепишем ее, применяя указатели.

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

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

Пример 9.7.

#include <iostream.h>

swp(int *x, int *y);

void main()

{ int a, b;

cout<<»Введите значения a и b»;

cin>>a>>b;

swp(&a, &b);

cout<<»Измененные значения: a=»<<a<<”b=”<<b;

}

void swp(int *x, int *y)

// x и y – указатели, *x и *y – значения, на которые они указывают

{ int c;

c=*x;

x=y;

*y=c;

}

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

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

cout<<»Среднее из заданных значений»<<mean (numbs, size)<<endl;

/* Находим среднее значение массива из n целых чисел.*/

int mean (int array [ ], int n)

{ int index;

long sum; /* Если массив содержит много элементов, сумма может оказаться довольно большой, поэтому используем тип long int */.

If (n>0)

{ for (index=0, sum=0; index<n; index++)

sum+=array [index];

return sum/n; // Возвращает int.

}

else

{ cout<<”Нет массива.”<<endl;

return 0;

}

}

Перепишем эту же программу с использованием указателей. Объявим iPtr указателем на тип int и заменим элемент массива array[index] на соответствующее значение: *(iPtr+index).

Наши рекомендации