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

 

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

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

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

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

 

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

 

// Листинг 9.3

#include <iostream>

using namespace std;

 

void modifyArray(int [], int); // Прототип функции

// Эквивалентный вид прототипа:

// void modifyArray(int *, int);

 

int main() {

const int n = 5; // Число элементов в массиве

int a[n] = {0, 1, 2, 3, 4};

 

// Вывод на экран значений исходного массива

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

cout << a[i] << '\t';

cout << endl;

 

// Массив передаётся по указателю

modifyArray(a, n);

 

// Вывод значений модифицированного массива

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

cout << a[i] << '\t';

cout << endl;

return 0;

}

 

void modifyArray(int b[], int n)

// Эквивалентный вид заголовка:

// void modifyArray(int *b, int n)

{

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

b[j] *= 2;

}

 

Результат выполнения программы:

0 1 2 3 4

0 2 4 6 8

 

Существует ещё один метод предоставления функции необ­ходимой информации – указание диапазона участка памяти с элементами. Это осуществляется путём передачи двух указате ­ лей: один идентифицирует начало диапазона, а второй – конец. В стандартной библиотеке шаблонов (STL) в основном реализовано использование диапазонов. В случае массива аргумент, указыва ­ ющий конец диапазона, представляет собой указатель на ячейку памяти, следующую за последним элементом из диапазона (так называемое «запредельное значение»). Аргументы, обозначаю ­ щие диапазон, указывают функции, какие элементы следует обрабатывать.

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

 

// Листинг 9.4

#include <iostream>

using namespace std;

 

int sum(int * begin, int* end) { // Указатели

int * p; // на начало и конец диапазона

int s = 0;

for (p = begin; p!= end; ++p)

s += *p;

return s;

}

 

int main() {

setlocale(LC_CTYPE, "Russian");

const int n = 7;

int mas[n] = {1, 2, 3, 4, 5, 6, 7};

cout << "Сумма всех элементов массива "

<< sum(mas, mas + n) << endl;

cout << "Сумма трёх первых элементов массива "

<< sum(mas, mas + 3) << endl;

cout << "Сумма 4-х последних элементов массива "

<< sum(mas + n - 4, mas + n) << endl;

return 0;

}

 

Результат выполнения программы:

Сумма всех элементов массива 28

Сумма трёх первых элементов массива 6

Сумма 4-х последних элементов массива 22

 

При передаче в качестве параметров многомерных массивов все размерности должны передаваться в качестве параметров.

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

 

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

 

// Листинг 9.5

#include <stdlib.h>

#include <iostream>

using namespace std;

 

int sum(int *, int, int); // Прототип функции

 

int main() {

int i, j, m, n, *b;

 

// Статический массив a имеет тип int[][]

int a[2][3] = {{1,2,3},{4,5,6}};

 

// Вывод элементов массива a

cout << "Массив a:" << endl;

for (i = 0; i < 2; ++i) {

for (j = 0; j < 3; ++j)

cout << a[i][j] << "\t";

cout << endl;

}

 

cout << "Сумма элементов a = "

<< sum(&a[0][0], 2, 3) << endl;

// Имя массива a в функцию sum передавать нельзя

// из-за несоответствия типов int* и int[][]

 

cout << "Введите количество строк и столбцов "

"матрицы b";

cin >> m >> n;

 

// Динамический массив в виде непрерывного

// участка памяти, b имеет тип int *

b = (int*)malloc(m*n*sizeof(int));

 

for (i = 0; i < m; ++i)

for (j = 0; j < n; ++j)

// Пересчёт двух индексов в один

cin >> b[i * n + j];

 

// Вывод элементов массива b

cout << "Массив b:" << endl;

for (i = 0; i < m; ++i) {

for (j = 0; j < n; ++j)

cout << b[i * n + j] << "\t";

cout << endl;

}

 

cout <<"Сумма элементов b = "<<sum(b,m,n)<<endl;

 

free(b); // Освобождение памяти

return 0;

}

 

// Функция возвращает сумму всех элементов матрицы

int sum(int * matr, int nr, int nc) {

int i, j, s = 0;

for (i = 0; i < nr; ++i)

for (j = 0; j < nc; ++j)

// Пересчёт двух индексов в один

s += matr[i * nc + j];

return s;

}

 

Для использования в функции двух индексов память для двумерного динамического массива необходимо выделять в два этапа (см. рис. 7.1 Практического занятия 7):

1) для одномерного вспомогательного массива указателей на одномерные массивы-строки;

2) для одномерных массивов – строк матрицы.

 

Рассмотрим программу, в которой в функцию передаётся в качестве параметров матрица (созданная в виде динамического массива) и её размерности.

 

Задача: сформировать массив, представляющий прямоу­гольную целочисленную матрицу, размеры (n – число строк, m – число столбцов) матрицы вводить с клавиатуры в процессе работы программы. Заполнить матрицу путём считывания данных из текстового файла (matrix.txt), вывести её на экран, вычислить сумму элементов матрицы, увеличить каждый элемент матрицы в два раза, записать измененную матрицу в новый файл (matrix1.txt), очистить динамическую память. Оформить вычисление суммы в виде функции.

 

// Листинг 9.6

#include <iostream>

#include <fstream>

using namespace std;

 

int sum(int **, int, int); // Прототип функции

 

void main() {

int n, m, i, j;

cin >> n >> m; // Число строк и столбцов

 

// Выделение динамической памяти для матрицы.

//matr - указатель на массив указателей на строки

int ** matr = new int * [n];

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

matr[i] = new int [m];

 

// Открытие файла для ввода данных

ifstream infile("matrix.txt");

if (!infile) {

cout << "File cannot be opened" << endl;

return; // Выход из программы

}

 

// Заполнение матрицы считыванием из файла

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

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

infile >> matr[i][j];

cout << matr[i][j] << "\t";

} // for j

cout << endl;

} // for i

 

infile.close(); // Закрытие файла

 

// Вычисление суммы

cout << "sum = " << sum(matr, n, m) << endl;

 

// Открытие файла для вывода

ofstream outfile("matrix1.txt");

if (!outfile) {

cout << "File cannot be opened" << endl;

return; // Выход из программы

}

 

// Изменение матрицы и запись в файл

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

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

matr[i][j] *= 2;

outfile << matr[i][j] << "\t";

} // for j

outfile << endl;

} // for i

outfile.close(); // Закрытие файла

 

// Освобождение динамической памяти

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

delete [] matr[i];

delete [] matr;

}

 

// Вычисление суммы всех элементов матрицы

int sum(int ** mass, int n, int m) {

int i, j, s = 0;

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

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

s += mass[i][j];

return s;

}

 

Задание. Реализовать на языке С++ программу, решающую задачу согласно варианту. Использовать динамическое выделение памяти для двумерных массивов. Размеры матрицы вводить с клавиатуры. Элементы матрицы вводить из заранее созданного текстового файла. Каждый пункт задания должен быть оформлен в виде отдельной функции, вычисляющей и возвращающей необходимое значение.

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

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

 

Вариант 1

Дана целочисленная прямоугольная матрица. Переставляя строки заданной матрицы, расположить их в соответствии с ростом характеристик. Характеристикой строки целочисленной матрицы назовем сумму её положительных чётных элементов.

 

Вариант 2

Дана целочисленная прямоугольная матрица. Определить номера строк и столбцов всех седловых точек матрицы. Матрица A имеет седловую точку Aij, если Aij является минимальным элементом в i-й строке и максимальным в j-м столбце.

 

Вариант 3

Дана вещественная квадратная матрица. Построить результат сглаживания заданной матрицы. Соседями элемента Aij в матрице назовём элементы Akl с i-1≤k≤i+1, j-1≤l≤j+1, (k,l)≠(i,j). Операция сглаживания матрицы формирует новую матрицу того же размера, каждый элемент которой получается как среднее арифметическое имеющихся соседей соответствующего элемента исходной матрицы.

 

Вариант 4

Дана целочисленная прямоугольная матрица. Определить номер строки, в которой находится самая длинная серия одинаковых элементов.

 

Вариант 5

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

 

 

Вариант 6

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

 

Вариант 7

Дана целочисленная матрица. Определить максимальное из чисел, встречающихся в заданной матрице более одного раза.

 

Вариант 8

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

 

Вариант 9

Дана вещественная квадратная матрица. Найти такие m, что реверс m-ой строки матрицы совпадает с m-м столбцом.

 

Вариант 10

Путём перестановки элементов квадратной вещественной матрицы добиться того, чтобы её максимальный элемент находился в левом верхнем углу, следующий по величине – в позиции (1,1), следующий по величине – в позиции (2,2) и т.д., заполнив таким образом всю главную диагональ.

 

Вариант 11

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

 

Вариант 12

Дана целочисленная прямоугольная матрица. Осуществить циклический сдвиг элементов каждой строки матрицы на k элементов вправо или сдвиг элементов каждого столбца вниз (в зависимости от введённого режима); k может быть больше количества элементов в строке или столбце.

 

Вариант 13

Дана целочисленная прямоугольная матрица. Уплотнить заданную матрицу, удаляя из неё строки и столбцы, заполненные нулями.

Вариант 14

Дана вещественная квадратная матрица. Осуществить циклический сдвиг элементов матрицы вправо на k элементов таким образом: элементы 1-й строки сдвигаются в последний столбец сверху вниз, из него – в последнюю строку справа налево, из неё – в первый столбец снизу вверх, из него – в первую строку; для остальных элементов – аналогично.

 

Вариант 15

Дана целочисленная квадратная матрица. Определить максимум среди сумм элементов диагоналей, параллельных главной диагонали матрицы.

 

Вариант 16

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

 

Вариант 17

Дана целочисленная прямоугольная матрица. Определить номера строк и столбцов всех седловых точек матрицы. Матрица М имеет седловую точку Мij, если Мij является максимальным элементом в i-й строке и минимальным в j-м столбце.

 

Вариант 18

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

 

Вариант 19

Дана целочисленная квадратная матрица. Подсчитать количество локальных минимумов заданной матрицы. Элемент матрицы называется локальным минимумом, если он строго меньше всех имеющихся у него соседей.

 

Вариант 20

Дана целочисленная квадратная матрица. Определить минимум среди сумм элементов диагоналей, параллельных главной диагонали матрицы.

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: